@bakery-framework/plugin-vue 2.4.1 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/compile.ts +30 -2
- package/src/handler.ts +15 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bakery-framework/plugin-vue",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "Bakery vue plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bakery",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"vue": "^3.5.38"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@bakery-framework/core": "^2.4.
|
|
46
|
+
"@bakery-framework/core": "^2.4.2"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
49
|
"bun": ">=1.4.0"
|
package/src/compile.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { compileText } from '@bakery-framework/core/compiler'
|
|
2
|
+
import { Try } from '@bakery-framework/core/utils'
|
|
2
3
|
import type { SFCStyleCompileResults } from '@vue/compiler-sfc'
|
|
3
4
|
|
|
4
5
|
import type {
|
|
@@ -65,6 +66,33 @@ export function setVuePluginOptions(opts?: VuePluginOptions) {
|
|
|
65
66
|
if (opts) vuePluginOptions = opts
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* A test of whether an event attribute's value is one JavaScript expression,
|
|
71
|
+
* asked the way Vue's template compiler asks it: Babel over the value in
|
|
72
|
+
* parentheses, with the app's `expressionPlugins` and the `typescript` plugin
|
|
73
|
+
* Vue always adds.
|
|
74
|
+
*
|
|
75
|
+
* Vue compiles such a value as written. A function or a member path becomes
|
|
76
|
+
* the handler itself, and any other expression is wrapped as
|
|
77
|
+
* `$event => (value)`. `parseVueFile` asks before it appends a `;` to a
|
|
78
|
+
* multi-line attribute, because the `;` makes Vue compile the value as
|
|
79
|
+
* statements instead.
|
|
80
|
+
*/
|
|
81
|
+
export async function loadExpressionCheck(): Promise<
|
|
82
|
+
(value: string) => boolean
|
|
83
|
+
> {
|
|
84
|
+
const { babelParse } = await loadCompiler()
|
|
85
|
+
const plugins = [
|
|
86
|
+
...(vuePluginOptions.compilerOptions?.expressionPlugins ?? []),
|
|
87
|
+
'typescript',
|
|
88
|
+
]
|
|
89
|
+
return value =>
|
|
90
|
+
Try.return(() => {
|
|
91
|
+
const { body } = babelParse(`(${value})`, { plugins }).program
|
|
92
|
+
return body.length === 1 && body[0].type === 'ExpressionStatement'
|
|
93
|
+
}, false)
|
|
94
|
+
}
|
|
95
|
+
|
|
68
96
|
/**
|
|
69
97
|
* `'runtime'` unless the app opted into the full build.
|
|
70
98
|
*
|
|
@@ -153,7 +181,7 @@ export async function compileScriptBlock(
|
|
|
153
181
|
hoistStatic: true,
|
|
154
182
|
})
|
|
155
183
|
return {
|
|
156
|
-
code: await compileText(result.content),
|
|
184
|
+
code: await compileText(result.content, { file: descriptor.filename }),
|
|
157
185
|
bindings: result.bindings || {},
|
|
158
186
|
}
|
|
159
187
|
}
|
|
@@ -238,7 +266,7 @@ export async function compileTemplateBlock(
|
|
|
238
266
|
// guarantee, so it is the one written down.
|
|
239
267
|
let code = result.code
|
|
240
268
|
code = code.replace(/^export\s+/m, '')
|
|
241
|
-
code = await compileText(code)
|
|
269
|
+
code = await compileText(code, { file: filename })
|
|
242
270
|
return { code, errors }
|
|
243
271
|
}
|
|
244
272
|
|
package/src/handler.ts
CHANGED
|
@@ -30,6 +30,7 @@ import { serveVueChunk, VUE_CHUNK_PREFIX } from './chunks'
|
|
|
30
30
|
import {
|
|
31
31
|
compileStyleBlock,
|
|
32
32
|
compileVueFile,
|
|
33
|
+
loadExpressionCheck,
|
|
33
34
|
parseVue,
|
|
34
35
|
vueBuildVariant,
|
|
35
36
|
} from './compile'
|
|
@@ -496,6 +497,19 @@ export class VueHandler extends DynamicHandler {
|
|
|
496
497
|
}
|
|
497
498
|
}
|
|
498
499
|
|
|
500
|
+
// A multi-line event attribute with no `;` gets one. Vue reads a value
|
|
501
|
+
// with no `;` as one expression, so two statements on two lines (as a
|
|
502
|
+
// formatter with `semi: false` writes them) came out wrapped in
|
|
503
|
+
// parentheses and failed to compile; with the `;`, Vue compiles the value
|
|
504
|
+
// as statements.
|
|
505
|
+
//
|
|
506
|
+
// Only when the value is not already one expression, which Vue compiles
|
|
507
|
+
// as written. With a `;` appended, an arrow handler broken across lines
|
|
508
|
+
// was emitted as `(d) => {…};` inside the render function's props and
|
|
509
|
+
// the module did not parse, a `function (e) {…}` failed Vue's own
|
|
510
|
+
// compile, and a member path (`saveDraft`) compiled to a statement that
|
|
511
|
+
// reads the function and never calls it.
|
|
512
|
+
const isExpression = await loadExpressionCheck()
|
|
499
513
|
const rxEventAttr =
|
|
500
514
|
/(@[\w.-]+|v-on:[\w.-]+)=("([^"\n]*\n[^"]*)"|'([^'\n]*\n[^']*)')/g
|
|
501
515
|
cleanContent = cleanContent.replace(
|
|
@@ -503,7 +517,7 @@ export class VueHandler extends DynamicHandler {
|
|
|
503
517
|
(match, attr, doubleMatch, innerDouble, innerSingle) => {
|
|
504
518
|
const quote = doubleMatch.startsWith('"') ? '"' : "'"
|
|
505
519
|
const val = innerDouble !== undefined ? innerDouble : innerSingle
|
|
506
|
-
if (!val.includes(';')) {
|
|
520
|
+
if (!val.includes(';') && !isExpression(val)) {
|
|
507
521
|
return `${attr}=${quote}${val};${quote}`
|
|
508
522
|
}
|
|
509
523
|
return match
|