@gmb/bitmark-parser-generator 5.37.0 → 5.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1212,6 +1212,7 @@ import { Enum } from "@ncoderz/superenum";
1212
1212
  // src/model/enum/GroupKey.ts
1213
1213
  import "@ncoderz/superenum";
1214
1214
  var groupKeys = {
1215
+ group_accessibilityDecorative: "group_accessibilityDecorative",
1215
1216
  group_standardAllBits: "group_standardAllBits",
1216
1217
  group_standardItemLead: "group_standardItemLead",
1217
1218
  group_standardItemLeadInstructionHint: "group_standardItemLeadInstructionHint",
@@ -1277,6 +1278,8 @@ var groupKeys = {
1277
1278
  // src/model/enum/PropertyKey.ts
1278
1279
  import "@ncoderz/superenum";
1279
1280
  var propertyKeys = {
1281
+ property_accessibilityGroupTag: "@accessibilityGroupTag",
1282
+ property_accessibilityTag: "@accessibilityTag",
1280
1283
  property_action: "@action",
1281
1284
  property_activityType: "@activityType",
1282
1285
  property_additionalSolutions: "@additionalSolutions",
@@ -4467,6 +4470,7 @@ var CARDSETS = {
4467
4470
  };
4468
4471
 
4469
4472
  // src/config/raw/groups.ts
4473
+ var ACCESSIBILITY_TAG_VALUES = ["complex", "functional", "decorative", "standard"];
4470
4474
  var GROUPS = {
4471
4475
  [ConfigKey.group_standardAllBits]: {
4472
4476
  name: "Standard",
@@ -4573,7 +4577,8 @@ var GROUPS = {
4573
4577
  {
4574
4578
  key: ConfigKey.property_isCollapsible,
4575
4579
  description: "If true, the bit is collapsible",
4576
- format: TagFormat.boolean
4580
+ format: TagFormat.boolean,
4581
+ nullable: true
4577
4582
  },
4578
4583
  {
4579
4584
  key: ConfigKey.property_spansPageBreak,
@@ -4738,6 +4743,36 @@ var GROUPS = {
4738
4743
  }
4739
4744
  ]
4740
4745
  },
4746
+ {
4747
+ key: ConfigKey.property_accessibilityTag,
4748
+ description: "The accessibility classification(s) for the bit",
4749
+ format: TagFormat.enumeration,
4750
+ values: ACCESSIBILITY_TAG_VALUES,
4751
+ nullable: true,
4752
+ maxCount: Count.infinity
4753
+ },
4754
+ {
4755
+ key: ConfigKey.property_accessibilityGroupTag,
4756
+ jsonKey: "accessibilityGroupTag.name",
4757
+ // Entity-merge semantics, as for `@groupTag`: repeated
4758
+ // `[@accessibilityGroupTag: name]` occurrences with the same value fold
4759
+ // into one entry; chained `@accessibilityTag` children's arrays merge as sets.
4760
+ exportJsonKey: { accessibilityGroupTag: [{ "@id": "name", name: "$" }] },
4761
+ description: "The accessibility group tag(s) for the bit",
4762
+ format: TagFormat.plainText,
4763
+ maxCount: Count.infinity,
4764
+ chain: [
4765
+ {
4766
+ key: ConfigKey.property_accessibilityTag,
4767
+ exportJsonKey: { tags: ["$"] },
4768
+ description: "The accessibility classification(s) for the group",
4769
+ format: TagFormat.enumeration,
4770
+ values: ACCESSIBILITY_TAG_VALUES,
4771
+ nullable: true,
4772
+ maxCount: Count.infinity
4773
+ }
4774
+ ]
4775
+ },
4741
4776
  {
4742
4777
  key: ConfigKey.property_reviewTag,
4743
4778
  description: "The review tag(s) for the bit",
@@ -4868,6 +4903,37 @@ var GROUPS = {
4868
4903
  }
4869
4904
  ]
4870
4905
  },
4906
+ [ConfigKey.group_accessibilityDecorative]: {
4907
+ name: "Accessibility (decorative)",
4908
+ description: "Accessibility tags defaulting to a decorative image, for bits that are decorative by definition",
4909
+ type: GroupConfigType.standard,
4910
+ // Re-declares `@accessibilityGroupTag` (in full — tag hydration is last-wins
4911
+ // per config key, it does not merge) with the decorative defaults. The
4912
+ // standalone `@accessibilityTag` is deliberately NOT re-declared: the default
4913
+ // belongs to the group structure only.
4914
+ tags: [
4915
+ {
4916
+ key: ConfigKey.property_accessibilityGroupTag,
4917
+ jsonKey: "accessibilityGroupTag.name",
4918
+ exportJsonKey: { accessibilityGroupTag: [{ "@id": "name", name: "$" }] },
4919
+ description: "The accessibility group tag(s) for the bit",
4920
+ format: TagFormat.plainText,
4921
+ defaultValue: "image",
4922
+ maxCount: Count.infinity,
4923
+ chain: [
4924
+ {
4925
+ key: ConfigKey.property_accessibilityTag,
4926
+ exportJsonKey: { tags: ["$"] },
4927
+ description: "The accessibility classification(s) for the group",
4928
+ format: TagFormat.enumeration,
4929
+ values: ACCESSIBILITY_TAG_VALUES,
4930
+ defaultValue: "decorative",
4931
+ maxCount: Count.infinity
4932
+ }
4933
+ ]
4934
+ }
4935
+ ]
4936
+ },
4871
4937
  [ConfigKey.group_standardItemLead]: {
4872
4938
  type: GroupConfigType.standard,
4873
4939
  description: "Standard group for item, lead, page number, and margin number tags",
@@ -8771,6 +8837,12 @@ var BITS = {
8771
8837
  description: "The progress of the chapter, used for tracking reading progress",
8772
8838
  format: TagFormat.boolean,
8773
8839
  defaultValue: "true"
8840
+ },
8841
+ {
8842
+ key: ConfigKey.property_isCollapsible,
8843
+ description: "If true, the chapter is collapsible (always emitted; defaults false)",
8844
+ format: TagFormat.boolean,
8845
+ defaultValue: "false"
8774
8846
  }
8775
8847
  ]
8776
8848
  },
@@ -10180,7 +10252,9 @@ var BITS = {
10180
10252
  },
10181
10253
  [BitType.printPageBreak]: {
10182
10254
  since: "5.4.0",
10183
- baseBitType: BitType.separator,
10255
+ // Based on `article`, not `separator`: `separator` adds nothing over `article`,
10256
+ // and basing on it would inherit the decorative accessibility defaults.
10257
+ baseBitType: BitType.article,
10184
10258
  description: "Print page break bit, used to create page breaks for printing in articles or books"
10185
10259
  },
10186
10260
  [BitType.releaseNotesSummary]: {
@@ -10266,12 +10340,24 @@ var BITS = {
10266
10340
  [BitType.separator]: {
10267
10341
  since: "1.4.15",
10268
10342
  baseBitType: BitType.article,
10269
- description: "Separator bit, used to create visual separators in articles or books"
10343
+ description: "Separator bit, used to create visual separators in articles or books",
10344
+ tags: [
10345
+ {
10346
+ key: ConfigKey.group_accessibilityDecorative,
10347
+ description: "Accessibility tags, defaulting to a decorative image"
10348
+ }
10349
+ ]
10270
10350
  },
10271
10351
  [BitType.separatorAlt]: {
10272
10352
  since: "1.16.0",
10273
10353
  baseBitType: BitType.separator,
10274
- description: "Alternative separator bit, used to create visual separators in articles or books with alternative styling"
10354
+ description: "Alternative separator bit, used to create visual separators in articles or books with alternative styling",
10355
+ tags: [
10356
+ {
10357
+ key: ConfigKey.group_accessibilityDecorative,
10358
+ description: "Accessibility tags, defaulting to a decorative image"
10359
+ }
10360
+ ]
10275
10361
  },
10276
10362
  [BitType.sticker]: {
10277
10363
  since: "1.5.28",
@@ -11507,7 +11593,13 @@ var BITS = {
11507
11593
  [BitType.imageMood]: {
11508
11594
  since: "1.3.0",
11509
11595
  baseBitType: BitType.image,
11510
- description: "Image mood bit, used to create mood images in articles or books"
11596
+ description: "Image mood bit, used to create mood images in articles or books",
11597
+ tags: [
11598
+ {
11599
+ key: ConfigKey.group_accessibilityDecorative,
11600
+ description: "Accessibility tags, defaulting to a decorative image"
11601
+ }
11602
+ ]
11511
11603
  },
11512
11604
  [BitType.imagePortrait]: {
11513
11605
  since: "1.3.0",
@@ -11527,6 +11619,10 @@ var BITS = {
11527
11619
  {
11528
11620
  key: ConfigKey.group_imageNoZoom,
11529
11621
  description: "Image no zoom tags for images, used to define whether images should have zoom functionality"
11622
+ },
11623
+ {
11624
+ key: ConfigKey.group_accessibilityDecorative,
11625
+ description: "Accessibility tags, defaulting to a decorative image"
11530
11626
  }
11531
11627
  ],
11532
11628
  resourceAttachmentAllowed: false
@@ -11534,7 +11630,13 @@ var BITS = {
11534
11630
  [BitType.imageSeparatorAlt]: {
11535
11631
  since: "1.16.0",
11536
11632
  baseBitType: BitType.imageSeparator,
11537
- description: "Alternative image separator bit, used to create alternative separators in articles or books"
11633
+ description: "Alternative image separator bit, used to create alternative separators in articles or books",
11634
+ tags: [
11635
+ {
11636
+ key: ConfigKey.group_accessibilityDecorative,
11637
+ description: "Accessibility tags, defaulting to a decorative image"
11638
+ }
11639
+ ]
11538
11640
  },
11539
11641
  [BitType.imageScreenshot]: {
11540
11642
  since: "1.3.0",
@@ -14813,7 +14915,7 @@ var instance2 = new Config();
14813
14915
  // src/generated/package_info.ts
14814
14916
  var PACKAGE_INFO = {
14815
14917
  "name": "@gmb/bitmark-parser-generator",
14816
- "version": "5.37.0",
14918
+ "version": "5.38.0",
14817
14919
  "author": "Get More Brain Ltd",
14818
14920
  "license": "ISC",
14819
14921
  "description": "A bitmark parser and generator using Peggy.js"
@@ -15167,6 +15269,10 @@ var NodeType = {
15167
15269
  // unknown
15168
15270
  __isDefaultExample: "__isDefaultExample",
15169
15271
  __typeAlias: "__typeAlias",
15272
+ accessibilityGroupTag: "accessibilityGroupTag",
15273
+ accessibilityGroupTagValue: "accessibilityGroupTagValue",
15274
+ accessibilityTag: "accessibilityTag",
15275
+ accessibilityTagValue: "accessibilityTagValue",
15170
15276
  action: "action",
15171
15277
  actionValue: "actionValue",
15172
15278
  activityType: "activityType",
@@ -27491,6 +27597,12 @@ var BaseBuilder = class {
27491
27597
  case TagFormat.plainText:
27492
27598
  if (instance6.asNumber(v) != null) v = `${v}`;
27493
27599
  return stringUtils.isString(v) ? stringUtils.trimmedString(v) : void 0;
27600
+ case TagFormat.enumeration: {
27601
+ if (instance6.asNumber(v) != null) v = `${v}`;
27602
+ const enumValue = stringUtils.isString(v) ? stringUtils.trimmedString(v) : void 0;
27603
+ if (enumValue == null || enumValue === "") return propertyConfig?.defaultValue ?? "";
27604
+ return enumValue;
27605
+ }
27494
27606
  case TagFormat.number:
27495
27607
  return instance6.asNumber(v);
27496
27608
  case TagFormat.boolean:
@@ -29057,6 +29169,10 @@ var Builder = class extends BaseBuilder {
29057
29169
  const bitType = data.bitType;
29058
29170
  const bitConfig = instance2.getBitConfig(bitType);
29059
29171
  const isCollapsibleDefaultsTrue = bitConfig.tags[ConfigKey.property_isCollapsible]?.defaultValue === "true";
29172
+ const accessibilityGroupTag = this.resolveAccessibilityGroupTag(
29173
+ bitConfig,
29174
+ data.accessibilityGroupTag
29175
+ );
29060
29176
  const deprecatedTextFormat = Enum7(DeprecatedTextFormat).fromValue(data.textFormat);
29061
29177
  let textFormat = Enum7(TextFormat).fromValue(data.textFormat) ?? bitConfig.textFormatDefault;
29062
29178
  if (deprecatedTextFormat === DeprecatedTextFormat.bitmarkMinusMinus) {
@@ -29292,6 +29408,13 @@ var Builder = class extends BaseBuilder {
29292
29408
  slug: this.toAstProperty(bitType, ConfigKey.property_slug, data.slug, options),
29293
29409
  tag: this.toAstProperty(bitType, ConfigKey.property_tag, data.tag, options),
29294
29410
  groupTag: this.buildGroupTags(context, data.groupTag),
29411
+ accessibilityTag: this.toAstProperty(
29412
+ bitType,
29413
+ ConfigKey.property_accessibilityTag,
29414
+ data.accessibilityTag,
29415
+ options
29416
+ ),
29417
+ accessibilityGroupTag: this.buildGroupTags(context, accessibilityGroupTag),
29295
29418
  reviewTag: this.toAstProperty(bitType, ConfigKey.property_reviewTag, data.reviewTag, options),
29296
29419
  reviewerTag: this.toAstProperty(
29297
29420
  bitType,
@@ -30344,6 +30467,26 @@ var Builder = class extends BaseBuilder {
30344
30467
  });
30345
30468
  return node;
30346
30469
  }
30470
+ /**
30471
+ * Resolve the accessibilityGroupTag data, materialising the bit type's default when absent.
30472
+ *
30473
+ * PLAN-019: `group_accessibilityDecorative` re-declares `@accessibilityGroupTag` with a
30474
+ * `defaultValue`, and its chained `@accessibilityTag` likewise. When the bit carries no
30475
+ * authored value, synthesize the default group so it reaches both generators. An authored
30476
+ * value always wins.
30477
+ *
30478
+ * @param bitConfig - the resolved config for the bit
30479
+ * @param data - authored data for the node, if any
30480
+ * @returns
30481
+ */
30482
+ resolveAccessibilityGroupTag(bitConfig, data) {
30483
+ if (data != null && (!Array.isArray(data) || data.length > 0)) return data;
30484
+ const groupConfig = bitConfig.tags[ConfigKey.property_accessibilityGroupTag];
30485
+ const name = groupConfig?.defaultValue;
30486
+ if (name == null) return data;
30487
+ const tag = groupConfig?.chain?.[ConfigKey.property_accessibilityTag]?.defaultValue;
30488
+ return [{ name, tags: tag != null ? [tag] : [] }];
30489
+ }
30347
30490
  /**
30348
30491
  * Build groupTag[] node
30349
30492
  *
@@ -32426,6 +32569,29 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
32426
32569
  }
32427
32570
  return false;
32428
32571
  }
32572
+ // bitmarkAst -> bits -> bitsValue -> accessibilityGroupTag
32573
+ enter_accessibilityGroupTag(node, route) {
32574
+ const accessibilityGroupTag = node.value;
32575
+ const parent = this.getParentNode(route);
32576
+ if (parent?.key !== NodeType.bitsValue) return true;
32577
+ for (const gt of accessibilityGroupTag) {
32578
+ const { name, tags: tags2 } = gt;
32579
+ this.writeProperty("accessibilityGroupTag", name, route, {
32580
+ format: TagFormat.plainText,
32581
+ writeEmpty: true
32582
+ });
32583
+ if (tags2 && tags2.length > 0) {
32584
+ for (const t of tags2) {
32585
+ this.writeProperty("accessibilityTag", t, route, {
32586
+ format: TagFormat.plainText,
32587
+ writeEmpty: true,
32588
+ forceChain: true
32589
+ });
32590
+ }
32591
+ }
32592
+ }
32593
+ return false;
32594
+ }
32429
32595
  // bitmarkAst -> bits -> bitsValue -> labelTrue / labelFalse
32430
32596
  leaf_labelTrue(node, route) {
32431
32597
  const value = node.value;
@@ -35184,10 +35350,14 @@ var JsonGenerator = class extends AstWalkerGenerator {
35184
35350
  }
35185
35351
  // bitmarkAst -> bits -> bitsValue -> isCollapsible
35186
35352
  /**
35187
- * PLAN-016: `isCollapsible` is emitted only when true. `false` is the implied
35188
- * default for every bit, so it is never written to the JSON — an absent key
35189
- * means the bit's configured default (`true` for the deprecated
35190
- * `*-collapsible` bit types, `false` everywhere else).
35353
+ * `isCollapsible` is emitted only when explicitly set on the bit — an explicit
35354
+ * `true`/`false` in the source is emitted as-is, and an absent tag yields no
35355
+ * JSON key (the tag is nullable in the config: no default, unset when absent).
35356
+ *
35357
+ * Two exceptions always carry a value: chapter bits default to `false`
35358
+ * (`defaultValue: 'false'` in the bit config, applied in `cleanBitJson()`),
35359
+ * and the deprecated `*-collapsible` bit types default to `true` (materialised
35360
+ * into the AST by the Builder).
35191
35361
  *
35192
35362
  * Defining these handlers suppresses the generic property handlers that
35193
35363
  * `generatePropertyHandlers()` would otherwise install for this tag.
@@ -35195,7 +35365,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
35195
35365
  leaf_isCollapsible(node, route) {
35196
35366
  const parent = this.getParentNode(route);
35197
35367
  if (parent?.key !== NodeType.bitsValue) return false;
35198
- if (node.value === true) this.bitJson.isCollapsible = true;
35368
+ if (node.value != null) this.bitJson.isCollapsible = node.value === true;
35199
35369
  return false;
35200
35370
  }
35201
35371
  enter_isCollapsible(node, route) {
@@ -36074,6 +36244,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
36074
36244
  if (instance2.isOfBitType(bitType, BitType.chapter)) {
36075
36245
  if (bitJson.toc == null) bitJson.toc = true;
36076
36246
  if (bitJson.progress == null) bitJson.progress = true;
36247
+ if (bitJson.isCollapsible == null) bitJson.isCollapsible = false;
36077
36248
  if (bitJson.level == null) bitJson.level = 1;
36078
36249
  if (bitJson.body == null) bitJson.body = this.bodyDefault;
36079
36250
  }
@@ -39588,19 +39759,25 @@ function handleStandardStringExample(context, _content, example, target) {
39588
39759
  }
39589
39760
 
39590
39761
  // src/parser/bitmark/peg/contentProcessors/GroupTagChainContentProcessor.ts
39591
- function groupTagChainContentProcessor(context, _contentDepth, tagsConfig, content, target) {
39762
+ var GROUP_TAG = { groupKey: "groupTag", memberKey: "tag" };
39763
+ var ACCESSIBILITY_GROUP_TAG = {
39764
+ groupKey: "accessibilityGroupTag",
39765
+ memberKey: "accessibilityTag"
39766
+ };
39767
+ function groupTagChainContentProcessor(context, _contentDepth, tagsConfig, content, target, keys = GROUP_TAG) {
39592
39768
  const { value } = content;
39593
- if (context.DEBUG_CHAIN_CONTENT) context.debugPrint("groupTag content", content);
39769
+ const { groupKey, memberKey } = keys;
39770
+ if (context.DEBUG_CHAIN_CONTENT) context.debugPrint(`${groupKey} content`, content);
39594
39771
  const tags2 = context.bitContentProcessor(ContentDepth.Chain, tagsConfig, content.chain);
39595
- if (context.DEBUG_CHAIN_TAGS) context.debugPrint("groupTag TAGS", tags2);
39596
- const { tag } = tags2;
39772
+ if (context.DEBUG_CHAIN_TAGS) context.debugPrint(`${groupKey} TAGS`, tags2);
39773
+ const memberTags = tags2[memberKey];
39597
39774
  const name = stringUtils.trimmedString(value) ?? "";
39598
39775
  const node = {
39599
39776
  name,
39600
- tags: tag ?? []
39777
+ tags: memberTags ?? []
39601
39778
  };
39602
- if (!Array.isArray(target.groupTag)) target.groupTag = [];
39603
- target.groupTag.push(node);
39779
+ if (!Array.isArray(target[groupKey])) target[groupKey] = [];
39780
+ target[groupKey].push(node);
39604
39781
  }
39605
39782
 
39606
39783
  // src/parser/bitmark/peg/contentProcessors/ImageSourceChainContentProcessor.ts
@@ -39820,6 +39997,16 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
39820
39997
  } else if (configKey === ConfigKey.property_groupTag) {
39821
39998
  groupTagChainContentProcessor(context, contentDepth, propertyConfig.chain, content, target);
39822
39999
  return;
40000
+ } else if (configKey === ConfigKey.property_accessibilityGroupTag) {
40001
+ groupTagChainContentProcessor(
40002
+ context,
40003
+ contentDepth,
40004
+ propertyConfig.chain,
40005
+ content,
40006
+ target,
40007
+ ACCESSIBILITY_GROUP_TAG
40008
+ );
40009
+ return;
39823
40010
  } else if (configKey === ConfigKey.property_ratingLevelStart || configKey === ConfigKey.property_ratingLevelEnd) {
39824
40011
  ratingLevelChainContentProcessor(
39825
40012
  context,
@@ -39872,6 +40059,23 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
39872
40059
  location: TextLocation.tag
39873
40060
  }
39874
40061
  );
40062
+ case TagFormat.enumeration: {
40063
+ const enumValue = instance3.unbreakscape(
40064
+ stringUtils.isString(v2) ? stringUtils.trimmedString(v2) : void 0,
40065
+ {
40066
+ format: TextFormat.plainText,
40067
+ location: TextLocation.tag
40068
+ }
40069
+ );
40070
+ if (enumValue == null || enumValue === "") return c.defaultValue ?? "";
40071
+ if (c.values && !c.values.includes(enumValue)) {
40072
+ context.addWarning(
40073
+ `Invalid value '${enumValue}' for property [@${tag}]. Valid values: ${c.values.join(" | ")}`,
40074
+ content
40075
+ );
40076
+ }
40077
+ return enumValue;
40078
+ }
39875
40079
  case TagFormat.number:
39876
40080
  return instance6.asNumber(
39877
40081
  instance3.unbreakscape(v2, {
@@ -45598,6 +45802,8 @@ var ConfigBuilder = class {
45598
45802
  format = "number";
45599
45803
  } else if (tag.format === TagFormat.coordinates) {
45600
45804
  format = "coordinates";
45805
+ } else if (tag.format === TagFormat.enumeration) {
45806
+ format = "enum";
45601
45807
  }
45602
45808
  } else if (tagType === BitTagConfigKeyType.resource) {
45603
45809
  format = "string";
@@ -45662,6 +45868,7 @@ var ConfigBuilder = class {
45662
45868
  { value: tag.htmlKey, present: hasHtml }
45663
45869
  ),
45664
45870
  ...format && format !== "string" ? { format } : {},
45871
+ ...tag.values != null ? { values: tag.values } : {},
45665
45872
  ...tag.defaultValue != null ? { default: tag.defaultValue } : {},
45666
45873
  ...tag.nullable ? { nullable: true } : {},
45667
45874
  ...tag.minCount != null && tag.minCount !== 0 ? { min: tag.minCount } : {},