vue-inbrowser-compiler
Advanced tools
Comparing version 4.54.1 to 4.55.0
# Change Log | ||
## 4.55.0 | ||
### Minor Changes | ||
- [#1422](https://github.com/vue-styleguidist/vue-styleguidist/pull/1422) [`570e197e`](https://github.com/vue-styleguidist/vue-styleguidist/commit/570e197e68a459647858a4a95f42f0e48d9018aa) Thanks [@elevatebart](https://github.com/elevatebart)! - enable script setup in examples | ||
### Patch Changes | ||
- Updated dependencies [[`570e197e`](https://github.com/vue-styleguidist/vue-styleguidist/commit/570e197e68a459647858a4a95f42f0e48d9018aa)]: | ||
- vue-inbrowser-compiler-utils@4.55.0 | ||
## 4.54.1 | ||
@@ -4,0 +15,0 @@ |
@@ -0,1 +1,2 @@ | ||
import { parseComponent } from 'vue-inbrowser-compiler-utils'; | ||
export declare function parseScriptCode(code: string): { | ||
@@ -9,2 +10,3 @@ preprocessing?: string; | ||
export declare function insertCreateElementFunction(before: string, after: string): string; | ||
export declare function parseScriptSetupCode(code: string): string; | ||
/** | ||
@@ -15,3 +17,3 @@ * Coming out of this function all SFC should be in the `new Vue()` format | ||
*/ | ||
export default function normalizeSfcComponent(code: string): { | ||
export default function normalizeSfcComponent(code: string, _parseComponent?: typeof parseComponent): { | ||
script: string; | ||
@@ -18,0 +20,0 @@ style?: string; |
@@ -46,46 +46,2 @@ 'use strict'; | ||
const UNNAMED = /import\s*['"]([^'"]+)['"];?/gi; | ||
const NAMED = /import\s*(\*\s*as)?\s*(\w*?)\s*,?\s*(?:\{([\s\S]*?)\})?\s*from\s*['"]([^'"]+)['"];?/gi; | ||
function alias(previousKey) { | ||
let key = previousKey.trim(); | ||
const name = key.split(' as '); | ||
if (name.length > 1) { | ||
key = name.shift() || ''; | ||
} | ||
return { key, name: name[0] }; | ||
} | ||
function generate(keys, dep, base, fn, offset = 0) { | ||
const depEnd = dep.split('/').pop(); | ||
const tmp = depEnd | ||
? depEnd.replace(/\W/g, '_') + '$' + offset // uniqueness | ||
: ''; | ||
const name = alias(tmp).name; | ||
dep = `${fn}('${dep}')`; | ||
let obj; | ||
let out = `const ${name} = ${dep};`; | ||
if (base) { | ||
out += `const ${base} = ${tmp}.default || ${tmp};`; | ||
} | ||
keys.forEach(key => { | ||
obj = alias(key); | ||
out += `const ${obj.name} = ${tmp}.${obj.key};`; | ||
}); | ||
return out; | ||
} | ||
function rewriteImports (str, offset, fn = 'require') { | ||
return str | ||
.replace(NAMED, (_, asterisk, base, req, dep) => generate(req ? req.split(',').filter((d) => d.trim()) : [], dep, base, fn, offset)) | ||
.replace(UNNAMED, (_, dep) => `${fn}('${dep}');`); | ||
} | ||
function transformOneImport(node, code, offset) { | ||
const start = node.start + offset; | ||
const end = node.end + offset; | ||
const statement = code.substring(start, end); | ||
const transpiledStatement = rewriteImports(statement, offset); | ||
code = code.substring(0, start) + transpiledStatement + code.substring(end); | ||
offset += transpiledStatement.length - statement.length; | ||
return { code, offset }; | ||
} | ||
const buildStyles = function (styles) { | ||
@@ -144,3 +100,3 @@ let _styles = ''; | ||
ImportDeclaration(node) { | ||
const ret = transformOneImport(node, code, offset); | ||
const ret = vueInbrowserCompilerUtils.transformOneImport(node, code, offset); | ||
offset = ret.offset; | ||
@@ -179,2 +135,38 @@ code = ret.code; | ||
} | ||
function parseScriptSetupCode(code) { | ||
const varNames = []; | ||
let offset = 0; | ||
walkes__default["default"](getAst(code), { | ||
VariableDeclaration(node) { | ||
node.declarations.forEach((declaration) => { | ||
if (declaration.id.name) { | ||
// simple variable declaration | ||
varNames.push(declaration.id.name); | ||
} | ||
else if (declaration.id.properties) { | ||
// spread variable declaration | ||
// const { all:names } = {all: 'foo'} | ||
declaration.id.properties.forEach((p) => { | ||
varNames.push(p.value.name); | ||
}); | ||
} | ||
}); | ||
}, | ||
FunctionDeclaration(node) { | ||
varNames.push(node.id.name); | ||
}, | ||
ImportDeclaration(node) { | ||
const ret = vueInbrowserCompilerUtils.transformOneImport(node, code, offset); | ||
offset = ret.offset; | ||
code = ret.code; | ||
} | ||
}); | ||
return `setup(){ | ||
${code} | ||
return {${varNames.join(',')}} | ||
function defineProps(){} | ||
function defineEmits(){} | ||
function defineExpose(){} | ||
}`; | ||
} | ||
/** | ||
@@ -185,10 +177,16 @@ * Coming out of this function all SFC should be in the `new Vue()` format | ||
*/ | ||
function normalizeSfcComponent(code) { | ||
var _a; | ||
const parts = vueInbrowserCompilerUtils.parseComponent(code); | ||
const { preprocessing = '', component = '', postprocessing = '' } = parts.script ? parseScriptCode(parts.script.content) : {}; | ||
function normalizeSfcComponent(code, _parseComponent = vueInbrowserCompilerUtils.parseComponent) { | ||
const { script, scriptSetup, template, styles } = _parseComponent(code); | ||
const { preprocessing = '', component = '', postprocessing = '' } = scriptSetup | ||
? { | ||
preprocessing: script, | ||
component: parseScriptSetupCode(scriptSetup.content) | ||
} | ||
: script | ||
? parseScriptCode(script.content) | ||
: {}; | ||
return { | ||
template: (_a = parts.template) === null || _a === void 0 ? void 0 : _a.content, | ||
template: template === null || template === void 0 ? void 0 : template.content, | ||
script: [preprocessing, `return {${component}}`, postprocessing].join('\n'), | ||
style: buildStyles(parts.styles.map(styleBlock => styleBlock.content)) | ||
style: buildStyles(styles.map(styleBlock => styleBlock.content)) | ||
}; | ||
@@ -289,3 +287,3 @@ } | ||
ImportDeclaration(node) { | ||
const ret = transformOneImport(node, code, offset); | ||
const ret = vueInbrowserCompilerUtils.transformOneImport(node, code, offset); | ||
offset = ret.offset; | ||
@@ -292,0 +290,0 @@ code = ret.code; |
@@ -1,2 +0,2 @@ | ||
import { isVue3, parseComponent, compileTemplateForEval, isCodeVueSfc } from 'vue-inbrowser-compiler-utils'; | ||
import { isVue3, parseComponent, transformOneImport, compileTemplateForEval, isCodeVueSfc } from 'vue-inbrowser-compiler-utils'; | ||
export { adaptCreateElement, addScopedStyle, compileTemplateForEval, concatenate, isCodeVueSfc, parseComponent } from 'vue-inbrowser-compiler-utils'; | ||
@@ -38,46 +38,2 @@ import walkes from 'walkes'; | ||
const UNNAMED = /import\s*['"]([^'"]+)['"];?/gi; | ||
const NAMED = /import\s*(\*\s*as)?\s*(\w*?)\s*,?\s*(?:\{([\s\S]*?)\})?\s*from\s*['"]([^'"]+)['"];?/gi; | ||
function alias(previousKey) { | ||
let key = previousKey.trim(); | ||
const name = key.split(' as '); | ||
if (name.length > 1) { | ||
key = name.shift() || ''; | ||
} | ||
return { key, name: name[0] }; | ||
} | ||
function generate(keys, dep, base, fn, offset = 0) { | ||
const depEnd = dep.split('/').pop(); | ||
const tmp = depEnd | ||
? depEnd.replace(/\W/g, '_') + '$' + offset // uniqueness | ||
: ''; | ||
const name = alias(tmp).name; | ||
dep = `${fn}('${dep}')`; | ||
let obj; | ||
let out = `const ${name} = ${dep};`; | ||
if (base) { | ||
out += `const ${base} = ${tmp}.default || ${tmp};`; | ||
} | ||
keys.forEach(key => { | ||
obj = alias(key); | ||
out += `const ${obj.name} = ${tmp}.${obj.key};`; | ||
}); | ||
return out; | ||
} | ||
function rewriteImports (str, offset, fn = 'require') { | ||
return str | ||
.replace(NAMED, (_, asterisk, base, req, dep) => generate(req ? req.split(',').filter((d) => d.trim()) : [], dep, base, fn, offset)) | ||
.replace(UNNAMED, (_, dep) => `${fn}('${dep}');`); | ||
} | ||
function transformOneImport(node, code, offset) { | ||
const start = node.start + offset; | ||
const end = node.end + offset; | ||
const statement = code.substring(start, end); | ||
const transpiledStatement = rewriteImports(statement, offset); | ||
code = code.substring(0, start) + transpiledStatement + code.substring(end); | ||
offset += transpiledStatement.length - statement.length; | ||
return { code, offset }; | ||
} | ||
const buildStyles = function (styles) { | ||
@@ -170,2 +126,38 @@ let _styles = ''; | ||
} | ||
function parseScriptSetupCode(code) { | ||
const varNames = []; | ||
let offset = 0; | ||
walkes(getAst(code), { | ||
VariableDeclaration(node) { | ||
node.declarations.forEach((declaration) => { | ||
if (declaration.id.name) { | ||
// simple variable declaration | ||
varNames.push(declaration.id.name); | ||
} | ||
else if (declaration.id.properties) { | ||
// spread variable declaration | ||
// const { all:names } = {all: 'foo'} | ||
declaration.id.properties.forEach((p) => { | ||
varNames.push(p.value.name); | ||
}); | ||
} | ||
}); | ||
}, | ||
FunctionDeclaration(node) { | ||
varNames.push(node.id.name); | ||
}, | ||
ImportDeclaration(node) { | ||
const ret = transformOneImport(node, code, offset); | ||
offset = ret.offset; | ||
code = ret.code; | ||
} | ||
}); | ||
return `setup(){ | ||
${code} | ||
return {${varNames.join(',')}} | ||
function defineProps(){} | ||
function defineEmits(){} | ||
function defineExpose(){} | ||
}`; | ||
} | ||
/** | ||
@@ -176,10 +168,16 @@ * Coming out of this function all SFC should be in the `new Vue()` format | ||
*/ | ||
function normalizeSfcComponent(code) { | ||
var _a; | ||
const parts = parseComponent(code); | ||
const { preprocessing = '', component = '', postprocessing = '' } = parts.script ? parseScriptCode(parts.script.content) : {}; | ||
function normalizeSfcComponent(code, _parseComponent = parseComponent) { | ||
const { script, scriptSetup, template, styles } = _parseComponent(code); | ||
const { preprocessing = '', component = '', postprocessing = '' } = scriptSetup | ||
? { | ||
preprocessing: script, | ||
component: parseScriptSetupCode(scriptSetup.content) | ||
} | ||
: script | ||
? parseScriptCode(script.content) | ||
: {}; | ||
return { | ||
template: (_a = parts.template) === null || _a === void 0 ? void 0 : _a.content, | ||
template: template === null || template === void 0 ? void 0 : template.content, | ||
script: [preprocessing, `return {${component}}`, postprocessing].join('\n'), | ||
style: buildStyles(parts.styles.map(styleBlock => styleBlock.content)) | ||
style: buildStyles(styles.map(styleBlock => styleBlock.content)) | ||
}; | ||
@@ -186,0 +184,0 @@ } |
{ | ||
"name": "vue-inbrowser-compiler", | ||
"version": "4.54.1", | ||
"version": "4.55.0", | ||
"description": "compile vue single file components right in your browser", | ||
@@ -22,3 +22,3 @@ "module": "lib/vue-inbrowser-compiler.esm.js", | ||
"detect-browser": "^5.2.0", | ||
"vue-inbrowser-compiler-utils": "^4.54.1", | ||
"vue-inbrowser-compiler-utils": "^4.55.0", | ||
"walkes": "^0.2.1" | ||
@@ -29,10 +29,12 @@ }, | ||
"@rollup/plugin-node-resolve": "9.0.0", | ||
"@rollup/plugin-typescript": "8.3.4", | ||
"@rollup/plugin-typescript": "8.5.0", | ||
"@types/buble": "0.20.1", | ||
"@vue/test-utils": "1.3.0", | ||
"rollup": "2.77.2", | ||
"tslib": "2.4.0", | ||
"typescript": "4.7.4", | ||
"vue": "2.7.8", | ||
"vue-template-compiler": "2.7.8" | ||
"@vue/test-utils": "1.3.3", | ||
"@vue/compiler-sfc": "3", | ||
"rollup": "2.79.1", | ||
"tslib": "2.4.1", | ||
"typescript": "4.8.4", | ||
"vue": "2.7.14", | ||
"vue3": "npm:vue@3", | ||
"vue-template-compiler": "2.7.14" | ||
}, | ||
@@ -39,0 +41,0 @@ "peerDependencies": { |
/* eslint-disable no-new-func */ | ||
import compileVueCodeForEvalFunction, { | ||
getEvaluableVue3RenderFunctionBody | ||
} from './compileVueCodeForEvalFunction' | ||
import { expect } from 'vitest' | ||
import compileVueCodeForEvalFunction from './compileVueCodeForEvalFunction' | ||
@@ -6,0 +5,0 @@ describe('compileVueCodeForEvalFunction', () => { |
@@ -7,5 +7,5 @@ import { transform, TransformOptions } from 'buble' | ||
isVue3, | ||
compileTemplateForEval | ||
compileTemplateForEval, | ||
transformOneImport | ||
} from 'vue-inbrowser-compiler-utils' | ||
import transformOneImport from './transformOneImport' | ||
import normalizeSfcComponent, { | ||
@@ -12,0 +12,0 @@ parseScriptCode, |
@@ -0,1 +1,3 @@ | ||
import { expect, vi } from 'vitest' | ||
import { parse } from '@vue/compiler-sfc' | ||
import normalizeSfcComponent from './normalizeSfcComponent' | ||
@@ -75,2 +77,41 @@ | ||
}) | ||
it('compiles script setup', () => { | ||
const sut = normalizeSfcComponent(` | ||
<script setup> | ||
import { ref } from 'vue' | ||
defineProps({}) | ||
defineEmits([]) | ||
defineExpose([]) | ||
const msg = ref('321') | ||
const { all:names } = {all: 'foo'} | ||
function hello() { | ||
} | ||
const STATUS_OK = 200 | ||
</script>`, (( source: string, opts: any ) => { | ||
const { descriptor } = parse(source, opts) | ||
return descriptor | ||
}) as any) | ||
expect(evalFunction(sut).setup.toString()).toMatchInlineSnapshot(` | ||
"setup(){ | ||
const vue$0 = require('vue');const ref = vue$0.ref; | ||
defineProps({}) | ||
defineEmits([]) | ||
defineExpose([]) | ||
const msg = ref('321') | ||
const { all:names } = {all: 'foo'} | ||
function hello() { | ||
} | ||
const STATUS_OK = 200 | ||
return {msg,names,hello,STATUS_OK} | ||
function defineProps(){} | ||
function defineEmits(){} | ||
function defineExpose(){} | ||
}" | ||
`) | ||
}) | ||
}) |
import walkes from 'walkes' | ||
import { parseComponent, isVue3 } from 'vue-inbrowser-compiler-utils' | ||
import { parseComponent, isVue3, transformOneImport } from 'vue-inbrowser-compiler-utils' | ||
import getAst from './getAst' | ||
import transformOneImport from './transformOneImport' | ||
@@ -110,2 +109,39 @@ const buildStyles = function (styles: string[] | undefined): string | undefined { | ||
export function parseScriptSetupCode(code: string): string { | ||
const varNames:string[] = [] | ||
let offset = 0 | ||
walkes(getAst(code), { | ||
VariableDeclaration(node: any) { | ||
node.declarations.forEach((declaration: any) => { | ||
if (declaration.id.name) { | ||
// simple variable declaration | ||
varNames.push(declaration.id.name) | ||
} else if (declaration.id.properties) { | ||
// spread variable declaration | ||
// const { all:names } = {all: 'foo'} | ||
declaration.id.properties.forEach((p: any) => { | ||
varNames.push(p.value.name) | ||
}) | ||
} | ||
}) | ||
}, | ||
FunctionDeclaration(node: any) { | ||
varNames.push(node.id.name) | ||
}, | ||
ImportDeclaration(node: any) { | ||
const ret = transformOneImport(node, code, offset) | ||
offset = ret.offset | ||
code = ret.code | ||
} | ||
}) | ||
return `setup(){ | ||
${code} | ||
return {${varNames.join(',')}} | ||
function defineProps(){} | ||
function defineEmits(){} | ||
function defineExpose(){} | ||
}` | ||
} | ||
/** | ||
@@ -116,3 +152,3 @@ * Coming out of this function all SFC should be in the `new Vue()` format | ||
*/ | ||
export default function normalizeSfcComponent(code: string): { | ||
export default function normalizeSfcComponent(code: string, _parseComponent = parseComponent): { | ||
script: string | ||
@@ -122,3 +158,4 @@ style?: string | ||
} { | ||
const parts = parseComponent(code) | ||
const { script, scriptSetup, template, styles } = _parseComponent(code) | ||
const { | ||
@@ -128,8 +165,16 @@ preprocessing = '', | ||
postprocessing = '' | ||
} = parts.script ? parseScriptCode(parts.script.content) : {} | ||
} = scriptSetup | ||
? { | ||
preprocessing: script, | ||
component: parseScriptSetupCode(scriptSetup.content) | ||
} | ||
: script | ||
? parseScriptCode(script.content) | ||
: {} | ||
return { | ||
template: parts.template?.content, | ||
template: template?.content, | ||
script: [preprocessing, `return {${component}}`, postprocessing].join('\n'), | ||
style: buildStyles(parts.styles.map(styleBlock => styleBlock.content)) | ||
style: buildStyles(styles.map(styleBlock => styleBlock.content)) | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
80850
12
26
1830