@gmb/bitmark-parser-generator 5.2.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -261,6 +261,7 @@ declare const BitType: {
261
261
  readonly flashcard1: "flashcard-1";
262
262
  readonly focusImage: "focus-image";
263
263
  readonly footNote: "foot-note";
264
+ readonly formFreeText: "form-free-text";
264
265
  readonly formula: "formula";
265
266
  readonly gapText: "gap-text";
266
267
  readonly gapTextInstructionGrouped: "gap-text-instruction-grouped";
@@ -273,6 +274,8 @@ declare const BitType: {
273
274
  readonly handInFeedbackExpert: "hand-in-feedback-expert";
274
275
  readonly handInFeedbackSelf: "hand-in-feedback-self";
275
276
  readonly handInFile: "hand-in-file";
277
+ readonly handInFreeText: "hand-in-free-text";
278
+ readonly handInFreeTextExpert: "hand-in-free-text-expert";
276
279
  readonly handInLocation: "hand-in-location";
277
280
  readonly handInPhoto: "hand-in-photo";
278
281
  readonly handInScan: "hand-in-scan";
@@ -868,6 +871,7 @@ declare const ConfigKey: {
868
871
  readonly property_platformMargin: "@platformMargin";
869
872
  readonly property_platformBorderRadius: "@platformBorderRadius";
870
873
  readonly property_platformSelectionBorderRadius: "@platformSelectionBorderRadius";
874
+ readonly property_platformLogoMaxHeight: "@platformLogoMaxHeight";
871
875
  readonly property_platformNeedsShadow: "@platformNeedsShadow";
872
876
  readonly property_platformSeparatorColor: "@platformSeparatorColor";
873
877
  readonly property_platformTextSelectionColor: "@platformTextSelectionColor";
@@ -1795,6 +1799,7 @@ interface BitJson {
1795
1799
  platformName: string;
1796
1800
  platformIcon: ImageResourceWrapperJson;
1797
1801
  platformLogo: ImageResourceWrapperJson;
1802
+ platformLogoMaxHeight: number;
1798
1803
  platformPrimaryColor: string;
1799
1804
  platformSecondaryColor: string;
1800
1805
  platformBackgroundColor: string;
@@ -2407,6 +2412,7 @@ interface Bit {
2407
2412
  platformName?: Property;
2408
2413
  platformIcon?: ImageResourceWrapperJson;
2409
2414
  platformLogo?: ImageResourceWrapperJson;
2415
+ platformLogoMaxHeight?: Property;
2410
2416
  platformPrimaryColor?: Property;
2411
2417
  platformSecondaryColor?: Property;
2412
2418
  platformBackgroundColor?: Property;
@@ -2925,6 +2931,8 @@ declare const NodeType: {
2925
2931
  readonly platformIconValue: "platformIconValue";
2926
2932
  readonly platformLogo: "platformLogo";
2927
2933
  readonly platformLogoValue: "platformLogoValue";
2934
+ readonly platformLogoMaxHeight: "platformLogoMaxHeight";
2935
+ readonly platformLogoMaxHeightValue: "platformLogoMaxHeightValue";
2928
2936
  readonly platformPrimaryColor: "platformPrimaryColor";
2929
2937
  readonly platformPrimaryColorValue: "platformPrimaryColorValue";
2930
2938
  readonly platformSecondaryColor: "platformSecondaryColor";
@@ -4210,6 +4218,7 @@ declare class Builder extends BaseBuilder {
4210
4218
  platformName?: string;
4211
4219
  platformIcon?: Partial<ImageResourceWrapperJson>;
4212
4220
  platformLogo?: Partial<ImageResourceWrapperJson>;
4221
+ platformLogoMaxHeight?: number;
4213
4222
  platformPrimaryColor?: string;
4214
4223
  platformSecondaryColor?: string;
4215
4224
  platformBackgroundColor?: string;
package/dist/index.d.ts CHANGED
@@ -261,6 +261,7 @@ declare const BitType: {
261
261
  readonly flashcard1: "flashcard-1";
262
262
  readonly focusImage: "focus-image";
263
263
  readonly footNote: "foot-note";
264
+ readonly formFreeText: "form-free-text";
264
265
  readonly formula: "formula";
265
266
  readonly gapText: "gap-text";
266
267
  readonly gapTextInstructionGrouped: "gap-text-instruction-grouped";
@@ -273,6 +274,8 @@ declare const BitType: {
273
274
  readonly handInFeedbackExpert: "hand-in-feedback-expert";
274
275
  readonly handInFeedbackSelf: "hand-in-feedback-self";
275
276
  readonly handInFile: "hand-in-file";
277
+ readonly handInFreeText: "hand-in-free-text";
278
+ readonly handInFreeTextExpert: "hand-in-free-text-expert";
276
279
  readonly handInLocation: "hand-in-location";
277
280
  readonly handInPhoto: "hand-in-photo";
278
281
  readonly handInScan: "hand-in-scan";
@@ -868,6 +871,7 @@ declare const ConfigKey: {
868
871
  readonly property_platformMargin: "@platformMargin";
869
872
  readonly property_platformBorderRadius: "@platformBorderRadius";
870
873
  readonly property_platformSelectionBorderRadius: "@platformSelectionBorderRadius";
874
+ readonly property_platformLogoMaxHeight: "@platformLogoMaxHeight";
871
875
  readonly property_platformNeedsShadow: "@platformNeedsShadow";
872
876
  readonly property_platformSeparatorColor: "@platformSeparatorColor";
873
877
  readonly property_platformTextSelectionColor: "@platformTextSelectionColor";
@@ -1795,6 +1799,7 @@ interface BitJson {
1795
1799
  platformName: string;
1796
1800
  platformIcon: ImageResourceWrapperJson;
1797
1801
  platformLogo: ImageResourceWrapperJson;
1802
+ platformLogoMaxHeight: number;
1798
1803
  platformPrimaryColor: string;
1799
1804
  platformSecondaryColor: string;
1800
1805
  platformBackgroundColor: string;
@@ -2407,6 +2412,7 @@ interface Bit {
2407
2412
  platformName?: Property;
2408
2413
  platformIcon?: ImageResourceWrapperJson;
2409
2414
  platformLogo?: ImageResourceWrapperJson;
2415
+ platformLogoMaxHeight?: Property;
2410
2416
  platformPrimaryColor?: Property;
2411
2417
  platformSecondaryColor?: Property;
2412
2418
  platformBackgroundColor?: Property;
@@ -2925,6 +2931,8 @@ declare const NodeType: {
2925
2931
  readonly platformIconValue: "platformIconValue";
2926
2932
  readonly platformLogo: "platformLogo";
2927
2933
  readonly platformLogoValue: "platformLogoValue";
2934
+ readonly platformLogoMaxHeight: "platformLogoMaxHeight";
2935
+ readonly platformLogoMaxHeightValue: "platformLogoMaxHeightValue";
2928
2936
  readonly platformPrimaryColor: "platformPrimaryColor";
2929
2937
  readonly platformPrimaryColorValue: "platformPrimaryColorValue";
2930
2938
  readonly platformSecondaryColor: "platformSecondaryColor";
@@ -4210,6 +4218,7 @@ declare class Builder extends BaseBuilder {
4210
4218
  platformName?: string;
4211
4219
  platformIcon?: Partial<ImageResourceWrapperJson>;
4212
4220
  platformLogo?: Partial<ImageResourceWrapperJson>;
4221
+ platformLogoMaxHeight?: number;
4213
4222
  platformPrimaryColor?: string;
4214
4223
  platformSecondaryColor?: string;
4215
4224
  platformBackgroundColor?: string;
package/dist/index.js CHANGED
@@ -270,6 +270,7 @@ var BitType = {
270
270
  flashcard1: "flashcard-1",
271
271
  focusImage: "focus-image",
272
272
  footNote: "foot-note",
273
+ formFreeText: "form-free-text",
273
274
  formula: "formula",
274
275
  gapText: "gap-text",
275
276
  gapTextInstructionGrouped: "gap-text-instruction-grouped",
@@ -282,6 +283,8 @@ var BitType = {
282
283
  handInFeedbackExpert: "hand-in-feedback-expert",
283
284
  handInFeedbackSelf: "hand-in-feedback-self",
284
285
  handInFile: "hand-in-file",
286
+ handInFreeText: "hand-in-free-text",
287
+ handInFreeTextExpert: "hand-in-free-text-expert",
285
288
  handInLocation: "hand-in-location",
286
289
  handInPhoto: "hand-in-photo",
287
290
  handInScan: "hand-in-scan",
@@ -1294,6 +1297,7 @@ var propertyKeys = {
1294
1297
  property_platformMargin: "@platformMargin",
1295
1298
  property_platformBorderRadius: "@platformBorderRadius",
1296
1299
  property_platformSelectionBorderRadius: "@platformSelectionBorderRadius",
1300
+ property_platformLogoMaxHeight: "@platformLogoMaxHeight",
1297
1301
  property_platformNeedsShadow: "@platformNeedsShadow",
1298
1302
  property_platformSeparatorColor: "@platformSeparatorColor",
1299
1303
  property_platformTextSelectionColor: "@platformTextSelectionColor",
@@ -8736,6 +8740,11 @@ var BITS = {
8736
8740
  ],
8737
8741
  maxCount: 1
8738
8742
  },
8743
+ {
8744
+ key: ConfigKey.property_platformLogoMaxHeight,
8745
+ description: "Maximum height for the platform logo",
8746
+ format: TagFormat.number
8747
+ },
8739
8748
  {
8740
8749
  key: ConfigKey.group_platformStylesCommon,
8741
8750
  description: "Common platform styles"
@@ -9430,6 +9439,11 @@ var BITS = {
9430
9439
  baseBitType: BitType._standard,
9431
9440
  description: "Footnote bit, used to create footnotes in articles or books"
9432
9441
  },
9442
+ [BitType.formFreeText]: {
9443
+ since: "5.3.0",
9444
+ baseBitType: BitType.interview,
9445
+ description: "Form free text bit, used to create free text forms in articles or books"
9446
+ },
9433
9447
  [BitType.groupBorn]: {
9434
9448
  since: "1.3.0",
9435
9449
  baseBitType: BitType._standard,
@@ -9489,6 +9503,16 @@ var BITS = {
9489
9503
  }
9490
9504
  ]
9491
9505
  },
9506
+ [BitType.handInFreeText]: {
9507
+ since: "5.3.0",
9508
+ baseBitType: BitType.interview,
9509
+ description: "Hand in free text bit, used to create free text submission sections in articles or books"
9510
+ },
9511
+ [BitType.handInFreeTextExpert]: {
9512
+ since: "5.3.0",
9513
+ baseBitType: BitType.interview,
9514
+ description: "Hand in free text expert bit, used to create free text expert submission sections in articles or books"
9515
+ },
9492
9516
  [BitType.handInLocation]: {
9493
9517
  since: "1.5.15",
9494
9518
  baseBitType: BitType._standard,
@@ -10232,7 +10256,7 @@ var instance2 = new Config();
10232
10256
  // src/generated/package_info.ts
10233
10257
  var PACKAGE_INFO = {
10234
10258
  "name": "@gmb/bitmark-parser-generator",
10235
- "version": "5.2.0",
10259
+ "version": "5.3.1",
10236
10260
  "author": "Get More Brain Ltd",
10237
10261
  "license": "ISC",
10238
10262
  "description": "A bitmark parser and generator using Peggy.js"
@@ -10974,6 +10998,8 @@ var NodeType = {
10974
10998
  platformIconValue: "platformIconValue",
10975
10999
  platformLogo: "platformLogo",
10976
11000
  platformLogoValue: "platformLogoValue",
11001
+ platformLogoMaxHeight: "platformLogoMaxHeight",
11002
+ platformLogoMaxHeightValue: "platformLogoMaxHeightValue",
10977
11003
  platformPrimaryColor: "platformPrimaryColor",
10978
11004
  platformPrimaryColorValue: "platformPrimaryColorValue",
10979
11005
  platformSecondaryColor: "platformSecondaryColor",
@@ -24762,6 +24788,12 @@ var Builder = class extends BaseBuilder {
24762
24788
  ),
24763
24789
  platformIcon: this.toImageResource(context, data.platformIcon),
24764
24790
  platformLogo: this.toImageResource(context, data.platformLogo),
24791
+ platformLogoMaxHeight: this.toAstProperty(
24792
+ bitType,
24793
+ ConfigKey.property_platformLogoMaxHeight,
24794
+ data.platformLogoMaxHeight,
24795
+ options
24796
+ ),
24765
24797
  platformPrimaryColor: this.toAstProperty(
24766
24798
  bitType,
24767
24799
  ConfigKey.property_platformPrimaryColor,
@@ -30516,6 +30548,9 @@ var JsonGenerator = class extends AstWalkerGenerator {
30516
30548
  if (instance2.isOfBitType(bitType, BitType.platformBrandTarget)) {
30517
30549
  if (bitJson.platformBrandTarget == null) bitJson.platformBrandTarget = "none";
30518
30550
  }
30551
+ if (instance2.isOfBitType(bitType, BitType.platformHeader)) {
30552
+ if (bitJson.platformLogoMaxHeight == null) bitJson.platformLogoMaxHeight = 40;
30553
+ }
30519
30554
  if (isTopLevelExample) {
30520
30555
  if (bitJson.isExample == null) bitJson.isExample = false;
30521
30556
  } else {
@@ -32803,6 +32838,9 @@ function parseFeedback(_context, _bitType, cardSet) {
32803
32838
  const choice = {
32804
32839
  choice: tfTags.choice,
32805
32840
  requireReason: tfTags.isCorrect,
32841
+ item: tfTags.item,
32842
+ lead: tfTags.lead,
32843
+ instruction: tfTags.instruction,
32806
32844
  __isDefaultExample,
32807
32845
  example
32808
32846
  };
@@ -38903,8 +38941,20 @@ var ConfigBuilder = class {
38903
38941
  this.buildFlat(opts);
38904
38942
  const bitConfigs = [];
38905
38943
  const groupConfigs = [];
38906
- const bitGroupConfigKeys = [];
38944
+ const bitGroupConfigKeys = /* @__PURE__ */ new Set();
38907
38945
  const bitGroupConfigs = [];
38946
+ for (const bt of Enum22(BitType).values()) {
38947
+ const bitType = instance2.getBitType(bt);
38948
+ const _bitConfig = BITS[bitType];
38949
+ if (_bitConfig?.baseBitType) {
38950
+ let currentBitType = _bitConfig.baseBitType;
38951
+ while (currentBitType) {
38952
+ bitGroupConfigKeys.add(currentBitType);
38953
+ const parentConfig = BITS[currentBitType];
38954
+ currentBitType = parentConfig?.baseBitType;
38955
+ }
38956
+ }
38957
+ }
38908
38958
  for (const bt of Enum22(BitType).values()) {
38909
38959
  const bitType = instance2.getBitType(bt);
38910
38960
  const _bitConfig = BITS[bitType];
@@ -38927,7 +38977,22 @@ var ConfigBuilder = class {
38927
38977
  const outputFolderGroups = path3.join(outputFolder, "partials");
38928
38978
  fs3.ensureDirSync(outputFolderBits);
38929
38979
  fs3.ensureDirSync(outputFolderGroups);
38980
+ const bitsFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
38981
+ for (const file of bitsFiles) {
38982
+ fs3.removeSync(path3.join(outputFolderBits, file));
38983
+ }
38984
+ const partialsFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
38985
+ for (const file of partialsFiles) {
38986
+ fs3.removeSync(path3.join(outputFolderGroups, file));
38987
+ }
38930
38988
  const fileWrites = [];
38989
+ const resolveGroupReferences = (groupKey) => {
38990
+ if (squashedGroups.has(groupKey)) {
38991
+ const replacements = squashedGroups.get(groupKey);
38992
+ return replacements.flatMap((r) => resolveGroupReferences(r));
38993
+ }
38994
+ return [groupKey];
38995
+ };
38931
38996
  const keyToJsonKey = (key, tagNameChain) => {
38932
38997
  let jsonKey = key;
38933
38998
  if (key === "%") {
@@ -38991,10 +39056,13 @@ var ConfigBuilder = class {
38991
39056
  if (k.startsWith("group_")) k = k.substring(6);
38992
39057
  k = /*'_' +*/
38993
39058
  stringUtils.camelToKebab(k);
38994
- tags2.push({
38995
- type: "group",
38996
- key: k
38997
- });
39059
+ const resolvedGroups = resolveGroupReferences(k);
39060
+ for (const groupKey of resolvedGroups) {
39061
+ tags2.push({
39062
+ type: "group",
39063
+ key: groupKey
39064
+ });
39065
+ }
38998
39066
  return tags2;
38999
39067
  }
39000
39068
  if (Array.isArray(tag.chain) && tag.chain.length > 0) {
@@ -39022,7 +39090,37 @@ var ConfigBuilder = class {
39022
39090
  tags2.push(t);
39023
39091
  return tags2;
39024
39092
  };
39093
+ for (const bt of bitGroupConfigKeys) {
39094
+ const bitType = instance2.getBitType(bt);
39095
+ const _bitConfig = BITS[bitType];
39096
+ if (_bitConfig) {
39097
+ _bitConfig.bitType = bitType;
39098
+ if (!bitGroupConfigs.some((c) => c.bitType === bitType)) {
39099
+ bitGroupConfigs.push(_bitConfig);
39100
+ }
39101
+ }
39102
+ }
39103
+ const squashedGroups = /* @__PURE__ */ new Map();
39104
+ for (const b of bitGroupConfigs) {
39105
+ const groupKey = `group-${b.bitType}`;
39106
+ const processedTags = [];
39107
+ for (const [, tag] of Object.entries(b.tags ?? [])) {
39108
+ processedTags.push(...processTagEntries(tag, []));
39109
+ }
39110
+ const allAreGroups = processedTags.every((t) => t.type === "group");
39111
+ if (allAreGroups && processedTags.length > 0) {
39112
+ const replacements = [];
39113
+ if (b.baseBitType) {
39114
+ replacements.push(`group-${b.baseBitType}`);
39115
+ }
39116
+ for (const t of processedTags) {
39117
+ replacements.push(t.key);
39118
+ }
39119
+ squashedGroups.set(groupKey, replacements);
39120
+ }
39121
+ }
39025
39122
  for (const b of bitConfigs) {
39123
+ const resolvedBitConfig = instance2.getBitConfig(b.bitType);
39026
39124
  const tags2 = [];
39027
39125
  const tagEntriesTypeOrder = [
39028
39126
  BitTagConfigKeyType.tag,
@@ -39039,47 +39137,52 @@ var ConfigBuilder = class {
39039
39137
  const typeOrder = tagEntriesTypeOrder.indexOf(typeA) - tagEntriesTypeOrder.indexOf(typeB);
39040
39138
  return typeOrder;
39041
39139
  });
39042
- if (b.baseBitType) {
39043
- tags2.push({
39044
- type: "group",
39045
- key: `group-${b.baseBitType}`
39046
- });
39047
- bitGroupConfigKeys.push(b.baseBitType);
39048
- }
39049
- for (const [_tagKey, tag] of tagEntries) {
39050
- tags2.push(...processTagEntries(tag, []));
39140
+ const isInheritedFrom = bitGroupConfigKeys.has(b.bitType);
39141
+ if (isInheritedFrom) {
39142
+ const resolvedGroups = resolveGroupReferences(`group-${b.bitType}`);
39143
+ for (const groupKey of resolvedGroups) {
39144
+ tags2.push({
39145
+ type: "group",
39146
+ key: groupKey
39147
+ });
39148
+ }
39149
+ } else {
39150
+ if (b.baseBitType) {
39151
+ const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
39152
+ for (const groupKey of resolvedGroups) {
39153
+ tags2.push({
39154
+ type: "group",
39155
+ key: groupKey
39156
+ });
39157
+ }
39158
+ }
39159
+ for (const [_tagKey, tag] of tagEntries) {
39160
+ tags2.push(...processTagEntries(tag, []));
39161
+ }
39051
39162
  }
39052
39163
  const bitJson = {
39053
39164
  name: b.bitType,
39054
39165
  description: b.description ?? "",
39055
- since: b.since,
39056
- deprecated: b.deprecated,
39166
+ since: resolvedBitConfig.since,
39167
+ deprecated: resolvedBitConfig.deprecated,
39057
39168
  history: [
39058
39169
  {
39059
- version: b.since,
39170
+ version: resolvedBitConfig.since,
39060
39171
  changes: ["Initial version"]
39061
39172
  }
39062
39173
  ],
39063
- format: b.textFormatDefault ?? "bitmark--",
39064
- bodyAllowed: b.bodyAllowed ?? true,
39065
- bodyRequired: b.bodyRequired ?? false,
39066
- footerAllowed: b.footerAllowed ?? true,
39067
- footerRequired: b.footerRequired ?? false,
39068
- resourceAttachmentAllowed: b.resourceAttachmentAllowed ?? true,
39174
+ format: resolvedBitConfig.textFormatDefault ?? "bitmark--",
39175
+ bodyAllowed: resolvedBitConfig.bodyAllowed ?? true,
39176
+ bodyRequired: resolvedBitConfig.bodyRequired ?? false,
39177
+ footerAllowed: resolvedBitConfig.footerAllowed ?? true,
39178
+ footerRequired: resolvedBitConfig.footerRequired ?? false,
39179
+ resourceAttachmentAllowed: resolvedBitConfig.resourceAttachmentAllowed ?? true,
39069
39180
  tags: tags2
39070
39181
  };
39071
39182
  const output = path3.join(outputFolderBits, `${b.bitType}.jsonc`);
39072
39183
  const str = JSON.stringify(bitJson, null, 2);
39073
39184
  fileWrites.push(fs3.writeFile(output, str));
39074
39185
  }
39075
- for (const bt of bitGroupConfigKeys) {
39076
- const bitType = instance2.getBitType(bt);
39077
- const _bitConfig = BITS[bitType];
39078
- if (_bitConfig) {
39079
- _bitConfig.bitType = bitType;
39080
- bitGroupConfigs.push(_bitConfig);
39081
- }
39082
- }
39083
39186
  const writeGroupConfigs = (groupConfigs2) => {
39084
39187
  for (const g of groupConfigs2) {
39085
39188
  const tags2 = [];
@@ -39144,7 +39247,19 @@ var ConfigBuilder = class {
39144
39247
  const writeBitsAsGroupConfigs = (bitsAsGroupConfigs) => {
39145
39248
  for (const b of bitsAsGroupConfigs) {
39146
39249
  const groupKey = `group-${b.bitType}`;
39250
+ if (squashedGroups.has(groupKey)) {
39251
+ continue;
39252
+ }
39147
39253
  const tags2 = [];
39254
+ if (b.baseBitType) {
39255
+ const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
39256
+ for (const gk of resolvedGroups) {
39257
+ tags2.push({
39258
+ type: "group",
39259
+ key: gk
39260
+ });
39261
+ }
39262
+ }
39148
39263
  const tagEntriesTypeOrder = [
39149
39264
  BitTagConfigKeyType.tag,
39150
39265
  BitTagConfigKeyType.property,
@@ -39182,6 +39297,84 @@ var ConfigBuilder = class {
39182
39297
  }
39183
39298
  };
39184
39299
  writeBitsAsGroupConfigs(bitGroupConfigs);
39300
+ Promise.all(fileWrites).then(() => {
39301
+ const validationErrors = this.validateConfigTree(outputFolder);
39302
+ if (validationErrors.length > 0) {
39303
+ console.error("\n\u26A0\uFE0F Config tree validation errors:");
39304
+ for (const error of validationErrors) {
39305
+ console.error(` - ${error}`);
39306
+ }
39307
+ throw new Error(`Config tree validation failed with ${validationErrors.length} error(s)`);
39308
+ } else {
39309
+ console.log("\u2705 Config tree validation passed");
39310
+ }
39311
+ }).catch((err) => {
39312
+ console.error("Error during config build or validation:", err);
39313
+ throw err;
39314
+ });
39315
+ }
39316
+ /**
39317
+ * Validate the config tree for missing group references
39318
+ * @param outputFolder - The folder containing the config files
39319
+ * @returns Array of validation errors, empty if valid
39320
+ */
39321
+ validateConfigTree(outputFolder) {
39322
+ const errors = [];
39323
+ const outputFolderBits = path3.join(outputFolder, "bits");
39324
+ const outputFolderGroups = path3.join(outputFolder, "partials");
39325
+ const availableGroups = /* @__PURE__ */ new Set();
39326
+ if (fs3.existsSync(outputFolderGroups)) {
39327
+ const groupFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
39328
+ for (const file of groupFiles) {
39329
+ const groupName = file.replace(".jsonc", "");
39330
+ availableGroups.add(groupName);
39331
+ }
39332
+ }
39333
+ const checkTags = (tags2, filePath, lineOffset) => {
39334
+ for (let i = 0; i < tags2.length; i++) {
39335
+ const tag = tags2[i];
39336
+ if (tag.type === "group") {
39337
+ if (!availableGroups.has(tag.key)) {
39338
+ const line = lineOffset + i + 1;
39339
+ errors.push(`Missing group reference '${tag.key}' in ${filePath}:${line}`);
39340
+ }
39341
+ }
39342
+ if (tag.tags && Array.isArray(tag.tags)) {
39343
+ checkTags(tag.tags, filePath, lineOffset + i + 1);
39344
+ }
39345
+ }
39346
+ };
39347
+ if (fs3.existsSync(outputFolderBits)) {
39348
+ const bitFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
39349
+ for (const file of bitFiles) {
39350
+ const filePath = path3.join(outputFolderBits, file);
39351
+ try {
39352
+ const content = fs3.readFileSync(filePath, "utf-8");
39353
+ const config = JSON.parse(content);
39354
+ if (config.tags && Array.isArray(config.tags)) {
39355
+ checkTags(config.tags, `bits/${file}`, 15);
39356
+ }
39357
+ } catch (err) {
39358
+ errors.push(`Failed to parse ${file}: ${err}`);
39359
+ }
39360
+ }
39361
+ }
39362
+ if (fs3.existsSync(outputFolderGroups)) {
39363
+ const groupFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
39364
+ for (const file of groupFiles) {
39365
+ const filePath = path3.join(outputFolderGroups, file);
39366
+ try {
39367
+ const content = fs3.readFileSync(filePath, "utf-8");
39368
+ const config = JSON.parse(content);
39369
+ if (config.tags && Array.isArray(config.tags)) {
39370
+ checkTags(config.tags, `partials/${file}`, 15);
39371
+ }
39372
+ } catch (err) {
39373
+ errors.push(`Failed to parse ${file}: ${err}`);
39374
+ }
39375
+ }
39376
+ }
39377
+ return errors;
39185
39378
  }
39186
39379
  // Build flat bit configs
39187
39380
  buildFlat(options) {
@@ -39195,6 +39388,10 @@ var ConfigBuilder = class {
39195
39388
  const outputFolder = opts.outputDir ?? "assets/config";
39196
39389
  const outputFolderBits = path3.join(outputFolder, "bits_flat");
39197
39390
  fs3.ensureDirSync(outputFolderBits);
39391
+ const existingFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
39392
+ for (const file of existingFiles) {
39393
+ fs3.removeSync(path3.join(outputFolderBits, file));
39394
+ }
39198
39395
  const processTagEntries = (tag) => {
39199
39396
  const tags2 = [];
39200
39397
  let tagName = tag.key;