11import deIndent from 'de-indent' ;
22import htmlMinifier from 'html-minifier' ;
3+ import { compile as compileTemplate } from 'vue-template-compiler' ;
34import parse5 from 'parse5' ;
45import validateTemplate from 'vue-template-validator' ;
56import { relative } from 'path' ;
@@ -38,6 +39,39 @@ function padContent(content) {
3839 . join ( '\n' ) ;
3940}
4041
42+ /**
43+ * Wrap code inside a with statement inside a function
44+ * This is necessary for Vue 2 template compilation
45+ *
46+ * @param {string } code
47+ * @returns {string }
48+ */
49+ function wrapRenderFunction ( code ) {
50+ // Replace with(this) by something that works on strict mode
51+ // https://github.com/vuejs/vue-template-es2015-compiler/blob/master/index.js
52+ return `function(){${ code . replace ( / w i t h \( t h i s \) / g, 'if("__VUE_WITH_STATEMENT__")' ) } }` ;
53+ }
54+
55+ /**
56+ * Only support for es5 modules
57+ *
58+ * @param script
59+ * @param render
60+ * @returns {string }
61+ */
62+ function injectRender ( script , render ) {
63+ const matches = / ( e x p o r t d e f a u l t [ ^ { ] * \{ ) / g. exec ( script ) ;
64+ if ( matches ) {
65+ return script . split ( matches [ 1 ] )
66+ . join ( `${ matches [ 1 ] } ` +
67+ `render: ${ wrapRenderFunction ( render . render ) } ,` +
68+ 'staticRenderFns: [' +
69+ `${ render . staticRenderFns . map ( wrapRenderFunction ) . join ( ',' ) } ],`
70+ ) ;
71+ }
72+ throw new Error ( '[rollup-plugin-vue] could not find place to inject template in script.' ) ;
73+ }
74+
4175/**
4276 * Only support for es5 modules
4377 *
@@ -78,19 +112,24 @@ function processTemplate(node, filePath, content) {
78112 * @param {string } content
79113 * @param {string } template
80114 */
81- function processScript ( node , filePath , content , template ) {
115+ function processScript ( node , filePath , content , { template, render } ) {
82116 const lang = checkLang ( node ) || 'js' ;
83117 let script = parse5 . serialize ( node ) ;
84118 // pad the script to ensure correct line number for syntax errors
85119 const location = content . indexOf ( script ) ;
86120 const before = padContent ( content . slice ( 0 , location ) ) ;
87121 script = before + script ;
88- script = injectTemplate ( script , template , lang ) ;
122+ if ( template ) {
123+ script = injectTemplate ( script , template , lang ) ;
124+ } else if ( render ) {
125+ script = injectRender ( script , render , lang ) ;
126+ }
89127 script = deIndent ( script ) ;
128+
90129 return script ;
91130}
92131
93- export default function vueTransform ( code , filePath ) {
132+ export default function vueTransform ( code , filePath , transformOptions ) {
94133 // 1. Parse the file into an HTML tree
95134 const fragment = parse5 . parseFragment ( code , { locationInfo : true } ) ;
96135
@@ -108,10 +147,17 @@ export default function vueTransform(code, filePath) {
108147
109148 // 4. Process template
110149 const template = processTemplate ( nodes . template , filePath , code ) ;
150+ let js ;
151+ if ( transformOptions . compileTemplate ) {
152+ const render = compileTemplate ( template ) ;
153+ js = processScript ( nodes . script , filePath , code , { render } ) ;
154+ } else {
155+ js = processScript ( nodes . script , filePath , code , { template } ) ;
156+ }
111157
112158 // 5. Process script & style
113159 return {
114- js : processScript ( nodes . script , filePath , code , template ) ,
160+ js,
115161 css : nodes . style && {
116162 content : parse5 . serialize ( nodes . style ) ,
117163 lang : checkLang ( nodes . style ) ,
0 commit comments