@gmb/bitmark-parser-generator 5.4.0 → 5.6.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
@@ -428,6 +428,7 @@ var BitType = {
428
428
  pageHero: "page-hero",
429
429
  pageOpenBook: "page-open-book",
430
430
  pageOpenBookList: "page-open-book-list",
431
+ printBook: "print-book",
431
432
  openBookChapter: "open-book-chapter",
432
433
  pagePerson: "page-person",
433
434
  pageProduct: "page-product",
@@ -1102,6 +1103,7 @@ var propertyKeys = {
1102
1103
  property_ageRange: "@ageRange",
1103
1104
  property_aiGenerated: "@aiGenerated",
1104
1105
  property_allowedBit: "@allowedBit",
1106
+ property_allowPrint: "@allowPrint",
1105
1107
  property_allowSubtitles: "@allowSubtitles",
1106
1108
  property_alt: "@alt",
1107
1109
  property_altLangTag: "@altLangTag",
@@ -1206,6 +1208,7 @@ var propertyKeys = {
1206
1208
  property_internalPrintPdf: "@internalPrintPdf",
1207
1209
  property_hasPrintRestriction: "@hasPrintRestriction",
1208
1210
  property_enforceUpdateOverUserInput: "@enforceUpdateOverUserInput",
1211
+ property_extractorExtractionTimestamp: "@extractorExtractionTimestamp",
1209
1212
  property_isCaseSensitive: "@isCaseSensitive",
1210
1213
  property_isInfoOnly: "@isInfoOnly",
1211
1214
  property_isPublic: "@isPublic",
@@ -1243,6 +1246,7 @@ var propertyKeys = {
1243
1246
  property_mute: "@mute",
1244
1247
  property_padletId: "@padletId",
1245
1248
  property_page: "@page",
1249
+ property_printParentChapterLevel: "@printParentChapterLevel",
1246
1250
  property_pageNo: "@pageNo",
1247
1251
  property_partialAnswer: "@partialAnswer",
1248
1252
  property_partner: "@partner",
@@ -3362,6 +3366,12 @@ var GROUPS = {
3362
3366
  description: "Url of the internal print PDF for the book",
3363
3367
  format: TagFormat.plainText
3364
3368
  },
3369
+ {
3370
+ key: ConfigKey.property_allowPrint,
3371
+ description: "If true, the book allows printing",
3372
+ format: TagFormat.boolean,
3373
+ defaultValue: "false"
3374
+ },
3365
3375
  {
3366
3376
  key: ConfigKey.property_hasPrintRestriction,
3367
3377
  description: "If true, the book has print restrictions",
@@ -3373,6 +3383,12 @@ var GROUPS = {
3373
3383
  description: "If true, prioritize new content over legacy content from the instance API",
3374
3384
  format: TagFormat.boolean,
3375
3385
  defaultValue: "false"
3386
+ },
3387
+ {
3388
+ key: ConfigKey.property_extractorExtractionTimestamp,
3389
+ description: "Extraction timestamps for book conversion",
3390
+ format: TagFormat.plainText,
3391
+ maxCount: Count.infinity
3376
3392
  }
3377
3393
  ]
3378
3394
  },
@@ -6769,6 +6785,12 @@ var BITS = {
6769
6785
  key: ConfigKey.property_buttonCaption,
6770
6786
  description: "The caption of the print button",
6771
6787
  format: TagFormat.plainText
6788
+ },
6789
+ {
6790
+ key: ConfigKey.property_printParentChapterLevel,
6791
+ description: "The parent chapter level to print",
6792
+ format: TagFormat.number,
6793
+ defaultValue: "-1"
6772
6794
  }
6773
6795
  ]
6774
6796
  },
@@ -7349,6 +7371,39 @@ var BITS = {
7349
7371
  }
7350
7372
  ]
7351
7373
  },
7374
+ [BitType.printBook]: {
7375
+ since: "5.5.0",
7376
+ baseBitType: BitType.article,
7377
+ description: "Print book bit, used to create pages that open books without author information in articles or books",
7378
+ tags: [
7379
+ {
7380
+ key: ConfigKey.property_slug,
7381
+ description: "Slug for the book, used to identify the book in the system",
7382
+ format: TagFormat.plainText
7383
+ },
7384
+ {
7385
+ key: ConfigKey.property_book,
7386
+ description: "Book reference for the page, used to link to a specific book",
7387
+ format: TagFormat.plainText,
7388
+ chain: [
7389
+ {
7390
+ key: ConfigKey.tag_reference,
7391
+ description: "Reference tag for the book, used to link to the book in the system",
7392
+ maxCount: 2
7393
+ }
7394
+ ]
7395
+ },
7396
+ {
7397
+ /* Allow incorrectly chained reference tag */
7398
+ key: ConfigKey.tag_reference,
7399
+ description: "Reference tag for the book, used to link to the book in the system"
7400
+ },
7401
+ {
7402
+ key: ConfigKey.property_buttonCaption,
7403
+ description: "Caption for the button, used to define the text displayed on the button"
7404
+ }
7405
+ ]
7406
+ },
7352
7407
  [BitType.openBookChapter]: {
7353
7408
  since: "4.16.0",
7354
7409
  baseBitType: BitType.pageOpenBook,
@@ -10244,7 +10299,7 @@ var instance2 = new Config();
10244
10299
  // src/generated/package_info.ts
10245
10300
  var PACKAGE_INFO = {
10246
10301
  "name": "@gmb/bitmark-parser-generator",
10247
- "version": "5.4.0",
10302
+ "version": "5.6.0",
10248
10303
  "license": "ISC"};
10249
10304
  var Environment = {
10250
10305
  unknown: "",
@@ -10573,6 +10628,8 @@ var NodeType = {
10573
10628
  alignment: "alignment",
10574
10629
  allowedBit: "allowedBit",
10575
10630
  allowedBitValue: "allowedBitValue",
10631
+ allowPrint: "allowPrint",
10632
+ allowPrintValue: "allowPrintValue",
10576
10633
  alt: "alt",
10577
10634
  alternativeAnswers: "alternativeAnswers",
10578
10635
  alternativeAnswersValue: "alternativeAnswersValue",
@@ -10835,6 +10892,8 @@ var NodeType = {
10835
10892
  hasPrintRestrictionValue: "hasPrintRestrictionValue",
10836
10893
  enforceUpdateOverUserInput: "enforceUpdateOverUserInput",
10837
10894
  enforceUpdateOverUserInputValue: "enforceUpdateOverUserInputValue",
10895
+ extractorExtractionTimestamp: "extractorExtractionTimestamp",
10896
+ extractorExtractionTimestampValue: "extractorExtractionTimestampValue",
10838
10897
  isCaseSensitive: "isCaseSensitive",
10839
10898
  isCommented: "isCommented",
10840
10899
  isCorrect: "isCorrect",
@@ -10938,6 +10997,8 @@ var NodeType = {
10938
10997
  pageNumber: "pageNumber",
10939
10998
  pageNumberValue: "pageNumberValue",
10940
10999
  pageValue: "pageValue",
11000
+ printParentChapterLevel: "printParentChapterLevel",
11001
+ printParentChapterLevelValue: "printParentChapterLevelValue",
10941
11002
  pairs: "pairs",
10942
11003
  pairsValue: "pairsValue",
10943
11004
  parent: "parent",
@@ -24533,6 +24594,12 @@ var Builder = class extends BaseBuilder {
24533
24594
  data.enforceUpdateOverUserInput,
24534
24595
  options
24535
24596
  ),
24597
+ extractorExtractionTimestamp: this.toAstProperty(
24598
+ bitType,
24599
+ ConfigKey.property_extractorExtractionTimestamp,
24600
+ data.extractorExtractionTimestamp,
24601
+ options
24602
+ ),
24536
24603
  tocResource: this.toAstProperty(
24537
24604
  bitType,
24538
24605
  ConfigKey.property_tocResource,
@@ -24546,6 +24613,18 @@ var Builder = class extends BaseBuilder {
24546
24613
  options
24547
24614
  ),
24548
24615
  page: this.toAstProperty(bitType, ConfigKey.property_page, data.page, options),
24616
+ allowPrint: this.toAstProperty(
24617
+ bitType,
24618
+ ConfigKey.property_allowPrint,
24619
+ data.allowPrint,
24620
+ options
24621
+ ),
24622
+ printParentChapterLevel: this.toAstProperty(
24623
+ bitType,
24624
+ ConfigKey.property_printParentChapterLevel,
24625
+ data.printParentChapterLevel,
24626
+ options
24627
+ ),
24549
24628
  platformBrandTarget: this.toAstProperty(
24550
24629
  bitType,
24551
24630
  ConfigKey.property_platformBrandTarget,
@@ -30191,6 +30270,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
30191
30270
  BitType.pageFooter,
30192
30271
  BitType.pageOpenBook,
30193
30272
  BitType.pagePerson,
30273
+ BitType.printBook,
30194
30274
  BitType.pageProduct,
30195
30275
  BitType.pageProductList,
30196
30276
  BitType.pageProductVideo,
@@ -30211,8 +30291,12 @@ var JsonGenerator = class extends AstWalkerGenerator {
30211
30291
  if (instance2.isOfBitType(bitType, BitType.tocContent)) {
30212
30292
  if (bitJson.tocContent == null) bitJson.tocContent = [];
30213
30293
  }
30294
+ if (instance2.isOfBitType(bitType, BitType.printThisChapter)) {
30295
+ if (bitJson.printParentChapterLevel == null) bitJson.printParentChapterLevel = -1;
30296
+ }
30214
30297
  if (instance2.isOfBitType(bitType, BitType.book)) {
30215
30298
  if (bitJson.maxTocChapterLevel == null) bitJson.maxTocChapterLevel = -1;
30299
+ if (bitJson.allowPrint == null) bitJson.allowPrint = false;
30216
30300
  if (bitJson.hasPrintRestriction == null) bitJson.hasPrintRestriction = true;
30217
30301
  if (bitJson.enforceUpdateOverUserInput == null) bitJson.enforceUpdateOverUserInput = false;
30218
30302
  if (bitJson.hasMarkAsDone == null) bitJson.hasMarkAsDone = false;
@@ -38514,6 +38598,7 @@ var JsonFileGenerator = class {
38514
38598
  this.generator.generateSync(_ast);
38515
38599
  }
38516
38600
  };
38601
+ var normalizeCardKey = (cardSetKey) => stringUtils.camelToKebab(cardSetKey);
38517
38602
  var ConfigBuilder = class {
38518
38603
  build(options) {
38519
38604
  const opts = Object.assign({}, options);
@@ -38554,8 +38639,10 @@ var ConfigBuilder = class {
38554
38639
  const outputFolder = opts.outputDir ?? "assets/config";
38555
38640
  const outputFolderBits = path3.join(outputFolder, "bits");
38556
38641
  const outputFolderGroups = path3.join(outputFolder, "partials");
38642
+ const outputFolderCards = path3.join(outputFolder, "cards");
38557
38643
  fs3.ensureDirSync(outputFolderBits);
38558
38644
  fs3.ensureDirSync(outputFolderGroups);
38645
+ fs3.ensureDirSync(outputFolderCards);
38559
38646
  const bitsFiles = fs3.readdirSync(outputFolderBits).filter((f) => f.endsWith(".jsonc"));
38560
38647
  for (const file of bitsFiles) {
38561
38648
  fs3.removeSync(path3.join(outputFolderBits, file));
@@ -38564,7 +38651,18 @@ var ConfigBuilder = class {
38564
38651
  for (const file of partialsFiles) {
38565
38652
  fs3.removeSync(path3.join(outputFolderGroups, file));
38566
38653
  }
38654
+ const cardsFiles = fs3.readdirSync(outputFolderCards).filter((f) => f.endsWith(".jsonc"));
38655
+ for (const file of cardsFiles) {
38656
+ fs3.removeSync(path3.join(outputFolderCards, file));
38657
+ }
38567
38658
  const fileWrites = [];
38659
+ const tagEntriesTypeOrder = [
38660
+ BitTagConfigKeyType.tag,
38661
+ BitTagConfigKeyType.property,
38662
+ BitTagConfigKeyType.resource,
38663
+ BitTagConfigKeyType.group,
38664
+ BitTagConfigKeyType.unknown
38665
+ ];
38568
38666
  const resolveGroupReferences = (groupKey) => {
38569
38667
  if (squashedGroups.has(groupKey)) {
38570
38668
  const replacements = squashedGroups.get(groupKey);
@@ -38669,6 +38767,38 @@ var ConfigBuilder = class {
38669
38767
  tags2.push(t);
38670
38768
  return tags2;
38671
38769
  };
38770
+ const serializeCardSet = (cardSetKey) => {
38771
+ const cardSetConfig = CARDSETS[cardSetKey];
38772
+ if (!cardSetConfig) return void 0;
38773
+ const normalizedKey = normalizeCardKey(cardSetKey);
38774
+ const sides = cardSetConfig.variants.map((variantList) => {
38775
+ const variants = variantList.map((variant) => {
38776
+ const variantTags = [];
38777
+ const variantTagEntries = Object.entries(variant.tags ?? []).sort((a, b) => {
38778
+ const tagA = a[1];
38779
+ const tagB = b[1];
38780
+ const typeA = typeFromConfigKey(tagA.key);
38781
+ const typeB = typeFromConfigKey(tagB.key);
38782
+ const typeOrder = tagEntriesTypeOrder.indexOf(typeA) - tagEntriesTypeOrder.indexOf(typeB);
38783
+ return typeOrder;
38784
+ });
38785
+ for (const [, variantTag] of variantTagEntries) {
38786
+ variantTags.push(...processTagEntries(variantTag, []));
38787
+ }
38788
+ return {
38789
+ tags: variantTags,
38790
+ repeatCount: variant.repeatCount ?? 1,
38791
+ bodyAllowed: variant.bodyAllowed ?? true,
38792
+ bodyRequired: variant.bodyRequired ?? false
38793
+ };
38794
+ });
38795
+ return { variants };
38796
+ });
38797
+ return {
38798
+ key: normalizedKey,
38799
+ sides
38800
+ };
38801
+ };
38672
38802
  for (const bt of bitGroupConfigKeys) {
38673
38803
  const bitType = instance2.getBitType(bt);
38674
38804
  const _bitConfig = BITS[bitType];
@@ -38701,13 +38831,6 @@ var ConfigBuilder = class {
38701
38831
  for (const b of bitConfigs) {
38702
38832
  const resolvedBitConfig = instance2.getBitConfig(b.bitType);
38703
38833
  const tags2 = [];
38704
- const tagEntriesTypeOrder = [
38705
- BitTagConfigKeyType.tag,
38706
- BitTagConfigKeyType.property,
38707
- BitTagConfigKeyType.resource,
38708
- BitTagConfigKeyType.group,
38709
- BitTagConfigKeyType.unknown
38710
- ];
38711
38834
  const tagEntries = Object.entries(b.tags ?? []).sort((a, b2) => {
38712
38835
  const tagA = a[1];
38713
38836
  const tagB = b2[1];
@@ -38739,6 +38862,10 @@ var ConfigBuilder = class {
38739
38862
  tags2.push(...processTagEntries(tag, []));
38740
38863
  }
38741
38864
  }
38865
+ let cardRef;
38866
+ if (b.cardSet && CARDSETS[b.cardSet]) {
38867
+ cardRef = normalizeCardKey(b.cardSet);
38868
+ }
38742
38869
  const bitJson = {
38743
38870
  name: b.bitType,
38744
38871
  description: b.description ?? "",
@@ -38756,7 +38883,8 @@ var ConfigBuilder = class {
38756
38883
  footerAllowed: resolvedBitConfig.footerAllowed ?? true,
38757
38884
  footerRequired: resolvedBitConfig.footerRequired ?? false,
38758
38885
  resourceAttachmentAllowed: resolvedBitConfig.resourceAttachmentAllowed ?? true,
38759
- tags: tags2
38886
+ tags: tags2,
38887
+ ...cardRef ? { card: cardRef } : {}
38760
38888
  };
38761
38889
  const output = path3.join(outputFolderBits, `${b.bitType}.jsonc`);
38762
38890
  const str = JSON.stringify(bitJson, null, 2);
@@ -38766,7 +38894,7 @@ var ConfigBuilder = class {
38766
38894
  for (const g of groupConfigs2) {
38767
38895
  const tags2 = [];
38768
38896
  const groupKey = stringUtils.camelToKebab(g.key);
38769
- const tagEntriesTypeOrder = [
38897
+ const tagEntriesTypeOrder2 = [
38770
38898
  BitTagConfigKeyType.tag,
38771
38899
  BitTagConfigKeyType.property,
38772
38900
  BitTagConfigKeyType.resource,
@@ -38775,7 +38903,7 @@ var ConfigBuilder = class {
38775
38903
  const tagEntries = Object.entries(g.tags ?? []).sort((a, b) => {
38776
38904
  const tagA = a[1];
38777
38905
  const tagB = b[1];
38778
- const typeOrder = tagEntriesTypeOrder.indexOf(tagA.type) - tagEntriesTypeOrder.indexOf(tagB.type);
38906
+ const typeOrder = tagEntriesTypeOrder2.indexOf(tagA.type) - tagEntriesTypeOrder2.indexOf(tagB.type);
38779
38907
  return typeOrder;
38780
38908
  });
38781
38909
  for (const [_tagKey, tag] of tagEntries) {
@@ -38823,6 +38951,15 @@ var ConfigBuilder = class {
38823
38951
  }
38824
38952
  };
38825
38953
  writeGroupConfigs(groupConfigs);
38954
+ const writeCardConfigs = () => {
38955
+ for (const cardSetKey of Object.keys(CARDSETS)) {
38956
+ const cardJson = serializeCardSet(cardSetKey);
38957
+ if (!cardJson) continue;
38958
+ const output = path3.join(outputFolderCards, `${cardJson.key}.jsonc`);
38959
+ const str = JSON.stringify(cardJson, null, 2);
38960
+ fileWrites.push(fs3.writeFile(output, str));
38961
+ }
38962
+ };
38826
38963
  const writeBitsAsGroupConfigs = (bitsAsGroupConfigs) => {
38827
38964
  for (const b of bitsAsGroupConfigs) {
38828
38965
  const groupKey = `group-${b.bitType}`;
@@ -38839,13 +38976,6 @@ var ConfigBuilder = class {
38839
38976
  });
38840
38977
  }
38841
38978
  }
38842
- const tagEntriesTypeOrder = [
38843
- BitTagConfigKeyType.tag,
38844
- BitTagConfigKeyType.property,
38845
- BitTagConfigKeyType.resource,
38846
- BitTagConfigKeyType.group,
38847
- BitTagConfigKeyType.unknown
38848
- ];
38849
38979
  const tagEntries = Object.entries(b.tags ?? []).sort((a, b2) => {
38850
38980
  const tagA = a[1];
38851
38981
  const tagB = b2[1];
@@ -38876,6 +39006,7 @@ var ConfigBuilder = class {
38876
39006
  }
38877
39007
  };
38878
39008
  writeBitsAsGroupConfigs(bitGroupConfigs);
39009
+ writeCardConfigs();
38879
39010
  Promise.all(fileWrites).then(() => {
38880
39011
  const validationErrors = this.validateConfigTree(outputFolder);
38881
39012
  if (validationErrors.length > 0) {
@@ -38901,6 +39032,7 @@ var ConfigBuilder = class {
38901
39032
  const errors = [];
38902
39033
  const outputFolderBits = path3.join(outputFolder, "bits");
38903
39034
  const outputFolderGroups = path3.join(outputFolder, "partials");
39035
+ const outputFolderCards = path3.join(outputFolder, "cards");
38904
39036
  const availableGroups = /* @__PURE__ */ new Set();
38905
39037
  if (fs3.existsSync(outputFolderGroups)) {
38906
39038
  const groupFiles = fs3.readdirSync(outputFolderGroups).filter((f) => f.endsWith(".jsonc"));
@@ -38909,16 +39041,22 @@ var ConfigBuilder = class {
38909
39041
  availableGroups.add(groupName);
38910
39042
  }
38911
39043
  }
39044
+ const availableCards = /* @__PURE__ */ new Set();
39045
+ const cardFiles = fs3.existsSync(outputFolderCards) ? fs3.readdirSync(outputFolderCards).filter((f) => f.endsWith(".jsonc")) : [];
39046
+ for (const file of cardFiles) {
39047
+ const cardName = file.replace(".jsonc", "");
39048
+ availableCards.add(cardName);
39049
+ }
38912
39050
  const checkTags = (tags2, filePath, lineOffset) => {
38913
39051
  for (let i = 0; i < tags2.length; i++) {
38914
39052
  const tag = tags2[i];
38915
- if (tag.type === "group") {
39053
+ if (tag?.type === "group" && tag.key) {
38916
39054
  if (!availableGroups.has(tag.key)) {
38917
39055
  const line = lineOffset + i + 1;
38918
39056
  errors.push(`Missing group reference '${tag.key}' in ${filePath}:${line}`);
38919
39057
  }
38920
39058
  }
38921
- if (tag.tags && Array.isArray(tag.tags)) {
39059
+ if (Array.isArray(tag?.tags)) {
38922
39060
  checkTags(tag.tags, filePath, lineOffset + i + 1);
38923
39061
  }
38924
39062
  }
@@ -38933,6 +39071,27 @@ var ConfigBuilder = class {
38933
39071
  if (config.tags && Array.isArray(config.tags)) {
38934
39072
  checkTags(config.tags, `bits/${file}`, 15);
38935
39073
  }
39074
+ if (typeof config.card === "string") {
39075
+ if (!availableCards.has(config.card)) {
39076
+ errors.push(`Missing card file '${config.card}' referenced in bits/${file}`);
39077
+ }
39078
+ } else if (config.card?.sides && Array.isArray(config.card.sides)) {
39079
+ config.card.sides.forEach((side, sideIdx) => {
39080
+ const variants = side.variants;
39081
+ if (Array.isArray(variants)) {
39082
+ variants.forEach((variant, variantIdx) => {
39083
+ const variantTags = variant.tags;
39084
+ if (Array.isArray(variantTags)) {
39085
+ checkTags(
39086
+ variantTags,
39087
+ `bits/${file} (card side ${sideIdx}, variant ${variantIdx})`,
39088
+ 15
39089
+ );
39090
+ }
39091
+ });
39092
+ }
39093
+ });
39094
+ }
38936
39095
  } catch (err) {
38937
39096
  errors.push(`Failed to parse ${file}: ${err}`);
38938
39097
  }
@@ -38953,6 +39112,38 @@ var ConfigBuilder = class {
38953
39112
  }
38954
39113
  }
38955
39114
  }
39115
+ if (cardFiles.length > 0) {
39116
+ for (const file of cardFiles) {
39117
+ const filePath = path3.join(outputFolderCards, file);
39118
+ try {
39119
+ const content = fs3.readFileSync(filePath, "utf-8");
39120
+ const config = JSON.parse(content);
39121
+ const expectedKey = file.replace(".jsonc", "");
39122
+ if (config.key && config.key !== expectedKey) {
39123
+ errors.push(`Card key mismatch in cards/${file}: expected '${expectedKey}'`);
39124
+ }
39125
+ if (Array.isArray(config.sides)) {
39126
+ config.sides.forEach((side, sideIdx) => {
39127
+ const variants = side.variants;
39128
+ if (Array.isArray(variants)) {
39129
+ variants.forEach((variant, variantIdx) => {
39130
+ const variantTags = variant.tags;
39131
+ if (Array.isArray(variantTags)) {
39132
+ checkTags(
39133
+ variantTags,
39134
+ `cards/${file} (side ${sideIdx}, variant ${variantIdx})`,
39135
+ 10
39136
+ );
39137
+ }
39138
+ });
39139
+ }
39140
+ });
39141
+ }
39142
+ } catch (err) {
39143
+ errors.push(`Failed to parse cards/${file}: ${err}`);
39144
+ }
39145
+ }
39146
+ }
38956
39147
  return errors;
38957
39148
  }
38958
39149
  // Build flat bit configs
@@ -39047,6 +39238,11 @@ var ConfigBuilder = class {
39047
39238
  for (const [_tagKey, tag] of tagEntries) {
39048
39239
  tags2.push(...processTagEntries(tag));
39049
39240
  }
39241
+ let cardRef;
39242
+ const cardSetKey = b.cardSet?.configKey;
39243
+ if (cardSetKey && CARDSETS[cardSetKey]) {
39244
+ cardRef = normalizeCardKey(cardSetKey);
39245
+ }
39050
39246
  const bitJson = {
39051
39247
  name: b.bitType,
39052
39248
  description: "",
@@ -39064,7 +39260,8 @@ var ConfigBuilder = class {
39064
39260
  footerAllowed: b.footerAllowed ?? true,
39065
39261
  footerRequired: b.footerRequired ?? false,
39066
39262
  resourceAttachmentAllowed: b.resourceAttachmentAllowed ?? true,
39067
- tags: tags2
39263
+ tags: tags2,
39264
+ ...cardRef ? { card: cardRef } : {}
39068
39265
  };
39069
39266
  const output = path3.join(outputFolderBits, `${b.bitType}.jsonc`);
39070
39267
  const str = JSON.stringify(bitJson, null, 2);