@reactra/language-tools 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +109 -0
- package/dist/cli/reactra-tsc.d.ts +3 -0
- package/dist/cli/reactra-tsc.d.ts.map +1 -0
- package/dist/cli/reactra-tsc.js +25 -0
- package/dist/cli/reactra-tsc.js.map +1 -0
- package/dist/diagnostic-plugin.d.ts +12 -0
- package/dist/diagnostic-plugin.d.ts.map +1 -0
- package/dist/diagnostic-plugin.js +112 -0
- package/dist/diagnostic-plugin.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/language-plugin.d.ts +44 -0
- package/dist/language-plugin.d.ts.map +1 -0
- package/dist/language-plugin.js +323 -0
- package/dist/language-plugin.js.map +1 -0
- package/dist/lsp/server.cjs +68546 -0
- package/dist/shadow/emitter.d.ts +15 -0
- package/dist/shadow/emitter.d.ts.map +1 -0
- package/dist/shadow/emitter.js +871 -0
- package/dist/shadow/emitter.js.map +1 -0
- package/dist/shadow/index.d.ts +3 -0
- package/dist/shadow/index.d.ts.map +1 -0
- package/dist/shadow/index.js +4 -0
- package/dist/shadow/index.js.map +1 -0
- package/dist/shadow/mapper.d.ts +55 -0
- package/dist/shadow/mapper.d.ts.map +1 -0
- package/dist/shadow/mapper.js +111 -0
- package/dist/shadow/mapper.js.map +1 -0
- package/dist/ts-plugin/impl.cjs +50132 -0
- package/dist/ts-plugin/index.cjs +3 -0
- package/dist/ts-plugin/package.json +8 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Akhil Shastri and the Reactra contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# @reactra/language-tools
|
|
2
|
+
|
|
3
|
+
TypeScript / IDE tooling for the Reactra DSL. It gives the terse Reactra `.tsx` DSL
|
|
4
|
+
**full, precise type-checking** — in your editor and in CI — without changing how the
|
|
5
|
+
DSL feels to write.
|
|
6
|
+
|
|
7
|
+
## The problem it solves
|
|
8
|
+
|
|
9
|
+
A Reactra `.tsx` file is not plain TypeScript. The moment a tool sees `state count = 0`,
|
|
10
|
+
`inject store cartStore`, or `await(user) { … } pending { … }`, stock `tsc` and your
|
|
11
|
+
editor's TypeScript language service give up — they can't parse it, so you lose
|
|
12
|
+
type-checking, hover, autocomplete, and go-to-definition on the parts that matter most.
|
|
13
|
+
|
|
14
|
+
`@reactra/language-tools` fixes this with a **shadow file**: for each DSL file it
|
|
15
|
+
synthesizes a parallel, fully-typed TypeScript projection (the "shadow"), runs the *real*
|
|
16
|
+
TypeScript type system over the shadow, and maps every diagnostic back to your DSL source
|
|
17
|
+
line. You write terse DSL; you get the type safety of hand-written React.
|
|
18
|
+
|
|
19
|
+
> **No suppression.** Earlier approaches hid the DSL from TypeScript (suppressing the
|
|
20
|
+
> errors it couldn't understand). This package does the opposite — it *synthesizes* a
|
|
21
|
+
> file TypeScript fully understands, so the types are real, not silenced.
|
|
22
|
+
|
|
23
|
+
## Does my editor work?
|
|
24
|
+
|
|
25
|
+
| Where | What you install | What you get |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| **VS Code · Cursor** | the Reactra editor extension (bundles the Volar language plugin) | live red squiggles, hover types, autocomplete, go-to-def on DSL bindings |
|
|
28
|
+
| **Zed · neovim · any LSP editor** | the standalone LSP — `reactra-lsp-server` (stdio) | the same, via your editor's generic LSP client |
|
|
29
|
+
| **CI · terminal · any editor or none** | `reactra-tsc` | headless, whole-project type-checking that fails the build on type errors |
|
|
30
|
+
|
|
31
|
+
All three are **one engine** — the same shadow emitter and the same Volar `LanguagePlugin`.
|
|
32
|
+
So your editor and your CI can't disagree: if the editor is green, `reactra-tsc` is green.
|
|
33
|
+
|
|
34
|
+
## `reactra-tsc` — the CLI
|
|
35
|
+
|
|
36
|
+
`reactra-tsc` is to Reactra what `vue-tsc` is to Vue: a drop-in `tsc` that understands the
|
|
37
|
+
DSL. Use it in CI or a pre-commit hook so type errors fail the build regardless of which
|
|
38
|
+
editor (if any) a developer uses.
|
|
39
|
+
|
|
40
|
+
```jsonc
|
|
41
|
+
// package.json
|
|
42
|
+
{
|
|
43
|
+
"scripts": {
|
|
44
|
+
"type-check": "reactra-tsc --noEmit -p tsconfig.json"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
$ reactra-tsc --noEmit -p tsconfig.json
|
|
51
|
+
src/pages/cart.tsx(14,7): error TS2322: Type 'string' is not assignable to type 'number'.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The error points at your **DSL** line — the shadow is generated fresh at check time and
|
|
55
|
+
never committed, so there's no stale artifact to drift.
|
|
56
|
+
|
|
57
|
+
> Today this is a clean gate for apps built from the fully-typed constructs. If your app
|
|
58
|
+
> uses one of the known-gap constructs below (`uses`, `query T[]`, store `input` types),
|
|
59
|
+
> `reactra-tsc` will also report advisory false positives on correct code — see **Current
|
|
60
|
+
> coverage**, and prefer an allow-listed gate until those gaps close.
|
|
61
|
+
|
|
62
|
+
## How it works (the anti-drift guarantee)
|
|
63
|
+
|
|
64
|
+
The shadow emitter consumes the **same `FileGraph`** the Reactra compiler's code-generation
|
|
65
|
+
pass consumes (`compile(source).graph`). Editor tooling and the build run off one parsed
|
|
66
|
+
model of your file, so a *grammar* change propagates to both through a single edit — the
|
|
67
|
+
shadow can never disagree with the build about how your file **parses**.
|
|
68
|
+
|
|
69
|
+
The two emitters still make *lowering* decisions independently off that shared graph (the
|
|
70
|
+
shadow emits typed TS; Pass 9 emits React), so lowering parity — e.g. that a store is
|
|
71
|
+
exported in the shadow exactly when the compiler exports it — is held construct-by-construct
|
|
72
|
+
by the `F`-gate suite, not for free by graph-sharing alone.
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
DSL source ──> compile() ──> FileGraph ──┬──> Pass 9 codegen ──> React 19 .tsx (what ships)
|
|
76
|
+
└──> reactra2tsx ─────> shadow .tsx (what tsc checks)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Package surface
|
|
80
|
+
|
|
81
|
+
- `createReactraLanguagePlugin()` — the Volar `LanguagePlugin` (consumed by the editor
|
|
82
|
+
extension and `reactra-tsc`).
|
|
83
|
+
- `emitShadow(graph, source, rewrites?)` — the shadow emitter (`reactra2tsx`).
|
|
84
|
+
- `reactra-tsc` — the CLI binary.
|
|
85
|
+
- `reactra-lsp-server` — the standalone, editor-agnostic LSP binary.
|
|
86
|
+
|
|
87
|
+
## Current coverage
|
|
88
|
+
|
|
89
|
+
Type fidelity is proven construct-by-construct against the real emitter output (the
|
|
90
|
+
`F`-gate suite): components (page + plain), `state` (+ the kept `setX` escape hatch),
|
|
91
|
+
`derived` (expression + block-IIFE), `action`, `resource`, all eight `inject store` forms,
|
|
92
|
+
`inject service`, `param` and store `input` annotations, `query` (incl. `T[]`/union casts),
|
|
93
|
+
`meta`, `errorBoundary`, the `view` body, and `await/pending/error`.
|
|
94
|
+
|
|
95
|
+
Known gaps still being closed:
|
|
96
|
+
|
|
97
|
+
- a `resource` fetcher that isn't a plain entity-name call (e.g. a `.then()` chain) lowers as
|
|
98
|
+
`Resource<unknown>` — name it with an intermediate `const` to recover the type.
|
|
99
|
+
|
|
100
|
+
Recently closed: `param X: T` and store `input X: T` annotations (now threaded through the
|
|
101
|
+
preprocessor and AST, so a route param and every route-store `input` field projects at its
|
|
102
|
+
declared type — the central route-store data-flow is fully typed); `uses <behaviour>` injected
|
|
103
|
+
names (`undo`/`redo`/… typed from the behaviour registry); and `query T[]` (cast to the declared
|
|
104
|
+
type). With those closed, the repo's example type-check gate (`scripts/typecheck-examples.mjs`)
|
|
105
|
+
is **blocking on DSL source** — any example `.tsx` type error fails it.
|
|
106
|
+
|
|
107
|
+
> **Honest status:** the typed constructs — now including `param`/`input` — are sound today.
|
|
108
|
+
> The one remaining gap is the non-entity-name `resource` fetcher above, which degrades to
|
|
109
|
+
> `Resource<unknown>` (a soundness-preserving widening, not a false positive).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactra-tsc.d.ts","sourceRoot":"","sources":["../../src/cli/reactra-tsc.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// reactra-tsc — headless type-checker for Reactra DSL files in CI.
|
|
3
|
+
// Per plan/phase-4-language-tools-spec.md §7 (reactra-tsc CLI / M3 gate).
|
|
4
|
+
//
|
|
5
|
+
// Equivalent to vue-tsc: runTsc() + the Reactra language plugin.
|
|
6
|
+
// Usage: reactra-tsc --noEmit --project tsconfig.json
|
|
7
|
+
//
|
|
8
|
+
// runTsc patches fs.readFileSync to intercept the TypeScript source and inject
|
|
9
|
+
// Volar's proxyCreateProgram. It must be pointed at `typescript/lib/tsc.js`
|
|
10
|
+
// (not `typescript/bin/tsc`) because the bin shim (`require('../lib/tsc.js')`)
|
|
11
|
+
// uses a path pattern that runTsc's shim-detection regex cannot handle on TS 5.9+;
|
|
12
|
+
// `lib/tsc.js` uses the `module.exports = require("./_tsc.js")` pattern that
|
|
13
|
+
// the regex expects.
|
|
14
|
+
import { runTsc } from "@volar/typescript/lib/quickstart/runTsc.js";
|
|
15
|
+
import { createReactraLanguagePlugin } from "../language-plugin.js";
|
|
16
|
+
import { createRequire } from "node:module";
|
|
17
|
+
// Surface the R026 missing-`;` advisory by default in the headless gate — this is
|
|
18
|
+
// the deliberate "strict check" context (a migrated v2 codebase has `;` everywhere,
|
|
19
|
+
// so it stays quiet; un-migrated code gets the migration nudge). Opt out with
|
|
20
|
+
// `REACTRA_R026=0`. `??=` respects an explicit value the caller already set.
|
|
21
|
+
process.env.REACTRA_R026 ??= "1";
|
|
22
|
+
// Node.js CJS interop — require.resolve for the tsc library path.
|
|
23
|
+
const require = createRequire(import.meta.url);
|
|
24
|
+
runTsc(require.resolve("typescript/lib/tsc.js"), { extraSupportedExtensions: [".tsx"], extraExtensionsToRemove: [] }, (_ts, _options) => [createReactraLanguagePlugin()]);
|
|
25
|
+
//# sourceMappingURL=reactra-tsc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactra-tsc.js","sourceRoot":"","sources":["../../src/cli/reactra-tsc.ts"],"names":[],"mappings":";AACA,mEAAmE;AACnE,0EAA0E;AAC1E,EAAE;AACF,iEAAiE;AACjE,sDAAsD;AACtD,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,mFAAmF;AACnF,6EAA6E;AAC7E,qBAAqB;AAErB,OAAO,EAAE,MAAM,EAAE,MAAM,4CAA4C,CAAA;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,kFAAkF;AAClF,oFAAoF;AACpF,8EAA8E;AAC9E,6EAA6E;AAC7E,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,CAAA;AAEhC,kEAAkE;AAClE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAE9C,MAAM,CACJ,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,EACxC,EAAE,wBAAwB,EAAE,CAAC,MAAM,CAAC,EAAE,uBAAuB,EAAE,EAAE,EAAE,EACnE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,2BAA2B,EAAE,CAAC,CACnD,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LanguageServicePlugin } from "@volar/language-server";
|
|
2
|
+
/**
|
|
3
|
+
* Service plugin that surfaces a Reactra DSL parse failure (annotated on the
|
|
4
|
+
* shadow VirtualCode by the language plugin) as a single LSP011 diagnostic.
|
|
5
|
+
*
|
|
6
|
+
* Register it in the standalone server's service-plugin array
|
|
7
|
+
* (`lsp/server.ts`). It is a no-op for any document without a
|
|
8
|
+
* `reactraParseError` annotation (clean DSL, non-DSL, or a transient
|
|
9
|
+
* dangling-dot edit that recovered).
|
|
10
|
+
*/
|
|
11
|
+
export declare const createReactraDiagnosticPlugin: () => LanguageServicePlugin;
|
|
12
|
+
//# sourceMappingURL=diagnostic-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic-plugin.d.ts","sourceRoot":"","sources":["../src/diagnostic-plugin.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAoEnE;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,QAAO,qBA4B/C,CAAA"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Reactra standalone-LSP diagnostic service plugin (framework-review §B2).
|
|
2
|
+
// Per plan/phase-4-language-tools-spec.md §6 (standalone LSP) + the VS Code
|
|
3
|
+
// Extension spec §9 (LSP011 — Reactra DSL syntax error).
|
|
4
|
+
//
|
|
5
|
+
// THE Zed/neovim gap closer. The standalone Volar language server
|
|
6
|
+
// (`lsp/server.ts`) previously returned a bare empty shadow on a DSL parse
|
|
7
|
+
// error, so a malformed file showed NOTHING in those editors. The language
|
|
8
|
+
// plugin now annotates that empty shadow with `reactraParseError` (C2); this
|
|
9
|
+
// service plugin reads it off the document's root VirtualCode and surfaces it as
|
|
10
|
+
// a single LSP011 diagnostic at the mapped DSL position (C1/C4/C5).
|
|
11
|
+
//
|
|
12
|
+
// The VirtualCode IS the channel (C1) — no URI-keyed side-channel map.
|
|
13
|
+
//
|
|
14
|
+
// Scope (C6): this is a `provideDiagnostics` service-plugin hook, which the
|
|
15
|
+
// hybrid tsserver path (`ts-plugin.ts`, `getSemanticDiagnostics`) does NOT see.
|
|
16
|
+
// VS Code is covered by the legacy `vscode-extension/server` (its own LSP011),
|
|
17
|
+
// so there is no VS Code gap; B2 closes only the standalone-server editors.
|
|
18
|
+
//
|
|
19
|
+
// LSP011 (C5) is already allocated (VS Code Extension spec §9) — same semantic,
|
|
20
|
+
// different surface. We reuse it; no new code. Message format + range rule
|
|
21
|
+
// mirror the legacy `computeLSP011` provider exactly.
|
|
22
|
+
import { URI } from "vscode-uri";
|
|
23
|
+
// vscode-languageserver-protocol's DiagnosticSeverity.Error === 1. Written as a
|
|
24
|
+
// literal so the protocol package stays a type-only import (matches the rest of
|
|
25
|
+
// this stack — no runtime value import of the protocol enums).
|
|
26
|
+
const SEVERITY_ERROR = 1;
|
|
27
|
+
/**
|
|
28
|
+
* Build the LSP011 diagnostic range from the mapped DSL offset (C4):
|
|
29
|
+
* - offset present → start = offset, end = end of that DSL line; if the offset
|
|
30
|
+
* is at/after the line end (EOF / line-end), fall back to a visible span
|
|
31
|
+
* from the first non-whitespace char (zero-width is invisible).
|
|
32
|
+
* - offset null → file-level: line 0, start → end of line 0.
|
|
33
|
+
* Mirrors the legacy `computeLSP011` rule so the two surfaces agree.
|
|
34
|
+
*/
|
|
35
|
+
const rangeFor = (text, dslOffset) => {
|
|
36
|
+
const lines = text.split("\n");
|
|
37
|
+
if (dslOffset === null) {
|
|
38
|
+
const line0 = lines[0] ?? "";
|
|
39
|
+
return {
|
|
40
|
+
start: { line: 0, character: 0 },
|
|
41
|
+
end: { line: 0, character: Math.max(1, line0.length) },
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// Convert the absolute DSL offset → { line, character }.
|
|
45
|
+
let line = 0;
|
|
46
|
+
let lineStart = 0;
|
|
47
|
+
for (let i = 0; i < dslOffset && i < text.length; i++) {
|
|
48
|
+
if (text[i] === "\n") {
|
|
49
|
+
line++;
|
|
50
|
+
lineStart = i + 1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const lineText = lines[line] ?? "";
|
|
54
|
+
let startChar = dslOffset - lineStart;
|
|
55
|
+
let endChar = lineText.length;
|
|
56
|
+
if (startChar >= endChar) {
|
|
57
|
+
const firstNonWs = lineText.search(/\S/);
|
|
58
|
+
startChar = firstNonWs < 0 ? 0 : firstNonWs;
|
|
59
|
+
endChar = Math.max(lineText.length, startChar + 1);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
start: { line, character: startChar },
|
|
63
|
+
end: { line, character: endChar },
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Read the parse-error annotation off the document's root VirtualCode.
|
|
68
|
+
* `context.language.scripts.get(uri).generated.root` is the same object the
|
|
69
|
+
* language plugin returned from `buildVirtualCode`/`updateVirtualCode`.
|
|
70
|
+
*/
|
|
71
|
+
const readParseError = (context, documentUri) => {
|
|
72
|
+
const script = context.language.scripts.get(URI.parse(documentUri));
|
|
73
|
+
const root = script?.generated?.root;
|
|
74
|
+
return root?.reactraParseError;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Service plugin that surfaces a Reactra DSL parse failure (annotated on the
|
|
78
|
+
* shadow VirtualCode by the language plugin) as a single LSP011 diagnostic.
|
|
79
|
+
*
|
|
80
|
+
* Register it in the standalone server's service-plugin array
|
|
81
|
+
* (`lsp/server.ts`). It is a no-op for any document without a
|
|
82
|
+
* `reactraParseError` annotation (clean DSL, non-DSL, or a transient
|
|
83
|
+
* dangling-dot edit that recovered).
|
|
84
|
+
*/
|
|
85
|
+
export const createReactraDiagnosticPlugin = () => ({
|
|
86
|
+
name: "reactra-diagnostics",
|
|
87
|
+
capabilities: {
|
|
88
|
+
diagnosticProvider: {
|
|
89
|
+
interFileDependencies: false,
|
|
90
|
+
workspaceDiagnostics: false,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
create(context) {
|
|
94
|
+
return {
|
|
95
|
+
provideDiagnostics(document) {
|
|
96
|
+
const parseError = readParseError(context, document.uri);
|
|
97
|
+
if (!parseError)
|
|
98
|
+
return [];
|
|
99
|
+
return [
|
|
100
|
+
{
|
|
101
|
+
severity: SEVERITY_ERROR,
|
|
102
|
+
code: "LSP011",
|
|
103
|
+
source: "reactra",
|
|
104
|
+
message: `Reactra DSL syntax error: ${parseError.message}`,
|
|
105
|
+
range: rangeFor(document.getText(), parseError.dslOffset),
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=diagnostic-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic-plugin.js","sourceRoot":"","sources":["../src/diagnostic-plugin.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { emitShadow } from "./shadow/index.ts";
|
|
2
|
+
export type { ShadowResult, ShadowMapping } from "./shadow/index.ts";
|
|
3
|
+
export { createReactraLanguagePlugin } from "./language-plugin.ts";
|
|
4
|
+
export type { ReactraVirtualCode } from "./language-plugin.ts";
|
|
5
|
+
export { createReactraDiagnosticPlugin } from "./diagnostic-plugin.ts";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAA;AAClE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @reactra/language-tools — public entry.
|
|
2
|
+
// Per plan/phase-4-language-tools-spec.md §1 (Package layout).
|
|
3
|
+
export { emitShadow } from "./shadow/index.js";
|
|
4
|
+
export { createReactraLanguagePlugin } from "./language-plugin.js";
|
|
5
|
+
// B2: the standalone-LSP parse-error diagnostic service plugin (LSP011).
|
|
6
|
+
export { createReactraDiagnosticPlugin } from "./diagnostic-plugin.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,+DAA+D;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAA;AAElE,yEAAyE;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { LanguagePlugin, VirtualCode } from "@volar/language-core";
|
|
2
|
+
/**
|
|
3
|
+
* A Reactra shadow VirtualCode that can carry a DSL parse error (B2 / C2).
|
|
4
|
+
*
|
|
5
|
+
* When `buildVirtualCode` cannot produce a usable shadow (a genuine DSL syntax
|
|
6
|
+
* error, after dangling-dot recovery has failed), it returns an empty-but-
|
|
7
|
+
* ANNOTATED VirtualCode: the `export {}` placeholder snapshot keeps downstream
|
|
8
|
+
* TypeScript happy (no spurious TS noise), while `reactraParseError` carries the
|
|
9
|
+
* mapped DSL position + cleaned message. The standalone LSP's diagnostic service
|
|
10
|
+
* plugin (`createReactraDiagnosticPlugin`) reads this field off
|
|
11
|
+
* `scripts.get(uri).generated.root` and surfaces it as LSP011 (Zed/neovim).
|
|
12
|
+
*
|
|
13
|
+
* The VirtualCode IS the channel — no URI-keyed side-channel map (C1).
|
|
14
|
+
*/
|
|
15
|
+
export interface ReactraVirtualCode extends VirtualCode {
|
|
16
|
+
/**
|
|
17
|
+
* Set only on a genuine parse failure. `dslOffset` is the error position in
|
|
18
|
+
* DSL-source coordinates (null when the babel error carried no usable
|
|
19
|
+
* position → file-level diagnostic). `message` is the babel message with the
|
|
20
|
+
* trailing `(line:col)` stripped (the range conveys position).
|
|
21
|
+
*/
|
|
22
|
+
reactraParseError?: {
|
|
23
|
+
dslOffset: number | null;
|
|
24
|
+
message: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create the Reactra Volar language plugin.
|
|
29
|
+
*
|
|
30
|
+
* Register this plugin with a Volar language service to enable type-checking,
|
|
31
|
+
* completions, hover, and goto-definition for Reactra DSL `.tsx` files.
|
|
32
|
+
*
|
|
33
|
+
* The `typescript.getServiceScript` property is required by `@volar/typescript`'s
|
|
34
|
+
* `createProxyLanguageService` to route TypeScript diagnostics from the shadow
|
|
35
|
+
* back to DSL positions. Without it, `getSemanticDiagnostics` returns nothing.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { createReactraLanguagePlugin } from "@reactra/language-tools/language-plugin"
|
|
40
|
+
* const plugin = createReactraLanguagePlugin()
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const createReactraLanguagePlugin: () => LanguagePlugin<string>;
|
|
44
|
+
//# sourceMappingURL=language-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-plugin.d.ts","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EAGZ,MAAM,sBAAsB,CAAA;AAsC7B;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAClE;AAsOD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,2BAA2B,QAAO,cAAc,CAAC,MAAM,CAqElE,CAAA"}
|