Skip to content

Commit

Permalink
feat plugin-vue-enhance
Browse files Browse the repository at this point in the history
  • Loading branch information
Akimyou committed Sep 3, 2020
1 parent 96d2ffc commit 1861a54
Show file tree
Hide file tree
Showing 25 changed files with 865 additions and 7 deletions.
1 change: 1 addition & 0 deletions plugins/plugin-vue/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
coverage
13 changes: 12 additions & 1 deletion plugins/plugin-vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,23 @@
"publishConfig": {
"access": "public"
},
"scripts": {
"test": "jest"
},
"dependencies": {
"@vue/compiler-sfc": "^3.0.0-0",
"hash-sum": "^2.0.0"
},
"devDependencies": {
"jest": "^26.4.2",
"vue": "*"
},
"gitHead": "a01616bb0787d56cd782f94cecf2daa12c7594e4"
"gitHead": "a01616bb0787d56cd782f94cecf2daa12c7594e4",
"jest": {
"collectCoverageFrom": [
"plugin.js",
"script-compilers.js",
"!**/node_modules/**"
]
}
}
22 changes: 22 additions & 0 deletions plugins/plugin-vue/plugin-tsx-jsx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const fs = require('fs');
const scriptCompilers = require('./src/script-compilers');

module.exports = function plugin(snowpackConfig, pluginOptions) {
const curPluginOptions = pluginOptions || {};
const {sourceMaps} = snowpackConfig.buildOptions;
const tsconfigFilePath = curPluginOptions.tsconfig;

return {
name: '@snowpack/plugin-vue-tsx-jsx',
resolve: {
input: ['.tsx', '.jsx'],
output: ['.js'],
},
async load({filePath, fileExt}) {
const content = fs.readFileSync(filePath, 'utf-8');
const lang = fileExt.slice(fileExt.lastIndexOf('.') + 1);
const result = scriptCompilers.esbuildCompile(content, lang, tsconfigFilePath);
return result;
},
};
};
24 changes: 18 additions & 6 deletions plugins/plugin-vue/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const fs = require('fs');
const path = require('path');
const hashsum = require('hash-sum');
const compiler = require('@vue/compiler-sfc');
const scriptCompilers = require('./src/script-compilers');

/** Friendly error display */
function displayError({contents, filePath, error}) {
Expand Down Expand Up @@ -31,7 +32,10 @@ function displayError({contents, filePath, error}) {
return output.join('\n');
}

module.exports = function plugin(snowpackConfig) {
module.exports = function plugin(snowpackConfig, pluginOptions) {
const curPluginOptions = pluginOptions || {};
const tsconfigFilePath = curPluginOptions.tsconfig;

return {
name: '@snowpack/plugin-vue',
resolve: {
Expand All @@ -56,14 +60,22 @@ module.exports = function plugin(snowpackConfig) {
};

if (descriptor.script) {
output['.js'].code += descriptor.script.content.replace(
`export default`,
'const defaultExport =',
);
const scriptLang = descriptor.script.lang;
let scriptContent = descriptor.script.content;
if (['jsx', 'ts', 'tsx'].includes(scriptLang)) {
scriptContent = scriptCompilers.esbuildCompile(
scriptContent,
scriptLang,
tsconfigFilePath,
);
}
if (['js', 'ts'].includes(scriptLang) || !scriptLang) {
scriptContent = scriptContent.replace(`export default`, 'const defaultExport =');
}
output['.js'].code += scriptContent;
} else {
output['.js'].code += `const defaultExport = {};`;
}

await Promise.all(
descriptor.styles.map((stylePart) => {
const css = compiler.compileStyle({
Expand Down
39 changes: 39 additions & 0 deletions plugins/plugin-vue/src/script-compilers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const esbuild = require('esbuild');

const codeSnippetH = `import { Fragment } from '/web_modules/vue.js';`;

// https://github.com/vitejs/vite/blob/master/src/client/vueJsxCompat.ts
const codeSnippetVueJsxCompat =
`import {createVNode, isVNode} from '/web_modules/vue.js';
const slice = Array.prototype.slice;
export function jsx(tag, props = null, children = null) {
if (arguments.length > 3 || isVNode(children)) {
children = slice.call(arguments, 2);
}
return createVNode(tag, props, children);
}`;

/**
* @param {string} content
* @param {'jsx' | 'ts' | 'tsx'} lang
* @param {string} [tsconfig]
*/
const esbuildCompile = (content, lang, tsconfig) => {
let result = '';
if (['jsx', 'tsx'].includes(lang)) {
result += `${codeSnippetH}\n`;
result += `${codeSnippetVueJsxCompat}\n`;
}
const {js} = esbuild.transformSync(content, {
loader: lang,
tsconfig,
jsxFactory: tsconfig ? undefined : 'jsx',
jsxFragment: tsconfig ? undefined : 'Fragment',
});
result += `\n${js.trim()}\n`;
return result.trim();
};

module.exports = {
esbuildCompile,
};
24 changes: 24 additions & 0 deletions plugins/plugin-vue/test/__snapshots__/plugin-tsx-jsx.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`plugin with jsx 1`] = `
"import { h, Fragment } from '/web_modules/vue.js';
import {defineComponent} from \\"vue\\";
export default defineComponent({
name: \\"JsxContent\\",
setup() {
return () => /* @__PURE__ */ h(Fragment, null, /* @__PURE__ */ h(\\"h1\\", null, \\"JsxContent\\"));
}
});"
`;

exports[`plugin with tsx 1`] = `
"import { h, Fragment } from '/web_modules/vue.js';
import {defineComponent} from \\"vue\\";
export default defineComponent({
name: \\"TsxContent\\",
setup() {
const name = \\"TsxContent\\";
return () => /* @__PURE__ */ h(Fragment, null, /* @__PURE__ */ h(\\"h1\\", null, \\"TsxContent\\"));
}
});"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`plugin vue with jsx 1`] = `
Object {
".css": Object {
"code": "",
"map": "",
},
".js": Object {
"code": "import { h, Fragment } from '/web_modules/vue.js';
import {defineComponent} from \\"vue\\";
export default defineComponent({
name: \\"VueContentJsx\\",
setup() {
return () => /* @__PURE__ */ h(Fragment, null, /* @__PURE__ */ h(\\"h1\\", null, \\"VueContentJsx\\"));
}
});",
"map": "",
},
}
`;

exports[`plugin vue with ts 1`] = `
Object {
".css": Object {
"code": "",
"map": "",
},
".js": Object {
"code": "import {defineComponent} from \\"vue\\";
const defaultExport = defineComponent({
name: \\"VueContentTs\\",
setup() {
const name = \\"VueContentTs\\";
}
});
import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"/web_modules/vue.js\\"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(\\"h1\\", null, \\"Vue Content Ts\\"))
}
defaultExport.render = render
export default defaultExport",
"map": "",
},
}
`;

exports[`plugin vue with tsx 1`] = `
Object {
".css": Object {
"code": "",
"map": "",
},
".js": Object {
"code": "import { h, Fragment } from '/web_modules/vue.js';
import {defineComponent} from \\"vue\\";
export default defineComponent({
name: \\"VueContentTsx\\",
setup() {
const name = \\"VueContentTsx\\";
return () => /* @__PURE__ */ h(Fragment, null, /* @__PURE__ */ h(\\"h1\\", null, \\"VueContentTsx\\"));
}
});",
"map": "",
},
}
`;
Loading

0 comments on commit 1861a54

Please sign in to comment.