@formspec/build 0.1.0-alpha.41 → 0.1.0-alpha.43

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/cli.cjs CHANGED
@@ -1622,12 +1622,25 @@ function applyCustomConstraint(schema, constraint, ctx) {
1622
1622
  `Cannot generate JSON Schema for custom constraint "${constraint.constraintId}" without a matching extension registration`
1623
1623
  );
1624
1624
  }
1625
- assignVendorPrefixedExtensionKeywords(
1626
- schema,
1627
- registration.toJsonSchema(constraint.payload, ctx.vendorPrefix),
1628
- ctx.vendorPrefix,
1629
- `custom constraint "${constraint.constraintId}"`
1630
- );
1625
+ const extensionSchema = registration.toJsonSchema(constraint.payload, ctx.vendorPrefix);
1626
+ if (registration.emitsVocabularyKeywords) {
1627
+ const target = schema;
1628
+ for (const [key, value] of Object.entries(extensionSchema)) {
1629
+ if (JSON_SCHEMA_STRUCTURAL_KEYWORDS.has(key)) {
1630
+ throw new Error(
1631
+ `Custom constraint "${constraint.constraintId}" with emitsVocabularyKeywords must not overwrite standard JSON Schema keyword "${key}"`
1632
+ );
1633
+ }
1634
+ target[key] = value;
1635
+ }
1636
+ } else {
1637
+ assignVendorPrefixedExtensionKeywords(
1638
+ schema,
1639
+ extensionSchema,
1640
+ ctx.vendorPrefix,
1641
+ `custom constraint "${constraint.constraintId}"`
1642
+ );
1643
+ }
1631
1644
  }
1632
1645
  function applyCustomAnnotation(schema, annotation, ctx) {
1633
1646
  const registration = ctx.extensionRegistry?.findAnnotation(annotation.annotationId);
@@ -1656,11 +1669,72 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
1656
1669
  schema[key] = value;
1657
1670
  }
1658
1671
  }
1672
+ var JSON_SCHEMA_STRUCTURAL_KEYWORDS;
1659
1673
  var init_ir_generator = __esm({
1660
1674
  "src/json-schema/ir-generator.ts"() {
1661
1675
  "use strict";
1662
1676
  init_metadata();
1663
1677
  init_collision_guards();
1678
+ JSON_SCHEMA_STRUCTURAL_KEYWORDS = /* @__PURE__ */ new Set([
1679
+ "$schema",
1680
+ "$ref",
1681
+ "$defs",
1682
+ "$id",
1683
+ "$anchor",
1684
+ "$dynamicRef",
1685
+ "$dynamicAnchor",
1686
+ "$vocabulary",
1687
+ "$comment",
1688
+ "type",
1689
+ "enum",
1690
+ "const",
1691
+ "properties",
1692
+ "patternProperties",
1693
+ "additionalProperties",
1694
+ "required",
1695
+ "items",
1696
+ "prefixItems",
1697
+ "additionalItems",
1698
+ "contains",
1699
+ "allOf",
1700
+ "oneOf",
1701
+ "anyOf",
1702
+ "not",
1703
+ "if",
1704
+ "then",
1705
+ "else",
1706
+ "minimum",
1707
+ "maximum",
1708
+ "exclusiveMinimum",
1709
+ "exclusiveMaximum",
1710
+ "multipleOf",
1711
+ "minLength",
1712
+ "maxLength",
1713
+ "pattern",
1714
+ "minItems",
1715
+ "maxItems",
1716
+ "uniqueItems",
1717
+ "minProperties",
1718
+ "maxProperties",
1719
+ "minContains",
1720
+ "maxContains",
1721
+ "format",
1722
+ "title",
1723
+ "description",
1724
+ "default",
1725
+ "deprecated",
1726
+ "readOnly",
1727
+ "writeOnly",
1728
+ "examples",
1729
+ "dependentRequired",
1730
+ "dependentSchemas",
1731
+ "propertyNames",
1732
+ "unevaluatedItems",
1733
+ "unevaluatedProperties",
1734
+ "contentEncoding",
1735
+ "contentMediaType",
1736
+ "contentSchema"
1737
+ ]);
1664
1738
  }
1665
1739
  });
1666
1740
 
@@ -2193,44 +2267,6 @@ var init_schema2 = __esm({
2193
2267
  });
2194
2268
 
2195
2269
  // src/analyzer/tsdoc-parser.ts
2196
- function createFormSpecTSDocConfig(extensionTagNames = []) {
2197
- const config = new import_tsdoc.TSDocConfiguration();
2198
- for (const tagName of Object.keys(import_internals4.BUILTIN_CONSTRAINT_DEFINITIONS)) {
2199
- config.addTagDefinition(
2200
- new import_tsdoc.TSDocTagDefinition({
2201
- tagName: "@" + tagName,
2202
- syntaxKind: import_tsdoc.TSDocTagSyntaxKind.BlockTag,
2203
- allowMultiple: true
2204
- })
2205
- );
2206
- }
2207
- for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
2208
- config.addTagDefinition(
2209
- new import_tsdoc.TSDocTagDefinition({
2210
- tagName: "@" + tagName,
2211
- syntaxKind: import_tsdoc.TSDocTagSyntaxKind.BlockTag,
2212
- allowMultiple: true
2213
- })
2214
- );
2215
- }
2216
- for (const tagName of extensionTagNames) {
2217
- config.addTagDefinition(
2218
- new import_tsdoc.TSDocTagDefinition({
2219
- tagName: "@" + tagName,
2220
- syntaxKind: import_tsdoc.TSDocTagSyntaxKind.BlockTag,
2221
- allowMultiple: true
2222
- })
2223
- );
2224
- }
2225
- return config;
2226
- }
2227
- function sharedCommentSyntaxOptions(options, offset) {
2228
- const extensions = options?.extensionRegistry?.extensions;
2229
- return {
2230
- ...offset !== void 0 ? { offset } : {},
2231
- ...extensions !== void 0 ? { extensions } : {}
2232
- };
2233
- }
2234
2270
  function sharedTagValueOptions(options) {
2235
2271
  return {
2236
2272
  ...options?.extensionRegistry !== void 0 ? { registry: options.extensionRegistry } : {},
@@ -2329,6 +2365,30 @@ function pushUniqueCompilerDiagnostics(target, additions) {
2329
2365
  target.push(diagnostic);
2330
2366
  }
2331
2367
  }
2368
+ function processConstraintTag(tagName, text, parsedTag, provenance, node, sourceFile, supportingDeclarations, options, constraints, diagnostics) {
2369
+ const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
2370
+ node,
2371
+ sourceFile,
2372
+ tagName,
2373
+ parsedTag,
2374
+ provenance,
2375
+ supportingDeclarations,
2376
+ options
2377
+ );
2378
+ if (compilerDiagnostics.length > 0) {
2379
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2380
+ return;
2381
+ }
2382
+ const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2383
+ tagName,
2384
+ text,
2385
+ provenance,
2386
+ sharedTagValueOptions(options)
2387
+ );
2388
+ if (constraintNode) {
2389
+ constraints.push(constraintNode);
2390
+ }
2391
+ }
2332
2392
  function renderSyntheticArgumentExpression(valueKind, argumentText) {
2333
2393
  const trimmed = argumentText.trim();
2334
2394
  if (trimmed === "") {
@@ -2614,8 +2674,8 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2614
2674
  )
2615
2675
  ];
2616
2676
  }
2617
- function getParser(options) {
2618
- const extensionTagNames = [
2677
+ function getExtensionTagNames(options) {
2678
+ return [
2619
2679
  ...options?.extensionRegistry?.extensions.flatMap(
2620
2680
  (extension) => (extension.constraintTags ?? []).map((tag) => (0, import_internal2.normalizeFormSpecTagName)(tag.tagName))
2621
2681
  ) ?? [],
@@ -2623,14 +2683,6 @@ function getParser(options) {
2623
2683
  (extension) => (extension.metadataSlots ?? []).map((slot) => (0, import_internal2.normalizeFormSpecTagName)(slot.tagName))
2624
2684
  ) ?? []
2625
2685
  ].sort();
2626
- const cacheKey = extensionTagNames.join("|");
2627
- const existing = parserCache.get(cacheKey);
2628
- if (existing) {
2629
- return existing;
2630
- }
2631
- const parser = new import_tsdoc.TSDocParser(createFormSpecTSDocConfig(extensionTagNames));
2632
- parserCache.set(cacheKey, parser);
2633
- return parser;
2634
2686
  }
2635
2687
  function getExtensionRegistryCacheKey(registry) {
2636
2688
  if (registry === void 0) {
@@ -2681,13 +2733,13 @@ function parseTSDocTags(node, file = "", options) {
2681
2733
  let placeholder;
2682
2734
  let displayNameProvenance;
2683
2735
  let placeholderProvenance;
2684
- const rawTextTags = [];
2685
2736
  const sourceFile = node.getSourceFile();
2686
2737
  const sourceText = sourceFile.getFullText();
2687
2738
  const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
2688
2739
  const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
2689
2740
  const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
2690
2741
  const rawTextFallbacks = collectRawTextFallbacks(node, file);
2742
+ const extensionTagNames = getExtensionTagNames(options);
2691
2743
  if (commentRanges) {
2692
2744
  for (const range of commentRanges) {
2693
2745
  if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
@@ -2697,38 +2749,18 @@ function parseTSDocTags(node, file = "", options) {
2697
2749
  if (!commentText.startsWith("/**")) {
2698
2750
  continue;
2699
2751
  }
2700
- const parser = getParser(options);
2701
- const parserContext = parser.parseRange(
2702
- import_tsdoc.TextRange.fromStringRange(sourceText, range.pos, range.end)
2703
- );
2704
- const docComment = parserContext.docComment;
2705
- const parsedComment = (0, import_internal2.parseCommentBlock)(
2706
- commentText,
2707
- sharedCommentSyntaxOptions(options, range.pos)
2708
- );
2709
- let parsedTagCursor = 0;
2710
- const nextParsedTag = (normalizedTagName) => {
2711
- while (parsedTagCursor < parsedComment.tags.length) {
2712
- const candidate = parsedComment.tags[parsedTagCursor];
2713
- parsedTagCursor += 1;
2714
- if (candidate?.normalizedTagName === normalizedTagName) {
2715
- return candidate;
2716
- }
2717
- }
2718
- return null;
2719
- };
2720
- for (const parsedTag of parsedComment.tags) {
2721
- if (TAGS_REQUIRING_RAW_TEXT.has(parsedTag.normalizedTagName)) {
2722
- rawTextTags.push({ tag: parsedTag, commentText, commentOffset: range.pos });
2723
- }
2724
- }
2725
- for (const block of docComment.customBlocks) {
2726
- const tagName = (0, import_internals4.normalizeConstraintTagName)(block.blockTag.tagName.substring(1));
2727
- const parsedTag = nextParsedTag(tagName);
2752
+ const extensions = options?.extensionRegistry?.extensions;
2753
+ const unified = (0, import_internal2.parseUnifiedComment)(commentText, {
2754
+ offset: range.pos,
2755
+ extensionTagNames,
2756
+ ...extensions !== void 0 ? { extensions } : {}
2757
+ });
2758
+ for (const tag of unified.tags) {
2759
+ const tagName = tag.normalizedTagName;
2728
2760
  if (tagName === "displayName" || tagName === "format" || tagName === "placeholder") {
2729
- const text2 = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
2761
+ const text2 = tag.resolvedPayloadText;
2730
2762
  if (text2 === "") continue;
2731
- const provenance2 = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
2763
+ const provenance2 = provenanceForParsedTag(tag, sourceFile, file);
2732
2764
  switch (tagName) {
2733
2765
  case "displayName":
2734
2766
  if (!isMemberTargetDisplayName(text2) && displayName === void 0) {
@@ -2753,64 +2785,69 @@ function parseTSDocTags(node, file = "", options) {
2753
2785
  }
2754
2786
  continue;
2755
2787
  }
2756
- if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2757
- const text = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
2758
- const expectedType = (0, import_internals4.isBuiltinConstraintName)(tagName) ? import_internals4.BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
2759
- if (text === "" && expectedType !== "boolean") continue;
2760
- const provenance = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
2761
- const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
2762
- node,
2763
- sourceFile,
2764
- tagName,
2765
- parsedTag,
2766
- provenance,
2767
- supportingDeclarations,
2768
- options
2769
- );
2770
- if (compilerDiagnostics.length > 0) {
2771
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2788
+ if (import_internal2.TAGS_REQUIRING_RAW_TEXT.has(tagName)) {
2789
+ const fallback = rawTextFallbacks.get(tagName)?.shift();
2790
+ const text2 = (0, import_internal2.choosePreferredPayloadText)(tag.resolvedPayloadText, fallback?.text ?? "");
2791
+ if (text2 === "") continue;
2792
+ const provenance2 = provenanceForParsedTag(tag, sourceFile, file);
2793
+ if (tagName === "defaultValue") {
2794
+ annotations.push((0, import_internal2.parseDefaultValueTagValue)(text2, provenance2));
2795
+ continue;
2796
+ }
2797
+ processConstraintTag(
2798
+ tagName,
2799
+ text2,
2800
+ tag,
2801
+ provenance2,
2802
+ node,
2803
+ sourceFile,
2804
+ supportingDeclarations,
2805
+ options,
2806
+ constraints,
2807
+ diagnostics
2808
+ );
2772
2809
  continue;
2773
2810
  }
2774
- const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2811
+ const text = tag.resolvedPayloadText;
2812
+ const expectedType = (0, import_internals4.isBuiltinConstraintName)(tagName) ? import_internals4.BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
2813
+ if (text === "" && expectedType !== "boolean") continue;
2814
+ const provenance = provenanceForParsedTag(tag, sourceFile, file);
2815
+ processConstraintTag(
2775
2816
  tagName,
2776
2817
  text,
2818
+ tag,
2777
2819
  provenance,
2778
- sharedTagValueOptions(options)
2820
+ node,
2821
+ sourceFile,
2822
+ supportingDeclarations,
2823
+ options,
2824
+ constraints,
2825
+ diagnostics
2779
2826
  );
2780
- if (constraintNode) {
2781
- constraints.push(constraintNode);
2782
- }
2783
2827
  }
2784
- if (docComment.deprecatedBlock !== void 0) {
2785
- const message = extractBlockText(docComment.deprecatedBlock).trim();
2828
+ if (unified.isDeprecated) {
2786
2829
  annotations.push({
2787
2830
  kind: "annotation",
2788
2831
  annotationKind: "deprecated",
2789
- ...message !== "" && { message },
2832
+ ...unified.deprecationMessage !== "" && { message: unified.deprecationMessage },
2790
2833
  provenance: provenanceForComment(range, sourceFile, file, "deprecated")
2791
2834
  });
2792
2835
  }
2793
- {
2794
- const summary = extractPlainText(docComment.summarySection).trim();
2795
- if (summary !== "") {
2796
- annotations.push({
2797
- kind: "annotation",
2798
- annotationKind: "description",
2799
- value: summary,
2800
- provenance: provenanceForComment(range, sourceFile, file, "summary")
2801
- });
2802
- }
2836
+ if (unified.summaryText !== "") {
2837
+ annotations.push({
2838
+ kind: "annotation",
2839
+ annotationKind: "description",
2840
+ value: unified.summaryText,
2841
+ provenance: provenanceForComment(range, sourceFile, file, "summary")
2842
+ });
2803
2843
  }
2804
- if (docComment.remarksBlock !== void 0) {
2805
- const remarksText = extractBlockText(docComment.remarksBlock).trim();
2806
- if (remarksText !== "") {
2807
- annotations.push({
2808
- kind: "annotation",
2809
- annotationKind: "remarks",
2810
- value: remarksText,
2811
- provenance: provenanceForComment(range, sourceFile, file, "remarks")
2812
- });
2813
- }
2844
+ if (unified.remarksText !== "") {
2845
+ annotations.push({
2846
+ kind: "annotation",
2847
+ annotationKind: "remarks",
2848
+ value: unified.remarksText,
2849
+ provenance: provenanceForComment(range, sourceFile, file, "remarks")
2850
+ });
2814
2851
  }
2815
2852
  }
2816
2853
  }
@@ -2830,77 +2867,27 @@ function parseTSDocTags(node, file = "", options) {
2830
2867
  provenance: placeholderProvenance
2831
2868
  });
2832
2869
  }
2833
- if (rawTextTags.length > 0) {
2834
- for (const rawTextTag of rawTextTags) {
2835
- const fallbackQueue = rawTextFallbacks.get(rawTextTag.tag.normalizedTagName);
2836
- const fallback = fallbackQueue?.shift();
2837
- const text = choosePreferredPayloadText(
2838
- getSharedPayloadText(rawTextTag.tag, rawTextTag.commentText, rawTextTag.commentOffset),
2839
- fallback?.text ?? ""
2840
- );
2841
- if (text === "") continue;
2842
- const provenance = provenanceForParsedTag(rawTextTag.tag, sourceFile, file);
2843
- if (rawTextTag.tag.normalizedTagName === "defaultValue") {
2844
- const defaultValueNode = (0, import_internal2.parseDefaultValueTagValue)(text, provenance);
2845
- annotations.push(defaultValueNode);
2846
- continue;
2847
- }
2848
- const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
2849
- node,
2850
- sourceFile,
2851
- rawTextTag.tag.normalizedTagName,
2852
- rawTextTag.tag,
2853
- provenance,
2854
- supportingDeclarations,
2855
- options
2856
- );
2857
- if (compilerDiagnostics.length > 0) {
2858
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2859
- continue;
2860
- }
2861
- const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2862
- rawTextTag.tag.normalizedTagName,
2863
- text,
2864
- provenance,
2865
- sharedTagValueOptions(options)
2866
- );
2867
- if (constraintNode) {
2868
- constraints.push(constraintNode);
2869
- }
2870
- }
2871
- }
2872
2870
  for (const [tagName, fallbacks] of rawTextFallbacks) {
2873
2871
  for (const fallback of fallbacks) {
2874
2872
  const text = fallback.text.trim();
2875
2873
  if (text === "") continue;
2876
2874
  const provenance = fallback.provenance;
2877
2875
  if (tagName === "defaultValue") {
2878
- const defaultValueNode = (0, import_internal2.parseDefaultValueTagValue)(text, provenance);
2879
- annotations.push(defaultValueNode);
2876
+ annotations.push((0, import_internal2.parseDefaultValueTagValue)(text, provenance));
2880
2877
  continue;
2881
2878
  }
2882
- const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
2883
- node,
2884
- sourceFile,
2879
+ processConstraintTag(
2885
2880
  tagName,
2881
+ text,
2886
2882
  null,
2887
2883
  provenance,
2884
+ node,
2885
+ sourceFile,
2888
2886
  supportingDeclarations,
2889
- options
2890
- );
2891
- if (compilerDiagnostics.length > 0) {
2892
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
2893
- continue;
2894
- }
2895
- const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2896
- tagName,
2897
- text,
2898
- provenance,
2899
- sharedTagValueOptions(options)
2887
+ options,
2888
+ constraints,
2889
+ diagnostics
2900
2890
  );
2901
- if (constraintNode) {
2902
- constraints.push(constraintNode);
2903
- }
2904
2891
  }
2905
2892
  }
2906
2893
  const result = { constraints, annotations, diagnostics };
@@ -2918,8 +2905,8 @@ function extractDisplayNameMetadata(node) {
2918
2905
  if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) continue;
2919
2906
  const commentText = sourceText.substring(range.pos, range.end);
2920
2907
  if (!commentText.startsWith("/**")) continue;
2921
- const parsed = (0, import_internal2.parseCommentBlock)(commentText);
2922
- for (const tag of parsed.tags) {
2908
+ const unified = (0, import_internal2.parseUnifiedComment)(commentText);
2909
+ for (const tag of unified.tags) {
2923
2910
  if (tag.normalizedTagName !== "displayName") {
2924
2911
  continue;
2925
2912
  }
@@ -2938,56 +2925,11 @@ function extractDisplayNameMetadata(node) {
2938
2925
  memberDisplayNames
2939
2926
  };
2940
2927
  }
2941
- function extractBlockText(block) {
2942
- return extractPlainText(block.content);
2943
- }
2944
- function extractPlainText(node) {
2945
- let result = "";
2946
- if (node instanceof import_tsdoc.DocExcerpt) {
2947
- return node.content.toString();
2948
- }
2949
- if (node instanceof import_tsdoc.DocPlainText) {
2950
- return node.text;
2951
- }
2952
- if (node instanceof import_tsdoc.DocSoftBreak) {
2953
- return " ";
2954
- }
2955
- if (typeof node.getChildNodes === "function") {
2956
- for (const child of node.getChildNodes()) {
2957
- result += extractPlainText(child);
2958
- }
2959
- }
2960
- return result;
2961
- }
2962
- function choosePreferredPayloadText(primary, fallback) {
2963
- const preferred = primary.trim();
2964
- const alternate = fallback.trim();
2965
- if (preferred === "") return alternate;
2966
- if (alternate === "") return preferred;
2967
- if (alternate.includes("\n")) return alternate;
2968
- if (alternate.length > preferred.length && alternate.startsWith(preferred)) {
2969
- return alternate;
2970
- }
2971
- return preferred;
2972
- }
2973
- function getSharedPayloadText(tag, commentText, commentOffset) {
2974
- if (tag.payloadSpan === null) {
2975
- return "";
2976
- }
2977
- return (0, import_internal2.sliceCommentSpan)(commentText, tag.payloadSpan, {
2978
- offset: commentOffset
2979
- }).trim();
2980
- }
2981
- function getBestBlockPayloadText(tag, commentText, commentOffset, block) {
2982
- const sharedText = tag === null ? "" : getSharedPayloadText(tag, commentText, commentOffset);
2983
- const blockText = extractBlockText(block).replace(/\s+/g, " ").trim();
2984
- return choosePreferredPayloadText(sharedText, blockText);
2985
- }
2986
2928
  function collectRawTextFallbacks(node, file) {
2987
2929
  const fallbacks = /* @__PURE__ */ new Map();
2988
2930
  for (const tag of ts.getJSDocTags(node)) {
2989
2931
  const tagName = (0, import_internals4.normalizeConstraintTagName)(tag.tagName.text);
2990
- if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2932
+ if (!import_internal2.TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2991
2933
  const commentText = getTagCommentText(tag)?.trim() ?? "";
2992
2934
  if (commentText === "") continue;
2993
2935
  const entries = fallbacks.get(tagName) ?? [];
@@ -3042,18 +2984,15 @@ function getTagCommentText(tag) {
3042
2984
  }
3043
2985
  return ts.getTextOfJSDocComment(tag.comment);
3044
2986
  }
3045
- var ts, import_internal2, import_tsdoc, import_internals4, import_internals5, TAGS_REQUIRING_RAW_TEXT, SYNTHETIC_TYPE_FORMAT_FLAGS, parserCache, parseResultCache;
2987
+ var ts, import_internal2, import_internals4, import_internals5, SYNTHETIC_TYPE_FORMAT_FLAGS, parseResultCache;
3046
2988
  var init_tsdoc_parser = __esm({
3047
2989
  "src/analyzer/tsdoc-parser.ts"() {
3048
2990
  "use strict";
3049
2991
  ts = __toESM(require("typescript"), 1);
3050
2992
  import_internal2 = require("@formspec/analysis/internal");
3051
- import_tsdoc = require("@microsoft/tsdoc");
3052
2993
  import_internals4 = require("@formspec/core/internals");
3053
2994
  import_internals5 = require("@formspec/core/internals");
3054
- TAGS_REQUIRING_RAW_TEXT = /* @__PURE__ */ new Set(["pattern", "enumOptions", "defaultValue"]);
3055
2995
  SYNTHETIC_TYPE_FORMAT_FLAGS = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
3056
- parserCache = /* @__PURE__ */ new Map();
3057
2996
  parseResultCache = /* @__PURE__ */ new Map();
3058
2997
  }
3059
2998
  });
@@ -4650,7 +4589,7 @@ function typeNodeContainsReference(type, targetName) {
4650
4589
  }
4651
4590
  }
4652
4591
  function shouldEmitResolvedObjectProperty(property, declaration) {
4653
- if (property.name.startsWith("__@")) {
4592
+ if (property.name.startsWith("__")) {
4654
4593
  return false;
4655
4594
  }
4656
4595
  if (declaration !== void 0 && "name" in declaration && declaration.name !== void 0) {
@@ -5680,7 +5619,9 @@ function generateSchemasFromClass(options) {
5680
5619
  classDecl,
5681
5620
  ctx.checker,
5682
5621
  options.filePath,
5622
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5683
5623
  options.extensionRegistry,
5624
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5684
5625
  options.metadata,
5685
5626
  options.discriminator
5686
5627
  );
@@ -5688,9 +5629,13 @@ function generateSchemasFromClass(options) {
5688
5629
  analysis,
5689
5630
  { file: options.filePath },
5690
5631
  {
5632
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5691
5633
  extensionRegistry: options.extensionRegistry,
5634
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5692
5635
  metadata: options.metadata,
5636
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5693
5637
  enumSerialization: options.enumSerialization,
5638
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5694
5639
  vendorPrefix: options.vendorPrefix
5695
5640
  }
5696
5641
  );
@@ -5737,7 +5682,12 @@ function generateSchemasDetailedInternal(options) {
5737
5682
  diagnostics: [createProgramContextFailureDiagnostic(options.filePath, error)]
5738
5683
  };
5739
5684
  }
5740
- return generateSchemasFromDetailedProgramContext(ctx, options.filePath, options.typeName, options);
5685
+ return generateSchemasFromDetailedProgramContext(
5686
+ ctx,
5687
+ options.filePath,
5688
+ options.typeName,
5689
+ options
5690
+ );
5741
5691
  }
5742
5692
  function generateSchemasFromProgramDetailed(options) {
5743
5693
  return generateSchemasFromProgram({
@@ -5755,7 +5705,12 @@ function generateSchemasFromProgramDetailedInternal(options) {
5755
5705
  diagnostics: [createProgramContextFailureDiagnostic(options.filePath, error)]
5756
5706
  };
5757
5707
  }
5758
- return generateSchemasFromDetailedProgramContext(ctx, options.filePath, options.typeName, options);
5708
+ return generateSchemasFromDetailedProgramContext(
5709
+ ctx,
5710
+ options.filePath,
5711
+ options.typeName,
5712
+ options
5713
+ );
5759
5714
  }
5760
5715
  function generateSchemasBatch(options) {
5761
5716
  const contextCache = /* @__PURE__ */ new Map();
@@ -5799,13 +5754,27 @@ function generateSchemasBatchFromProgram(options) {
5799
5754
  );
5800
5755
  });
5801
5756
  }
5757
+ function resolveOptions(options) {
5758
+ const configRegistry = options.config?.extensions !== void 0 ? createExtensionRegistry(options.config.extensions) : void 0;
5759
+ return {
5760
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5761
+ extensionRegistry: options.extensionRegistry ?? configRegistry,
5762
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5763
+ vendorPrefix: options.vendorPrefix ?? options.config?.vendorPrefix,
5764
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5765
+ enumSerialization: options.enumSerialization ?? options.config?.enumSerialization,
5766
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5767
+ metadata: options.metadata ?? options.config?.metadata
5768
+ };
5769
+ }
5802
5770
  function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, options) {
5771
+ const resolved = resolveOptions(options);
5803
5772
  const analysisResult = analyzeNamedTypeToIRFromProgramContextDetailed(
5804
5773
  ctx,
5805
5774
  filePath,
5806
5775
  typeName,
5807
- options.extensionRegistry,
5808
- options.metadata,
5776
+ resolved.extensionRegistry,
5777
+ resolved.metadata,
5809
5778
  options.discriminator
5810
5779
  );
5811
5780
  if (!analysisResult.ok) {
@@ -5818,10 +5787,10 @@ function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, opti
5818
5787
  analysisResult.analysis,
5819
5788
  { file: filePath },
5820
5789
  {
5821
- extensionRegistry: options.extensionRegistry,
5822
- metadata: options.metadata,
5823
- enumSerialization: options.enumSerialization,
5824
- vendorPrefix: options.vendorPrefix
5790
+ extensionRegistry: resolved.extensionRegistry,
5791
+ metadata: resolved.metadata,
5792
+ enumSerialization: resolved.enumSerialization,
5793
+ vendorPrefix: resolved.vendorPrefix
5825
5794
  }
5826
5795
  );
5827
5796
  }
@@ -5855,6 +5824,7 @@ var init_class_schema = __esm({
5855
5824
  init_class_analyzer();
5856
5825
  init_canonicalize();
5857
5826
  init_ir_generator();
5827
+ init_extensions();
5858
5828
  init_ir_generator2();
5859
5829
  init_validate();
5860
5830
  }
@@ -5975,6 +5945,7 @@ function omitApiName(metadata) {
5975
5945
  }
5976
5946
  function enforceRequiredMetadata(metadata, declarationKind, logicalName, options) {
5977
5947
  const declarationPolicy = getDeclarationMetadataPolicy(
5948
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
5978
5949
  normalizeMetadataPolicy(options.metadata),
5979
5950
  declarationKind
5980
5951
  );
@@ -6049,6 +6020,7 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
6049
6020
  provenance: syntheticField.provenance
6050
6021
  },
6051
6022
  {
6023
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6052
6024
  policy: normalizeMetadataPolicy(options?.metadata),
6053
6025
  surface: "tsdoc",
6054
6026
  rootLogicalName: root.name
@@ -6057,8 +6029,11 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
6057
6029
  const schema = generateJsonSchemaFromIR(
6058
6030
  ir,
6059
6031
  {
6032
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6060
6033
  extensionRegistry: options?.extensionRegistry,
6034
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6061
6035
  enumSerialization: options?.enumSerialization,
6036
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6062
6037
  vendorPrefix: options?.vendorPrefix
6063
6038
  }
6064
6039
  );
@@ -6084,9 +6059,13 @@ function generateSchemasFromAnalysis(analysis, filePath, options) {
6084
6059
  analysis,
6085
6060
  { file: filePath },
6086
6061
  {
6062
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6087
6063
  extensionRegistry: options?.extensionRegistry,
6064
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6088
6065
  enumSerialization: options?.enumSerialization,
6066
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6089
6067
  metadata: options?.metadata,
6068
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6090
6069
  vendorPrefix: options?.vendorPrefix
6091
6070
  }
6092
6071
  ),
@@ -6111,7 +6090,9 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
6111
6090
  typeRegistry,
6112
6091
  /* @__PURE__ */ new Set(),
6113
6092
  options.sourceNode,
6093
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6114
6094
  createAnalyzerMetadataPolicy(options.metadata, options.discriminator),
6095
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6115
6096
  options.extensionRegistry,
6116
6097
  diagnostics
6117
6098
  );
@@ -6160,7 +6141,9 @@ function generateSchemasFromDeclaration(options) {
6160
6141
  options.declaration,
6161
6142
  options.context.checker,
6162
6143
  filePath,
6144
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6163
6145
  options.extensionRegistry,
6146
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6164
6147
  options.metadata,
6165
6148
  options.discriminator
6166
6149
  ),
@@ -6174,7 +6157,9 @@ function generateSchemasFromDeclaration(options) {
6174
6157
  options.declaration,
6175
6158
  options.context.checker,
6176
6159
  filePath,
6160
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6177
6161
  options.extensionRegistry,
6162
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6178
6163
  options.metadata,
6179
6164
  options.discriminator
6180
6165
  ),
@@ -6187,7 +6172,9 @@ function generateSchemasFromDeclaration(options) {
6187
6172
  options.declaration,
6188
6173
  options.context.checker,
6189
6174
  filePath,
6175
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6190
6176
  options.extensionRegistry,
6177
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6191
6178
  options.metadata,
6192
6179
  options.discriminator
6193
6180
  );
@@ -6198,7 +6185,9 @@ function generateSchemasFromDeclaration(options) {
6198
6185
  options.declaration,
6199
6186
  options.context.checker,
6200
6187
  filePath,
6188
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6201
6189
  options.extensionRegistry,
6190
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6202
6191
  options.metadata
6203
6192
  );
6204
6193
  if (aliasRootInfo.diagnostics.length > 0) {
@@ -6253,7 +6242,9 @@ function resolveDeclarationMetadata(options) {
6253
6242
  const analysis = (0, import_internal5.analyzeMetadataForNodeWithChecker)({
6254
6243
  checker: options.context.checker,
6255
6244
  node: options.declaration,
6245
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6256
6246
  metadata: options.metadata,
6247
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6257
6248
  extensions: options.extensionRegistry?.extensions,
6258
6249
  buildContext: options.context
6259
6250
  });
@@ -6303,7 +6294,9 @@ function buildMixedAuthoringSchemas(options) {
6303
6294
  const analysis = analyzeNamedTypeToIR(
6304
6295
  filePath,
6305
6296
  typeName,
6297
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6306
6298
  schemaOptions.extensionRegistry,
6299
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6307
6300
  schemaOptions.metadata,
6308
6301
  schemaOptions.discriminator
6309
6302
  );
@@ -6311,6 +6304,7 @@ function buildMixedAuthoringSchemas(options) {
6311
6304
  const ir = canonicalizeTSDoc(
6312
6305
  composedAnalysis,
6313
6306
  { file: filePath },
6307
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
6314
6308
  schemaOptions.metadata !== void 0 ? { metadata: schemaOptions.metadata } : void 0
6315
6309
  );
6316
6310
  return {