@bakery-framework/plugin-vue 2.5.0-alpha.0 → 2.5.0-alpha.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakery-framework/plugin-vue",
3
- "version": "2.5.0-alpha.0",
3
+ "version": "2.5.0-alpha.1",
4
4
  "description": "Bakery vue plugin.",
5
5
  "keywords": [
6
6
  "bakery",
@@ -43,9 +43,9 @@
43
43
  "vue": "^3.5.38"
44
44
  },
45
45
  "dependencies": {
46
- "@bakery-framework/core": "^2.5.0-alpha.0"
46
+ "@bakery-framework/core": "^2.5.0-alpha.1"
47
47
  },
48
48
  "engines": {
49
- "bun": ">=1.4.0"
49
+ "bun": ">=1.4.4"
50
50
  }
51
51
  }
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 @@ 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'
@@ -495,6 +496,19 @@ export class VueHandler extends DynamicHandler {
495
496
  }
496
497
  }
497
498
 
499
+ // A multi-line event attribute with no `;` gets one. Vue reads a value
500
+ // with no `;` as one expression, so two statements on two lines (as a
501
+ // formatter with `semi: false` writes them) came out wrapped in
502
+ // parentheses and failed to compile; with the `;`, Vue compiles the value
503
+ // as statements.
504
+ //
505
+ // Only when the value is not already one expression, which Vue compiles
506
+ // as written. With a `;` appended, an arrow handler broken across lines
507
+ // was emitted as `(d) => {…};` inside the render function's props and
508
+ // the module did not parse, a `function (e) {…}` failed Vue's own
509
+ // compile, and a member path (`saveDraft`) compiled to a statement that
510
+ // reads the function and never calls it.
511
+ const isExpression = await loadExpressionCheck()
498
512
  const rxEventAttr =
499
513
  /(@[\w.-]+|v-on:[\w.-]+)=("([^"\n]*\n[^"]*)"|'([^'\n]*\n[^']*)')/g
500
514
  cleanContent = cleanContent.replace(
@@ -502,7 +516,7 @@ export class VueHandler extends DynamicHandler {
502
516
  (match, attr, doubleMatch, innerDouble, innerSingle) => {
503
517
  const quote = doubleMatch.startsWith('"') ? '"' : "'"
504
518
  const val = innerDouble !== undefined ? innerDouble : innerSingle
505
- if (!val.includes(';')) {
519
+ if (!val.includes(';') && !isExpression(val)) {
506
520
  return `${attr}=${quote}${val};${quote}`
507
521
  }
508
522
  return match