diff --git a/package.json b/package.json index fbcd65b..a814d40 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "dependencies": { "de-indent": "latest", "html-minifier": "latest", + "magic-string": "^0.16.0", "parse5": "latest", "rollup-pluginutils": "latest", "vue-template-compiler": "^2.0.0-rc.4", diff --git a/src/index.js b/src/index.js index 2e6b614..88afa8a 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import { createFilter } from 'rollup-pluginutils'; import { writeFile } from 'fs'; +import MagicString from 'magic-string'; import vueTransform from './vueTransform'; import DEFAULT_OPTIONS from './options'; @@ -106,18 +107,25 @@ export default function vue(options = {}) { return null; } - const { js, css } = vueTransform(source, id, options); + const { js, css, map } = vueTransform(source, id, options); // Map of every stylesheet styles[id] = css || {}; // Component javascript with inlined html template - return js; + return { + code: js, + map: map.generateMap({ hires: true }), + }; }, transformBundle(source) { generateStyleBundle(); + const map = new MagicString(source); - return source.replace(/if[\s]*\('__VUE_WITH_STATEMENT__'\)/g, 'with(this)'); + return { + code: source.replace(/if[\s]*\('__VUE_WITH_STATEMENT__'\)/g, 'with(this)'), + map: map.generateMap({ hires: true }), + }; }, ongenerate(opts, rendered) { generateStyleBundle(); diff --git a/src/vueTransform.js b/src/vueTransform.js index da94021..6bd7082 100644 --- a/src/vueTransform.js +++ b/src/vueTransform.js @@ -3,6 +3,7 @@ import htmlMinifier from 'html-minifier'; import parse5 from 'parse5'; import validateTemplate from 'vue-template-validator'; import { relative } from 'path'; +import MagicString from 'magic-string'; /** * Check the lang attribute of a parse5 node. @@ -125,6 +126,8 @@ function processScript(node, filePath, content, templateOrRender) { const before = padContent(content.slice(0, location)); script = before + script; + const map = new MagicString(script); + if (template) { script = injectTemplate(script, template, lang); } else if (render) { @@ -132,7 +135,10 @@ function processScript(node, filePath, content, templateOrRender) { } script = deIndent(script); - return script; + return { + code: script, + map, + }; } export default function vueTransform(code, filePath, options) { @@ -146,17 +152,19 @@ export default function vueTransform(code, filePath, options) { } // 3. Don't touch files that don't look like Vue components - if (!nodes.template && !nodes.script) { + if (!nodes.script) { throw new Error('There must be at least one script tag or one' + ' template tag per *.vue file.'); } // 4. Process template - const template = processTemplate(nodes.template, filePath, code, options); + const template = nodes.template + ? processTemplate(nodes.template, filePath, code, options) + : undefined; let js; if (options.compileTemplate) { /* eslint-disable */ - const render = require('vue-template-compiler').compile(template); + const render = template ? require('vue-template-compiler').compile(template) : undefined; /* eslint-enable */ js = processScript(nodes.script, filePath, code, { render }); } else { @@ -165,7 +173,8 @@ export default function vueTransform(code, filePath, options) { // 5. Process script & style return { - js, + js: js.code, + map: js.map, css: nodes.style && { content: parse5.serialize(nodes.style), lang: checkLang(nodes.style), diff --git a/test/expects/noTemplate.js b/test/expects/noTemplate.js new file mode 100644 index 0000000..06a8b08 --- /dev/null +++ b/test/expects/noTemplate.js @@ -0,0 +1,10 @@ +var noTemplate = { + render(h, c) { + return h('h1', c.data.title); + }, + data() { + return { title: 'Hello' }; + }, +}; + +export default noTemplate; \ No newline at end of file diff --git a/test/fixtures/noTemplate.vue b/test/fixtures/noTemplate.vue new file mode 100644 index 0000000..d6eef2e --- /dev/null +++ b/test/fixtures/noTemplate.vue @@ -0,0 +1,10 @@ +