UNPKG

vue-jsx-vapor

Version:
207 lines (202 loc) 7.14 kB
import { transformVueJsxVapor } from "./core-CJgJmh2O.js"; import { transformSync } from "@babel/core"; import babelTypescript from "@babel/plugin-transform-typescript"; import macros from "@vue-jsx-vapor/macros/raw"; import { transformJsxDirective } from "@vue-macros/jsx-directive/api"; import { createFilter, normalizePath } from "unplugin-utils"; import { isFunctionalNode } from "@vue-jsx-vapor/macros/api"; import getHash from "hash-sum"; import { relative } from "pathe"; import jsx from "@vue/babel-plugin-jsx"; //#region src/core/ssr.ts const ssrRegisterHelperId = "/__vue-jsx-ssr-register-helper"; const ssrRegisterHelperCode = `import { useSSRContext } from "vue"\nexport const ssrRegisterHelper = ${ssrRegisterHelper.toString()}`; /** * This function is serialized with toString() and evaluated as a virtual * module during SSR */ function ssrRegisterHelper(comp, filename) { const setup = comp.setup; comp.setup = (props, ctx) => { const ssrContext = useSSRContext(); (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add(filename); if (setup) return setup(props, ctx); }; } function injectSSR(id, hotComponents, root = "") { const normalizedId = normalizePath(relative(root, id)); let ssrInjectCode = `\nimport { ssrRegisterHelper } from "${ssrRegisterHelperId}"\nconst __moduleId = ${JSON.stringify(normalizedId)}`; for (const { local } of hotComponents) ssrInjectCode += `\nssrRegisterHelper(${local}, __moduleId)`; return ssrInjectCode; } //#endregion //#region src/core/hmr.ts function injectHMRAndSSR(result, id, options) { const ssr = options?.ssr; const defineComponentNames = options?.defineComponentNames ?? ["defineComponent", "defineVaporComponent"]; const { ast } = result; const declaredComponents = []; const hotComponents = []; let hasDefaultExport = false; for (const node of ast.program.body) { if (node.type === "VariableDeclaration") { const names = parseComponentDecls(node, defineComponentNames); if (names.length) declaredComponents.push(...names); } if (node.type === "ExportNamedDeclaration") { if (node.declaration && node.declaration.type === "VariableDeclaration") hotComponents.push(...parseComponentDecls(node.declaration, defineComponentNames).map((name) => ({ local: name, exported: name, id: getHash(id + name) }))); else if (node.specifiers.length) { for (const spec of node.specifiers) if (spec.type === "ExportSpecifier" && spec.exported.type === "Identifier") { const matched = declaredComponents.find((name) => name === spec.local.name); if (matched) hotComponents.push({ local: spec.local.name, exported: spec.exported.name, id: getHash(id + spec.exported.name) }); } } } if (node.type === "ExportDefaultDeclaration") { if (node.declaration.type === "Identifier") { const _name = node.declaration.name; const matched = declaredComponents.find((name) => name === _name); if (matched) hotComponents.push({ local: _name, exported: "default", id: getHash(`${id}default`) }); } else if (isDefineComponentCall(node.declaration, defineComponentNames) || isFunctionalNode(node.declaration)) { hasDefaultExport = true; hotComponents.push({ local: "__default__", exported: "default", id: getHash(`${id}default`) }); } } } if (hotComponents.length) { if (hasDefaultExport || ssr) result.code = `${result.code.replaceAll(`export default `, `const __default__ = `)}\nexport default __default__;`; if (!ssr && !/\?vue&type=script/.test(id)) { let code = result.code; let callbackCode = ``; for (const { local, exported, id: id$1 } of hotComponents) { code += `\n${local}.__hmrId = "${id$1}";\n__VUE_HMR_RUNTIME__.createRecord("${id$1}", ${local});`; callbackCode += ` __VUE_HMR_RUNTIME__[typeof mod['${exported}'] === 'function' ? 'rerender' : 'reload'](mod['${exported}'].__hmrId, mod['${exported}']);`; } code += ` if (import.meta.hot) { import.meta.hot.accept(mod => {${callbackCode}\n }); }`; result.code = code; } if (ssr) result.code += injectSSR(id, hotComponents, options?.root); } } function parseComponentDecls(node, fnNames) { const names = []; for (const decl of node.declarations) if (decl.id.type === "Identifier" && (isDefineComponentCall(decl.init, fnNames) || isFunctionalNode(decl.init))) names.push(decl.id.name); return names; } function isDefineComponentCall(node, names) { return !!(node && node.type === "CallExpression" && node.callee.type === "Identifier" && names.includes(node.callee.name)); } //#endregion //#region src/core/vue-jsx.ts function transformVueJsx(code, id, needSourceMap = false) { const result = transformSync(code, { plugins: [jsx, ...id.endsWith(".tsx") ? [[babelTypescript, { isTSX: true, allowExtensions: true }]] : []], filename: id, sourceMaps: needSourceMap, sourceFileName: id, babelrc: false, configFile: false }); if (result?.code && result.code !== code) return { code: result.code, map: result.map }; } //#endregion //#region src/raw.ts const plugin = (options = {}) => { const transformInclude = createFilter(options?.include || /\.[cm]?[jt]sx$/, options?.exclude || /node_modules/); let root = ""; let needHMR = false; let needSourceMap = options.sourceMap || false; return [ { name: "vue-jsx-vapor", vite: { config(config) { return { esbuild: { include: /\.ts$/ }, define: { __VUE_OPTIONS_API__: config.define?.__VUE_OPTIONS_API__ ?? true, __VUE_PROD_DEVTOOLS__: config.define?.__VUE_PROD_DEVTOOLS__ ?? false, __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: config.define?.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ ?? false } }; }, configResolved(config) { root = config.root; needHMR = config.command === "serve"; needSourceMap ||= config.command === "serve" || !!config.build.sourcemap; } }, resolveId(id) { if (id === ssrRegisterHelperId) return id; }, loadInclude(id) { if (id === ssrRegisterHelperId) return true; }, load(id) { if (id === ssrRegisterHelperId) return ssrRegisterHelperCode; }, transformInclude, transform(code, id, opt) { const result = transformVueJsxVapor(code, id, options, needSourceMap); if (result?.code) { (needHMR || opt?.ssr) && injectHMRAndSSR(result, id, { ssr: opt?.ssr, root }); return { code: result.code, map: result.map }; } } }, { name: "@vue-macros/jsx-directive", transformInclude, transform(code, id, opt) { if (options.interop || opt?.ssr) return transformJsxDirective(code, id, { lib: "vue", prefix: "v-", version: 3.6 }); } }, { name: "@vitejs/plugin-vue-jsx", transformInclude, transform(code, id, opt) { if (options.interop || opt?.ssr) return transformVueJsx(code, id, needSourceMap); } }, ...options.macros === false ? [] : options.macros ? [macros(options.macros === true ? void 0 : options.macros)] : [] ]; }; var raw_default = plugin; //#endregion export { raw_default };