|
|
@@ -1,3 +1,101 @@
|
|
|
-export function compileTemplate() {
|
|
|
- // TODO
|
|
|
+import {
|
|
|
+ CompilerOptions,
|
|
|
+ CodegenResult,
|
|
|
+ CompilerError
|
|
|
+} from '@vue/compiler-core'
|
|
|
+import { RawSourceMap } from 'source-map'
|
|
|
+import { transformAssetUrl } from './templateTransformAssetUrl'
|
|
|
+import { transformSrcset } from './templateTransformSrcset'
|
|
|
+
|
|
|
+const consolidate = require('consolidate')
|
|
|
+
|
|
|
+export interface TemplateCompileResults {
|
|
|
+ code: string
|
|
|
+ source: string
|
|
|
+ tips: string[]
|
|
|
+ errors: (string | CompilerError)[]
|
|
|
+ map?: RawSourceMap
|
|
|
+}
|
|
|
+
|
|
|
+export interface TemplateCompiler {
|
|
|
+ compile(template: string, options: CompilerOptions): CodegenResult
|
|
|
+}
|
|
|
+
|
|
|
+export interface TemplateCompileOptions {
|
|
|
+ source: string
|
|
|
+ filename: string
|
|
|
+ compiler: TemplateCompiler
|
|
|
+ compilerOptions?: CompilerOptions
|
|
|
+ preprocessLang?: string
|
|
|
+ preprocessOptions?: any
|
|
|
+}
|
|
|
+
|
|
|
+function preprocess(
|
|
|
+ { source, filename, preprocessOptions }: TemplateCompileOptions,
|
|
|
+ preprocessor: any
|
|
|
+): string {
|
|
|
+ // Consolidate exposes a callback based API, but the callback is in fact
|
|
|
+ // called synchronously for most templating engines. In our case, we have to
|
|
|
+ // expose a synchronous API so that it is usable in Jest transforms (which
|
|
|
+ // have to be sync because they are applied via Node.js require hooks)
|
|
|
+ let res: any, err
|
|
|
+ preprocessor.render(
|
|
|
+ source,
|
|
|
+ { filename, ...preprocessOptions },
|
|
|
+ (_err: Error | null, _res: string) => {
|
|
|
+ if (_err) err = _err
|
|
|
+ res = _res
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ if (err) throw err
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
+export function compileTemplate(
|
|
|
+ options: TemplateCompileOptions
|
|
|
+): TemplateCompileResults {
|
|
|
+ const { preprocessLang } = options
|
|
|
+ const preprocessor = preprocessLang && consolidate[preprocessLang]
|
|
|
+ if (preprocessor) {
|
|
|
+ return doCompileTemplate({
|
|
|
+ ...options,
|
|
|
+ source: preprocess(options, preprocessor)
|
|
|
+ })
|
|
|
+ } else if (preprocessLang) {
|
|
|
+ return {
|
|
|
+ code: `export default function render() {}`,
|
|
|
+ source: options.source,
|
|
|
+ tips: [
|
|
|
+ `Component ${
|
|
|
+ options.filename
|
|
|
+ } uses lang ${preprocessLang} for template. Please install the language preprocessor.`
|
|
|
+ ],
|
|
|
+ errors: [
|
|
|
+ `Component ${
|
|
|
+ options.filename
|
|
|
+ } uses lang ${preprocessLang} for template, however it is not installed.`
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return doCompileTemplate(options)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function doCompileTemplate({
|
|
|
+ source,
|
|
|
+ compiler,
|
|
|
+ compilerOptions = {},
|
|
|
+ filename
|
|
|
+}: TemplateCompileOptions): TemplateCompileResults {
|
|
|
+ const errors: CompilerError[] = []
|
|
|
+ const { code, map } = compiler.compile(source, {
|
|
|
+ ...compilerOptions,
|
|
|
+ filename,
|
|
|
+ mode: 'module',
|
|
|
+ sourceMap: true,
|
|
|
+ nodeTransforms: [transformAssetUrl, transformSrcset],
|
|
|
+ onError: e => errors.push(e)
|
|
|
+ })
|
|
|
+ return { code, source, errors, tips: [], map }
|
|
|
}
|