@gmb/bitmark-parser-generator 5.1.0 → 5.3.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.cjs CHANGED
@@ -331,6 +331,7 @@ var BitType = {
331
331
  flashcard1: "flashcard-1",
332
332
  focusImage: "focus-image",
333
333
  footNote: "foot-note",
334
+ formFreeText: "form-free-text",
334
335
  formula: "formula",
335
336
  gapText: "gap-text",
336
337
  gapTextInstructionGrouped: "gap-text-instruction-grouped",
@@ -343,6 +344,8 @@ var BitType = {
343
344
  handInFeedbackExpert: "hand-in-feedback-expert",
344
345
  handInFeedbackSelf: "hand-in-feedback-self",
345
346
  handInFile: "hand-in-file",
347
+ handInFreeText: "hand-in-free-text",
348
+ handInFreeTextExpert: "hand-in-free-text-expert",
346
349
  handInLocation: "hand-in-location",
347
350
  handInPhoto: "hand-in-photo",
348
351
  handInScan: "hand-in-scan",
@@ -655,6 +658,7 @@ var BitType = {
655
658
  trueFalse: "true-false",
656
659
  trueFalse1: "true-false-1",
657
660
  vendorAmcharts5Chart: "vendor-amcharts-5-chart",
661
+ vendorDatadogDashboard: "vendor-datadog-dashboard",
658
662
  vendorDatadogDashboardEmbed: "vendor-datadog-dashboard-embed",
659
663
  vendorFormbricksEmbed: "vendor-formbricks-embed",
660
664
  vendorFormbricksLink: "vendor-formbricks-link",
@@ -1294,6 +1298,7 @@ var propertyKeys = {
1294
1298
  property_internalComment: "@internalComment",
1295
1299
  property_internalPrintPdf: "@internalPrintPdf",
1296
1300
  property_hasPrintRestriction: "@hasPrintRestriction",
1301
+ property_enforceUpdateOverUserInput: "@enforceUpdateOverUserInput",
1297
1302
  property_isCaseSensitive: "@isCaseSensitive",
1298
1303
  property_isInfoOnly: "@isInfoOnly",
1299
1304
  property_isPublic: "@isPublic",
@@ -1320,6 +1325,7 @@ var propertyKeys = {
1320
1325
  property_listItemIndent: "@listItemIndent",
1321
1326
  property_location: "@location",
1322
1327
  property_machineTranslated: "@machineTranslated",
1328
+ property_translationOf: "@translationOf",
1323
1329
  property_spansPageBreak: "@spansPageBreak",
1324
1330
  property_mailingList: "@mailingList",
1325
1331
  property_mark: "@mark",
@@ -1352,6 +1358,7 @@ var propertyKeys = {
1352
1358
  property_platformMargin: "@platformMargin",
1353
1359
  property_platformBorderRadius: "@platformBorderRadius",
1354
1360
  property_platformSelectionBorderRadius: "@platformSelectionBorderRadius",
1361
+ property_platformLogoMaxHeight: "@platformLogoMaxHeight",
1355
1362
  property_platformNeedsShadow: "@platformNeedsShadow",
1356
1363
  property_platformSeparatorColor: "@platformSeparatorColor",
1357
1364
  property_platformTextSelectionColor: "@platformTextSelectionColor",
@@ -2807,6 +2814,11 @@ var GROUPS = {
2807
2814
  description: "If true, the bit is machine-translated",
2808
2815
  format: TagFormat.plainText
2809
2816
  },
2817
+ {
2818
+ key: ConfigKey.property_translationOf,
2819
+ description: "Translation source reference",
2820
+ format: TagFormat.plainText
2821
+ },
2810
2822
  {
2811
2823
  key: ConfigKey.property_spansPageBreak,
2812
2824
  description: "If true, the bit spans a page break",
@@ -3457,6 +3469,12 @@ var GROUPS = {
3457
3469
  description: "If true, the book has print restrictions",
3458
3470
  format: TagFormat.boolean,
3459
3471
  defaultValue: "true"
3472
+ },
3473
+ {
3474
+ key: ConfigKey.property_enforceUpdateOverUserInput,
3475
+ description: "If true, prioritize new content over legacy content from the instance API",
3476
+ format: TagFormat.boolean,
3477
+ defaultValue: "false"
3460
3478
  }
3461
3479
  ]
3462
3480
  },
@@ -8783,6 +8801,11 @@ var BITS = {
8783
8801
  ],
8784
8802
  maxCount: 1
8785
8803
  },
8804
+ {
8805
+ key: ConfigKey.property_platformLogoMaxHeight,
8806
+ description: "Maximum height for the platform logo",
8807
+ format: TagFormat.number
8808
+ },
8786
8809
  {
8787
8810
  key: ConfigKey.group_platformStylesCommon,
8788
8811
  description: "Common platform styles"
@@ -9477,6 +9500,11 @@ var BITS = {
9477
9500
  baseBitType: BitType._standard,
9478
9501
  description: "Footnote bit, used to create footnotes in articles or books"
9479
9502
  },
9503
+ [BitType.formFreeText]: {
9504
+ since: "5.3.0",
9505
+ baseBitType: BitType.interview,
9506
+ description: "Form free text bit, used to create free text forms in articles or books"
9507
+ },
9480
9508
  [BitType.groupBorn]: {
9481
9509
  since: "1.3.0",
9482
9510
  baseBitType: BitType._standard,
@@ -9536,6 +9564,16 @@ var BITS = {
9536
9564
  }
9537
9565
  ]
9538
9566
  },
9567
+ [BitType.handInFreeText]: {
9568
+ since: "5.3.0",
9569
+ baseBitType: BitType.interview,
9570
+ description: "Hand in free text bit, used to create free text submission sections in articles or books"
9571
+ },
9572
+ [BitType.handInFreeTextExpert]: {
9573
+ since: "5.3.0",
9574
+ baseBitType: BitType.interview,
9575
+ description: "Hand in free text expert bit, used to create free text expert submission sections in articles or books"
9576
+ },
9539
9577
  [BitType.handInLocation]: {
9540
9578
  since: "1.5.15",
9541
9579
  baseBitType: BitType._standard,
@@ -9645,6 +9683,11 @@ var BITS = {
9645
9683
  description: "AmCharts 5 chart bit, used to embed AmCharts 5 charts in articles or books",
9646
9684
  textFormatDefault: TextFormat.json
9647
9685
  },
9686
+ [BitType.vendorDatadogDashboard]: {
9687
+ since: "5.2.0",
9688
+ baseBitType: BitType.nonProductionPrototypeIframe,
9689
+ description: "A Datadog dashboard bit, used to embed Datadog dashboards"
9690
+ },
9648
9691
  [BitType.vendorDatadogDashboardEmbed]: {
9649
9692
  since: "3.12.0",
9650
9693
  baseBitType: BitType.code,
@@ -10274,7 +10317,7 @@ var instance2 = new Config();
10274
10317
  // src/generated/package_info.ts
10275
10318
  var PACKAGE_INFO = {
10276
10319
  "name": "@gmb/bitmark-parser-generator",
10277
- "version": "5.1.0",
10320
+ "version": "5.3.0",
10278
10321
  "author": "Get More Brain Ltd",
10279
10322
  "license": "ISC",
10280
10323
  "description": "A bitmark parser and generator using Peggy.js"
@@ -10895,6 +10938,8 @@ var NodeType = {
10895
10938
  internalPrintPdfValue: "internalPrintPdfValue",
10896
10939
  hasPrintRestriction: "hasPrintRestriction",
10897
10940
  hasPrintRestrictionValue: "hasPrintRestrictionValue",
10941
+ enforceUpdateOverUserInput: "enforceUpdateOverUserInput",
10942
+ enforceUpdateOverUserInputValue: "enforceUpdateOverUserInputValue",
10898
10943
  isCaseSensitive: "isCaseSensitive",
10899
10944
  isCommented: "isCommented",
10900
10945
  isCorrect: "isCorrect",
@@ -10961,6 +11006,8 @@ var NodeType = {
10961
11006
  locationValue: "locationValue",
10962
11007
  machineTranslated: "machineTranslated",
10963
11008
  machineTranslatedValue: "machineTranslatedValue",
11009
+ translationOf: "translationOf",
11010
+ translationOfValue: "translationOfValue",
10964
11011
  spansPageBreak: "spansPageBreak",
10965
11012
  spansPageBreakValue: "spansPageBreakValue",
10966
11013
  mailingList: "mailingList",
@@ -11012,6 +11059,8 @@ var NodeType = {
11012
11059
  platformIconValue: "platformIconValue",
11013
11060
  platformLogo: "platformLogo",
11014
11061
  platformLogoValue: "platformLogoValue",
11062
+ platformLogoMaxHeight: "platformLogoMaxHeight",
11063
+ platformLogoMaxHeightValue: "platformLogoMaxHeightValue",
11015
11064
  platformPrimaryColor: "platformPrimaryColor",
11016
11065
  platformPrimaryColorValue: "platformPrimaryColorValue",
11017
11066
  platformSecondaryColor: "platformSecondaryColor",
@@ -12080,7 +12129,7 @@ var Stage = {
12080
12129
  between: "between",
12081
12130
  exit: "exit"
12082
12131
  };
12083
- var TextGenerator = class extends AstWalkerGenerator {
12132
+ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
12084
12133
  /**
12085
12134
  * Generate text from a bitmark text AST
12086
12135
  *
@@ -12092,6 +12141,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12092
12141
  __publicField(this, "ast", new Ast());
12093
12142
  __publicField(this, "bitmarkVersion");
12094
12143
  __publicField(this, "options");
12144
+ __publicField(this, "internalTextGenerator", null);
12095
12145
  // State
12096
12146
  __publicField(this, "generateOptions", {});
12097
12147
  __publicField(this, "textFormat", TextFormat.bitmarkText);
@@ -12107,6 +12157,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12107
12157
  __publicField(this, "exitedCodeBlock", false);
12108
12158
  __publicField(this, "inBulletList", false);
12109
12159
  __publicField(this, "inInline", false);
12160
+ __publicField(this, "markDepth", 0);
12110
12161
  __publicField(this, "textDepth", 0);
12111
12162
  __publicField(this, "placeholderIndex", 0);
12112
12163
  __publicField(this, "placeholders", {});
@@ -12131,6 +12182,13 @@ var TextGenerator = class extends AstWalkerGenerator {
12131
12182
  this.between = this.between.bind(this);
12132
12183
  this.exit = this.exit.bind(this);
12133
12184
  this.leaf = this.leaf.bind(this);
12185
+ if (!this.options.isInternal) {
12186
+ this.internalTextGenerator = new _TextGenerator(bitmarkVersion, {
12187
+ ...this.options,
12188
+ writeCallback: void 0,
12189
+ isInternal: true
12190
+ });
12191
+ }
12134
12192
  }
12135
12193
  /**
12136
12194
  * Generate text from a bitmark text AST
@@ -12187,6 +12245,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12187
12245
  this.exitedCodeBlock = false;
12188
12246
  this.inBulletList = false;
12189
12247
  this.inInline = false;
12248
+ this.markDepth = 0;
12190
12249
  this.textDepth = 0;
12191
12250
  this.placeholderIndex = 0;
12192
12251
  this.placeholders = {};
@@ -12234,8 +12293,16 @@ var TextGenerator = class extends AstWalkerGenerator {
12234
12293
  exit_contentValueValue(node, route) {
12235
12294
  return this.handleExitNode(node.value, route);
12236
12295
  }
12296
+ // * -> marks
12297
+ enter_marks(_node, _route) {
12298
+ this.markDepth++;
12299
+ }
12300
+ exit_marks(_node, _route) {
12301
+ this.markDepth--;
12302
+ }
12237
12303
  // END NODE HANDLERS
12238
12304
  handleEnterNode(node, route) {
12305
+ if (this.markDepth > 0) return;
12239
12306
  this.handleEnterNodePreTextCheck(node, route);
12240
12307
  this.handleIndent(node);
12241
12308
  switch (node.type) {
@@ -12246,7 +12313,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12246
12313
  case TextNodeType.hardBreak:
12247
12314
  this.writeHardBreak(node);
12248
12315
  break;
12249
- case TextNodeType.text:
12316
+ case TextNodeType.text: {
12250
12317
  this.writeMarks(node, Stage.enter);
12251
12318
  this.writeText(node);
12252
12319
  this.writeMarks(node, Stage.between);
@@ -12255,6 +12322,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12255
12322
  }
12256
12323
  this.textDepth++;
12257
12324
  break;
12325
+ }
12258
12326
  case TextNodeType.heading:
12259
12327
  this.writeHeading(node);
12260
12328
  this.inHeading = true;
@@ -12305,6 +12373,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12305
12373
  }
12306
12374
  }
12307
12375
  handleExitNode(node, _route) {
12376
+ if (this.markDepth > 0) return;
12308
12377
  switch (node.type) {
12309
12378
  case TextNodeType.text:
12310
12379
  this.textDepth--;
@@ -12611,7 +12680,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12611
12680
  */
12612
12681
  writeMarks(node, stage) {
12613
12682
  if (node.marks) {
12614
- const forceSingleMark = !!(this.inInline || this.inHeading);
12683
+ const forceSingleMark = this.generateOptions.forceInline || !!(this.inInline || this.inHeading);
12615
12684
  this.thisNodeIsPreText = false;
12616
12685
  const emptyMarks = node.marks.length === 0;
12617
12686
  if (emptyMarks) {
@@ -12842,13 +12911,33 @@ var TextGenerator = class extends AstWalkerGenerator {
12842
12911
  s += `|provider:${provider}`;
12843
12912
  this.write(s);
12844
12913
  }
12845
- writeFootnoteMark(_mark) {
12914
+ writeFootnoteMark(mark) {
12846
12915
  const s = `footnote:`;
12847
12916
  this.write(s);
12917
+ const text = this.internalTextGenerator?.generateSync(
12918
+ mark.attrs?.content,
12919
+ this.textFormat,
12920
+ this.textLocation,
12921
+ {
12922
+ ...this.generateOptions,
12923
+ forceInline: true
12924
+ }
12925
+ ) ?? "";
12926
+ this.write(text);
12848
12927
  }
12849
- writeFootnoteStarMark(_mark) {
12928
+ writeFootnoteStarMark(mark) {
12850
12929
  const s = `footnote*:`;
12851
12930
  this.write(s);
12931
+ const text = this.internalTextGenerator?.generateSync(
12932
+ mark.attrs?.content,
12933
+ this.textFormat,
12934
+ this.textLocation,
12935
+ {
12936
+ ...this.generateOptions,
12937
+ forceInline: true
12938
+ }
12939
+ ) ?? "";
12940
+ this.write(text);
12852
12941
  }
12853
12942
  writeSymbolMark(mark) {
12854
12943
  if (mark.attrs == null) return;
@@ -24005,6 +24094,12 @@ var Builder = class extends BaseBuilder {
24005
24094
  data.machineTranslated,
24006
24095
  options
24007
24096
  ),
24097
+ translationOf: this.toAstProperty(
24098
+ bitType,
24099
+ ConfigKey.property_translationOf,
24100
+ data.translationOf,
24101
+ options
24102
+ ),
24008
24103
  spansPageBreak: this.toAstProperty(
24009
24104
  bitType,
24010
24105
  ConfigKey.property_spansPageBreak,
@@ -24721,6 +24816,12 @@ var Builder = class extends BaseBuilder {
24721
24816
  data.hasPrintRestriction,
24722
24817
  options
24723
24818
  ),
24819
+ enforceUpdateOverUserInput: this.toAstProperty(
24820
+ bitType,
24821
+ ConfigKey.property_enforceUpdateOverUserInput,
24822
+ data.enforceUpdateOverUserInput,
24823
+ options
24824
+ ),
24724
24825
  tocResource: this.toAstProperty(
24725
24826
  bitType,
24726
24827
  ConfigKey.property_tocResource,
@@ -24748,6 +24849,12 @@ var Builder = class extends BaseBuilder {
24748
24849
  ),
24749
24850
  platformIcon: this.toImageResource(context, data.platformIcon),
24750
24851
  platformLogo: this.toImageResource(context, data.platformLogo),
24852
+ platformLogoMaxHeight: this.toAstProperty(
24853
+ bitType,
24854
+ ConfigKey.property_platformLogoMaxHeight,
24855
+ data.platformLogoMaxHeight,
24856
+ options
24857
+ ),
24751
24858
  platformPrimaryColor: this.toAstProperty(
24752
24859
  bitType,
24753
24860
  ConfigKey.property_platformPrimaryColor,
@@ -30421,6 +30528,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
30421
30528
  if (instance2.isOfBitType(bitType, BitType.book)) {
30422
30529
  if (bitJson.maxTocChapterLevel == null) bitJson.maxTocChapterLevel = -1;
30423
30530
  if (bitJson.hasPrintRestriction == null) bitJson.hasPrintRestriction = true;
30531
+ if (bitJson.enforceUpdateOverUserInput == null) bitJson.enforceUpdateOverUserInput = false;
30424
30532
  if (bitJson.hasMarkAsDone == null) bitJson.hasMarkAsDone = false;
30425
30533
  if (bitJson.processHandIn == null) bitJson.processHandIn = false;
30426
30534
  if (bitJson.isPublic == null) bitJson.isPublic = false;
@@ -30501,6 +30609,9 @@ var JsonGenerator = class extends AstWalkerGenerator {
30501
30609
  if (instance2.isOfBitType(bitType, BitType.platformBrandTarget)) {
30502
30610
  if (bitJson.platformBrandTarget == null) bitJson.platformBrandTarget = "none";
30503
30611
  }
30612
+ if (instance2.isOfBitType(bitType, BitType.platformHeader)) {
30613
+ if (bitJson.platformLogoMaxHeight == null) bitJson.platformLogoMaxHeight = 40;
30614
+ }
30504
30615
  if (isTopLevelExample) {
30505
30616
  if (bitJson.isExample == null) bitJson.isExample = false;
30506
30617
  } else {
@@ -32788,6 +32899,9 @@ function parseFeedback(_context, _bitType, cardSet) {
32788
32899
  const choice = {
32789
32900
  choice: tfTags.choice,
32790
32901
  requireReason: tfTags.isCorrect,
32902
+ item: tfTags.item,
32903
+ lead: tfTags.lead,
32904
+ instruction: tfTags.instruction,
32791
32905
  __isDefaultExample,
32792
32906
  example
32793
32907
  };
@@ -38888,8 +39002,20 @@ var ConfigBuilder = class {
38888
39002
  this.buildFlat(opts);
38889
39003
  const bitConfigs = [];
38890
39004
  const groupConfigs = [];
38891
- const bitGroupConfigKeys = [];
39005
+ const bitGroupConfigKeys = /* @__PURE__ */ new Set();
38892
39006
  const bitGroupConfigs = [];
39007
+ for (const bt of (0, import_superenum50.Enum)(BitType).values()) {
39008
+ const bitType = instance2.getBitType(bt);
39009
+ const _bitConfig = BITS[bitType];
39010
+ if (_bitConfig?.baseBitType) {
39011
+ let currentBitType = _bitConfig.baseBitType;
39012
+ while (currentBitType) {
39013
+ bitGroupConfigKeys.add(currentBitType);
39014
+ const parentConfig = BITS[currentBitType];
39015
+ currentBitType = parentConfig?.baseBitType;
39016
+ }
39017
+ }
39018
+ }
38893
39019
  for (const bt of (0, import_superenum50.Enum)(BitType).values()) {
38894
39020
  const bitType = instance2.getBitType(bt);
38895
39021
  const _bitConfig = BITS[bitType];
@@ -38912,7 +39038,22 @@ var ConfigBuilder = class {
38912
39038
  const outputFolderGroups = import_node_path3.default.join(outputFolder, "partials");
38913
39039
  import_fs_extra3.default.ensureDirSync(outputFolderBits);
38914
39040
  import_fs_extra3.default.ensureDirSync(outputFolderGroups);
39041
+ const bitsFiles = import_fs_extra3.default.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
39042
+ for (const file of bitsFiles) {
39043
+ import_fs_extra3.default.removeSync(import_node_path3.default.join(outputFolderBits, file));
39044
+ }
39045
+ const partialsFiles = import_fs_extra3.default.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
39046
+ for (const file of partialsFiles) {
39047
+ import_fs_extra3.default.removeSync(import_node_path3.default.join(outputFolderGroups, file));
39048
+ }
38915
39049
  const fileWrites = [];
39050
+ const resolveGroupReferences = (groupKey) => {
39051
+ if (squashedGroups.has(groupKey)) {
39052
+ const replacements = squashedGroups.get(groupKey);
39053
+ return replacements.flatMap((r) => resolveGroupReferences(r));
39054
+ }
39055
+ return [groupKey];
39056
+ };
38916
39057
  const keyToJsonKey = (key, tagNameChain) => {
38917
39058
  let jsonKey = key;
38918
39059
  if (key === "%") {
@@ -38976,10 +39117,13 @@ var ConfigBuilder = class {
38976
39117
  if (k.startsWith("group_")) k = k.substring(6);
38977
39118
  k = /*'_' +*/
38978
39119
  stringUtils.camelToKebab(k);
38979
- tags2.push({
38980
- type: "group",
38981
- key: k
38982
- });
39120
+ const resolvedGroups = resolveGroupReferences(k);
39121
+ for (const groupKey of resolvedGroups) {
39122
+ tags2.push({
39123
+ type: "group",
39124
+ key: groupKey
39125
+ });
39126
+ }
38983
39127
  return tags2;
38984
39128
  }
38985
39129
  if (Array.isArray(tag.chain) && tag.chain.length > 0) {
@@ -39007,7 +39151,37 @@ var ConfigBuilder = class {
39007
39151
  tags2.push(t);
39008
39152
  return tags2;
39009
39153
  };
39154
+ for (const bt of bitGroupConfigKeys) {
39155
+ const bitType = instance2.getBitType(bt);
39156
+ const _bitConfig = BITS[bitType];
39157
+ if (_bitConfig) {
39158
+ _bitConfig.bitType = bitType;
39159
+ if (!bitGroupConfigs.some((c) => c.bitType === bitType)) {
39160
+ bitGroupConfigs.push(_bitConfig);
39161
+ }
39162
+ }
39163
+ }
39164
+ const squashedGroups = /* @__PURE__ */ new Map();
39165
+ for (const b of bitGroupConfigs) {
39166
+ const groupKey = `group-${b.bitType}`;
39167
+ const processedTags = [];
39168
+ for (const [, tag] of Object.entries(b.tags ?? [])) {
39169
+ processedTags.push(...processTagEntries(tag, []));
39170
+ }
39171
+ const allAreGroups = processedTags.every((t) => t.type === "group");
39172
+ if (allAreGroups && processedTags.length > 0) {
39173
+ const replacements = [];
39174
+ if (b.baseBitType) {
39175
+ replacements.push(`group-${b.baseBitType}`);
39176
+ }
39177
+ for (const t of processedTags) {
39178
+ replacements.push(t.key);
39179
+ }
39180
+ squashedGroups.set(groupKey, replacements);
39181
+ }
39182
+ }
39010
39183
  for (const b of bitConfigs) {
39184
+ const resolvedBitConfig = instance2.getBitConfig(b.bitType);
39011
39185
  const tags2 = [];
39012
39186
  const tagEntriesTypeOrder = [
39013
39187
  BitTagConfigKeyType.tag,
@@ -39024,47 +39198,52 @@ var ConfigBuilder = class {
39024
39198
  const typeOrder = tagEntriesTypeOrder.indexOf(typeA) - tagEntriesTypeOrder.indexOf(typeB);
39025
39199
  return typeOrder;
39026
39200
  });
39027
- if (b.baseBitType) {
39028
- tags2.push({
39029
- type: "group",
39030
- key: `group-${b.baseBitType}`
39031
- });
39032
- bitGroupConfigKeys.push(b.baseBitType);
39033
- }
39034
- for (const [_tagKey, tag] of tagEntries) {
39035
- tags2.push(...processTagEntries(tag, []));
39201
+ const isInheritedFrom = bitGroupConfigKeys.has(b.bitType);
39202
+ if (isInheritedFrom) {
39203
+ const resolvedGroups = resolveGroupReferences(`group-${b.bitType}`);
39204
+ for (const groupKey of resolvedGroups) {
39205
+ tags2.push({
39206
+ type: "group",
39207
+ key: groupKey
39208
+ });
39209
+ }
39210
+ } else {
39211
+ if (b.baseBitType) {
39212
+ const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
39213
+ for (const groupKey of resolvedGroups) {
39214
+ tags2.push({
39215
+ type: "group",
39216
+ key: groupKey
39217
+ });
39218
+ }
39219
+ }
39220
+ for (const [_tagKey, tag] of tagEntries) {
39221
+ tags2.push(...processTagEntries(tag, []));
39222
+ }
39036
39223
  }
39037
39224
  const bitJson = {
39038
39225
  name: b.bitType,
39039
39226
  description: b.description ?? "",
39040
- since: b.since,
39041
- deprecated: b.deprecated,
39227
+ since: resolvedBitConfig.since,
39228
+ deprecated: resolvedBitConfig.deprecated,
39042
39229
  history: [
39043
39230
  {
39044
- version: b.since,
39231
+ version: resolvedBitConfig.since,
39045
39232
  changes: ["Initial version"]
39046
39233
  }
39047
39234
  ],
39048
- format: b.textFormatDefault ?? "bitmark--",
39049
- bodyAllowed: b.bodyAllowed ?? true,
39050
- bodyRequired: b.bodyRequired ?? false,
39051
- footerAllowed: b.footerAllowed ?? true,
39052
- footerRequired: b.footerRequired ?? false,
39053
- resourceAttachmentAllowed: b.resourceAttachmentAllowed ?? true,
39235
+ format: resolvedBitConfig.textFormatDefault ?? "bitmark--",
39236
+ bodyAllowed: resolvedBitConfig.bodyAllowed ?? true,
39237
+ bodyRequired: resolvedBitConfig.bodyRequired ?? false,
39238
+ footerAllowed: resolvedBitConfig.footerAllowed ?? true,
39239
+ footerRequired: resolvedBitConfig.footerRequired ?? false,
39240
+ resourceAttachmentAllowed: resolvedBitConfig.resourceAttachmentAllowed ?? true,
39054
39241
  tags: tags2
39055
39242
  };
39056
39243
  const output = import_node_path3.default.join(outputFolderBits, `${b.bitType}.jsonc`);
39057
39244
  const str = JSON.stringify(bitJson, null, 2);
39058
39245
  fileWrites.push(import_fs_extra3.default.writeFile(output, str));
39059
39246
  }
39060
- for (const bt of bitGroupConfigKeys) {
39061
- const bitType = instance2.getBitType(bt);
39062
- const _bitConfig = BITS[bitType];
39063
- if (_bitConfig) {
39064
- _bitConfig.bitType = bitType;
39065
- bitGroupConfigs.push(_bitConfig);
39066
- }
39067
- }
39068
39247
  const writeGroupConfigs = (groupConfigs2) => {
39069
39248
  for (const g of groupConfigs2) {
39070
39249
  const tags2 = [];
@@ -39129,7 +39308,19 @@ var ConfigBuilder = class {
39129
39308
  const writeBitsAsGroupConfigs = (bitsAsGroupConfigs) => {
39130
39309
  for (const b of bitsAsGroupConfigs) {
39131
39310
  const groupKey = `group-${b.bitType}`;
39311
+ if (squashedGroups.has(groupKey)) {
39312
+ continue;
39313
+ }
39132
39314
  const tags2 = [];
39315
+ if (b.baseBitType) {
39316
+ const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
39317
+ for (const gk of resolvedGroups) {
39318
+ tags2.push({
39319
+ type: "group",
39320
+ key: gk
39321
+ });
39322
+ }
39323
+ }
39133
39324
  const tagEntriesTypeOrder = [
39134
39325
  BitTagConfigKeyType.tag,
39135
39326
  BitTagConfigKeyType.property,
@@ -39167,6 +39358,84 @@ var ConfigBuilder = class {
39167
39358
  }
39168
39359
  };
39169
39360
  writeBitsAsGroupConfigs(bitGroupConfigs);
39361
+ Promise.all(fileWrites).then(() => {
39362
+ const validationErrors = this.validateConfigTree(outputFolder);
39363
+ if (validationErrors.length > 0) {
39364
+ console.error("\n\u26A0\uFE0F Config tree validation errors:");
39365
+ for (const error of validationErrors) {
39366
+ console.error(` - ${error}`);
39367
+ }
39368
+ throw new Error(`Config tree validation failed with ${validationErrors.length} error(s)`);
39369
+ } else {
39370
+ console.log("\u2705 Config tree validation passed");
39371
+ }
39372
+ }).catch((err) => {
39373
+ console.error("Error during config build or validation:", err);
39374
+ throw err;
39375
+ });
39376
+ }
39377
+ /**
39378
+ * Validate the config tree for missing group references
39379
+ * @param outputFolder - The folder containing the config files
39380
+ * @returns Array of validation errors, empty if valid
39381
+ */
39382
+ validateConfigTree(outputFolder) {
39383
+ const errors = [];
39384
+ const outputFolderBits = import_node_path3.default.join(outputFolder, "bits");
39385
+ const outputFolderGroups = import_node_path3.default.join(outputFolder, "partials");
39386
+ const availableGroups = /* @__PURE__ */ new Set();
39387
+ if (import_fs_extra3.default.existsSync(outputFolderGroups)) {
39388
+ const groupFiles = import_fs_extra3.default.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
39389
+ for (const file of groupFiles) {
39390
+ const groupName = file.replace(".jsonc", "");
39391
+ availableGroups.add(groupName);
39392
+ }
39393
+ }
39394
+ const checkTags = (tags2, filePath, lineOffset) => {
39395
+ for (let i = 0; i < tags2.length; i++) {
39396
+ const tag = tags2[i];
39397
+ if (tag.type === "group") {
39398
+ if (!availableGroups.has(tag.key)) {
39399
+ const line = lineOffset + i + 1;
39400
+ errors.push(`Missing group reference '${tag.key}' in ${filePath}:${line}`);
39401
+ }
39402
+ }
39403
+ if (tag.tags && Array.isArray(tag.tags)) {
39404
+ checkTags(tag.tags, filePath, lineOffset + i + 1);
39405
+ }
39406
+ }
39407
+ };
39408
+ if (import_fs_extra3.default.existsSync(outputFolderBits)) {
39409
+ const bitFiles = import_fs_extra3.default.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
39410
+ for (const file of bitFiles) {
39411
+ const filePath = import_node_path3.default.join(outputFolderBits, file);
39412
+ try {
39413
+ const content = import_fs_extra3.default.readFileSync(filePath, "utf-8");
39414
+ const config = JSON.parse(content);
39415
+ if (config.tags && Array.isArray(config.tags)) {
39416
+ checkTags(config.tags, `bits/${file}`, 15);
39417
+ }
39418
+ } catch (err) {
39419
+ errors.push(`Failed to parse ${file}: ${err}`);
39420
+ }
39421
+ }
39422
+ }
39423
+ if (import_fs_extra3.default.existsSync(outputFolderGroups)) {
39424
+ const groupFiles = import_fs_extra3.default.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
39425
+ for (const file of groupFiles) {
39426
+ const filePath = import_node_path3.default.join(outputFolderGroups, file);
39427
+ try {
39428
+ const content = import_fs_extra3.default.readFileSync(filePath, "utf-8");
39429
+ const config = JSON.parse(content);
39430
+ if (config.tags && Array.isArray(config.tags)) {
39431
+ checkTags(config.tags, `partials/${file}`, 15);
39432
+ }
39433
+ } catch (err) {
39434
+ errors.push(`Failed to parse ${file}: ${err}`);
39435
+ }
39436
+ }
39437
+ }
39438
+ return errors;
39170
39439
  }
39171
39440
  // Build flat bit configs
39172
39441
  buildFlat(options) {
@@ -39180,6 +39449,10 @@ var ConfigBuilder = class {
39180
39449
  const outputFolder = opts.outputDir ?? "assets/config";
39181
39450
  const outputFolderBits = import_node_path3.default.join(outputFolder, "bits_flat");
39182
39451
  import_fs_extra3.default.ensureDirSync(outputFolderBits);
39452
+ const existingFiles = import_fs_extra3.default.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
39453
+ for (const file of existingFiles) {
39454
+ import_fs_extra3.default.removeSync(import_node_path3.default.join(outputFolderBits, file));
39455
+ }
39183
39456
  const processTagEntries = (tag) => {
39184
39457
  const tags2 = [];
39185
39458
  let tagName = tag.key;