@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.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",
@@ -1355,6 +1358,7 @@ var propertyKeys = {
1355
1358
  property_platformMargin: "@platformMargin",
1356
1359
  property_platformBorderRadius: "@platformBorderRadius",
1357
1360
  property_platformSelectionBorderRadius: "@platformSelectionBorderRadius",
1361
+ property_platformLogoMaxHeight: "@platformLogoMaxHeight",
1358
1362
  property_platformNeedsShadow: "@platformNeedsShadow",
1359
1363
  property_platformSeparatorColor: "@platformSeparatorColor",
1360
1364
  property_platformTextSelectionColor: "@platformTextSelectionColor",
@@ -8797,6 +8801,11 @@ var BITS = {
8797
8801
  ],
8798
8802
  maxCount: 1
8799
8803
  },
8804
+ {
8805
+ key: ConfigKey.property_platformLogoMaxHeight,
8806
+ description: "Maximum height for the platform logo",
8807
+ format: TagFormat.number
8808
+ },
8800
8809
  {
8801
8810
  key: ConfigKey.group_platformStylesCommon,
8802
8811
  description: "Common platform styles"
@@ -9491,6 +9500,11 @@ var BITS = {
9491
9500
  baseBitType: BitType._standard,
9492
9501
  description: "Footnote bit, used to create footnotes in articles or books"
9493
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
+ },
9494
9508
  [BitType.groupBorn]: {
9495
9509
  since: "1.3.0",
9496
9510
  baseBitType: BitType._standard,
@@ -9550,6 +9564,16 @@ var BITS = {
9550
9564
  }
9551
9565
  ]
9552
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
+ },
9553
9577
  [BitType.handInLocation]: {
9554
9578
  since: "1.5.15",
9555
9579
  baseBitType: BitType._standard,
@@ -10293,7 +10317,7 @@ var instance2 = new Config();
10293
10317
  // src/generated/package_info.ts
10294
10318
  var PACKAGE_INFO = {
10295
10319
  "name": "@gmb/bitmark-parser-generator",
10296
- "version": "5.2.0",
10320
+ "version": "5.3.1",
10297
10321
  "author": "Get More Brain Ltd",
10298
10322
  "license": "ISC",
10299
10323
  "description": "A bitmark parser and generator using Peggy.js"
@@ -11035,6 +11059,8 @@ var NodeType = {
11035
11059
  platformIconValue: "platformIconValue",
11036
11060
  platformLogo: "platformLogo",
11037
11061
  platformLogoValue: "platformLogoValue",
11062
+ platformLogoMaxHeight: "platformLogoMaxHeight",
11063
+ platformLogoMaxHeightValue: "platformLogoMaxHeightValue",
11038
11064
  platformPrimaryColor: "platformPrimaryColor",
11039
11065
  platformPrimaryColorValue: "platformPrimaryColorValue",
11040
11066
  platformSecondaryColor: "platformSecondaryColor",
@@ -24823,6 +24849,12 @@ var Builder = class extends BaseBuilder {
24823
24849
  ),
24824
24850
  platformIcon: this.toImageResource(context, data.platformIcon),
24825
24851
  platformLogo: this.toImageResource(context, data.platformLogo),
24852
+ platformLogoMaxHeight: this.toAstProperty(
24853
+ bitType,
24854
+ ConfigKey.property_platformLogoMaxHeight,
24855
+ data.platformLogoMaxHeight,
24856
+ options
24857
+ ),
24826
24858
  platformPrimaryColor: this.toAstProperty(
24827
24859
  bitType,
24828
24860
  ConfigKey.property_platformPrimaryColor,
@@ -30577,6 +30609,9 @@ var JsonGenerator = class extends AstWalkerGenerator {
30577
30609
  if (instance2.isOfBitType(bitType, BitType.platformBrandTarget)) {
30578
30610
  if (bitJson.platformBrandTarget == null) bitJson.platformBrandTarget = "none";
30579
30611
  }
30612
+ if (instance2.isOfBitType(bitType, BitType.platformHeader)) {
30613
+ if (bitJson.platformLogoMaxHeight == null) bitJson.platformLogoMaxHeight = 40;
30614
+ }
30580
30615
  if (isTopLevelExample) {
30581
30616
  if (bitJson.isExample == null) bitJson.isExample = false;
30582
30617
  } else {
@@ -32864,6 +32899,9 @@ function parseFeedback(_context, _bitType, cardSet) {
32864
32899
  const choice = {
32865
32900
  choice: tfTags.choice,
32866
32901
  requireReason: tfTags.isCorrect,
32902
+ item: tfTags.item,
32903
+ lead: tfTags.lead,
32904
+ instruction: tfTags.instruction,
32867
32905
  __isDefaultExample,
32868
32906
  example
32869
32907
  };
@@ -38964,8 +39002,20 @@ var ConfigBuilder = class {
38964
39002
  this.buildFlat(opts);
38965
39003
  const bitConfigs = [];
38966
39004
  const groupConfigs = [];
38967
- const bitGroupConfigKeys = [];
39005
+ const bitGroupConfigKeys = /* @__PURE__ */ new Set();
38968
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
+ }
38969
39019
  for (const bt of (0, import_superenum50.Enum)(BitType).values()) {
38970
39020
  const bitType = instance2.getBitType(bt);
38971
39021
  const _bitConfig = BITS[bitType];
@@ -38988,7 +39038,22 @@ var ConfigBuilder = class {
38988
39038
  const outputFolderGroups = import_node_path3.default.join(outputFolder, "partials");
38989
39039
  import_fs_extra3.default.ensureDirSync(outputFolderBits);
38990
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
+ }
38991
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
+ };
38992
39057
  const keyToJsonKey = (key, tagNameChain) => {
38993
39058
  let jsonKey = key;
38994
39059
  if (key === "%") {
@@ -39052,10 +39117,13 @@ var ConfigBuilder = class {
39052
39117
  if (k.startsWith("group_")) k = k.substring(6);
39053
39118
  k = /*'_' +*/
39054
39119
  stringUtils.camelToKebab(k);
39055
- tags2.push({
39056
- type: "group",
39057
- key: k
39058
- });
39120
+ const resolvedGroups = resolveGroupReferences(k);
39121
+ for (const groupKey of resolvedGroups) {
39122
+ tags2.push({
39123
+ type: "group",
39124
+ key: groupKey
39125
+ });
39126
+ }
39059
39127
  return tags2;
39060
39128
  }
39061
39129
  if (Array.isArray(tag.chain) && tag.chain.length > 0) {
@@ -39083,7 +39151,37 @@ var ConfigBuilder = class {
39083
39151
  tags2.push(t);
39084
39152
  return tags2;
39085
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
+ }
39086
39183
  for (const b of bitConfigs) {
39184
+ const resolvedBitConfig = instance2.getBitConfig(b.bitType);
39087
39185
  const tags2 = [];
39088
39186
  const tagEntriesTypeOrder = [
39089
39187
  BitTagConfigKeyType.tag,
@@ -39100,47 +39198,52 @@ var ConfigBuilder = class {
39100
39198
  const typeOrder = tagEntriesTypeOrder.indexOf(typeA) - tagEntriesTypeOrder.indexOf(typeB);
39101
39199
  return typeOrder;
39102
39200
  });
39103
- if (b.baseBitType) {
39104
- tags2.push({
39105
- type: "group",
39106
- key: `group-${b.baseBitType}`
39107
- });
39108
- bitGroupConfigKeys.push(b.baseBitType);
39109
- }
39110
- for (const [_tagKey, tag] of tagEntries) {
39111
- 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
+ }
39112
39223
  }
39113
39224
  const bitJson = {
39114
39225
  name: b.bitType,
39115
39226
  description: b.description ?? "",
39116
- since: b.since,
39117
- deprecated: b.deprecated,
39227
+ since: resolvedBitConfig.since,
39228
+ deprecated: resolvedBitConfig.deprecated,
39118
39229
  history: [
39119
39230
  {
39120
- version: b.since,
39231
+ version: resolvedBitConfig.since,
39121
39232
  changes: ["Initial version"]
39122
39233
  }
39123
39234
  ],
39124
- format: b.textFormatDefault ?? "bitmark--",
39125
- bodyAllowed: b.bodyAllowed ?? true,
39126
- bodyRequired: b.bodyRequired ?? false,
39127
- footerAllowed: b.footerAllowed ?? true,
39128
- footerRequired: b.footerRequired ?? false,
39129
- 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,
39130
39241
  tags: tags2
39131
39242
  };
39132
39243
  const output = import_node_path3.default.join(outputFolderBits, `${b.bitType}.jsonc`);
39133
39244
  const str = JSON.stringify(bitJson, null, 2);
39134
39245
  fileWrites.push(import_fs_extra3.default.writeFile(output, str));
39135
39246
  }
39136
- for (const bt of bitGroupConfigKeys) {
39137
- const bitType = instance2.getBitType(bt);
39138
- const _bitConfig = BITS[bitType];
39139
- if (_bitConfig) {
39140
- _bitConfig.bitType = bitType;
39141
- bitGroupConfigs.push(_bitConfig);
39142
- }
39143
- }
39144
39247
  const writeGroupConfigs = (groupConfigs2) => {
39145
39248
  for (const g of groupConfigs2) {
39146
39249
  const tags2 = [];
@@ -39205,7 +39308,19 @@ var ConfigBuilder = class {
39205
39308
  const writeBitsAsGroupConfigs = (bitsAsGroupConfigs) => {
39206
39309
  for (const b of bitsAsGroupConfigs) {
39207
39310
  const groupKey = `group-${b.bitType}`;
39311
+ if (squashedGroups.has(groupKey)) {
39312
+ continue;
39313
+ }
39208
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
+ }
39209
39324
  const tagEntriesTypeOrder = [
39210
39325
  BitTagConfigKeyType.tag,
39211
39326
  BitTagConfigKeyType.property,
@@ -39243,6 +39358,84 @@ var ConfigBuilder = class {
39243
39358
  }
39244
39359
  };
39245
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;
39246
39439
  }
39247
39440
  // Build flat bit configs
39248
39441
  buildFlat(options) {
@@ -39256,6 +39449,10 @@ var ConfigBuilder = class {
39256
39449
  const outputFolder = opts.outputDir ?? "assets/config";
39257
39450
  const outputFolderBits = import_node_path3.default.join(outputFolder, "bits_flat");
39258
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
+ }
39259
39456
  const processTagEntries = (tag) => {
39260
39457
  const tags2 = [];
39261
39458
  let tagName = tag.key;