@azerothjs/language-service 0.4.0-beta.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 +259 -0
- package/dist/html-source.d.ts +12 -0
- package/dist/html-source.d.ts.map +1 -0
- package/dist/html-source.js +108 -0
- package/dist/html-source.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/language-data.d.ts +41 -0
- package/dist/language-data.d.ts.map +1 -0
- package/dist/language-data.js +164 -0
- package/dist/language-data.js.map +1 -0
- package/dist/mapping.d.ts +71 -0
- package/dist/mapping.d.ts.map +1 -0
- package/dist/mapping.js +123 -0
- package/dist/mapping.js.map +1 -0
- package/dist/markup-model.d.ts +67 -0
- package/dist/markup-model.d.ts.map +1 -0
- package/dist/markup-model.js +313 -0
- package/dist/markup-model.js.map +1 -0
- package/dist/protocol.d.ts +176 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +58 -0
- package/dist/protocol.js.map +1 -0
- package/dist/providers/completion.d.ts +26 -0
- package/dist/providers/completion.d.ts.map +1 -0
- package/dist/providers/completion.js +339 -0
- package/dist/providers/completion.js.map +1 -0
- package/dist/providers/css-service.d.ts +7 -0
- package/dist/providers/css-service.d.ts.map +1 -0
- package/dist/providers/css-service.js +84 -0
- package/dist/providers/css-service.js.map +1 -0
- package/dist/providers/diagnostics.d.ts +5 -0
- package/dist/providers/diagnostics.d.ts.map +1 -0
- package/dist/providers/diagnostics.js +89 -0
- package/dist/providers/diagnostics.js.map +1 -0
- package/dist/providers/editing.d.ts +17 -0
- package/dist/providers/editing.d.ts.map +1 -0
- package/dist/providers/editing.js +176 -0
- package/dist/providers/editing.js.map +1 -0
- package/dist/providers/hover.d.ts +5 -0
- package/dist/providers/hover.d.ts.map +1 -0
- package/dist/providers/hover.js +213 -0
- package/dist/providers/hover.js.map +1 -0
- package/dist/providers/html-service.d.ts +8 -0
- package/dist/providers/html-service.d.ts.map +1 -0
- package/dist/providers/html-service.js +108 -0
- package/dist/providers/html-service.js.map +1 -0
- package/dist/providers/inlay-hints.d.ts +25 -0
- package/dist/providers/inlay-hints.d.ts.map +1 -0
- package/dist/providers/inlay-hints.js +52 -0
- package/dist/providers/inlay-hints.js.map +1 -0
- package/dist/providers/navigation.d.ts +16 -0
- package/dist/providers/navigation.d.ts.map +1 -0
- package/dist/providers/navigation.js +107 -0
- package/dist/providers/navigation.js.map +1 -0
- package/dist/providers/semantic-tokens.d.ts +5 -0
- package/dist/providers/semantic-tokens.d.ts.map +1 -0
- package/dist/providers/semantic-tokens.js +63 -0
- package/dist/providers/semantic-tokens.js.map +1 -0
- package/dist/providers/signature.d.ts +5 -0
- package/dist/providers/signature.d.ts.map +1 -0
- package/dist/providers/signature.js +38 -0
- package/dist/providers/signature.js.map +1 -0
- package/dist/providers/structure.d.ts +19 -0
- package/dist/providers/structure.d.ts.map +1 -0
- package/dist/providers/structure.js +188 -0
- package/dist/providers/structure.js.map +1 -0
- package/dist/providers/symbols.d.ts +8 -0
- package/dist/providers/symbols.d.ts.map +1 -0
- package/dist/providers/symbols.js +108 -0
- package/dist/providers/symbols.js.map +1 -0
- package/dist/request.d.ts +37 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +49 -0
- package/dist/request.js.map +1 -0
- package/dist/service.d.ts +73 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +177 -0
- package/dist/service.js.map +1 -0
- package/dist/text.d.ts +25 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +66 -0
- package/dist/text.js.map +1 -0
- package/dist/ts-project.d.ts +75 -0
- package/dist/ts-project.d.ts.map +1 -0
- package/dist/ts-project.js +266 -0
- package/dist/ts-project.js.map +1 -0
- package/dist/uri.d.ts +21 -0
- package/dist/uri.d.ts.map +1 -0
- package/dist/uri.js +41 -0
- package/dist/uri.js.map +1 -0
- package/dist/virtual-code.d.ts +27 -0
- package/dist/virtual-code.d.ts.map +1 -0
- package/dist/virtual-code.js +360 -0
- package/dist/virtual-code.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# @azerothjs/language-service
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Compiler-aware language intelligence for `.azeroth` files, packaged so it can be
|
|
6
|
+
driven by any editor frontend. The bundled LSP server
|
|
7
|
+
(`@azerothjs/language-server`) is a thin adapter over this package; the test
|
|
8
|
+
suite and any other host use it directly.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { AzerothLanguageService } from '@azerothjs/language-service';
|
|
12
|
+
|
|
13
|
+
const ls = new AzerothLanguageService(process.cwd());
|
|
14
|
+
ls.didOpen('file:///App.azeroth', 'export default () => <h1>Hi {name()}</h1>;');
|
|
15
|
+
ls.getHover('file:///App.azeroth', { line: 0, character: 32 }); // the type of name()
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The package depends only on `typescript` and `@azerothjs/compiler`, so it runs
|
|
19
|
+
(and is unit-tested) without an editor in the loop.
|
|
20
|
+
|
|
21
|
+
## Architecture
|
|
22
|
+
|
|
23
|
+
A `.azeroth` file is a TypeScript module whose markup regions are written in a
|
|
24
|
+
JSX-style syntax. The AzerothJS compiler has no separate type system, symbol
|
|
25
|
+
table, or semantic analyzer: it locates markup regions and rewrites them into
|
|
26
|
+
`h(...)` calls, leaving everything else byte-for-byte. The authoritative
|
|
27
|
+
semantic engine for the language is therefore TypeScript itself.
|
|
28
|
+
|
|
29
|
+
That observation drives the whole design. Rather than re-implement type
|
|
30
|
+
inference, scope resolution, or symbol tables, the service:
|
|
31
|
+
|
|
32
|
+
1. Reuses the compiler (`scanner`, `parser`, AST, `walkComponentTags`) to locate
|
|
33
|
+
and understand markup.
|
|
34
|
+
2. Compiles each `.azeroth` file to a virtual TypeScript module that matches
|
|
35
|
+
what the compiler ships, while recording a precise, bidirectional offset map
|
|
36
|
+
for every user-authored span.
|
|
37
|
+
3. Runs a single `ts.LanguageService` over those virtual modules. Every
|
|
38
|
+
type-aware feature (inference, completion, hover, definitions, references,
|
|
39
|
+
rename, signatures, diagnostics) comes from the TypeScript compiler.
|
|
40
|
+
4. Layers a markup model on top for the things TypeScript cannot know about:
|
|
41
|
+
HTML tags, attribute and event names, and built-in components.
|
|
42
|
+
|
|
43
|
+
The dependency direction is one way. The facade (`service.ts`) owns the four
|
|
44
|
+
foundational modules; the providers build on all of them:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
service.ts (facade)
|
|
48
|
+
markup-model.ts classify the caret; reuses scanner + parser
|
|
49
|
+
virtual-code.ts .azeroth to virtual TS + CodeMapping; reuses scanner + parser
|
|
50
|
+
ts-project.ts ts.LanguageService host over virtual files; cross-file resolve
|
|
51
|
+
language-data.ts HTML/event vocabulary + built-in component data
|
|
52
|
+
|
|
53
|
+
providers/ one focused module per feature, built on the four above:
|
|
54
|
+
completion, hover, navigation, symbols, diagnostics, signature,
|
|
55
|
+
semantic-tokens, structure (folding/code-actions/format), editing,
|
|
56
|
+
inlay-hints, html-service, css-service
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Virtual code and offset mapping
|
|
60
|
+
|
|
61
|
+
This is the keystone of the package. `<h1>Count: {count()}</h1>` compiles to
|
|
62
|
+
`h('h1', { }, 'Count: ', () => (count()))`. `virtual-code.ts` walks the same
|
|
63
|
+
parser AST the compiler uses, emitting the same `h()` and component calls. Every
|
|
64
|
+
user-authored slice (the script between markup, expression-hole bodies,
|
|
65
|
+
attribute expressions, and component tag names) is copied byte-for-byte and
|
|
66
|
+
registered as a `MappingSegment`. Generated scaffolding (`h('h1', {`, quotes,
|
|
67
|
+
getters) is emitted but not mapped.
|
|
68
|
+
|
|
69
|
+
Because those copied spans are equal length, an offset inside one translates by
|
|
70
|
+
a simple additive shift. `CodeMapping` (`mapping.ts`) stores the segments sorted
|
|
71
|
+
both ways and binary-searches them, so:
|
|
72
|
+
|
|
73
|
+
- a request at an original offset is translated with `toGenerated`, then asked
|
|
74
|
+
of TypeScript;
|
|
75
|
+
- each `TextSpan` TypeScript returns is translated back with `toOriginal` into
|
|
76
|
+
an editor range.
|
|
77
|
+
|
|
78
|
+
The markup-bearing portion of a real `.azeroth` file is small relative to the
|
|
79
|
+
surrounding TypeScript, so the majority of every file is copied 1:1. That is why
|
|
80
|
+
the TypeScript-powered features behave consistently across the whole document.
|
|
81
|
+
|
|
82
|
+
If the markup fails to parse mid-edit, `generateVirtualCode` copies the
|
|
83
|
+
remainder verbatim instead of throwing, so completion and hover keep working
|
|
84
|
+
while the user is still typing.
|
|
85
|
+
|
|
86
|
+
### Where intelligence comes from
|
|
87
|
+
|
|
88
|
+
There is no second language implementation. Intelligence is split along the seam
|
|
89
|
+
the compiler already defines:
|
|
90
|
+
|
|
91
|
+
- Everything that is TypeScript (variables, functions, classes, generics, types,
|
|
92
|
+
imports, scopes, visibility, the runtime API, and type inference) is answered
|
|
93
|
+
by the `ts.LanguageService` in `ts-project.ts`, queried at mapped offsets. The
|
|
94
|
+
runtime packages ship `.d.ts` and JSDoc, so this stays in sync with the
|
|
95
|
+
framework.
|
|
96
|
+
- Host-element HTML (valid tags, attributes, attribute values, and MDN
|
|
97
|
+
documentation) is answered by `vscode-html-languageservice`, the same engine
|
|
98
|
+
VS Code's HTML support uses, applied to an embedded HTML view of the markup
|
|
99
|
+
(`html-source.ts` and `providers/html-service.ts`).
|
|
100
|
+
- Inline `style="..."` values are answered by `vscode-css-languageservice`
|
|
101
|
+
(`providers/css-service.ts`).
|
|
102
|
+
- Framework markup (the built-in components, their props, and the camelCase
|
|
103
|
+
`on*` events AzerothJS binds) is the AzerothJS layer, from `language-data.ts`
|
|
104
|
+
(transcribed from the runtime's own prop interfaces) and the TypeScript bridge
|
|
105
|
+
(for user components).
|
|
106
|
+
- `markup-model.ts`, built on the compiler's parser, decides which of these
|
|
107
|
+
applies at the caret.
|
|
108
|
+
|
|
109
|
+
`AzerothProject` presents each `Foo.azeroth` to TypeScript as a synthetic
|
|
110
|
+
`Foo.azeroth.ts` whose contents are the virtual module. It resolves
|
|
111
|
+
`import './Bar.azeroth'` to `Bar.azeroth.ts` (its virtual twin) so types and
|
|
112
|
+
definitions flow across `.azeroth` files, reads every real file from disk, and
|
|
113
|
+
honours the nearest `tsconfig.json` (including its `paths`), forcing only the
|
|
114
|
+
options the virtual modules require.
|
|
115
|
+
|
|
116
|
+
## Components
|
|
117
|
+
|
|
118
|
+
| File | Role |
|
|
119
|
+
| --- | --- |
|
|
120
|
+
| `service.ts` | The `AzerothLanguageService` facade; one instance per workspace. |
|
|
121
|
+
| `virtual-code.ts` | Compiles `.azeroth` to virtual TS with a `CodeMapping`. Reuses the compiler. |
|
|
122
|
+
| `mapping.ts` | `CodeMapping`: binary-searched bidirectional offset translation. |
|
|
123
|
+
| `markup-model.ts` | Caret classification and markup-node collection (reuses scanner/parser). |
|
|
124
|
+
| `ts-project.ts` | `AzerothProject`: the `ts.LanguageService` host over virtual files. |
|
|
125
|
+
| `language-data.ts` | HTML/event vocabulary and built-in component data. |
|
|
126
|
+
| `html-source.ts` | Builds the embedded HTML view (non-markup blanked to spaces). |
|
|
127
|
+
| `request.ts` | Per-request context plus offset/range translation helpers. |
|
|
128
|
+
| `text.ts` | `LineIndex`: line/column to offset conversion. |
|
|
129
|
+
| `uri.ts` | URI to filesystem path conversion. |
|
|
130
|
+
| `protocol.ts` | LSP-shaped result types, kept independent of the server package. |
|
|
131
|
+
| `providers/*.ts` | One focused module per editor feature. |
|
|
132
|
+
|
|
133
|
+
The public API is the `AzerothLanguageService` facade. Its lifecycle methods are
|
|
134
|
+
`didOpen`, `didChange`, and `didClose`; the rest are query methods named after
|
|
135
|
+
the LSP request they serve (`getCompletions`, `resolveCompletion`, `getHover`,
|
|
136
|
+
`getDefinition`, `getReferences`, `getRenameEdits`, `getDocumentSymbols`,
|
|
137
|
+
`getDiagnostics`, `getSemanticTokens`, `getCodeActions`, and so on). Result types
|
|
138
|
+
already mirror the LSP shapes, so the server adapter is close to a passthrough.
|
|
139
|
+
|
|
140
|
+
### Completion (`providers/completion.ts`)
|
|
141
|
+
|
|
142
|
+
Completion is context-first. `classifyPosition` (resilient to half-typed input)
|
|
143
|
+
decides which vocabulary applies:
|
|
144
|
+
|
|
145
|
+
| Caret context | Suggestions |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| Tag name (`<di`, `<Cou`) | HTML elements (with MDN docs) plus built-in components plus in-scope, non-ambient PascalCase identifiers (user components, via TypeScript). |
|
|
148
|
+
| Attribute name (`<button cla`) | Host element: HTML attributes plus camelCase DOM events. Component: its documented props and events. |
|
|
149
|
+
| Attribute value (`<input type="`) | Host element: HTML value enums and booleans from the HTML engine. Inline `style`: CSS property/value completion. |
|
|
150
|
+
| Expression / script / text | Full type-aware TypeScript completion at the mapped offset, plus tag suggestions immediately after a `<`. |
|
|
151
|
+
|
|
152
|
+
User-component candidates come from TypeScript completion entries filtered to
|
|
153
|
+
PascalCase values that are not `declare`d ambients, so `<Cou` offers the imported
|
|
154
|
+
`Counter` rather than the thousands of global DOM and JS types. TypeScript-sourced
|
|
155
|
+
items carry a `data` payload so `resolveCompletion` can fetch detail and JSDoc
|
|
156
|
+
lazily, and may attach an auto-import edit through `additionalTextEdits`. Snippet
|
|
157
|
+
completions (for example `when={$0}`) are emitted for component props and events.
|
|
158
|
+
Ranking is via `sortText`.
|
|
159
|
+
|
|
160
|
+
### Hover (`providers/hover.ts`)
|
|
161
|
+
|
|
162
|
+
For any mapped position (the script, an expression hole, an attribute expression,
|
|
163
|
+
or a component tag name) hover is TypeScript's quick-info: signature plus JSDoc,
|
|
164
|
+
rendered as Markdown. Host-element markup uses the HTML language service's
|
|
165
|
+
MDN-backed hover, with a fallback table for common form attributes the standard
|
|
166
|
+
HTML dataset ships without descriptions. Built-in components show their framework
|
|
167
|
+
documentation. Context is decided before the offset map is consulted, so a host
|
|
168
|
+
tag never shows a stray TypeScript result mid-edit.
|
|
169
|
+
|
|
170
|
+
### Navigation and symbols (`providers/navigation.ts`, `providers/symbols.ts`)
|
|
171
|
+
|
|
172
|
+
Definition, type-definition, references, and rename are TypeScript queries at the
|
|
173
|
+
mapped offset. Results are document spans that may live in this file or another
|
|
174
|
+
(`.azeroth` or `.ts`); `resolveLocation` maps a virtual-file span back through
|
|
175
|
+
that file's `CodeMapping` and reports the `.azeroth` URI, while real files report
|
|
176
|
+
directly. A declaration that contains markup straddles generated scaffolding, so
|
|
177
|
+
its full span is not one contiguous mapping; document symbols map the two
|
|
178
|
+
endpoints (which sit in verbatim script) independently to recover the source
|
|
179
|
+
range. Workspace symbols use TypeScript's `getNavigateToItems`.
|
|
180
|
+
|
|
181
|
+
### Diagnostics (`providers/diagnostics.ts`)
|
|
182
|
+
|
|
183
|
+
Two sources, prioritised. First, markup parse errors: the compiler's own
|
|
184
|
+
`parseMarkup` is run over each region and a `CompileError` is reported at its
|
|
185
|
+
exact offset with `source: 'azeroth'`. A hard markup error means the virtual
|
|
186
|
+
module is incomplete, so TypeScript diagnostics would be noise and are suppressed
|
|
187
|
+
until the markup parses. Second, TypeScript syntactic and semantic diagnostics
|
|
188
|
+
over the virtual module, mapped back to original ranges; diagnostics that land
|
|
189
|
+
purely in generated scaffolding are dropped, so what surfaces are genuine errors
|
|
190
|
+
in the user's expressions and script (`source: 'azeroth-ts'`).
|
|
191
|
+
|
|
192
|
+
### Structure (`providers/structure.ts`)
|
|
193
|
+
|
|
194
|
+
Quick fixes reuse TypeScript's `getCodeFixesAtPosition` for the diagnostics at a
|
|
195
|
+
range, with the resulting edits mapped back to the source. Formatting runs
|
|
196
|
+
TypeScript's formatter over the virtual module and keeps only the edits that fall
|
|
197
|
+
inside mapped (user-authored) spans, tidying the script and expressions without
|
|
198
|
+
disturbing the markup. This module also provides folding ranges, on-type
|
|
199
|
+
formatting, and selection ranges.
|
|
200
|
+
|
|
201
|
+
## Development
|
|
202
|
+
|
|
203
|
+
The source is TypeScript with ESM `.ts`-extension imports, 4-space indentation,
|
|
204
|
+
and Allman braces, matching the rest of the monorepo. Each module carries a
|
|
205
|
+
header comment describing its responsibility, and exported symbols carry JSDoc.
|
|
206
|
+
|
|
207
|
+
A good reading order follows the runtime pipeline: `virtual-code.ts` and
|
|
208
|
+
`mapping.ts`, then `ts-project.ts`, then `markup-model.ts`, then the providers,
|
|
209
|
+
then `service.ts`.
|
|
210
|
+
|
|
211
|
+
## Building
|
|
212
|
+
|
|
213
|
+
```sh
|
|
214
|
+
npm run build -w @azerothjs/language-service
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
This runs `tsc -p tsconfig.build.json` and emits `dist/`. The build depends on
|
|
218
|
+
`@azerothjs/compiler` being built first; the repository root `npm run build`
|
|
219
|
+
builds the packages in dependency order.
|
|
220
|
+
|
|
221
|
+
## Testing
|
|
222
|
+
|
|
223
|
+
Tests live under `test/language-service/` at the repository root and run with
|
|
224
|
+
Vitest:
|
|
225
|
+
|
|
226
|
+
```sh
|
|
227
|
+
npm test # whole repository
|
|
228
|
+
npx vitest run test/language-service
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`language-service.test.ts` exercises the public facade end to end (completion,
|
|
232
|
+
hover, diagnostics, navigation) and `virtual-code.test.ts` checks the
|
|
233
|
+
compilation and offset mapping directly. Because the package needs no editor, the
|
|
234
|
+
tests construct an `AzerothLanguageService` over a temporary workspace and assert
|
|
235
|
+
on its results.
|
|
236
|
+
|
|
237
|
+
## Configuration
|
|
238
|
+
|
|
239
|
+
The service reads the nearest `tsconfig.json` for each file (including `paths`)
|
|
240
|
+
and forces only the options the virtual modules require (TypeScript source,
|
|
241
|
+
bundler-style module resolution). Per-feature toggles are passed in by the caller
|
|
242
|
+
through `CompletionOptions` and `InlayHintOptions`; the server maps editor
|
|
243
|
+
settings onto these.
|
|
244
|
+
|
|
245
|
+
## Examples
|
|
246
|
+
|
|
247
|
+
`packages/compiler/examples/Showcase.azeroth` is a single comprehensive file
|
|
248
|
+
(both a function component and a class component) used to exercise the features
|
|
249
|
+
by hand in an editor.
|
|
250
|
+
|
|
251
|
+
## Contributing
|
|
252
|
+
|
|
253
|
+
Keep the seam intact: anything that is really TypeScript should be answered by
|
|
254
|
+
the TypeScript bridge rather than re-implemented, and anything markup-specific
|
|
255
|
+
belongs in `markup-model.ts` or `language-data.ts`. New features generally take
|
|
256
|
+
the shape of a new module under `providers/` plus a method on the facade. Add or
|
|
257
|
+
update tests under `test/language-service/`, and run the build with
|
|
258
|
+
`--noUnusedLocals --noUnusedParameters` (the repository default) before sending a
|
|
259
|
+
change.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the embedded HTML view of `source`: markup preserved at its original
|
|
3
|
+
* offsets, everything else turned into whitespace.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* generateHtmlSource('const x = <a href="/">hi</a>;');
|
|
8
|
+
* // ' <a href="/">hi</a> '
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateHtmlSource(source: string): string;
|
|
12
|
+
//# sourceMappingURL=html-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-source.d.ts","sourceRoot":"","sources":["../src/html-source.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA2GzD"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Produces a *virtual HTML document* for the markup in a `.azeroth` file, so the
|
|
2
|
+
// HTML language service (the engine behind VS Code's HTML support) can answer
|
|
3
|
+
// tag/attribute/value completion and MDN-backed hover for host elements.
|
|
4
|
+
//
|
|
5
|
+
// The trick that keeps it cheap: the virtual document is the same length as the
|
|
6
|
+
// source, with every non-markup character replaced by a space (newlines kept).
|
|
7
|
+
// So a caret offset in the `.azeroth` file is the *same* offset in the HTML
|
|
8
|
+
// document - no second mapping layer is needed. Markup is copied verbatim;
|
|
9
|
+
// inside `{ ... }` holes and attribute expressions the JavaScript is blanked
|
|
10
|
+
// (its braces kept), except for any markup nested in a hole, which is restored
|
|
11
|
+
// so `{cond && <p class="x"/>}` still gets HTML intelligence on the `<p>`.
|
|
12
|
+
//
|
|
13
|
+
// Reuses the compiler's scanner (findMarkupStart) and parser (parseMarkup); a
|
|
14
|
+
// half-typed tail is copied verbatim so completion keeps working mid-edit.
|
|
15
|
+
import { findMarkupStart } from '@azerothjs/compiler';
|
|
16
|
+
import { parseMarkup } from '@azerothjs/compiler';
|
|
17
|
+
/**
|
|
18
|
+
* Builds the embedded HTML view of `source`: markup preserved at its original
|
|
19
|
+
* offsets, everything else turned into whitespace.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* generateHtmlSource('const x = <a href="/">hi</a>;');
|
|
24
|
+
* // ' <a href="/">hi</a> '
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function generateHtmlSource(source) {
|
|
28
|
+
const chars = new Array(source.length);
|
|
29
|
+
for (let k = 0; k < source.length; k++) {
|
|
30
|
+
const c = source[k];
|
|
31
|
+
chars[k] = c === '\n' || c === '\r' ? c : ' ';
|
|
32
|
+
}
|
|
33
|
+
const copyVerbatim = (a, b) => {
|
|
34
|
+
for (let k = a; k < b && k < source.length; k++) {
|
|
35
|
+
const c = source[k];
|
|
36
|
+
if (c !== '\n' && c !== '\r') {
|
|
37
|
+
chars[k] = c;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const blank = (a, b) => {
|
|
42
|
+
for (let k = a; k < b && k < source.length; k++) {
|
|
43
|
+
const c = source[k];
|
|
44
|
+
if (c !== '\n' && c !== '\r') {
|
|
45
|
+
chars[k] = ' ';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const copyRegions = (lo, hi) => {
|
|
50
|
+
let i = lo;
|
|
51
|
+
for (;;) {
|
|
52
|
+
const s = findMarkupStart(source, i);
|
|
53
|
+
if (s === -1 || s >= hi) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let node;
|
|
57
|
+
let end;
|
|
58
|
+
try {
|
|
59
|
+
({ node, end } = parseMarkup(source, s));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Half-typed tail: copy it so the HTML service still sees the
|
|
63
|
+
// partial tag and offers completions while the author types.
|
|
64
|
+
copyVerbatim(s, hi);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
copyVerbatim(node.start, node.end);
|
|
68
|
+
blankHoles(node);
|
|
69
|
+
i = end;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const blankHoles = (node) => {
|
|
73
|
+
if (node.kind === 'element') {
|
|
74
|
+
for (const attr of node.attributes) {
|
|
75
|
+
const open = source.indexOf('{', attr.start);
|
|
76
|
+
const close = attr.end - 1;
|
|
77
|
+
if (open === -1 || close <= open) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (attr.spread) {
|
|
81
|
+
// `{...rest}` has no attribute name; drop it entirely so it
|
|
82
|
+
// doesn't break the surrounding tag's attribute parsing.
|
|
83
|
+
blank(open, close + 1);
|
|
84
|
+
}
|
|
85
|
+
else if (attr.value.kind === 'expression') {
|
|
86
|
+
// Turn `name={expr}` into `name=" "`: a clean quoted value
|
|
87
|
+
// keeps the HTML scanner's attribute boundaries intact, so
|
|
88
|
+
// hover/completion still work on neighbouring attributes.
|
|
89
|
+
chars[open] = '"';
|
|
90
|
+
chars[close] = '"';
|
|
91
|
+
blank(open + 1, close);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const child of node.children) {
|
|
96
|
+
if (child.kind === 'expression') {
|
|
97
|
+
blank(child.start + 1, child.end - 1);
|
|
98
|
+
copyRegions(child.start + 1, child.end - 1);
|
|
99
|
+
}
|
|
100
|
+
else if (child.kind === 'element' || child.kind === 'fragment') {
|
|
101
|
+
blankHoles(child);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
copyRegions(0, source.length);
|
|
106
|
+
return chars.join('');
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=html-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-source.js","sourceRoot":"","sources":["../src/html-source.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { AzerothLanguageService } from './service.ts';
|
|
2
|
+
export type { CompletionOptions } from './providers/completion.ts';
|
|
3
|
+
export type { InlayHintOptions } from './providers/inlay-hints.ts';
|
|
4
|
+
export { AzerothProject, isVirtualFile, toVirtualFile, toAzerothPath } from './ts-project.ts';
|
|
5
|
+
export { generateVirtualCode, BUILTIN_COMPONENTS, type VirtualCode } from './virtual-code.ts';
|
|
6
|
+
export { CodeMapping, type MappingSegment, type MappingKind } from './mapping.ts';
|
|
7
|
+
export { classifyPosition, collectMarkupNodes, type PositionContext } from './markup-model.ts';
|
|
8
|
+
export { BUILTIN_COMPONENT_MAP, DOM_EVENTS, type BuiltinComponent } from './language-data.ts';
|
|
9
|
+
export { LineIndex } from './text.ts';
|
|
10
|
+
export { uriToPath, pathToUri } from './uri.ts';
|
|
11
|
+
export { CompletionItemKind, SymbolKind, DiagnosticSeverity, SEMANTIC_TOKEN_TYPES, type Position, type Range, type Location, type CompletionItem, type Hover, type SignatureHelp, type SignatureInformation, type TextEdit, type WorkspaceEdit, type DocumentSymbol, type DocumentHighlight, type WorkspaceSymbol, type Diagnostic, type FoldingRange, type InlayHint, type SelectionRange, type CodeAction, type SemanticTokens, type SemanticTokenType } from './protocol.ts';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACH,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACH,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,WAAW,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAElF,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,eAAe,EACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,qBAAqB,EACrB,UAAU,EACV,KAAK,gBAAgB,EACxB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EACH,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,QAAQ,EACb,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACzB,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @azerothjs/language-service
|
|
2
|
+
//
|
|
3
|
+
// Compiler-aware language intelligence for `.azeroth` files, packaged for any
|
|
4
|
+
// editor frontend (the bundled LSP server in @azerothjs/language-server, a
|
|
5
|
+
// test harness, or a browser playground).
|
|
6
|
+
//
|
|
7
|
+
// The pipeline, in the order it runs (and a good order to read it in):
|
|
8
|
+
// virtual-code - reuse the compiler's scanner + parser to compile a
|
|
9
|
+
// `.azeroth` file into a virtual TypeScript module, recording a
|
|
10
|
+
// precise offset mapping for every user-authored span
|
|
11
|
+
// ts-project - run a single ts.LanguageService over those virtual modules
|
|
12
|
+
// (the engine for type inference, completion, hover, etc.)
|
|
13
|
+
// markup-model - classify the caret (tag name / attribute / expression / …)
|
|
14
|
+
// so the providers know which vocabulary to offer
|
|
15
|
+
// providers - one focused module per editor feature
|
|
16
|
+
// service - the AzerothLanguageService facade that ties them together
|
|
17
|
+
//
|
|
18
|
+
// The core depends only on `typescript` and `@azerothjs/compiler`, so it runs
|
|
19
|
+
// (and is tested) without an editor in the loop.
|
|
20
|
+
export { AzerothLanguageService } from "./service.js";
|
|
21
|
+
export { AzerothProject, isVirtualFile, toVirtualFile, toAzerothPath } from "./ts-project.js";
|
|
22
|
+
export { generateVirtualCode, BUILTIN_COMPONENTS } from "./virtual-code.js";
|
|
23
|
+
export { CodeMapping } from "./mapping.js";
|
|
24
|
+
export { classifyPosition, collectMarkupNodes } from "./markup-model.js";
|
|
25
|
+
export { BUILTIN_COMPONENT_MAP, DOM_EVENTS } from "./language-data.js";
|
|
26
|
+
export { LineIndex } from "./text.js";
|
|
27
|
+
export { uriToPath, pathToUri } from "./uri.js";
|
|
28
|
+
export { CompletionItemKind, SymbolKind, DiagnosticSeverity, SEMANTIC_TOKEN_TYPES } from "./protocol.js";
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,0CAA0C;AAC1C,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,iFAAiF;AACjF,uEAAuE;AACvE,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,mEAAmE;AACnE,yDAAyD;AACzD,6EAA6E;AAC7E,EAAE;AACF,8EAA8E;AAC9E,iDAAiD;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAItD,OAAO,EACH,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACH,mBAAmB,EACnB,kBAAkB,EAErB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAyC,MAAM,cAAc,CAAC;AAElF,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAErB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,qBAAqB,EACrB,UAAU,EAEb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EACH,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EAoBvB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** A completion-ready description of a built-in component. */
|
|
2
|
+
export interface BuiltinComponent {
|
|
3
|
+
name: string;
|
|
4
|
+
/** Short signature-like detail shown beside the name. */
|
|
5
|
+
detail: string;
|
|
6
|
+
/** Markdown documentation. */
|
|
7
|
+
doc: string;
|
|
8
|
+
/** Known prop names with one-line docs, for attribute completion. */
|
|
9
|
+
props: {
|
|
10
|
+
name: string;
|
|
11
|
+
doc: string;
|
|
12
|
+
required: boolean;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The components the compiler auto-imports from `@azerothjs/core` when markup
|
|
17
|
+
* uses them. Mirrors @azerothjs/compiler's BUILTIN_COMPONENTS, with prop data
|
|
18
|
+
* taken from the renderer/component prop interfaces.
|
|
19
|
+
*/
|
|
20
|
+
export declare const BUILTIN_COMPONENTS: BuiltinComponent[];
|
|
21
|
+
/** Fast lookup of built-in component data by name. */
|
|
22
|
+
export declare const BUILTIN_COMPONENT_MAP: Map<string, BuiltinComponent>;
|
|
23
|
+
/**
|
|
24
|
+
* DOM event handler attribute names. AzerothJS binds any `on<Event>` prop as a
|
|
25
|
+
* listener (camelCase) and passes the handler through verbatim (see the
|
|
26
|
+
* compiler's codegen) - this differs from HTML's lowercase `onclick`, so it is
|
|
27
|
+
* supplied here rather than by the HTML service.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DOM_EVENTS: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Concise documentation for common element attributes that the standard HTML
|
|
32
|
+
* dataset ships *without* a description (form/input attributes especially), so
|
|
33
|
+
* `type`, `placeholder`, `value`, … aren't left blank on hover/completion.
|
|
34
|
+
* Global attributes (`class`, `id`, `title`, `style`, `aria-*`) and many tag
|
|
35
|
+
* attributes already carry MDN docs straight from the HTML engine; this only
|
|
36
|
+
* fills the gaps.
|
|
37
|
+
*/
|
|
38
|
+
export declare const ATTRIBUTE_DOCS: Record<string, string>;
|
|
39
|
+
/** Fallback documentation for a common element attribute, or undefined. */
|
|
40
|
+
export declare function attributeDocumentation(name: string): string | undefined;
|
|
41
|
+
//# sourceMappingURL=language-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-data.d.ts","sourceRoot":"","sources":["../src/language-data.ts"],"names":[],"mappings":"AAWA,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAE7B,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC7D;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAsFhD,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,+BAA4E,CAAC;AAQ/G;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,EAW9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA0BjD,CAAC;AAEF,2EAA2E;AAC3E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGvE"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Static language knowledge that isn't derivable from a single `.azeroth`
|
|
2
|
+
// file: the HTML vocabulary markup targets (tags, global attributes, DOM
|
|
3
|
+
// events) and the framework's built-in components.
|
|
4
|
+
//
|
|
5
|
+
// The built-in component data here is transcribed directly from the runtime's
|
|
6
|
+
// own prop interfaces (@azerothjs/renderer, @azerothjs/component, the compiler's
|
|
7
|
+
// auto-import set) - it is not invented. Deep type detail (exact prop types,
|
|
8
|
+
// generics) still flows from TypeScript at hover/signature time; this table
|
|
9
|
+
// exists so completion can *offer* the components and their props with a useful
|
|
10
|
+
// one-line summary before the type bridge fills in the rest.
|
|
11
|
+
/**
|
|
12
|
+
* The components the compiler auto-imports from `@azerothjs/core` when markup
|
|
13
|
+
* uses them. Mirrors @azerothjs/compiler's BUILTIN_COMPONENTS, with prop data
|
|
14
|
+
* taken from the renderer/component prop interfaces.
|
|
15
|
+
*/
|
|
16
|
+
export const BUILTIN_COMPONENTS = [
|
|
17
|
+
{
|
|
18
|
+
name: 'Show',
|
|
19
|
+
detail: '<Show when={…} fallback={…}>…</Show>',
|
|
20
|
+
doc: 'Conditionally renders its children when `when` is truthy, otherwise the optional `fallback`. Swaps automatically when the reactive condition changes.',
|
|
21
|
+
props: [
|
|
22
|
+
{ name: 'when', doc: 'Reactive condition. Children show while truthy.', required: true },
|
|
23
|
+
{ name: 'fallback', doc: 'Rendered when `when` is false. Optional.', required: false }
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'For',
|
|
28
|
+
detail: '<For each={…} key={…}>{(item, i) => …}</For>',
|
|
29
|
+
doc: 'Keyed list rendering. Re-uses DOM elements across updates by `key`, so only changed rows touch the DOM. The child is a render function `(item, index) => element`.',
|
|
30
|
+
props: [
|
|
31
|
+
{ name: 'each', doc: 'Reactive getter returning the array of items.', required: true },
|
|
32
|
+
{ name: 'key', doc: 'Returns a stable unique key per item: `(item, index) => string | number`.', required: true }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'Switch',
|
|
37
|
+
detail: '<Switch fallback={…}><Match/>…</Switch>',
|
|
38
|
+
doc: 'Renders the first `<Match>` whose `when` is truthy (priority order). Optional `fallback` when none match.',
|
|
39
|
+
props: [
|
|
40
|
+
{ name: 'fallback', doc: 'Rendered when no `<Match>` matches. Optional.', required: false }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'Match',
|
|
45
|
+
detail: '<Match when={…}>…</Match>',
|
|
46
|
+
doc: 'A single case inside `<Switch>`. Rendered when its `when` condition is the first truthy one.',
|
|
47
|
+
props: [
|
|
48
|
+
{ name: 'when', doc: 'Reactive condition for this case.', required: true }
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Portal',
|
|
53
|
+
detail: '<Portal target={…}>…</Portal>',
|
|
54
|
+
doc: 'Renders its children into a different DOM node (defaults to `document.body`). Useful for modals, tooltips, and overlays.',
|
|
55
|
+
props: [
|
|
56
|
+
{ name: 'target', doc: 'Destination element. Defaults to `document.body`.', required: false }
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'Dynamic',
|
|
61
|
+
detail: '<Dynamic component={…} props={…} />',
|
|
62
|
+
doc: 'Renders a component chosen at runtime. When the `component` getter changes, the old one is removed and the new one mounted.',
|
|
63
|
+
props: [
|
|
64
|
+
{ name: 'component', doc: 'Reactive getter returning the component to render (or null).', required: true },
|
|
65
|
+
{ name: 'props', doc: 'Optional reactive getter returning props for the component.', required: false }
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'Suspense',
|
|
70
|
+
detail: '<Suspense on={[…]} fallback={…}>…</Suspense>',
|
|
71
|
+
doc: 'Shows `fallback` while any watched resource is loading, then reveals children once all have settled.',
|
|
72
|
+
props: [
|
|
73
|
+
{ name: 'on', doc: 'Array of resources to watch (captured once, not reactive to array mutation).', required: true },
|
|
74
|
+
{ name: 'fallback', doc: 'Rendered while any watched resource is loading.', required: true }
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'Transition',
|
|
79
|
+
detail: '<Transition when={…} name="…">…</Transition>',
|
|
80
|
+
doc: 'Animated show/hide. With a `name`, auto-generates the 6-class enter/leave family; without one, falls back to an instant swap.',
|
|
81
|
+
props: [
|
|
82
|
+
{ name: 'when', doc: 'Reactive boolean: true to show, false to hide.', required: true },
|
|
83
|
+
{ name: 'name', doc: 'Class-name prefix for the enter/leave transition classes.', required: false },
|
|
84
|
+
{ name: 'duration', doc: 'Fallback transition timeout in ms. Default 1000.', required: false }
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'ErrorBoundary',
|
|
89
|
+
detail: '<ErrorBoundary fallback={(err, reset) => …}>…</ErrorBoundary>',
|
|
90
|
+
doc: 'Catches errors thrown while rendering its subtree and shows `fallback(error, reset)` instead. Call `reset` to retry.',
|
|
91
|
+
props: [
|
|
92
|
+
{ name: 'fallback', doc: 'Renders the error UI: `(error, reset) => element`.', required: true }
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'Outlet',
|
|
97
|
+
detail: '<Outlet />',
|
|
98
|
+
doc: 'Renders nested-route content inside a layout component. Provided automatically by `<Routes>`.',
|
|
99
|
+
props: []
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
/** Fast lookup of built-in component data by name. */
|
|
103
|
+
export const BUILTIN_COMPONENT_MAP = new Map(BUILTIN_COMPONENTS.map(component => [component.name, component]));
|
|
104
|
+
// Host-element vocabulary (HTML tags, attributes, and attribute values, with
|
|
105
|
+
// MDN documentation) is provided by `vscode-html-languageservice` - the same
|
|
106
|
+
// engine VS Code's HTML support uses - via providers/html-service.ts, so it is
|
|
107
|
+
// complete and stays current without a hand-maintained list here. What remains
|
|
108
|
+
// below is genuinely AzerothJS-specific.
|
|
109
|
+
/**
|
|
110
|
+
* DOM event handler attribute names. AzerothJS binds any `on<Event>` prop as a
|
|
111
|
+
* listener (camelCase) and passes the handler through verbatim (see the
|
|
112
|
+
* compiler's codegen) - this differs from HTML's lowercase `onclick`, so it is
|
|
113
|
+
* supplied here rather than by the HTML service.
|
|
114
|
+
*/
|
|
115
|
+
export const DOM_EVENTS = [
|
|
116
|
+
'onClick', 'onDblClick', 'onMouseDown', 'onMouseUp', 'onMouseEnter', 'onMouseLeave',
|
|
117
|
+
'onMouseMove', 'onMouseOver', 'onMouseOut', 'onContextMenu',
|
|
118
|
+
'onInput', 'onChange', 'onSubmit', 'onReset', 'onFocus', 'onBlur', 'onFocusIn', 'onFocusOut',
|
|
119
|
+
'onKeyDown', 'onKeyUp', 'onKeyPress',
|
|
120
|
+
'onPointerDown', 'onPointerUp', 'onPointerMove', 'onPointerEnter', 'onPointerLeave',
|
|
121
|
+
'onTouchStart', 'onTouchEnd', 'onTouchMove',
|
|
122
|
+
'onScroll', 'onWheel', 'onDrag', 'onDragStart', 'onDragEnd', 'onDragOver', 'onDrop',
|
|
123
|
+
'onCopy', 'onCut', 'onPaste',
|
|
124
|
+
'onLoad', 'onError', 'onAnimationEnd', 'onTransitionEnd'
|
|
125
|
+
];
|
|
126
|
+
/**
|
|
127
|
+
* Concise documentation for common element attributes that the standard HTML
|
|
128
|
+
* dataset ships *without* a description (form/input attributes especially), so
|
|
129
|
+
* `type`, `placeholder`, `value`, … aren't left blank on hover/completion.
|
|
130
|
+
* Global attributes (`class`, `id`, `title`, `style`, `aria-*`) and many tag
|
|
131
|
+
* attributes already carry MDN docs straight from the HTML engine; this only
|
|
132
|
+
* fills the gaps.
|
|
133
|
+
*/
|
|
134
|
+
export const ATTRIBUTE_DOCS = {
|
|
135
|
+
type: 'The kind of control to render (e.g. `text`, `checkbox`, `email`, `number`, `password`).',
|
|
136
|
+
value: 'The control’s current value. In AzerothJS, bind it reactively: `value={signal()}`.',
|
|
137
|
+
placeholder: 'Hint text shown while the field is empty.',
|
|
138
|
+
checked: 'Whether a checkbox/radio is selected. Bind reactively: `checked={done()}`.',
|
|
139
|
+
disabled: 'When present, the control is non-interactive.',
|
|
140
|
+
readonly: 'When present, the value can’t be edited (but is still submitted).',
|
|
141
|
+
required: 'Marks the field as required for form submission.',
|
|
142
|
+
name: 'The control name, submitted with the form data.',
|
|
143
|
+
min: 'Minimum allowed value (numeric/date inputs).',
|
|
144
|
+
max: 'Maximum allowed value (numeric/date inputs).',
|
|
145
|
+
step: 'Granularity of allowed values (numeric/date inputs).',
|
|
146
|
+
pattern: 'A regular expression the value must match.',
|
|
147
|
+
autocomplete: 'Hint for the browser’s autofill behaviour.',
|
|
148
|
+
selected: 'Marks an `<option>` as initially selected.',
|
|
149
|
+
multiple: 'Allows selecting or entering multiple values.',
|
|
150
|
+
rows: 'Visible number of text rows in a `<textarea>`.',
|
|
151
|
+
cols: 'Visible width, in characters, of a `<textarea>`.',
|
|
152
|
+
src: 'The URL of the resource (image, script, media, …).',
|
|
153
|
+
alt: 'Alternative text describing an image.',
|
|
154
|
+
for: 'Associates a `<label>` with a control by its `id`.',
|
|
155
|
+
action: 'The URL that processes the form submission.',
|
|
156
|
+
method: 'The HTTP method used to submit the form (`get` / `post`).',
|
|
157
|
+
colspan: 'Number of columns a table cell spans.',
|
|
158
|
+
rowspan: 'Number of rows a table cell spans.'
|
|
159
|
+
};
|
|
160
|
+
/** Fallback documentation for a common element attribute, or undefined. */
|
|
161
|
+
export function attributeDocumentation(name) {
|
|
162
|
+
return ATTRIBUTE_DOCS[name.toLowerCase()];
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=language-data.js.map
|