import { extend } from 'shared/util' import { CompilerOptions, CompiledResult, WarningMessage } from 'types/compiler' import { detectErrors } from './error-detector' import { createCompileToFunctionFn } from './to-function' export function createCompilerCreator(baseCompile: Function): Function { return function createCompiler(baseOptions: CompilerOptions) { function compile( template: string, options?: CompilerOptions ): CompiledResult { const finalOptions = Object.create(baseOptions) const errors: WarningMessage[] = [] const tips: WarningMessage[] = [] let warn = ( msg: WarningMessage, range: { start: number; end: number }, tip: string ) => { ;(tip ? tips : errors).push(msg) } if (options) { if (__DEV__ && options.outputSourceRange) { // $flow-disable-line const leadingSpaceLength = template.match(/^\s*/)![0].length warn = ( msg: WarningMessage | string, range: { start: number; end: number }, tip: string ) => { const data: WarningMessage = typeof msg === 'string' ? { msg } : msg if (range) { if (range.start != null) { data.start = range.start + leadingSpaceLength } if (range.end != null) { data.end = range.end + leadingSpaceLength } } ;(tip ? tips : errors).push(data) } } // merge custom modules if (options.modules) { finalOptions.modules = (baseOptions.modules || []).concat( options.modules ) } // merge custom directives if (options.directives) { finalOptions.directives = extend( Object.create(baseOptions.directives || null), options.directives ) } // copy other options for (const key in options) { if (key !== 'modules' && key !== 'directives') { finalOptions[key] = options[key as keyof CompilerOptions] } } } finalOptions.warn = warn const compiled = baseCompile(template.trim(), finalOptions) if (__DEV__) { detectErrors(compiled.ast, warn) } compiled.errors = errors compiled.tips = tips return compiled } return { compile, compileToFunctions: createCompileToFunctionFn(compile) } } }