@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/cli/main.js CHANGED
@@ -2,7 +2,7 @@ import process2 from 'process';
2
2
  import { Command, Option, Help, Argument, InvalidArgumentError } from 'commander';
3
3
  import { Enum } from '@ncoderz/superenum';
4
4
  import path3 from 'path';
5
- import fs4 from 'fs-extra';
5
+ import fs3 from 'fs-extra';
6
6
  import 'fs';
7
7
  import os from 'os';
8
8
 
@@ -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",
@@ -594,6 +597,7 @@ var BitType = {
594
597
  trueFalse: "true-false",
595
598
  trueFalse1: "true-false-1",
596
599
  vendorAmcharts5Chart: "vendor-amcharts-5-chart",
600
+ vendorDatadogDashboard: "vendor-datadog-dashboard",
597
601
  vendorDatadogDashboardEmbed: "vendor-datadog-dashboard-embed",
598
602
  vendorFormbricksEmbed: "vendor-formbricks-embed",
599
603
  vendorFormbricksLink: "vendor-formbricks-link",
@@ -1198,6 +1202,7 @@ var propertyKeys = {
1198
1202
  property_internalComment: "@internalComment",
1199
1203
  property_internalPrintPdf: "@internalPrintPdf",
1200
1204
  property_hasPrintRestriction: "@hasPrintRestriction",
1205
+ property_enforceUpdateOverUserInput: "@enforceUpdateOverUserInput",
1201
1206
  property_isCaseSensitive: "@isCaseSensitive",
1202
1207
  property_isInfoOnly: "@isInfoOnly",
1203
1208
  property_isPublic: "@isPublic",
@@ -1224,6 +1229,7 @@ var propertyKeys = {
1224
1229
  property_listItemIndent: "@listItemIndent",
1225
1230
  property_location: "@location",
1226
1231
  property_machineTranslated: "@machineTranslated",
1232
+ property_translationOf: "@translationOf",
1227
1233
  property_spansPageBreak: "@spansPageBreak",
1228
1234
  property_mailingList: "@mailingList",
1229
1235
  property_mark: "@mark",
@@ -1256,6 +1262,7 @@ var propertyKeys = {
1256
1262
  property_platformMargin: "@platformMargin",
1257
1263
  property_platformBorderRadius: "@platformBorderRadius",
1258
1264
  property_platformSelectionBorderRadius: "@platformSelectionBorderRadius",
1265
+ property_platformLogoMaxHeight: "@platformLogoMaxHeight",
1259
1266
  property_platformNeedsShadow: "@platformNeedsShadow",
1260
1267
  property_platformSeparatorColor: "@platformSeparatorColor",
1261
1268
  property_platformTextSelectionColor: "@platformTextSelectionColor",
@@ -2702,6 +2709,11 @@ var GROUPS = {
2702
2709
  description: "If true, the bit is machine-translated",
2703
2710
  format: TagFormat.plainText
2704
2711
  },
2712
+ {
2713
+ key: ConfigKey.property_translationOf,
2714
+ description: "Translation source reference",
2715
+ format: TagFormat.plainText
2716
+ },
2705
2717
  {
2706
2718
  key: ConfigKey.property_spansPageBreak,
2707
2719
  description: "If true, the bit spans a page break",
@@ -3352,6 +3364,12 @@ var GROUPS = {
3352
3364
  description: "If true, the book has print restrictions",
3353
3365
  format: TagFormat.boolean,
3354
3366
  defaultValue: "true"
3367
+ },
3368
+ {
3369
+ key: ConfigKey.property_enforceUpdateOverUserInput,
3370
+ description: "If true, prioritize new content over legacy content from the instance API",
3371
+ format: TagFormat.boolean,
3372
+ defaultValue: "false"
3355
3373
  }
3356
3374
  ]
3357
3375
  },
@@ -8678,6 +8696,11 @@ var BITS = {
8678
8696
  ],
8679
8697
  maxCount: 1
8680
8698
  },
8699
+ {
8700
+ key: ConfigKey.property_platformLogoMaxHeight,
8701
+ description: "Maximum height for the platform logo",
8702
+ format: TagFormat.number
8703
+ },
8681
8704
  {
8682
8705
  key: ConfigKey.group_platformStylesCommon,
8683
8706
  description: "Common platform styles"
@@ -9372,6 +9395,11 @@ var BITS = {
9372
9395
  baseBitType: BitType._standard,
9373
9396
  description: "Footnote bit, used to create footnotes in articles or books"
9374
9397
  },
9398
+ [BitType.formFreeText]: {
9399
+ since: "5.3.0",
9400
+ baseBitType: BitType.interview,
9401
+ description: "Form free text bit, used to create free text forms in articles or books"
9402
+ },
9375
9403
  [BitType.groupBorn]: {
9376
9404
  since: "1.3.0",
9377
9405
  baseBitType: BitType._standard,
@@ -9431,6 +9459,16 @@ var BITS = {
9431
9459
  }
9432
9460
  ]
9433
9461
  },
9462
+ [BitType.handInFreeText]: {
9463
+ since: "5.3.0",
9464
+ baseBitType: BitType.interview,
9465
+ description: "Hand in free text bit, used to create free text submission sections in articles or books"
9466
+ },
9467
+ [BitType.handInFreeTextExpert]: {
9468
+ since: "5.3.0",
9469
+ baseBitType: BitType.interview,
9470
+ description: "Hand in free text expert bit, used to create free text expert submission sections in articles or books"
9471
+ },
9434
9472
  [BitType.handInLocation]: {
9435
9473
  since: "1.5.15",
9436
9474
  baseBitType: BitType._standard,
@@ -9540,6 +9578,11 @@ var BITS = {
9540
9578
  description: "AmCharts 5 chart bit, used to embed AmCharts 5 charts in articles or books",
9541
9579
  textFormatDefault: TextFormat.json
9542
9580
  },
9581
+ [BitType.vendorDatadogDashboard]: {
9582
+ since: "5.2.0",
9583
+ baseBitType: BitType.nonProductionPrototypeIframe,
9584
+ description: "A Datadog dashboard bit, used to embed Datadog dashboards"
9585
+ },
9543
9586
  [BitType.vendorDatadogDashboardEmbed]: {
9544
9587
  since: "3.12.0",
9545
9588
  baseBitType: BitType.code,
@@ -10169,7 +10212,7 @@ var instance2 = new Config();
10169
10212
  // src/generated/package_info.ts
10170
10213
  var PACKAGE_INFO = {
10171
10214
  "name": "@gmb/bitmark-parser-generator",
10172
- "version": "5.1.0",
10215
+ "version": "5.3.0",
10173
10216
  "license": "ISC"};
10174
10217
  var Environment = {
10175
10218
  unknown: "",
@@ -10758,6 +10801,8 @@ var NodeType = {
10758
10801
  internalPrintPdfValue: "internalPrintPdfValue",
10759
10802
  hasPrintRestriction: "hasPrintRestriction",
10760
10803
  hasPrintRestrictionValue: "hasPrintRestrictionValue",
10804
+ enforceUpdateOverUserInput: "enforceUpdateOverUserInput",
10805
+ enforceUpdateOverUserInputValue: "enforceUpdateOverUserInputValue",
10761
10806
  isCaseSensitive: "isCaseSensitive",
10762
10807
  isCommented: "isCommented",
10763
10808
  isCorrect: "isCorrect",
@@ -10824,6 +10869,8 @@ var NodeType = {
10824
10869
  locationValue: "locationValue",
10825
10870
  machineTranslated: "machineTranslated",
10826
10871
  machineTranslatedValue: "machineTranslatedValue",
10872
+ translationOf: "translationOf",
10873
+ translationOfValue: "translationOfValue",
10827
10874
  spansPageBreak: "spansPageBreak",
10828
10875
  spansPageBreakValue: "spansPageBreakValue",
10829
10876
  mailingList: "mailingList",
@@ -10875,6 +10922,8 @@ var NodeType = {
10875
10922
  platformIconValue: "platformIconValue",
10876
10923
  platformLogo: "platformLogo",
10877
10924
  platformLogoValue: "platformLogoValue",
10925
+ platformLogoMaxHeight: "platformLogoMaxHeight",
10926
+ platformLogoMaxHeightValue: "platformLogoMaxHeightValue",
10878
10927
  platformPrimaryColor: "platformPrimaryColor",
10879
10928
  platformPrimaryColorValue: "platformPrimaryColorValue",
10880
10929
  platformSecondaryColor: "platformSecondaryColor",
@@ -11919,10 +11968,11 @@ var Stage = {
11919
11968
  between: "between",
11920
11969
  exit: "exit"
11921
11970
  };
11922
- var TextGenerator = class extends AstWalkerGenerator {
11971
+ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
11923
11972
  ast = new Ast();
11924
11973
  bitmarkVersion;
11925
11974
  options;
11975
+ internalTextGenerator = null;
11926
11976
  // State
11927
11977
  generateOptions = {};
11928
11978
  textFormat = TextFormat.bitmarkText;
@@ -11938,6 +11988,7 @@ var TextGenerator = class extends AstWalkerGenerator {
11938
11988
  exitedCodeBlock = false;
11939
11989
  inBulletList = false;
11940
11990
  inInline = false;
11991
+ markDepth = 0;
11941
11992
  textDepth = 0;
11942
11993
  placeholderIndex = 0;
11943
11994
  placeholders = {};
@@ -11968,6 +12019,13 @@ var TextGenerator = class extends AstWalkerGenerator {
11968
12019
  this.between = this.between.bind(this);
11969
12020
  this.exit = this.exit.bind(this);
11970
12021
  this.leaf = this.leaf.bind(this);
12022
+ if (!this.options.isInternal) {
12023
+ this.internalTextGenerator = new _TextGenerator(bitmarkVersion, {
12024
+ ...this.options,
12025
+ writeCallback: void 0,
12026
+ isInternal: true
12027
+ });
12028
+ }
11971
12029
  }
11972
12030
  /**
11973
12031
  * Generate text from a bitmark text AST
@@ -12024,6 +12082,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12024
12082
  this.exitedCodeBlock = false;
12025
12083
  this.inBulletList = false;
12026
12084
  this.inInline = false;
12085
+ this.markDepth = 0;
12027
12086
  this.textDepth = 0;
12028
12087
  this.placeholderIndex = 0;
12029
12088
  this.placeholders = {};
@@ -12071,8 +12130,16 @@ var TextGenerator = class extends AstWalkerGenerator {
12071
12130
  exit_contentValueValue(node, route) {
12072
12131
  return this.handleExitNode(node.value, route);
12073
12132
  }
12133
+ // * -> marks
12134
+ enter_marks(_node, _route) {
12135
+ this.markDepth++;
12136
+ }
12137
+ exit_marks(_node, _route) {
12138
+ this.markDepth--;
12139
+ }
12074
12140
  // END NODE HANDLERS
12075
12141
  handleEnterNode(node, route) {
12142
+ if (this.markDepth > 0) return;
12076
12143
  this.handleEnterNodePreTextCheck(node, route);
12077
12144
  this.handleIndent(node);
12078
12145
  switch (node.type) {
@@ -12083,7 +12150,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12083
12150
  case TextNodeType.hardBreak:
12084
12151
  this.writeHardBreak(node);
12085
12152
  break;
12086
- case TextNodeType.text:
12153
+ case TextNodeType.text: {
12087
12154
  this.writeMarks(node, Stage.enter);
12088
12155
  this.writeText(node);
12089
12156
  this.writeMarks(node, Stage.between);
@@ -12092,6 +12159,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12092
12159
  }
12093
12160
  this.textDepth++;
12094
12161
  break;
12162
+ }
12095
12163
  case TextNodeType.heading:
12096
12164
  this.writeHeading(node);
12097
12165
  this.inHeading = true;
@@ -12140,6 +12208,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12140
12208
  }
12141
12209
  }
12142
12210
  handleExitNode(node, _route) {
12211
+ if (this.markDepth > 0) return;
12143
12212
  switch (node.type) {
12144
12213
  case TextNodeType.text:
12145
12214
  this.textDepth--;
@@ -12443,7 +12512,7 @@ var TextGenerator = class extends AstWalkerGenerator {
12443
12512
  */
12444
12513
  writeMarks(node, stage) {
12445
12514
  if (node.marks) {
12446
- const forceSingleMark = !!(this.inInline || this.inHeading);
12515
+ const forceSingleMark = this.generateOptions.forceInline || !!(this.inInline || this.inHeading);
12447
12516
  this.thisNodeIsPreText = false;
12448
12517
  const emptyMarks = node.marks.length === 0;
12449
12518
  if (emptyMarks) {
@@ -12671,13 +12740,33 @@ var TextGenerator = class extends AstWalkerGenerator {
12671
12740
  s += `|provider:${provider}`;
12672
12741
  this.write(s);
12673
12742
  }
12674
- writeFootnoteMark(_mark) {
12743
+ writeFootnoteMark(mark) {
12675
12744
  const s = `footnote:`;
12676
12745
  this.write(s);
12746
+ const text = this.internalTextGenerator?.generateSync(
12747
+ mark.attrs?.content,
12748
+ this.textFormat,
12749
+ this.textLocation,
12750
+ {
12751
+ ...this.generateOptions,
12752
+ forceInline: true
12753
+ }
12754
+ ) ?? "";
12755
+ this.write(text);
12677
12756
  }
12678
- writeFootnoteStarMark(_mark) {
12757
+ writeFootnoteStarMark(mark) {
12679
12758
  const s = `footnote*:`;
12680
12759
  this.write(s);
12760
+ const text = this.internalTextGenerator?.generateSync(
12761
+ mark.attrs?.content,
12762
+ this.textFormat,
12763
+ this.textLocation,
12764
+ {
12765
+ ...this.generateOptions,
12766
+ forceInline: true
12767
+ }
12768
+ ) ?? "";
12769
+ this.write(text);
12681
12770
  }
12682
12771
  writeSymbolMark(mark) {
12683
12772
  if (mark.attrs == null) return;
@@ -23684,6 +23773,12 @@ var Builder = class extends BaseBuilder {
23684
23773
  data.machineTranslated,
23685
23774
  options
23686
23775
  ),
23776
+ translationOf: this.toAstProperty(
23777
+ bitType,
23778
+ ConfigKey.property_translationOf,
23779
+ data.translationOf,
23780
+ options
23781
+ ),
23687
23782
  spansPageBreak: this.toAstProperty(
23688
23783
  bitType,
23689
23784
  ConfigKey.property_spansPageBreak,
@@ -24400,6 +24495,12 @@ var Builder = class extends BaseBuilder {
24400
24495
  data.hasPrintRestriction,
24401
24496
  options
24402
24497
  ),
24498
+ enforceUpdateOverUserInput: this.toAstProperty(
24499
+ bitType,
24500
+ ConfigKey.property_enforceUpdateOverUserInput,
24501
+ data.enforceUpdateOverUserInput,
24502
+ options
24503
+ ),
24403
24504
  tocResource: this.toAstProperty(
24404
24505
  bitType,
24405
24506
  ConfigKey.property_tocResource,
@@ -24427,6 +24528,12 @@ var Builder = class extends BaseBuilder {
24427
24528
  ),
24428
24529
  platformIcon: this.toImageResource(context, data.platformIcon),
24429
24530
  platformLogo: this.toImageResource(context, data.platformLogo),
24531
+ platformLogoMaxHeight: this.toAstProperty(
24532
+ bitType,
24533
+ ConfigKey.property_platformLogoMaxHeight,
24534
+ data.platformLogoMaxHeight,
24535
+ options
24536
+ ),
24430
24537
  platformPrimaryColor: this.toAstProperty(
24431
24538
  bitType,
24432
24539
  ConfigKey.property_platformPrimaryColor,
@@ -30075,6 +30182,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
30075
30182
  if (instance2.isOfBitType(bitType, BitType.book)) {
30076
30183
  if (bitJson.maxTocChapterLevel == null) bitJson.maxTocChapterLevel = -1;
30077
30184
  if (bitJson.hasPrintRestriction == null) bitJson.hasPrintRestriction = true;
30185
+ if (bitJson.enforceUpdateOverUserInput == null) bitJson.enforceUpdateOverUserInput = false;
30078
30186
  if (bitJson.hasMarkAsDone == null) bitJson.hasMarkAsDone = false;
30079
30187
  if (bitJson.processHandIn == null) bitJson.processHandIn = false;
30080
30188
  if (bitJson.isPublic == null) bitJson.isPublic = false;
@@ -30155,6 +30263,9 @@ var JsonGenerator = class extends AstWalkerGenerator {
30155
30263
  if (instance2.isOfBitType(bitType, BitType.platformBrandTarget)) {
30156
30264
  if (bitJson.platformBrandTarget == null) bitJson.platformBrandTarget = "none";
30157
30265
  }
30266
+ if (instance2.isOfBitType(bitType, BitType.platformHeader)) {
30267
+ if (bitJson.platformLogoMaxHeight == null) bitJson.platformLogoMaxHeight = 40;
30268
+ }
30158
30269
  if (isTopLevelExample) {
30159
30270
  if (bitJson.isExample == null) bitJson.isExample = false;
30160
30271
  } else {
@@ -32368,6 +32479,9 @@ function parseFeedback(_context, _bitType, cardSet) {
32368
32479
  const choice = {
32369
32480
  choice: tfTags.choice,
32370
32481
  requireReason: tfTags.isCorrect,
32482
+ item: tfTags.item,
32483
+ lead: tfTags.lead,
32484
+ instruction: tfTags.instruction,
32371
32485
  __isDefaultExample,
32372
32486
  example
32373
32487
  };
@@ -38162,8 +38276,8 @@ var FileWriter = class extends StreamWriter {
38162
38276
  async open() {
38163
38277
  return new Promise((resolve, reject) => {
38164
38278
  const flags = this._append ? "a" : "w";
38165
- fs4.ensureDirSync(path3.dirname(this._path.toString()));
38166
- const stream = fs4.createWriteStream(this._path, {
38279
+ fs3.ensureDirSync(path3.dirname(this._path.toString()));
38280
+ const stream = fs3.createWriteStream(this._path, {
38167
38281
  flags,
38168
38282
  encoding: "utf8"
38169
38283
  });
@@ -38237,8 +38351,8 @@ var SyncFileWriter = class {
38237
38351
  }
38238
38352
  openSync() {
38239
38353
  const flag = this._append ? "a" : "w";
38240
- fs4.ensureDirSync(path3.dirname(this._path.toString()));
38241
- fs4.writeFileSync(this._path, "", {
38354
+ fs3.ensureDirSync(path3.dirname(this._path.toString()));
38355
+ fs3.writeFileSync(this._path, "", {
38242
38356
  flag,
38243
38357
  encoding: this._encoding
38244
38358
  });
@@ -38255,7 +38369,7 @@ var SyncFileWriter = class {
38255
38369
  } else {
38256
38370
  line = this.endOfLineString;
38257
38371
  }
38258
- fs4.appendFileSync(this._path, line, {
38372
+ fs3.appendFileSync(this._path, line, {
38259
38373
  encoding: this._encoding
38260
38374
  });
38261
38375
  this.lastWrite = line;
@@ -38273,7 +38387,7 @@ var SyncFileWriter = class {
38273
38387
  }
38274
38388
  str += this.endOfLineString;
38275
38389
  }
38276
- fs4.appendFileSync(this._path, str, {
38390
+ fs3.appendFileSync(this._path, str, {
38277
38391
  encoding: this._encoding
38278
38392
  });
38279
38393
  this.lastWrite = str;
@@ -38283,7 +38397,7 @@ var SyncFileWriter = class {
38283
38397
  if (!this._open) return this;
38284
38398
  if (value == null) return this;
38285
38399
  if (value) this.lastWrite = value;
38286
- fs4.appendFileSync(this._path, value, {
38400
+ fs3.appendFileSync(this._path, value, {
38287
38401
  encoding: this._encoding
38288
38402
  });
38289
38403
  return this;
@@ -38374,8 +38488,20 @@ var ConfigBuilder = class {
38374
38488
  this.buildFlat(opts);
38375
38489
  const bitConfigs = [];
38376
38490
  const groupConfigs = [];
38377
- const bitGroupConfigKeys = [];
38491
+ const bitGroupConfigKeys = /* @__PURE__ */ new Set();
38378
38492
  const bitGroupConfigs = [];
38493
+ for (const bt of Enum(BitType).values()) {
38494
+ const bitType = instance2.getBitType(bt);
38495
+ const _bitConfig = BITS[bitType];
38496
+ if (_bitConfig?.baseBitType) {
38497
+ let currentBitType = _bitConfig.baseBitType;
38498
+ while (currentBitType) {
38499
+ bitGroupConfigKeys.add(currentBitType);
38500
+ const parentConfig = BITS[currentBitType];
38501
+ currentBitType = parentConfig?.baseBitType;
38502
+ }
38503
+ }
38504
+ }
38379
38505
  for (const bt of Enum(BitType).values()) {
38380
38506
  const bitType = instance2.getBitType(bt);
38381
38507
  const _bitConfig = BITS[bitType];
@@ -38396,9 +38522,24 @@ var ConfigBuilder = class {
38396
38522
  const outputFolder = opts.outputDir ?? "assets/config";
38397
38523
  const outputFolderBits = path3.join(outputFolder, "bits");
38398
38524
  const outputFolderGroups = path3.join(outputFolder, "partials");
38399
- fs4.ensureDirSync(outputFolderBits);
38400
- fs4.ensureDirSync(outputFolderGroups);
38525
+ fs3.ensureDirSync(outputFolderBits);
38526
+ fs3.ensureDirSync(outputFolderGroups);
38527
+ const bitsFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
38528
+ for (const file of bitsFiles) {
38529
+ fs3.removeSync(path3.join(outputFolderBits, file));
38530
+ }
38531
+ const partialsFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
38532
+ for (const file of partialsFiles) {
38533
+ fs3.removeSync(path3.join(outputFolderGroups, file));
38534
+ }
38401
38535
  const fileWrites = [];
38536
+ const resolveGroupReferences = (groupKey) => {
38537
+ if (squashedGroups.has(groupKey)) {
38538
+ const replacements = squashedGroups.get(groupKey);
38539
+ return replacements.flatMap((r) => resolveGroupReferences(r));
38540
+ }
38541
+ return [groupKey];
38542
+ };
38402
38543
  const keyToJsonKey = (key, tagNameChain) => {
38403
38544
  let jsonKey = key;
38404
38545
  if (key === "%") {
@@ -38462,10 +38603,13 @@ var ConfigBuilder = class {
38462
38603
  if (k.startsWith("group_")) k = k.substring(6);
38463
38604
  k = /*'_' +*/
38464
38605
  stringUtils.camelToKebab(k);
38465
- tags2.push({
38466
- type: "group",
38467
- key: k
38468
- });
38606
+ const resolvedGroups = resolveGroupReferences(k);
38607
+ for (const groupKey of resolvedGroups) {
38608
+ tags2.push({
38609
+ type: "group",
38610
+ key: groupKey
38611
+ });
38612
+ }
38469
38613
  return tags2;
38470
38614
  }
38471
38615
  if (Array.isArray(tag.chain) && tag.chain.length > 0) {
@@ -38493,7 +38637,37 @@ var ConfigBuilder = class {
38493
38637
  tags2.push(t);
38494
38638
  return tags2;
38495
38639
  };
38640
+ for (const bt of bitGroupConfigKeys) {
38641
+ const bitType = instance2.getBitType(bt);
38642
+ const _bitConfig = BITS[bitType];
38643
+ if (_bitConfig) {
38644
+ _bitConfig.bitType = bitType;
38645
+ if (!bitGroupConfigs.some((c) => c.bitType === bitType)) {
38646
+ bitGroupConfigs.push(_bitConfig);
38647
+ }
38648
+ }
38649
+ }
38650
+ const squashedGroups = /* @__PURE__ */ new Map();
38651
+ for (const b of bitGroupConfigs) {
38652
+ const groupKey = `group-${b.bitType}`;
38653
+ const processedTags = [];
38654
+ for (const [, tag] of Object.entries(b.tags ?? [])) {
38655
+ processedTags.push(...processTagEntries(tag, []));
38656
+ }
38657
+ const allAreGroups = processedTags.every((t) => t.type === "group");
38658
+ if (allAreGroups && processedTags.length > 0) {
38659
+ const replacements = [];
38660
+ if (b.baseBitType) {
38661
+ replacements.push(`group-${b.baseBitType}`);
38662
+ }
38663
+ for (const t of processedTags) {
38664
+ replacements.push(t.key);
38665
+ }
38666
+ squashedGroups.set(groupKey, replacements);
38667
+ }
38668
+ }
38496
38669
  for (const b of bitConfigs) {
38670
+ const resolvedBitConfig = instance2.getBitConfig(b.bitType);
38497
38671
  const tags2 = [];
38498
38672
  const tagEntriesTypeOrder = [
38499
38673
  BitTagConfigKeyType.tag,
@@ -38510,46 +38684,51 @@ var ConfigBuilder = class {
38510
38684
  const typeOrder = tagEntriesTypeOrder.indexOf(typeA) - tagEntriesTypeOrder.indexOf(typeB);
38511
38685
  return typeOrder;
38512
38686
  });
38513
- if (b.baseBitType) {
38514
- tags2.push({
38515
- type: "group",
38516
- key: `group-${b.baseBitType}`
38517
- });
38518
- bitGroupConfigKeys.push(b.baseBitType);
38519
- }
38520
- for (const [_tagKey, tag] of tagEntries) {
38521
- tags2.push(...processTagEntries(tag, []));
38687
+ const isInheritedFrom = bitGroupConfigKeys.has(b.bitType);
38688
+ if (isInheritedFrom) {
38689
+ const resolvedGroups = resolveGroupReferences(`group-${b.bitType}`);
38690
+ for (const groupKey of resolvedGroups) {
38691
+ tags2.push({
38692
+ type: "group",
38693
+ key: groupKey
38694
+ });
38695
+ }
38696
+ } else {
38697
+ if (b.baseBitType) {
38698
+ const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
38699
+ for (const groupKey of resolvedGroups) {
38700
+ tags2.push({
38701
+ type: "group",
38702
+ key: groupKey
38703
+ });
38704
+ }
38705
+ }
38706
+ for (const [_tagKey, tag] of tagEntries) {
38707
+ tags2.push(...processTagEntries(tag, []));
38708
+ }
38522
38709
  }
38523
38710
  const bitJson = {
38524
38711
  name: b.bitType,
38525
38712
  description: b.description ?? "",
38526
- since: b.since,
38527
- deprecated: b.deprecated,
38713
+ since: resolvedBitConfig.since,
38714
+ deprecated: resolvedBitConfig.deprecated,
38528
38715
  history: [
38529
38716
  {
38530
- version: b.since,
38717
+ version: resolvedBitConfig.since,
38531
38718
  changes: ["Initial version"]
38532
38719
  }
38533
38720
  ],
38534
- format: b.textFormatDefault ?? "bitmark--",
38535
- bodyAllowed: b.bodyAllowed ?? true,
38536
- bodyRequired: b.bodyRequired ?? false,
38537
- footerAllowed: b.footerAllowed ?? true,
38538
- footerRequired: b.footerRequired ?? false,
38539
- resourceAttachmentAllowed: b.resourceAttachmentAllowed ?? true,
38721
+ format: resolvedBitConfig.textFormatDefault ?? "bitmark--",
38722
+ bodyAllowed: resolvedBitConfig.bodyAllowed ?? true,
38723
+ bodyRequired: resolvedBitConfig.bodyRequired ?? false,
38724
+ footerAllowed: resolvedBitConfig.footerAllowed ?? true,
38725
+ footerRequired: resolvedBitConfig.footerRequired ?? false,
38726
+ resourceAttachmentAllowed: resolvedBitConfig.resourceAttachmentAllowed ?? true,
38540
38727
  tags: tags2
38541
38728
  };
38542
38729
  const output = path3.join(outputFolderBits, `${b.bitType}.jsonc`);
38543
38730
  const str = JSON.stringify(bitJson, null, 2);
38544
- fileWrites.push(fs4.writeFile(output, str));
38545
- }
38546
- for (const bt of bitGroupConfigKeys) {
38547
- const bitType = instance2.getBitType(bt);
38548
- const _bitConfig = BITS[bitType];
38549
- if (_bitConfig) {
38550
- _bitConfig.bitType = bitType;
38551
- bitGroupConfigs.push(_bitConfig);
38552
- }
38731
+ fileWrites.push(fs3.writeFile(output, str));
38553
38732
  }
38554
38733
  const writeGroupConfigs = (groupConfigs2) => {
38555
38734
  for (const g of groupConfigs2) {
@@ -38608,14 +38787,26 @@ var ConfigBuilder = class {
38608
38787
  };
38609
38788
  const output = path3.join(outputFolderGroups, `${groupKey}.jsonc`);
38610
38789
  const str = JSON.stringify(bitJson, null, 2);
38611
- fs4.writeFileSync(output, str);
38790
+ fs3.writeFileSync(output, str);
38612
38791
  }
38613
38792
  };
38614
38793
  writeGroupConfigs(groupConfigs);
38615
38794
  const writeBitsAsGroupConfigs = (bitsAsGroupConfigs) => {
38616
38795
  for (const b of bitsAsGroupConfigs) {
38617
38796
  const groupKey = `group-${b.bitType}`;
38797
+ if (squashedGroups.has(groupKey)) {
38798
+ continue;
38799
+ }
38618
38800
  const tags2 = [];
38801
+ if (b.baseBitType) {
38802
+ const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
38803
+ for (const gk of resolvedGroups) {
38804
+ tags2.push({
38805
+ type: "group",
38806
+ key: gk
38807
+ });
38808
+ }
38809
+ }
38619
38810
  const tagEntriesTypeOrder = [
38620
38811
  BitTagConfigKeyType.tag,
38621
38812
  BitTagConfigKeyType.property,
@@ -38649,10 +38840,88 @@ var ConfigBuilder = class {
38649
38840
  };
38650
38841
  const output = path3.join(outputFolderGroups, `${groupKey}.jsonc`);
38651
38842
  const str = JSON.stringify(bitJson, null, 2);
38652
- fs4.writeFileSync(output, str);
38843
+ fs3.writeFileSync(output, str);
38653
38844
  }
38654
38845
  };
38655
38846
  writeBitsAsGroupConfigs(bitGroupConfigs);
38847
+ Promise.all(fileWrites).then(() => {
38848
+ const validationErrors = this.validateConfigTree(outputFolder);
38849
+ if (validationErrors.length > 0) {
38850
+ console.error("\n\u26A0\uFE0F Config tree validation errors:");
38851
+ for (const error of validationErrors) {
38852
+ console.error(` - ${error}`);
38853
+ }
38854
+ throw new Error(`Config tree validation failed with ${validationErrors.length} error(s)`);
38855
+ } else {
38856
+ console.log("\u2705 Config tree validation passed");
38857
+ }
38858
+ }).catch((err) => {
38859
+ console.error("Error during config build or validation:", err);
38860
+ throw err;
38861
+ });
38862
+ }
38863
+ /**
38864
+ * Validate the config tree for missing group references
38865
+ * @param outputFolder - The folder containing the config files
38866
+ * @returns Array of validation errors, empty if valid
38867
+ */
38868
+ validateConfigTree(outputFolder) {
38869
+ const errors = [];
38870
+ const outputFolderBits = path3.join(outputFolder, "bits");
38871
+ const outputFolderGroups = path3.join(outputFolder, "partials");
38872
+ const availableGroups = /* @__PURE__ */ new Set();
38873
+ if (fs3.existsSync(outputFolderGroups)) {
38874
+ const groupFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
38875
+ for (const file of groupFiles) {
38876
+ const groupName = file.replace(".jsonc", "");
38877
+ availableGroups.add(groupName);
38878
+ }
38879
+ }
38880
+ const checkTags = (tags2, filePath, lineOffset) => {
38881
+ for (let i = 0; i < tags2.length; i++) {
38882
+ const tag = tags2[i];
38883
+ if (tag.type === "group") {
38884
+ if (!availableGroups.has(tag.key)) {
38885
+ const line = lineOffset + i + 1;
38886
+ errors.push(`Missing group reference '${tag.key}' in ${filePath}:${line}`);
38887
+ }
38888
+ }
38889
+ if (tag.tags && Array.isArray(tag.tags)) {
38890
+ checkTags(tag.tags, filePath, lineOffset + i + 1);
38891
+ }
38892
+ }
38893
+ };
38894
+ if (fs3.existsSync(outputFolderBits)) {
38895
+ const bitFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
38896
+ for (const file of bitFiles) {
38897
+ const filePath = path3.join(outputFolderBits, file);
38898
+ try {
38899
+ const content = fs3.readFileSync(filePath, "utf-8");
38900
+ const config = JSON.parse(content);
38901
+ if (config.tags && Array.isArray(config.tags)) {
38902
+ checkTags(config.tags, `bits/${file}`, 15);
38903
+ }
38904
+ } catch (err) {
38905
+ errors.push(`Failed to parse ${file}: ${err}`);
38906
+ }
38907
+ }
38908
+ }
38909
+ if (fs3.existsSync(outputFolderGroups)) {
38910
+ const groupFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
38911
+ for (const file of groupFiles) {
38912
+ const filePath = path3.join(outputFolderGroups, file);
38913
+ try {
38914
+ const content = fs3.readFileSync(filePath, "utf-8");
38915
+ const config = JSON.parse(content);
38916
+ if (config.tags && Array.isArray(config.tags)) {
38917
+ checkTags(config.tags, `partials/${file}`, 15);
38918
+ }
38919
+ } catch (err) {
38920
+ errors.push(`Failed to parse ${file}: ${err}`);
38921
+ }
38922
+ }
38923
+ }
38924
+ return errors;
38656
38925
  }
38657
38926
  // Build flat bit configs
38658
38927
  buildFlat(options) {
@@ -38665,7 +38934,11 @@ var ConfigBuilder = class {
38665
38934
  }
38666
38935
  const outputFolder = opts.outputDir ?? "assets/config";
38667
38936
  const outputFolderBits = path3.join(outputFolder, "bits_flat");
38668
- fs4.ensureDirSync(outputFolderBits);
38937
+ fs3.ensureDirSync(outputFolderBits);
38938
+ const existingFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
38939
+ for (const file of existingFiles) {
38940
+ fs3.removeSync(path3.join(outputFolderBits, file));
38941
+ }
38669
38942
  const processTagEntries = (tag) => {
38670
38943
  const tags2 = [];
38671
38944
  let tagName = tag.key;
@@ -38763,7 +39036,7 @@ var ConfigBuilder = class {
38763
39036
  };
38764
39037
  const output = path3.join(outputFolderBits, `${b.bitType}.jsonc`);
38765
39038
  const str = JSON.stringify(bitJson, null, 2);
38766
- fs4.writeFileSync(output, str);
39039
+ fs3.writeFileSync(output, str);
38767
39040
  }
38768
39041
  }
38769
39042
  };
@@ -38901,8 +39174,8 @@ var BitmarkParserGenerator = class {
38901
39174
  }
38902
39175
  if (!opts.inputFormat || opts.inputFormat === Input.file) {
38903
39176
  if (env.isNode) {
38904
- if (inputIsString && fs4.existsSync(inStr)) {
38905
- inStr = fs4.readFileSync(inStr, {
39177
+ if (inputIsString && fs3.existsSync(inStr)) {
39178
+ inStr = fs3.readFileSync(inStr, {
38906
39179
  encoding: "utf8"
38907
39180
  });
38908
39181
  }
@@ -39044,8 +39317,8 @@ var BitmarkParserGenerator = class {
39044
39317
  }
39045
39318
  if (!opts.inputFormat || opts.inputFormat === Input.file) {
39046
39319
  if (env.isNode) {
39047
- if (inputIsString && fs4.existsSync(inStr)) {
39048
- inStr = fs4.readFileSync(inStr, {
39320
+ if (inputIsString && fs3.existsSync(inStr)) {
39321
+ inStr = fs3.readFileSync(inStr, {
39049
39322
  encoding: "utf8"
39050
39323
  });
39051
39324
  }
@@ -39103,8 +39376,8 @@ var BitmarkParserGenerator = class {
39103
39376
  const opts = Object.assign({}, options);
39104
39377
  if (!opts.inputFormat || opts.inputFormat === Input.file) {
39105
39378
  if (env.isNode) {
39106
- if (inputIsString && fs4.existsSync(inStr)) {
39107
- inStr = fs4.readFileSync(inStr, {
39379
+ if (inputIsString && fs3.existsSync(inStr)) {
39380
+ inStr = fs3.readFileSync(inStr, {
39108
39381
  encoding: "utf8"
39109
39382
  });
39110
39383
  }
@@ -39164,8 +39437,8 @@ var BitmarkParserGenerator = class {
39164
39437
  }
39165
39438
  if (!opts.inputFormat || opts.inputFormat === Input.file) {
39166
39439
  if (env.isNode) {
39167
- if (inputIsString && fs4.existsSync(inStr)) {
39168
- inStr = fs4.readFileSync(inStr, {
39440
+ if (inputIsString && fs3.existsSync(inStr)) {
39441
+ inStr = fs3.readFileSync(inStr, {
39169
39442
  encoding: "utf8"
39170
39443
  });
39171
39444
  }
@@ -39188,8 +39461,8 @@ var BitmarkParserGenerator = class {
39188
39461
  strRes = this.jsonStringifyPrettify(preRes, jsonOptions, true);
39189
39462
  }
39190
39463
  const flag = fileOptions.append ? "a" : "w";
39191
- fs4.ensureDirSync(path3.dirname(output));
39192
- fs4.writeFileSync(output, strRes, {
39464
+ fs3.ensureDirSync(path3.dirname(output));
39465
+ fs3.writeFileSync(output, strRes, {
39193
39466
  flag
39194
39467
  });
39195
39468
  } else {
@@ -39232,8 +39505,8 @@ var BitmarkParserGenerator = class {
39232
39505
  }
39233
39506
  if (!opts.inputFormat || opts.inputFormat === Input.file) {
39234
39507
  if (env.isNode) {
39235
- if (inputIsString && fs4.existsSync(inStr)) {
39236
- inStr = fs4.readFileSync(inStr, {
39508
+ if (inputIsString && fs3.existsSync(inStr)) {
39509
+ inStr = fs3.readFileSync(inStr, {
39237
39510
  encoding: "utf8"
39238
39511
  });
39239
39512
  }
@@ -39246,8 +39519,8 @@ var BitmarkParserGenerator = class {
39246
39519
  if (opts.outputFile) {
39247
39520
  const output = opts.outputFile.toString();
39248
39521
  const flag = fileOptions.append ? "a" : "w";
39249
- fs4.ensureDirSync(path3.dirname(output));
39250
- fs4.writeFileSync(output, res, {
39522
+ fs3.ensureDirSync(path3.dirname(output));
39523
+ fs3.writeFileSync(output, res, {
39251
39524
  flag
39252
39525
  });
39253
39526
  } else {
@@ -39285,8 +39558,8 @@ var BitmarkParserGenerator = class {
39285
39558
  }
39286
39559
  if (!opts.inputFormat || opts.inputFormat === Input.file) {
39287
39560
  if (env.isNode) {
39288
- if (inputIsString && fs4.existsSync(inStr)) {
39289
- inStr = fs4.readFileSync(inStr, {
39561
+ if (inputIsString && fs3.existsSync(inStr)) {
39562
+ inStr = fs3.readFileSync(inStr, {
39290
39563
  encoding: "utf8"
39291
39564
  });
39292
39565
  }
@@ -39299,8 +39572,8 @@ var BitmarkParserGenerator = class {
39299
39572
  if (opts.outputFile) {
39300
39573
  const output = opts.outputFile.toString();
39301
39574
  const flag = fileOptions.append ? "a" : "w";
39302
- fs4.ensureDirSync(path3.dirname(output));
39303
- fs4.writeFileSync(output, res, {
39575
+ fs3.ensureDirSync(path3.dirname(output));
39576
+ fs3.writeFileSync(output, res, {
39304
39577
  flag
39305
39578
  });
39306
39579
  } else {
@@ -39345,8 +39618,8 @@ var BitmarkParserGenerator = class {
39345
39618
  init();
39346
39619
  async function readInput(input) {
39347
39620
  if (input !== void 0) {
39348
- if (await fs4.pathExists(input)) {
39349
- return fs4.readFile(input, "utf8");
39621
+ if (await fs3.pathExists(input)) {
39622
+ return fs3.readFile(input, "utf8");
39350
39623
  }
39351
39624
  return input;
39352
39625
  }
@@ -39359,8 +39632,8 @@ async function readInput(input) {
39359
39632
  async function writeOutput(content, outputFile, append = false) {
39360
39633
  const text = typeof content === "string" ? content : JSON.stringify(content);
39361
39634
  if (outputFile) {
39362
- await fs4.ensureDir(path3.dirname(outputFile));
39363
- await fs4.writeFile(outputFile, text, { flag: append ? "a" : "w" });
39635
+ await fs3.ensureDir(path3.dirname(outputFile));
39636
+ await fs3.writeFile(outputFile, text, { flag: append ? "a" : "w" });
39364
39637
  } else {
39365
39638
  console.log(text);
39366
39639
  }