@jigs.design/compiler 0.3.4 → 0.3.6

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/dist/compile.d.ts CHANGED
@@ -116,6 +116,12 @@ export interface CompiledDefine {
116
116
  procedures: ReadonlyArray<ProcedureUse>;
117
117
  props: Array<DefineProp>;
118
118
  statements: Array<Statement>;
119
+ /**
120
+ * The tags a library jig's body draws: components and the jigs it
121
+ * calls. Empty for a document's own define: those are on the
122
+ * document's result.
123
+ */
124
+ tags: ReadonlySet<string>;
119
125
  }
120
126
  /** One component the document actually renders, and how often it is written. */
121
127
  interface DefineUse {
@@ -168,7 +174,36 @@ export interface CompileResult {
168
174
  * source with the fixes applied. It names every tag the program draws.
169
175
  */
170
176
  source: string;
177
+ /**
178
+ * The tags the program draws, from its tree and its own defines'
179
+ * bodies, fixes included: each component and each jig it calls, not
180
+ * the tags those jigs draw (on the library's defines). Nothing in prose
181
+ * or in string literals counts.
182
+ */
183
+ tags: ReadonlySet<string>;
171
184
  }
185
+ /** The language's own tags: no component or define may take these names. */
186
+ export declare const RESERVED_TAGS: ReadonlySet<string>;
187
+ /** What `extendLibrary` built, and what it found in each jig. */
188
+ export interface ExtendedLibrary {
189
+ /**
190
+ * Each jig's diagnostics, by name, numbered by its own source. A name
191
+ * here but not in `library` was dropped.
192
+ */
193
+ diagnostics: ReadonlyMap<string, ReadonlyArray<Diagnostic$1>>;
194
+ /** `base`, then each jig that entered, in order. */
195
+ library: Library;
196
+ }
197
+ /**
198
+ * `base` extended by `jigs`, in order, leniently: a jig may use `base`
199
+ * and the jigs before it. Never throws. A jig enters when its source has
200
+ * exactly one `<define>`, of its name, whose name is not already in the
201
+ * library, and none of its findings leave code that cannot run (an
202
+ * `undefined_reference`, an `invalid_statement`, an `unclosed` tag). A
203
+ * jig with other findings, such as an unknown component or prop, enters
204
+ * with what still compiles, and its diagnostics say what was removed.
205
+ */
206
+ export declare function extendLibrary(base: Library, jigs: ReadonlyArray<Jig>, catalog: CompileCatalog): ExtendedLibrary;
172
207
  /**
173
208
  * Compiles `jigs` against `catalog`, in order: a jig may use the ones
174
209
  * before it. Throws when a jig has any diagnostic. Cached per catalog and
package/dist/compile.js CHANGED
@@ -7,6 +7,7 @@ import { parseJigs } from "./parse.js";
7
7
  import { isValidValue } from "./spec.js";
8
8
  import { blockHoists } from "./block-hoist.js";
9
9
  //#region src/compile.ts
10
+ /** The language's own tags: no component or define may take these names. */
10
11
  const RESERVED_TAGS = /* @__PURE__ */ new Set([
11
12
  "define",
12
13
  "each",
@@ -196,7 +197,8 @@ function readDefine(node, findings, libraryNames, components) {
196
197
  origin: "doc",
197
198
  procedures: [],
198
199
  props,
199
- statements: []
200
+ statements: [],
201
+ tags: /* @__PURE__ */ new Set()
200
202
  };
201
203
  }
202
204
  function lookupHint(name, candidates) {
@@ -707,6 +709,14 @@ function describeNumber(spec) {
707
709
  if (spec.kind === "number" && spec.min !== void 0 && spec.max !== void 0) return `a number from ${spec.min} to ${spec.max}`;
708
710
  return `a ${spec.kind} value`;
709
711
  }
712
+ /** Each component `nodes` draw and each jig they call, by name, added to `into`. */
713
+ function collectTags(nodes, into) {
714
+ for (const node of nodes) {
715
+ if (node.type === "element") into.add(node.component);
716
+ else if (node.type === "call") into.add(node.name);
717
+ if (node.type === "call" || node.type === "each" || node.type === "element" || node.type === "if") collectTags(node.children, into);
718
+ }
719
+ }
710
720
  function visitRender(nodes, visit) {
711
721
  for (const node of nodes) if (node.type === "call") {
712
722
  visit(node);
@@ -848,6 +858,9 @@ function compileDocument(source, library, components) {
848
858
  findings.push(...generated.findings);
849
859
  for (const finding of findings) if (finding.start !== void 0) finding.line = lineAt(source, finding.start);
850
860
  findings.sort((a, b) => a.line - b.line);
861
+ const drawn = /* @__PURE__ */ new Set();
862
+ collectTags(tree, drawn);
863
+ for (const def of docDefines) collectTags(def.body, drawn);
851
864
  return {
852
865
  defines: docDefines,
853
866
  fields: uses.fields,
@@ -861,7 +874,8 @@ function compileDocument(source, library, components) {
861
874
  tree
862
875
  },
863
876
  reads: uses.reads,
864
- source
877
+ source,
878
+ tags: drawn
865
879
  };
866
880
  }
867
881
  function buildLibrary(list, components) {
@@ -877,11 +891,67 @@ function buildLibrary(list, components) {
877
891
  built.set(def.name, {
878
892
  ...def,
879
893
  origin: "library",
880
- procedures: result.procedures
894
+ procedures: result.procedures,
895
+ tags: result.tags
881
896
  });
882
897
  }
883
898
  return built;
884
899
  }
900
+ /** Findings that leave a define whose code cannot run: it is dropped. */
901
+ const UNRUNNABLE = /* @__PURE__ */ new Set([
902
+ "invalid_statement",
903
+ "unclosed",
904
+ "undefined_reference"
905
+ ]);
906
+ /**
907
+ * `base` extended by `jigs`, in order, leniently: a jig may use `base`
908
+ * and the jigs before it. Never throws. A jig enters when its source has
909
+ * exactly one `<define>`, of its name, whose name is not already in the
910
+ * library, and none of its findings leave code that cannot run (an
911
+ * `undefined_reference`, an `invalid_statement`, an `unclosed` tag). A
912
+ * jig with other findings, such as an unknown component or prop, enters
913
+ * with what still compiles, and its diagnostics say what was removed.
914
+ */
915
+ function extendLibrary(base, jigs, catalog) {
916
+ const built = new Map(base);
917
+ const diagnostics = /* @__PURE__ */ new Map();
918
+ const seen = /* @__PURE__ */ new Set();
919
+ const refuse = (jig, found, message) => {
920
+ diagnostics.set(jig.name, [...found, {
921
+ code: "invalid_define",
922
+ message,
923
+ severity: "error",
924
+ span: { line: 1 }
925
+ }]);
926
+ };
927
+ for (const jig of jigs) {
928
+ if (seen.has(jig.name)) continue;
929
+ seen.add(jig.name);
930
+ if (built.has(jig.name)) {
931
+ refuse(jig, [], `<${jig.name}> is already in the library; this one was dropped`);
932
+ continue;
933
+ }
934
+ const result = compileDocument(jig.source, built, catalog);
935
+ const found = result.findings.map((finding) => toDiagnostic(jig.source, finding));
936
+ const def = result.defines[0];
937
+ if (result.defines.length !== 1 || def?.name !== jig.name) {
938
+ refuse(jig, found, `The source must be one <define name="${jig.name}">; it was dropped`);
939
+ continue;
940
+ }
941
+ diagnostics.set(jig.name, found);
942
+ if (result.findings.some((finding) => finding.severity === "error" && UNRUNNABLE.has(finding.code))) continue;
943
+ built.set(def.name, {
944
+ ...def,
945
+ origin: "library",
946
+ procedures: result.procedures,
947
+ tags: result.tags
948
+ });
949
+ }
950
+ return {
951
+ diagnostics,
952
+ library: built
953
+ };
954
+ }
885
955
  /**
886
956
  * Compiles `jigs` against `catalog`, in order: a jig may use the ones
887
957
  * before it. Throws when a jig has any diagnostic. Cached per catalog and
@@ -969,4 +1039,4 @@ function compileJigs(source, options) {
969
1039
  } : finding));
970
1040
  }
971
1041
  //#endregion
972
- export { compileJigs, compileLibrary };
1042
+ export { RESERVED_TAGS, compileJigs, compileLibrary, extendLibrary };
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, Jig, Library, Program, RenderNode, compileJigs, compileLibrary } from "./compile.js";
5
+ import { CompileOptions, CompileResult, CompiledDefine, Diagnostic, ExtendedLibrary, Jig, Library, Program, RESERVED_TAGS, RenderNode, compileJigs, compileLibrary, extendLibrary } from "./compile.js";
6
6
  import { DataFields, 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
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 DataFields, 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 };
12
+ export { type CompileCatalog, type CompileOptions, type CompileResult, type CompiledDefine, type ComponentSpec, type DataFields, type DataRead, type Diagnostic, ELEMENT, type Edit, type EditFailure, type EditFailureReason, type ExtendedLibrary, type Hoisted, type Jig, type JigsNode, type Library, type ProcedureUse, type Program, type ProgramOutput, type PropSpec, RESERVED_TAGS, type RenderNode, SEARCH_MARKER, type Statement, applyEdits, columnAt, compileJigs, compileLibrary, editBreakage, extendLibrary, hoistDeclarations, isEditReply, jigSignature, lineAt, nearest, parseEdits, parseJigs, rangeIn, spanIn };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { nearest } from "./suggest.js";
3
3
  import { ELEMENT } from "./check-code.js";
4
4
  import { parseJigs } from "./parse.js";
5
5
  import { hoistDeclarations } from "./hoist.js";
6
- import { compileJigs, compileLibrary } from "./compile.js";
6
+ import { RESERVED_TAGS, compileJigs, compileLibrary, extendLibrary } from "./compile.js";
7
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, jigSignature, lineAt, nearest, parseEdits, parseJigs, rangeIn, spanIn };
9
+ export { ELEMENT, RESERVED_TAGS, SEARCH_MARKER, applyEdits, columnAt, compileJigs, compileLibrary, editBreakage, extendLibrary, hoistDeclarations, isEditReply, jigSignature, lineAt, nearest, parseEdits, parseJigs, rangeIn, spanIn };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jigs.design/compiler",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "The Jigs compiler: parser, checker against a catalog, code generator, jig libraries, and the edit helpers. It evolves in place, behind the server API.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,6 +26,6 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "acorn": "8.19.0",
29
- "@jigs.design/protocol": "0.3.4"
29
+ "@jigs.design/protocol": "0.3.6"
30
30
  }
31
31
  }