@cockernutx/language-plugin-brace 0.1.0 → 0.1.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/README.md +27 -101
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,33 +6,6 @@ Without it, Volar hands the brace source to the HTML parser: template expression
|
|
|
6
6
|
*checked*, so `@if (…)` / `@for (…)` conditions are seen as plain text and the whole block
|
|
7
7
|
produces spurious errors and no hover.
|
|
8
8
|
|
|
9
|
-
## Build before you use it
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
deno task build:plugin # from the repo root
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
**Volar loads a language plugin by resolving it and calling `require()` on the result**, in
|
|
16
|
-
`vue-tsc` and in the editor's language server — both Node processes. Serving
|
|
17
|
-
`src/index.ts` works only under Deno, which can `require()` TypeScript directly. In Node it
|
|
18
|
-
is a `SyntaxError`; Volar catches it and carries on **without the plugin**, so every brace
|
|
19
|
-
template loses hover, completions and diagnostics, and the only trace is a warning in the
|
|
20
|
-
Vue Language Server output channel:
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
[Vue] Resolve plugin path failed: @cockernutx/language-plugin-brace SyntaxError: …
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
This is the failure mode this package was written in, and it is worth knowing because it
|
|
27
|
-
looks like "the plugin does nothing" rather than "the plugin did not load". `index.cjs`
|
|
28
|
-
therefore loads `dist/index.js`, and `deno task test` rebuilds it; a test fails if `dist` is
|
|
29
|
-
missing or older than the source it came from.
|
|
30
|
-
|
|
31
|
-
**How to tell it loaded:** open a brace template and hover a variable in a `@try` block. With
|
|
32
|
-
the plugin loaded you get a type; without it, `any` (or nothing) — and Volar will be reporting
|
|
33
|
-
errors on lines of brace syntax that are perfectly valid. **Reload the window** after building:
|
|
34
|
-
the language server only loads plugins at startup.
|
|
35
|
-
|
|
36
9
|
## Setup
|
|
37
10
|
|
|
38
11
|
```jsonc
|
|
@@ -44,85 +17,38 @@ the language server only loads plugins at startup.
|
|
|
44
17
|
}
|
|
45
18
|
```
|
|
46
19
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
Volar reaches a custom template language through three hooks. The plugin implements all
|
|
50
|
-
three:
|
|
51
|
-
|
|
52
|
-
1. **`getEmbeddedCodes` / `resolveEmbeddedCode`** — publish the raw brace block as an
|
|
53
|
-
embedded document with `lang: 'brace'`. Volar's built-in `vue-sfc-template` plugin only
|
|
54
|
-
does this for `lang === 'html'`, so without these hooks a brace template has no virtual
|
|
55
|
-
file at all: no highlighting and no in-template features.
|
|
56
|
-
2. **`compileSFCTemplate`** — compiles the generated template with language-core's
|
|
57
|
-
`compileTemplate` and supplies the AST that template type checking works from.
|
|
58
|
-
3. **Offset remapping** — every location in that AST is rewritten back into brace-source
|
|
59
|
-
coordinates.
|
|
60
|
-
|
|
61
|
-
Step 3 is why `compileBrace` returns a map. Because the transform emits one line per input
|
|
62
|
-
line, a generated line belongs to exactly one source line, and within it every copied
|
|
63
|
-
fragment is recorded as a `{ gen, src, length }` segment. A generated position inside one of
|
|
64
|
-
those segments maps to the exact source character; anything else is synthesised markup
|
|
65
|
-
(`<template v-if="…">`) and falls back to the end of the nearest copied run, or to the end of
|
|
66
|
-
the source line when it has none.
|
|
67
|
-
|
|
68
|
-
Per-fragment mapping matters more than it sounds. One `@for` line becomes
|
|
69
|
-
`<template v-for="item in items" :key="item.id">`, so `item`, `items` and `item.id` all sit
|
|
70
|
-
at different offsets from their generated counterparts; a single shift per line gets only
|
|
71
|
-
the first of them right, and the rest — the ones outside an `@if` line, which is most of a
|
|
72
|
-
template — point at the wrong token, which is what makes hover and go-to-definition fail.
|
|
73
|
-
|
|
74
|
-
The embedded content pushed in step 1 is the *raw brace source*, which is the same
|
|
75
|
-
coordinate space the remapped AST uses. Keeping those two in step is the whole trick, and
|
|
76
|
-
it is why the two hooks cannot be implemented independently.
|
|
77
|
-
|
|
78
|
-
A malformed block is reported through `onError` rather than thrown, so a bad template
|
|
79
|
-
produces a diagnostic instead of a dead language server.
|
|
80
|
-
|
|
81
|
-
### Why the AST must stay in brace coordinates
|
|
82
|
-
|
|
83
|
-
Volar does not only read offsets out of this AST — it also slices text:
|
|
20
|
+
## Build before you use it
|
|
84
21
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
the node. That is the one place where the two coordinate spaces collide, and it is what used
|
|
89
|
-
to make `@for` with `index` / `key` report two TypeScript syntax errors; the alignment pass
|
|
90
|
-
described under Caveats is what reconciles them. Everything else is consistent because both
|
|
91
|
-
the offsets and the document they describe end up in brace coordinates.
|
|
22
|
+
```sh
|
|
23
|
+
deno task build:plugin # from the repo root
|
|
24
|
+
```
|
|
92
25
|
|
|
93
|
-
|
|
26
|
+
Volar loads the plugin by calling `require()` on it in a Node process (`vue-tsc` and the
|
|
27
|
+
editor's language server), so the entry must be built JavaScript — `src/index.ts` resolves only
|
|
28
|
+
under Deno. When the load fails Volar swallows the `SyntaxError` and runs **without the plugin**:
|
|
29
|
+
brace templates lose hover, completions and diagnostics, and the only trace is this line in the
|
|
30
|
+
Vue Language Server output channel:
|
|
94
31
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
plain text.
|
|
32
|
+
```
|
|
33
|
+
[Vue] Resolve plugin path failed: @cockernutx/language-plugin-brace SyntaxError: …
|
|
34
|
+
```
|
|
99
35
|
|
|
100
|
-
|
|
36
|
+
`index.cjs` loads `dist/index.js`, `deno task test` rebuilds it, and a test fails if `dist` is
|
|
37
|
+
missing or older than the source it came from.
|
|
101
38
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
that **Node** can load. `index.cjs` re-exports the default from `dist/index.js`, which
|
|
105
|
-
`deno task build:plugin` produces. Pointing it at `src/index.ts` instead is the trap
|
|
106
|
-
described at the top of this file: Deno loads it happily and the editor never does.
|
|
39
|
+
**Check it loaded:** hover a variable inside `@try` — a type means loaded, `any` (or nothing)
|
|
40
|
+
means not. In that case Volar also reports errors on valid brace syntax.
|
|
107
41
|
|
|
108
|
-
|
|
42
|
+
**Reload the window** after building: the language server only loads plugins at startup.
|
|
109
43
|
|
|
110
|
-
|
|
111
|
-
`[2, 2.1, 2.2]`; anything else makes it drop the plugin with only a console warning.
|
|
112
|
-
- **`@for` with `index` or `key` needs the element aligned to the author's column.** Volar
|
|
113
|
-
rebuilds the
|
|
114
|
-
`v-for` binding by slicing the generated `<template v-for="(item, i) in …">` text with
|
|
115
|
-
offsets *relative to the element*, so those deltas have to come out as the generated ones.
|
|
116
|
-
`collectVForPatterns` reads the binding names with generated deltas *before* the remap;
|
|
117
|
-
`alignVForPatterns` then anchors the element on the `@for` column the author wrote and
|
|
118
|
-
rebuilds `loc.source` as a padded pattern occupying the author's own columns. Before that,
|
|
119
|
-
the slice produced garbage: the errors above, plus garbage binding names whose semantic
|
|
120
|
-
tokens landed across the template. (An earlier attempt moved the element's start onto the
|
|
121
|
-
generated geometry instead. That repairs the slice and corrupts every other consumer of that
|
|
122
|
-
offset, which reads it as a *source* position — do not reintroduce it.)
|
|
123
|
-
- **`vue-tsc` needs a Node runtime.** It cannot run under Deno — Volar registers `.vue`
|
|
124
|
-
support by rewriting `tsc.js` through an `fs.readFileSync` hook that Deno bypasses — so a
|
|
125
|
-
Node binary has to be present to type-check templates. That is how the loader bug above was
|
|
126
|
-
found: `node …/vue-tsc.js --noEmit` reported `Resolve plugin path failed`, and
|
|
127
|
-
`--listFiles` showed no `.vue` files in the program at all.
|
|
44
|
+
## Notes
|
|
128
45
|
|
|
46
|
+
- Highlighting is separate: install [`vscode-vue-brace`](../vscode-vue-brace) for the `brace`
|
|
47
|
+
language id and the grammar. The plugin only supplies language features.
|
|
48
|
+
- The plugin API version is pinned to `2.2`, one of language-core's `validVersions`
|
|
49
|
+
(`[2, 2.1, 2.2]`); anything else drops the plugin with a console warning only.
|
|
50
|
+
- **`@for` with `index` / `key`, and the `@catch` bindings, depend on offset alignment that is
|
|
51
|
+
load-bearing.** Read [`docs/internals/volar-and-editor-notes.md`](../../docs/internals/volar-and-editor-notes.md)
|
|
52
|
+
before changing it.
|
|
53
|
+
- **`vue-tsc` needs a Node runtime** and cannot run under Deno: Volar registers `.vue` support
|
|
54
|
+
through an `fs.readFileSync` hook that Deno bypasses.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cockernutx/language-plugin-brace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Volar / Vue language tools plugin for lang=\"brace\" SFC templates",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"homepage": "https://github.com/strawberyy-coconut/vue-brace#readme",
|
|
28
28
|
"bugs": "https://github.com/strawberyy-coconut/vue-brace/issues",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cockernutx/brace-template": "^0.1.
|
|
30
|
+
"@cockernutx/brace-template": "^0.1.1",
|
|
31
31
|
"@vue/language-core": "^3.3.11"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|