@jigs.design/compiler 0.2.0 → 0.3.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 +6 -6
- package/dist/compile.d.ts +10 -10
- package/dist/compile.js +17 -17
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/patch.d.ts +21 -9
- package/dist/patch.js +80 -34
- package/dist/signature.d.ts +2 -2
- package/dist/signature.js +6 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @jigs.design/compiler
|
|
2
2
|
|
|
3
|
-
Today's Jigs compiler: the parser, the checker against a catalog, the code generator,
|
|
3
|
+
Today's Jigs compiler: the parser, the checker against a catalog, the code generator, jig libraries, and the SEARCH/REPLACE edit helpers. `@jigs.design/server` and `@jigs.design/prompt` use it. You import it for tooling, not to run a session.
|
|
4
4
|
|
|
5
5
|
Its diagnostics are the `Diagnostic` type from `@jigs.design/protocol`, the shape the server sends; it imports that package's types and nothing else from it. It parses embedded code with [acorn](https://github.com/acornjs/acorn) in strict mode, the mode programs run in, and checks names and the JavaScript subset. It has no built-in catalog. Every caller passes one, and its prop kinds are boolean, enum, handler, number, rows and string.
|
|
6
6
|
|
|
7
|
-
The [language
|
|
7
|
+
It evolves in place, behind the same server API. The [language plan's record](../../.agent-docs/notes/language-v2-2026-10.md) says what each phase changed, and `.agent-docs/deferred.md` what is set aside.
|
|
8
8
|
|
|
9
9
|
## Exports
|
|
10
10
|
|
|
@@ -12,18 +12,18 @@ The [language RFC](../../docs/language-v2/rfc.md) plans its next changes. It evo
|
|
|
12
12
|
| ---------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
13
13
|
| `parseJigs` | Source to a document tree. Tolerates a prefix cut off mid-stream |
|
|
14
14
|
| `compileJigs` | Checks a document against a catalog and generates its program |
|
|
15
|
-
| `compileLibrary` | Compiles
|
|
16
|
-
| `
|
|
15
|
+
| `compileLibrary` | Compiles jigs into a library a document can use |
|
|
16
|
+
| `jigSignature` | A jig's props and slot, as the prompt lists them |
|
|
17
17
|
| `isEditReply`, `parseEdits`, `applyEdits`, `SEARCH_MARKER` | Recognise and apply a reply made of SEARCH/REPLACE edits |
|
|
18
18
|
| `CompileCatalog`, `ComponentSpec`, `PropSpec` | What the compiler checks against |
|
|
19
19
|
|
|
20
20
|
## Source
|
|
21
21
|
|
|
22
22
|
- `src/parse.ts`, `src/ast.ts`: the parser and its tree.
|
|
23
|
-
- `src/compile.ts`: checking,
|
|
23
|
+
- `src/compile.ts`: checking, jig libraries and diagnostics.
|
|
24
24
|
- `src/script.ts`, `src/check-code.ts`: embedded code read with acorn, and the checks on it.
|
|
25
25
|
- `src/suggest.ts`: the nearest name, for "did you mean".
|
|
26
26
|
- `src/codegen.ts`: the JavaScript the sandbox runs.
|
|
27
27
|
- `src/patch.ts`: SEARCH/REPLACE edits.
|
|
28
|
-
- `src/spec.ts`, `src/signature.ts`: catalog specs and
|
|
28
|
+
- `src/spec.ts`, `src/signature.ts`: catalog specs and jig signatures.
|
|
29
29
|
- `src/test-catalog.ts`: the catalog the tests run against.
|
package/dist/compile.d.ts
CHANGED
|
@@ -110,7 +110,7 @@ export interface CompiledDefine {
|
|
|
110
110
|
name: string;
|
|
111
111
|
origin: "doc" | "library";
|
|
112
112
|
/**
|
|
113
|
-
* The procedure calls in a library
|
|
113
|
+
* The procedure calls in a library jig's source, by its lines. Empty
|
|
114
114
|
* for a document's own define: those are on the document's result.
|
|
115
115
|
*/
|
|
116
116
|
procedures: ReadonlyArray<ProcedureUse>;
|
|
@@ -130,28 +130,28 @@ export interface Program {
|
|
|
130
130
|
tree: Array<RenderNode>;
|
|
131
131
|
}
|
|
132
132
|
/** A reusable component written in Jigs: source with exactly one `<define>`. */
|
|
133
|
-
export interface
|
|
133
|
+
export interface Jig {
|
|
134
134
|
name: string;
|
|
135
135
|
source: string;
|
|
136
136
|
}
|
|
137
|
-
/**
|
|
137
|
+
/** Jigs compiled against one catalog, ready to use in documents. */
|
|
138
138
|
export type Library = ReadonlyMap<string, CompiledDefine>;
|
|
139
139
|
export interface CompileOptions {
|
|
140
140
|
/** The components a document may use. */
|
|
141
141
|
catalog: CompileCatalog;
|
|
142
|
-
/**
|
|
142
|
+
/** Jigs in scope, from `compileLibrary` with the same catalog. */
|
|
143
143
|
library?: Library;
|
|
144
144
|
}
|
|
145
145
|
export interface CompileResult {
|
|
146
146
|
defines: ReadonlyArray<CompiledDefine>;
|
|
147
147
|
diagnostics: Array<Diagnostic$1>;
|
|
148
|
-
/** The
|
|
148
|
+
/** The jigs this document was compiled against. */
|
|
149
149
|
library: ReadonlyMap<string, CompiledDefine>;
|
|
150
150
|
output: ProgramOutput;
|
|
151
151
|
/**
|
|
152
152
|
* Every `useQuery`, `useMutation` and `useAction` call in the parsed
|
|
153
153
|
* code of the document and its defines, in line order: nothing in
|
|
154
|
-
* prose or in string literals.
|
|
154
|
+
* prose or in string literals. Library jigs' calls are on the library's
|
|
155
155
|
* defines.
|
|
156
156
|
*/
|
|
157
157
|
procedures: ReadonlyArray<ProcedureUse>;
|
|
@@ -165,11 +165,11 @@ export interface CompileResult {
|
|
|
165
165
|
source: string;
|
|
166
166
|
}
|
|
167
167
|
/**
|
|
168
|
-
* Compiles `
|
|
169
|
-
* before it. Throws when a
|
|
170
|
-
*
|
|
168
|
+
* Compiles `jigs` against `catalog`, in order: a jig may use the ones
|
|
169
|
+
* before it. Throws when a jig has any diagnostic. Cached per catalog and
|
|
170
|
+
* jig list.
|
|
171
171
|
*/
|
|
172
|
-
export declare function compileLibrary(
|
|
172
|
+
export declare function compileLibrary(jigs: ReadonlyArray<Jig>, catalog: CompileCatalog): Library;
|
|
173
173
|
/**
|
|
174
174
|
* Compiles a document. An error that carries a fix is applied rather than
|
|
175
175
|
* sent to the model: the fixed source is compiled again, and when it has
|
package/dist/compile.js
CHANGED
|
@@ -58,7 +58,7 @@ function hookMisuse(code, kind, block) {
|
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
60
60
|
const NO_LIBRARY = /* @__PURE__ */ new Map();
|
|
61
|
-
/** Libraries by catalog, then by
|
|
61
|
+
/** Libraries by catalog, then by jig list. */
|
|
62
62
|
const libraryCache = /* @__PURE__ */ new WeakMap();
|
|
63
63
|
function propSpec(spec, name) {
|
|
64
64
|
const props = spec.props;
|
|
@@ -738,7 +738,7 @@ function emittedDefines(tree, docDefines, available) {
|
|
|
738
738
|
}
|
|
739
739
|
/**
|
|
740
740
|
* Static call sites in the document tree and in document-local define bodies.
|
|
741
|
-
* A tag inside a library
|
|
741
|
+
* A tag inside a library jig is not counted again.
|
|
742
742
|
*/
|
|
743
743
|
function countUses(tree, docDefines) {
|
|
744
744
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -865,14 +865,14 @@ function compileDocument(source, library, components) {
|
|
|
865
865
|
}
|
|
866
866
|
function buildLibrary(list, components) {
|
|
867
867
|
const built = /* @__PURE__ */ new Map();
|
|
868
|
-
for (const
|
|
869
|
-
if (built.has(
|
|
870
|
-
const result = compileDocument(
|
|
868
|
+
for (const jig of list) {
|
|
869
|
+
if (built.has(jig.name)) throw new Error(`Jig name "${jig.name}" is duplicated`);
|
|
870
|
+
const result = compileDocument(jig.source, built, components);
|
|
871
871
|
const problem = result.findings[0];
|
|
872
|
-
if (problem !== void 0) throw new Error(`
|
|
872
|
+
if (problem !== void 0) throw new Error(`Jig "${jig.name}" failed to compile: line ${problem.line}: ${problem.message}`);
|
|
873
873
|
const def = result.defines[0];
|
|
874
|
-
if (result.defines.length !== 1 || def === void 0) throw new Error(`
|
|
875
|
-
if (def.name !==
|
|
874
|
+
if (result.defines.length !== 1 || def === void 0) throw new Error(`Jig "${jig.name}" must contain exactly one <define>`);
|
|
875
|
+
if (def.name !== jig.name) throw new Error(`Jig "${jig.name}" defines <${def.name}> instead`);
|
|
876
876
|
built.set(def.name, {
|
|
877
877
|
...def,
|
|
878
878
|
origin: "library",
|
|
@@ -882,17 +882,17 @@ function buildLibrary(list, components) {
|
|
|
882
882
|
return built;
|
|
883
883
|
}
|
|
884
884
|
/**
|
|
885
|
-
* Compiles `
|
|
886
|
-
* before it. Throws when a
|
|
887
|
-
*
|
|
885
|
+
* Compiles `jigs` against `catalog`, in order: a jig may use the ones
|
|
886
|
+
* before it. Throws when a jig has any diagnostic. Cached per catalog and
|
|
887
|
+
* jig list.
|
|
888
888
|
*/
|
|
889
|
-
function compileLibrary(
|
|
890
|
-
const
|
|
891
|
-
libraryCache.set(catalog,
|
|
892
|
-
const existing =
|
|
889
|
+
function compileLibrary(jigs, catalog) {
|
|
890
|
+
const byJigs = libraryCache.get(catalog) ?? /* @__PURE__ */ new WeakMap();
|
|
891
|
+
libraryCache.set(catalog, byJigs);
|
|
892
|
+
const existing = byJigs.get(jigs);
|
|
893
893
|
if (existing !== void 0) return existing;
|
|
894
|
-
const built = buildLibrary(
|
|
895
|
-
|
|
894
|
+
const built = buildLibrary(jigs, catalog);
|
|
895
|
+
byJigs.set(jigs, built);
|
|
896
896
|
return built;
|
|
897
897
|
}
|
|
898
898
|
/** `source` with the fixes' edits applied. */
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { columnAt, lineAt, rangeIn, spanIn } from "./offsets.js";
|
|
|
2
2
|
import { JigsNode, Statement } from "./ast.js";
|
|
3
3
|
import { CompileCatalog, ComponentSpec, PropSpec } from "./spec.js";
|
|
4
4
|
import { ProgramOutput } from "./codegen.js";
|
|
5
|
-
import { CompileOptions, CompileResult, CompiledDefine, Diagnostic, Library, Program,
|
|
5
|
+
import { CompileOptions, CompileResult, CompiledDefine, Diagnostic, Jig, Library, Program, RenderNode, compileJigs, compileLibrary } from "./compile.js";
|
|
6
6
|
import { DataRead, ELEMENT, ProcedureUse } from "./check-code.js";
|
|
7
7
|
import { Hoisted, hoistDeclarations } from "./hoist.js";
|
|
8
8
|
import { parseJigs } from "./parse.js";
|
|
9
9
|
import { nearest } from "./suggest.js";
|
|
10
|
-
import {
|
|
10
|
+
import { jigSignature } from "./signature.js";
|
|
11
11
|
import { Edit, EditFailure, EditFailureReason, SEARCH_MARKER, applyEdits, editBreakage, isEditReply, parseEdits } from "./patch.js";
|
|
12
|
-
export { type CompileCatalog, type CompileOptions, type CompileResult, type CompiledDefine, type ComponentSpec, type DataRead, type Diagnostic, ELEMENT, type Edit, type EditFailure, type EditFailureReason, type Hoisted, type JigsNode, type Library, type ProcedureUse, type Program, type ProgramOutput, type PropSpec, type
|
|
12
|
+
export { type CompileCatalog, type CompileOptions, type CompileResult, type CompiledDefine, type ComponentSpec, type DataRead, type Diagnostic, ELEMENT, type Edit, type EditFailure, type EditFailureReason, type Hoisted, type Jig, type JigsNode, type Library, type ProcedureUse, type Program, type ProgramOutput, type PropSpec, type RenderNode, SEARCH_MARKER, type Statement, applyEdits, columnAt, compileJigs, compileLibrary, editBreakage, hoistDeclarations, isEditReply, jigSignature, lineAt, nearest, parseEdits, parseJigs, rangeIn, spanIn };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,6 @@ import { ELEMENT } from "./check-code.js";
|
|
|
4
4
|
import { parseJigs } from "./parse.js";
|
|
5
5
|
import { hoistDeclarations } from "./hoist.js";
|
|
6
6
|
import { compileJigs, compileLibrary } from "./compile.js";
|
|
7
|
-
import {
|
|
7
|
+
import { jigSignature } from "./signature.js";
|
|
8
8
|
import { SEARCH_MARKER, applyEdits, editBreakage, isEditReply, parseEdits } from "./patch.js";
|
|
9
|
-
export { ELEMENT, SEARCH_MARKER, applyEdits, columnAt, compileJigs, compileLibrary, editBreakage, hoistDeclarations, isEditReply, lineAt, nearest, parseEdits, parseJigs, rangeIn,
|
|
9
|
+
export { ELEMENT, SEARCH_MARKER, applyEdits, columnAt, compileJigs, compileLibrary, editBreakage, hoistDeclarations, isEditReply, jigSignature, lineAt, nearest, parseEdits, parseJigs, rangeIn, spanIn };
|
package/dist/patch.d.ts
CHANGED
|
@@ -13,11 +13,13 @@ export declare function isEditReply(text: string): boolean | null;
|
|
|
13
13
|
export declare function parseEdits(text: string): Array<Edit>;
|
|
14
14
|
/**
|
|
15
15
|
* Why an edit was rejected. `missing`: its SEARCH is not in the document.
|
|
16
|
-
* `ambiguous`: its SEARCH is there more than once. `
|
|
17
|
-
*
|
|
18
|
-
* the
|
|
16
|
+
* `ambiguous`: its SEARCH is there more than once. `overlapping`: its SEARCH
|
|
17
|
+
* spans lines an earlier edit of the same reply also changes. `malformed`:
|
|
18
|
+
* the block itself is broken. `broken`: it applied, but the result needs
|
|
19
|
+
* parser repairs the document did not (see `editBreakage`); the server
|
|
20
|
+
* reports this one.
|
|
19
21
|
*/
|
|
20
|
-
export type EditFailureReason = "ambiguous" | "broken" | "malformed" | "missing";
|
|
22
|
+
export type EditFailureReason = "ambiguous" | "broken" | "malformed" | "missing" | "overlapping";
|
|
21
23
|
export interface EditFailure {
|
|
22
24
|
/** For `broken`: the repairs the edited document needs and the base did not. */
|
|
23
25
|
breakage?: ReadonlyArray<{
|
|
@@ -25,8 +27,13 @@ export interface EditFailure {
|
|
|
25
27
|
message: string;
|
|
26
28
|
}>;
|
|
27
29
|
failed: Edit;
|
|
28
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* For `ambiguous`: the line each match starts on. For `overlapping`: the
|
|
32
|
+
* line the earlier edit's SEARCH starts on, then this one's.
|
|
33
|
+
*/
|
|
29
34
|
lines?: ReadonlyArray<number>;
|
|
35
|
+
/** For `overlapping`: the earlier edit whose lines this one also changes. */
|
|
36
|
+
overlaps?: Edit;
|
|
30
37
|
reason: EditFailureReason;
|
|
31
38
|
}
|
|
32
39
|
export type ApplyResult = (EditFailure & {
|
|
@@ -36,10 +43,15 @@ export type ApplyResult = (EditFailure & {
|
|
|
36
43
|
text: string;
|
|
37
44
|
};
|
|
38
45
|
/**
|
|
39
|
-
* Applies
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
46
|
+
* Applies a reply's edits to the document it was written against. Every
|
|
47
|
+
* SEARCH is located in that document first, exactly or ignoring
|
|
48
|
+
* indentation, and must be there once; the replacements are then made from
|
|
49
|
+
* the end, so one edit's REPLACE never moves or breaks another's anchor. An
|
|
50
|
+
* empty SEARCH appends. A SEARCH that is not in the document, or that spans
|
|
51
|
+
* lines an earlier edit's SEARCH spans, applies to the text as the edits
|
|
52
|
+
* before it leave it when it is there once, as edits written one after
|
|
53
|
+
* another; the edits after it anchor to that text. Otherwise it fails as
|
|
54
|
+
* `missing` or `overlapping`. Stops at the first edit that fails.
|
|
43
55
|
*/
|
|
44
56
|
export declare function applyEdits(base: string, edits: ReadonlyArray<Edit>): ApplyResult;
|
|
45
57
|
/**
|
package/dist/patch.js
CHANGED
|
@@ -40,18 +40,39 @@ function parseEdits(text) {
|
|
|
40
40
|
}
|
|
41
41
|
return edits;
|
|
42
42
|
}
|
|
43
|
-
/**
|
|
44
|
-
function findLoose(
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
/** Every line range of `text` matching `search` when leading and trailing whitespace is ignored. */
|
|
44
|
+
function findLoose(text, search) {
|
|
45
|
+
const lines = text.split("\n");
|
|
46
|
+
const target = search.split("\n").map((line) => line.trim());
|
|
47
|
+
const offsets = [];
|
|
48
|
+
let offset = 0;
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
offsets.push(offset);
|
|
51
|
+
offset += line.length + 1;
|
|
52
|
+
}
|
|
53
|
+
const ranges = [];
|
|
54
|
+
for (let start = 0; start + target.length <= lines.length; start++) {
|
|
55
|
+
const last = start + target.length - 1;
|
|
56
|
+
if (target.every((line, index) => lines[start + index]?.trim() === line)) ranges.push({
|
|
57
|
+
end: (offsets[last] ?? 0) + (lines[last]?.length ?? 0),
|
|
58
|
+
start: offsets[start] ?? 0
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return ranges;
|
|
49
62
|
}
|
|
50
|
-
/** Every
|
|
63
|
+
/** Every range at which `search` occurs in `text`, without overlaps. */
|
|
51
64
|
function findExact(text, search) {
|
|
52
|
-
const
|
|
53
|
-
for (let index = text.indexOf(search); index !== -1; index = text.indexOf(search, index + search.length))
|
|
54
|
-
|
|
65
|
+
const ranges = [];
|
|
66
|
+
for (let index = text.indexOf(search); index !== -1; index = text.indexOf(search, index + search.length)) ranges.push({
|
|
67
|
+
end: index + search.length,
|
|
68
|
+
start: index
|
|
69
|
+
});
|
|
70
|
+
return ranges;
|
|
71
|
+
}
|
|
72
|
+
/** Where `search` is in `text`: exactly if it is there, else ignoring indentation. */
|
|
73
|
+
function locate(text, search) {
|
|
74
|
+
const exact = findExact(text, search);
|
|
75
|
+
return exact.length > 0 ? exact : findLoose(text, search);
|
|
55
76
|
}
|
|
56
77
|
const lineAt = (text, index) => text.slice(0, index).split("\n").length;
|
|
57
78
|
const MARKERS = /* @__PURE__ */ new Set([
|
|
@@ -61,13 +82,31 @@ const MARKERS = /* @__PURE__ */ new Set([
|
|
|
61
82
|
]);
|
|
62
83
|
const hasMarker = (text) => text.split("\n").some((line) => MARKERS.has(line.trim()));
|
|
63
84
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
* `text` with the anchored replacements made from the end, so none moves
|
|
86
|
+
* another's range, then the appends in order.
|
|
87
|
+
*/
|
|
88
|
+
function applyAnchored(text, anchored, appended) {
|
|
89
|
+
let result = text;
|
|
90
|
+
const fromEnd = anchored.toSorted((a, b) => b.range.start - a.range.start);
|
|
91
|
+
for (const place of fromEnd) result = result.slice(0, place.range.start) + place.edit.replace + result.slice(place.range.end);
|
|
92
|
+
for (const replace of appended) result = `${result.trimEnd()}\n${replace}`;
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Applies a reply's edits to the document it was written against. Every
|
|
97
|
+
* SEARCH is located in that document first, exactly or ignoring
|
|
98
|
+
* indentation, and must be there once; the replacements are then made from
|
|
99
|
+
* the end, so one edit's REPLACE never moves or breaks another's anchor. An
|
|
100
|
+
* empty SEARCH appends. A SEARCH that is not in the document, or that spans
|
|
101
|
+
* lines an earlier edit's SEARCH spans, applies to the text as the edits
|
|
102
|
+
* before it leave it when it is there once, as edits written one after
|
|
103
|
+
* another; the edits after it anchor to that text. Otherwise it fails as
|
|
104
|
+
* `missing` or `overlapping`. Stops at the first edit that fails.
|
|
68
105
|
*/
|
|
69
106
|
function applyEdits(base, edits) {
|
|
70
107
|
let text = base;
|
|
108
|
+
let anchored = [];
|
|
109
|
+
let appended = [];
|
|
71
110
|
for (const edit of edits) {
|
|
72
111
|
if (hasMarker(edit.replace)) return {
|
|
73
112
|
failed: edit,
|
|
@@ -75,42 +114,49 @@ function applyEdits(base, edits) {
|
|
|
75
114
|
reason: "malformed"
|
|
76
115
|
};
|
|
77
116
|
if (edit.search.trim() === "") {
|
|
78
|
-
|
|
117
|
+
appended.push(edit.replace);
|
|
79
118
|
continue;
|
|
80
119
|
}
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
120
|
+
const ranges = locate(text, edit.search);
|
|
121
|
+
if (ranges.length > 1) return {
|
|
83
122
|
failed: edit,
|
|
84
|
-
lines:
|
|
123
|
+
lines: ranges.map((range) => lineAt(text, range.start)),
|
|
85
124
|
ok: false,
|
|
86
125
|
reason: "ambiguous"
|
|
87
126
|
};
|
|
88
|
-
const [
|
|
89
|
-
|
|
90
|
-
|
|
127
|
+
const [range] = ranges;
|
|
128
|
+
const overlap = range === void 0 ? void 0 : anchored.find((other) => range.start < other.range.end && other.range.start < range.end);
|
|
129
|
+
if (range !== void 0 && overlap === void 0) {
|
|
130
|
+
anchored.push({
|
|
131
|
+
edit,
|
|
132
|
+
range
|
|
133
|
+
});
|
|
91
134
|
continue;
|
|
92
135
|
}
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
136
|
+
const edited = applyAnchored(text, anchored, appended);
|
|
137
|
+
const later = locate(edited, edit.search);
|
|
138
|
+
const [found] = later;
|
|
139
|
+
if (found === void 0 || later.length > 1) return range === void 0 || overlap === void 0 ? {
|
|
97
140
|
failed: edit,
|
|
98
|
-
lines: starts.map((start) => start + 1),
|
|
99
141
|
ok: false,
|
|
100
|
-
reason: "
|
|
101
|
-
}
|
|
102
|
-
const [start] = starts;
|
|
103
|
-
if (start === void 0) return {
|
|
142
|
+
reason: "missing"
|
|
143
|
+
} : {
|
|
104
144
|
failed: edit,
|
|
145
|
+
lines: [lineAt(text, overlap.range.start), lineAt(text, range.start)],
|
|
105
146
|
ok: false,
|
|
106
|
-
|
|
147
|
+
overlaps: overlap.edit,
|
|
148
|
+
reason: "overlapping"
|
|
107
149
|
};
|
|
108
|
-
|
|
109
|
-
|
|
150
|
+
text = edited;
|
|
151
|
+
anchored = [{
|
|
152
|
+
edit,
|
|
153
|
+
range: found
|
|
154
|
+
}];
|
|
155
|
+
appended = [];
|
|
110
156
|
}
|
|
111
157
|
return {
|
|
112
158
|
ok: true,
|
|
113
|
-
text
|
|
159
|
+
text: applyAnchored(text, anchored, appended)
|
|
114
160
|
};
|
|
115
161
|
}
|
|
116
162
|
/** Diagnostic codes the parser reports when it changed the source to make it parse. */
|
package/dist/signature.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Jig } from "./compile.js";
|
|
2
2
|
//#region src/signature.d.ts
|
|
3
3
|
/** `<statCard label value delta={0} note="">…</statCard>` when the define has a slot. */
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function jigSignature(jig: Jig): string;
|
|
5
5
|
//#endregion
|
package/dist/signature.js
CHANGED
|
@@ -14,12 +14,12 @@ function hasSlot(nodes) {
|
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
/** `<statCard label value delta={0} note="">…</statCard>` when the define has a slot. */
|
|
17
|
-
function
|
|
18
|
-
const define = parseJigs(
|
|
19
|
-
if (define === void 0) return `<${
|
|
17
|
+
function jigSignature(jig) {
|
|
18
|
+
const define = parseJigs(jig.source).children.find((node) => node.type === "element" && node.name === "define");
|
|
19
|
+
if (define === void 0) return `<${jig.name}>`;
|
|
20
20
|
const attrs = define.props.filter((prop) => prop.name !== "name").map((prop) => formatAttr(prop));
|
|
21
|
-
const open = attrs.length === 0 ? `<${
|
|
22
|
-
return hasSlot(define.children) ? `${open}…</${
|
|
21
|
+
const open = attrs.length === 0 ? `<${jig.name}>` : `<${jig.name} ${attrs.join(" ")}>`;
|
|
22
|
+
return hasSlot(define.children) ? `${open}…</${jig.name}>` : open;
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
|
-
export {
|
|
25
|
+
export { jigSignature };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jigs.design/compiler",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Today's Jigs compiler: parser, checker against a catalog, code generator,
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Today's Jigs compiler: parser, checker against a catalog, code generator, jig libraries, and the edit helpers. The v2 rewrite replaces it.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"acorn": "8.19.0",
|
|
29
|
-
"@jigs.design/protocol": "0.
|
|
29
|
+
"@jigs.design/protocol": "0.3.1"
|
|
30
30
|
}
|
|
31
31
|
}
|