@objectstack/sdui-parser 17.2.0 → 17.4.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/dist/index.js CHANGED
@@ -20,9 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ CONSUMED_WIDGET_OPTION_KEYS: () => CONSUMED_WIDGET_OPTION_KEYS,
24
+ DASHBOARD_WIDGET_HOST_TYPES: () => DASHBOARD_WIDGET_HOST_TYPES,
25
+ MANIFEST_INPUT_TYPES: () => MANIFEST_INPUT_TYPES,
26
+ UNCONSUMED_WIDGET_OPTION: () => UNCONSUMED_WIDGET_OPTION,
27
+ canonicalizeInputType: () => canonicalizeInputType,
28
+ checkDashboardWidgetOptions: () => checkDashboardWidgetOptions,
23
29
  compile: () => compile,
24
30
  generateBlockList: () => generateBlockList,
25
31
  generateDts: () => generateDts,
32
+ inputTypeArms: () => inputTypeArms,
26
33
  interpretBrace: () => interpretBrace,
27
34
  manifestFromConfigs: () => manifestFromConfigs,
28
35
  parseJsx: () => parseJsx,
@@ -34,6 +41,7 @@ module.exports = __toCommonJS(index_exports);
34
41
  // src/parse.ts
35
42
  var EVENT_ATTR = /^on[A-Z]/;
36
43
  var FORBIDDEN_ATTRS = /* @__PURE__ */ new Set(["dangerouslySetInnerHTML", "ref", "key"]);
44
+ var DISCRIMINATOR_ATTR = "type";
37
45
  function parseJsx(source, options = {}) {
38
46
  return new Parser(source, options).parseDocument();
39
47
  }
@@ -80,7 +88,7 @@ var Parser = class {
80
88
  if (c === "" || c === ">" || c === "/") break;
81
89
  const attr = this.parseAttr(start, tag);
82
90
  if (!attr) break;
83
- props[attr.name] = attr.value;
91
+ if (!attr.drop) props[attr.name] = attr.value;
84
92
  }
85
93
  this.skipWs();
86
94
  let children;
@@ -91,7 +99,7 @@ var Parser = class {
91
99
  } else {
92
100
  this.error("unterminated-open-tag", `Unterminated <${tag}> open tag`, start, tag);
93
101
  }
94
- const node = { type: tag, ...props };
102
+ const node = { ...props, type: tag };
95
103
  if (children && children.length) node.children = children;
96
104
  return node;
97
105
  }
@@ -108,6 +116,15 @@ var Parser = class {
108
116
  this.skipWs();
109
117
  value = this.parseAttrValue(tag);
110
118
  }
119
+ if (name === DISCRIMINATOR_ATTR) {
120
+ this.error(
121
+ "forbidden-attr",
122
+ `Attribute "${DISCRIMINATOR_ATTR}" is not allowed on <${tag}> \u2014 on this tier the tag name IS the component, so <${tag}> already means type "${tag}". Delete the attribute, or write the tag of the component you meant.`,
123
+ elStart,
124
+ tag
125
+ );
126
+ return { name, value: void 0, drop: true };
127
+ }
111
128
  if (EVENT_ATTR.test(name) || FORBIDDEN_ATTRS.has(name)) {
112
129
  this.error("forbidden-attr", `Attribute "${name}" is not allowed on <${tag}>`, elStart, tag);
113
130
  return { name: `__forbidden_${name}`, value: void 0 };
@@ -165,8 +182,17 @@ var Parser = class {
165
182
  continue;
166
183
  }
167
184
  const text = this.readTextRun();
168
- const trimmed = text.replace(/\s+/g, " ").trim();
169
- if (trimmed) children.push(trimmed);
185
+ const collapsed = text.replace(/\s+/g, " ");
186
+ const core = collapsed.trim();
187
+ const afterSibling = children.length > 0;
188
+ const beforeElement = this.peek() === "<" && !this.src.startsWith("</", this.pos);
189
+ if (core) {
190
+ const lead = afterSibling && collapsed.startsWith(" ") ? " " : "";
191
+ const trail = beforeElement && collapsed.endsWith(" ") ? " " : "";
192
+ children.push(`${lead}${core}${trail}`);
193
+ } else if (collapsed && afterSibling && beforeElement) {
194
+ children.push(" ");
195
+ }
170
196
  }
171
197
  return children;
172
198
  }
@@ -250,9 +276,268 @@ function interpretBrace(raw) {
250
276
  try {
251
277
  return JSON.parse(trimmed);
252
278
  } catch {
253
- return { $expr: trimmed };
279
+ const literal = readLiteral(trimmed);
280
+ return literal === NOT_LITERAL ? { $expr: trimmed } : literal;
254
281
  }
255
282
  }
283
+ var NOT_LITERAL = /* @__PURE__ */ Symbol("not-a-literal");
284
+ var LITERAL_WS = /[ \t\n\r]/;
285
+ var IDENT_START = /[A-Za-z_$]/;
286
+ var IDENT_CHAR = /[A-Za-z0-9_$]/;
287
+ var NUMBER = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/;
288
+ var SIMPLE_ESCAPE = {
289
+ '"': '"',
290
+ "\\": "\\",
291
+ "/": "/",
292
+ b: "\b",
293
+ f: "\f",
294
+ n: "\n",
295
+ r: "\r",
296
+ t: " "
297
+ };
298
+ function readLiteral(src) {
299
+ const reader = new LiteralReader(src);
300
+ const value = reader.value();
301
+ if (value === NOT_LITERAL) return NOT_LITERAL;
302
+ reader.ws();
303
+ return reader.done() ? value : NOT_LITERAL;
304
+ }
305
+ var LiteralReader = class {
306
+ constructor(src) {
307
+ this.src = src;
308
+ this.pos = 0;
309
+ }
310
+ done() {
311
+ return this.pos >= this.src.length;
312
+ }
313
+ ws() {
314
+ while (this.pos < this.src.length && LITERAL_WS.test(this.src[this.pos])) this.pos++;
315
+ }
316
+ value() {
317
+ this.ws();
318
+ const c = this.src[this.pos];
319
+ if (c === void 0) return NOT_LITERAL;
320
+ if (c === '"' || c === "'") return this.string(c);
321
+ if (c === "[") return this.array();
322
+ if (c === "{") return this.object();
323
+ if (this.keyword("true")) return true;
324
+ if (this.keyword("false")) return false;
325
+ if (this.keyword("null")) return null;
326
+ return this.number();
327
+ }
328
+ /** A keyword only when it is not the prefix of a longer identifier. */
329
+ keyword(word) {
330
+ if (!this.src.startsWith(word, this.pos)) return false;
331
+ const after = this.src[this.pos + word.length];
332
+ if (after !== void 0 && IDENT_CHAR.test(after)) return false;
333
+ this.pos += word.length;
334
+ return true;
335
+ }
336
+ number() {
337
+ const m = NUMBER.exec(this.src.slice(this.pos));
338
+ if (!m) return NOT_LITERAL;
339
+ this.pos += m[0].length;
340
+ return Number(m[0]);
341
+ }
342
+ string(quote) {
343
+ this.pos++;
344
+ let out = "";
345
+ for (; ; ) {
346
+ const c = this.src[this.pos];
347
+ if (c === void 0) return NOT_LITERAL;
348
+ if (c === quote) {
349
+ this.pos++;
350
+ return out;
351
+ }
352
+ if (c === "\\") {
353
+ const esc = this.src[this.pos + 1];
354
+ if (esc === void 0) return NOT_LITERAL;
355
+ if (esc === "u") {
356
+ const hex = this.src.slice(this.pos + 2, this.pos + 6);
357
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) return NOT_LITERAL;
358
+ out += String.fromCharCode(parseInt(hex, 16));
359
+ this.pos += 6;
360
+ continue;
361
+ }
362
+ if (esc === "'" && quote === "'") {
363
+ out += "'";
364
+ this.pos += 2;
365
+ continue;
366
+ }
367
+ const simple = SIMPLE_ESCAPE[esc];
368
+ if (simple === void 0) return NOT_LITERAL;
369
+ out += simple;
370
+ this.pos += 2;
371
+ continue;
372
+ }
373
+ if (c < " ") return NOT_LITERAL;
374
+ out += c;
375
+ this.pos++;
376
+ }
377
+ }
378
+ array() {
379
+ this.pos++;
380
+ const out = [];
381
+ this.ws();
382
+ if (this.src[this.pos] === "]") {
383
+ this.pos++;
384
+ return out;
385
+ }
386
+ for (; ; ) {
387
+ const item = this.value();
388
+ if (item === NOT_LITERAL) return NOT_LITERAL;
389
+ out.push(item);
390
+ this.ws();
391
+ const c = this.src[this.pos];
392
+ if (c === ",") {
393
+ this.pos++;
394
+ continue;
395
+ }
396
+ if (c === "]") {
397
+ this.pos++;
398
+ return out;
399
+ }
400
+ return NOT_LITERAL;
401
+ }
402
+ }
403
+ object() {
404
+ this.pos++;
405
+ const out = {};
406
+ this.ws();
407
+ if (this.src[this.pos] === "}") {
408
+ this.pos++;
409
+ return out;
410
+ }
411
+ for (; ; ) {
412
+ this.ws();
413
+ const key = this.key();
414
+ if (key === NOT_LITERAL) return NOT_LITERAL;
415
+ this.ws();
416
+ if (this.src[this.pos] !== ":") return NOT_LITERAL;
417
+ this.pos++;
418
+ const item = this.value();
419
+ if (item === NOT_LITERAL) return NOT_LITERAL;
420
+ Object.defineProperty(out, key, {
421
+ value: item,
422
+ writable: true,
423
+ enumerable: true,
424
+ configurable: true
425
+ });
426
+ this.ws();
427
+ const c = this.src[this.pos];
428
+ if (c === ",") {
429
+ this.pos++;
430
+ continue;
431
+ }
432
+ if (c === "}") {
433
+ this.pos++;
434
+ return out;
435
+ }
436
+ return NOT_LITERAL;
437
+ }
438
+ }
439
+ /** A quoted string, or a bare identifier — the second ruled widening. */
440
+ key() {
441
+ const c = this.src[this.pos];
442
+ if (c === '"' || c === "'") return this.string(c);
443
+ if (c !== void 0 && IDENT_START.test(c)) {
444
+ const start = this.pos;
445
+ this.pos++;
446
+ while (this.pos < this.src.length && IDENT_CHAR.test(this.src[this.pos])) this.pos++;
447
+ return this.src.slice(start, this.pos);
448
+ }
449
+ return NOT_LITERAL;
450
+ }
451
+ };
452
+
453
+ // src/input-type.ts
454
+ var MANIFEST_INPUT_TYPES = /* @__PURE__ */ new Set([
455
+ "string",
456
+ "number",
457
+ "boolean",
458
+ "enum",
459
+ "array",
460
+ "object",
461
+ "color",
462
+ "date",
463
+ "code",
464
+ "file",
465
+ "slot"
466
+ ]);
467
+ function inputTypeArms(type) {
468
+ if (type === void 0) return [];
469
+ return Array.isArray(type) ? type : [type];
470
+ }
471
+ function canonicalizeInputType(type) {
472
+ const arms = (Array.isArray(type) ? type : [type]).filter(
473
+ (arm) => typeof arm === "string" && MANIFEST_INPUT_TYPES.has(arm)
474
+ );
475
+ const distinct = [...new Set(arms)];
476
+ if (distinct.length === 0) return "string";
477
+ if (distinct.length === 1) return distinct[0];
478
+ return distinct;
479
+ }
480
+
481
+ // src/dashboard-widget-options.ts
482
+ var UNCONSUMED_WIDGET_OPTION = "unconsumed-widget-option";
483
+ var DASHBOARD_WIDGET_HOST_TYPES = /* @__PURE__ */ new Set([
484
+ "dashboard",
485
+ "dashboard-grid"
486
+ ]);
487
+ var CONSUMED_WIDGET_OPTION_KEYS = [
488
+ "dateGranularity",
489
+ "description",
490
+ "limit",
491
+ "sortBy",
492
+ "sortOrder",
493
+ "stageOrder"
494
+ ];
495
+ var CONSUMED = new Set(CONSUMED_WIDGET_OPTION_KEYS);
496
+ var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
497
+ var isExpr = (v) => isPlainObject(v) && "$expr" in v;
498
+ function checkDashboardWidgetOptions(node) {
499
+ if (!DASHBOARD_WIDGET_HOST_TYPES.has(node.type)) return [];
500
+ const widgets = node.widgets;
501
+ if (!Array.isArray(widgets)) return [];
502
+ const diagnostics = [];
503
+ widgets.forEach((widget, index) => {
504
+ if (!isPlainObject(widget) || isExpr(widget)) return;
505
+ if (widget.component !== void 0) return;
506
+ if (widget.dataset === void 0 || widget.dataset === null || widget.dataset === "") return;
507
+ const options = widget.options;
508
+ if (!isPlainObject(options) || isExpr(options)) return;
509
+ if (Array.isArray(widget.suppressWarnings) && widget.suppressWarnings.includes(UNCONSUMED_WIDGET_OPTION)) {
510
+ return;
511
+ }
512
+ const label = typeof widget.id === "string" && widget.id !== "" ? widget.id : `#${index}`;
513
+ const widgetType = typeof widget.type === "string" && widget.type !== "" ? widget.type : "widget";
514
+ for (const key of Object.keys(options)) {
515
+ if (CONSUMED.has(key)) continue;
516
+ diagnostics.push({
517
+ severity: "warning",
518
+ // DIVERGENCE FROM OBJECTUI, and the only one below this file's header:
519
+ // objectui writes `code: UNCONSUMED_WIDGET_OPTION` here. This repo runs
520
+ // `check:dispatcher-error-vocabulary`, whose `objlitconst` shape reads
521
+ // the SCREAMING_SNAKE constant NAME at a `code:` position and then must
522
+ // reduce it to a literal — and its literal grammar is
523
+ // `[A-Za-z][A-Za-z0-9_]*`, which a KEBAB-case value cannot satisfy. So
524
+ // the constant form is reported as an unresolvable code constant, and
525
+ // that finding cannot be declared away. `unconsumed-widget-option` is a
526
+ // parser DIAGNOSTIC code, not an ADR-0112 wire code, and an inline
527
+ // quoted literal is the form both vocabulary gates already accept for
528
+ // the six sibling diagnostic codes in `validate.ts`
529
+ // (`unknown-component`, `unknown-prop`, `not-a-container`,
530
+ // `inert-expression`, `type-mismatch`, `invalid-enum`). The emitted
531
+ // VALUE is unchanged, and the test next door pins it equal to
532
+ // `UNCONSUMED_WIDGET_OPTION` so the two spellings cannot drift apart.
533
+ code: "unconsumed-widget-option",
534
+ message: `<${node.type}> widget "${label}" (${widgetType}): options.${key} reaches no renderer \u2014 dashboard widget renderers read only: ${CONSUMED_WIDGET_OPTION_KEYS.join(", ")}`,
535
+ tag: node.type
536
+ });
537
+ }
538
+ });
539
+ return diagnostics;
540
+ }
256
541
 
257
542
  // src/validate.ts
258
543
  var BASE_PROPS = /* @__PURE__ */ new Set([
@@ -266,7 +551,7 @@ var BASE_PROPS = /* @__PURE__ */ new Set([
266
551
  "disabledOn",
267
552
  "children"
268
553
  ]);
269
- var isExpr = (v) => typeof v === "object" && v !== null && "$expr" in v;
554
+ var isExpr2 = (v) => typeof v === "object" && v !== null && "$expr" in v;
270
555
  function validateTree(tree, manifest) {
271
556
  const diagnostics = [];
272
557
  const requires = /* @__PURE__ */ new Set();
@@ -309,7 +594,14 @@ function validateTree(tree, manifest) {
309
594
  if (input.binding) {
310
595
  bindings.push({ tag: node.type, input: key, kind: input.binding, value });
311
596
  }
312
- if (!isExpr(value)) {
597
+ if (isExpr2(value)) {
598
+ diagnostics.push({
599
+ severity: "warning",
600
+ code: "inert-expression",
601
+ message: `<${node.type}> prop "${key}" is a braced expression this tier never evaluates \u2014 the value will be silently ignored at render. This tier materializes LITERALS only (strings, numbers, booleans, null, arrays, objects; quotes may be single or double, object keys may be unquoted), e.g. columns={['name','amount']} works \u2014 columns={rows.map((r) => r.name)} cannot`,
602
+ tag: node.type
603
+ });
604
+ } else {
313
605
  const typeDiag = checkType(node.type, input, value);
314
606
  if (typeDiag) diagnostics.push(typeDiag);
315
607
  }
@@ -322,46 +614,70 @@ function validateTree(tree, manifest) {
322
614
  tag: node.type
323
615
  });
324
616
  }
617
+ diagnostics.push(...checkDashboardWidgetOptions(node));
325
618
  }
326
619
  if (node.children) node.children.forEach(visit);
327
620
  };
328
621
  if (tree) visit(tree);
329
622
  return { diagnostics, requires: [...requires], bindings };
330
623
  }
331
- function checkType(tag, input, value) {
332
- const mismatch = (expected) => ({
333
- severity: "warning",
334
- code: "type-mismatch",
335
- message: `<${tag}> prop "${input.name}" expected ${expected}`,
336
- tag
337
- });
338
- switch (input.type) {
624
+ var enumValues = (input) => (input.enum ?? []).map((e) => typeof e === "object" ? e.value : e);
625
+ function armAccepts(arm, input, value) {
626
+ switch (arm) {
339
627
  case "number":
340
- return typeof value === "number" ? null : mismatch("a number");
628
+ return typeof value === "number";
341
629
  case "boolean":
342
- return typeof value === "boolean" ? null : mismatch("a boolean");
630
+ return typeof value === "boolean";
343
631
  case "string":
344
632
  case "color":
345
633
  case "date":
346
634
  case "code":
347
635
  case "file":
348
- return typeof value === "string" ? null : mismatch("a string");
636
+ return typeof value === "string";
349
637
  case "array":
350
- return Array.isArray(value) ? null : mismatch("an array");
638
+ return Array.isArray(value);
351
639
  case "object":
352
- return typeof value === "object" && value !== null && !Array.isArray(value) ? null : mismatch("an object");
353
- case "enum": {
354
- const allowed = (input.enum ?? []).map((e) => typeof e === "object" ? e.value : e);
355
- return allowed.includes(value) ? null : {
356
- severity: "error",
357
- code: "invalid-enum",
358
- message: `<${tag}> prop "${input.name}"=${JSON.stringify(value)} is not one of ${JSON.stringify(allowed)}`,
359
- tag
360
- };
361
- }
640
+ return typeof value === "object" && value !== null && !Array.isArray(value);
641
+ case "enum":
642
+ return enumValues(input).includes(value);
362
643
  default:
363
- return null;
644
+ return true;
645
+ }
646
+ }
647
+ function armExpectation(arm, input) {
648
+ switch (arm) {
649
+ case "number":
650
+ return "a number";
651
+ case "boolean":
652
+ return "a boolean";
653
+ case "array":
654
+ return "an array";
655
+ case "object":
656
+ return "an object";
657
+ case "enum":
658
+ return `one of ${JSON.stringify(enumValues(input))}`;
659
+ default:
660
+ return "a string";
661
+ }
662
+ }
663
+ function checkType(tag, input, value) {
664
+ const arms = inputTypeArms(input.type);
665
+ if (arms.length === 0) return null;
666
+ if (arms.some((arm) => armAccepts(arm, input, value))) return null;
667
+ if (arms.length === 1 && arms[0] === "enum") {
668
+ return {
669
+ severity: "error",
670
+ code: "invalid-enum",
671
+ message: `<${tag}> prop "${input.name}"=${JSON.stringify(value)} is not one of ${JSON.stringify(enumValues(input))}`,
672
+ tag
673
+ };
364
674
  }
675
+ return {
676
+ severity: arms.includes("enum") ? "error" : "warning",
677
+ code: "type-mismatch",
678
+ message: `<${tag}> prop "${input.name}" expected ${arms.map((arm) => armExpectation(arm, input)).join(" or ")}`,
679
+ tag
680
+ };
365
681
  }
366
682
 
367
683
  // src/codegen.ts
@@ -378,7 +694,6 @@ function generateDts(manifest, options = {}) {
378
694
  interface ElementChildrenAttribute { children: object; }` : "";
379
695
  return `// AUTO-GENERATED by @object-ui/sdui-parser \u2014 DO NOT EDIT.
380
696
  // Source of truth: ComponentRegistry inputs (ADR-0080 \xA73). Regenerate via codegen.
381
- /* eslint-disable */
382
697
 
383
698
  export interface SduiBaseProps {
384
699
  id?: string;
@@ -405,17 +720,18 @@ export {};
405
720
  `;
406
721
  }
407
722
  function emitInterface(comp) {
408
- const lines = comp.inputs.filter((i) => i.type !== "slot").map((i) => ` ${propLine(i)}`).join("\n");
723
+ const lines = comp.inputs.filter((i) => valueArms(i).length > 0).map((i) => ` ${propLine(i)}`).join("\n");
409
724
  return `export interface ${propsName(comp.type)} extends SduiBaseProps {
410
725
  ${lines}
411
726
  }`;
412
727
  }
728
+ var valueArms = (input) => inputTypeArms(input.type).filter((arm) => arm !== "slot");
413
729
  function propLine(input) {
414
730
  const opt = input.required ? "" : "?";
415
731
  return `${quoteKeyIfNeeded(input.name)}${opt}: ${tsType(input)};`;
416
732
  }
417
- function tsType(input) {
418
- switch (input.type) {
733
+ function armTsType(arm, input) {
734
+ switch (arm) {
419
735
  case "number":
420
736
  return "number";
421
737
  case "boolean":
@@ -428,15 +744,16 @@ function tsType(input) {
428
744
  const vals = (input.enum ?? []).map((e) => typeof e === "object" ? e.value : e);
429
745
  return vals.length ? vals.map((v) => JSON.stringify(v)).join(" | ") : "string";
430
746
  }
431
- case "string":
432
- case "color":
433
- case "date":
434
- case "code":
435
- case "file":
436
747
  default:
437
748
  return "string";
438
749
  }
439
750
  }
751
+ function tsType(input) {
752
+ const arms = valueArms(input);
753
+ if (arms.length === 0) return "string";
754
+ const emitted = [...new Set(arms.map((arm) => armTsType(arm, input)))];
755
+ return emitted.join(" | ");
756
+ }
440
757
  var IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
441
758
  var quoteKeyIfNeeded = (name) => IDENT.test(name) ? name : JSON.stringify(name);
442
759
  function propsName(type) {
@@ -475,19 +792,6 @@ function compile(source, manifest) {
475
792
  ok: !diagnostics.some((d) => d.severity === "error")
476
793
  };
477
794
  }
478
- var INPUT_TYPES = /* @__PURE__ */ new Set([
479
- "string",
480
- "number",
481
- "boolean",
482
- "enum",
483
- "array",
484
- "object",
485
- "color",
486
- "date",
487
- "code",
488
- "file",
489
- "slot"
490
- ]);
491
795
  function manifestFromConfigs(configs, opts = {}) {
492
796
  const components = {};
493
797
  for (const c of configs) {
@@ -499,7 +803,7 @@ function manifestFromConfigs(configs, opts = {}) {
499
803
  isContainer: c.isContainer,
500
804
  inputs: (c.inputs ?? []).map((i) => ({
501
805
  name: i.name,
502
- type: INPUT_TYPES.has(i.type) ? i.type : "string",
806
+ type: canonicalizeInputType(i.type),
503
807
  required: i.required,
504
808
  enum: i.enum,
505
809
  binding: i.binding,
@@ -511,9 +815,16 @@ function manifestFromConfigs(configs, opts = {}) {
511
815
  }
512
816
  // Annotate the CommonJS export names for ESM import in node:
513
817
  0 && (module.exports = {
818
+ CONSUMED_WIDGET_OPTION_KEYS,
819
+ DASHBOARD_WIDGET_HOST_TYPES,
820
+ MANIFEST_INPUT_TYPES,
821
+ UNCONSUMED_WIDGET_OPTION,
822
+ canonicalizeInputType,
823
+ checkDashboardWidgetOptions,
514
824
  compile,
515
825
  generateBlockList,
516
826
  generateDts,
827
+ inputTypeArms,
517
828
  interpretBrace,
518
829
  manifestFromConfigs,
519
830
  parseJsx,