@gmb/bitmark-parser-generator 5.21.0 → 5.23.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
@@ -278,6 +278,7 @@ var BitType = {
278
278
  footNote: "foot-note",
279
279
  formFreeText: "form-free-text",
280
280
  formula: "formula",
281
+ formulaImage: "formula-image",
281
282
  gapText: "gap-text",
282
283
  gapTextInstructionGrouped: "gap-text-instruction-grouped",
283
284
  glossaryTerm: "glossary-term",
@@ -633,6 +634,7 @@ var BitType = {
633
634
  vendorPadletEmbed: "vendor-padlet-embed",
634
635
  vendorStripePricingTable: "vendor-stripe-pricing-table",
635
636
  vendorStripePricingTableExternal: "vendor-stripe-pricing-table-external",
637
+ vendorStripePricingTablePrintOnRequest: "vendor-stripe-pricing-table-print-on-request",
636
638
  video: "video",
637
639
  videoEmbed: "video-embed",
638
640
  videoEmbedLandscape: "video-embed-landscape",
@@ -687,8 +689,10 @@ var TagFormat = {
687
689
  // If the value is treated as a boolean
688
690
  invertedBoolean: "invertedBoolean",
689
691
  // If the value is treated as a boolean with the value inverted (e.g. isLongAnswer ==> isShortAnswer = false)
690
- enumeration: "enumeration"
692
+ enumeration: "enumeration",
691
693
  // If the value is treated as an enumeration (the value is a string that must be one of a predefined set of values)
694
+ coordinates: "coordinates"
695
+ // Comma-separated list of 4 numbers (e.g. bounding-box x, y, x1, y1)
692
696
  };
693
697
  var TextFormat = {
694
698
  // plain text
@@ -759,7 +763,11 @@ var AbstractTagConfig = class {
759
763
  // Default: 0
760
764
  chain;
761
765
  jsonKey;
762
- // If the json key is different from the tag
766
+ // Legacy string-form jsonKey
767
+ exportJsonKey;
768
+ // New JSON-pattern jsonKey (export-only)
769
+ hasExportJsonKey;
770
+ // True iff exportJsonKey was explicitly set
763
771
  deprecated;
764
772
  // Deprecated version
765
773
  constructor(params) {
@@ -770,6 +778,8 @@ var AbstractTagConfig = class {
770
778
  this.minCount = params.minCount;
771
779
  this.chain = params.chain;
772
780
  this.jsonKey = params.jsonKey;
781
+ this.exportJsonKey = params.exportJsonKey;
782
+ this.hasExportJsonKey = params.hasExportJsonKey;
773
783
  this.deprecated = params.deprecated;
774
784
  }
775
785
  };
@@ -780,7 +790,6 @@ var MarkupTagConfig = class extends AbstractTagConfig {
780
790
  constructor(params) {
781
791
  super({
782
792
  type: BitTagConfigKeyType.tag,
783
- jsonKey: void 0,
784
793
  ...params
785
794
  });
786
795
  }
@@ -900,13 +909,21 @@ var CardVariantConfig = class {
900
909
  // Default: 1
901
910
  // JSON mapping fields
902
911
  jsonKey;
903
- // JSON path for body text
904
- constructor(tags2, bodyAllowed, bodyRequired, repeatCount, jsonKey) {
912
+ // JSON path for body text (legacy)
913
+ exportJsonKey;
914
+ // New JSON-pattern jsonKey
915
+ hasExportJsonKey;
916
+ format;
917
+ // Body text format. Default: bitmark++
918
+ constructor(tags2, bodyAllowed, bodyRequired, repeatCount, jsonKey, exportJsonKey, hasExportJsonKey = false, format) {
905
919
  this.tags = tags2;
906
920
  this.bodyAllowed = bodyAllowed == null ? true : bodyAllowed;
907
921
  this.bodyRequired = bodyRequired;
908
922
  this.repeatCount = repeatCount;
909
923
  this.jsonKey = jsonKey;
924
+ this.exportJsonKey = exportJsonKey;
925
+ this.hasExportJsonKey = hasExportJsonKey;
926
+ this.format = format;
910
927
  }
911
928
  toString(options) {
912
929
  const opts = Object.assign({}, options);
@@ -933,11 +950,15 @@ var CardSideConfig = class {
933
950
  name;
934
951
  repeat;
935
952
  jsonKey;
953
+ exportJsonKey;
954
+ hasExportJsonKey;
936
955
  variants;
937
- constructor(name, repeat, variants, jsonKey) {
956
+ constructor(name, repeat, variants, jsonKey, exportJsonKey, hasExportJsonKey = false) {
938
957
  this.name = name;
939
958
  this.repeat = repeat;
940
959
  this.jsonKey = jsonKey;
960
+ this.exportJsonKey = exportJsonKey;
961
+ this.hasExportJsonKey = hasExportJsonKey;
941
962
  this.variants = variants;
942
963
  }
943
964
  toString(options) {
@@ -961,6 +982,8 @@ var CardSideConfig = class {
961
982
  var CardSetConfig = class {
962
983
  configKey;
963
984
  jsonKey;
985
+ exportJsonKey;
986
+ hasExportJsonKey;
964
987
  sections;
965
988
  sides;
966
989
  // Legacy accessor — provides the same shape as the old `variants: CardVariantConfig[][]`
@@ -968,9 +991,11 @@ var CardSetConfig = class {
968
991
  get variants() {
969
992
  return this.sides.map((side) => side.variants);
970
993
  }
971
- constructor(configKey, jsonKey, sections, sides) {
994
+ constructor(configKey, jsonKey, exportJsonKey, hasExportJsonKey, sections, sides) {
972
995
  this.configKey = configKey;
973
996
  this.jsonKey = jsonKey;
997
+ this.exportJsonKey = exportJsonKey;
998
+ this.hasExportJsonKey = hasExportJsonKey;
974
999
  this.sections = sections;
975
1000
  this.sides = sides;
976
1001
  }
@@ -1251,6 +1276,7 @@ var propertyKeys = {
1251
1276
  property_formula: "@formula",
1252
1277
  property_fullName: "@fullName",
1253
1278
  property_groupTag: "@groupTag",
1279
+ property_gUri: "@gUri",
1254
1280
  property_handInAcceptFileType: "@handInAcceptFileType",
1255
1281
  property_handInInstruction: "@handInInstruction",
1256
1282
  property_handInRequirement: "@handInRequirement",
@@ -1309,6 +1335,8 @@ var propertyKeys = {
1309
1335
  property_padletId: "@padletId",
1310
1336
  property_page: "@page",
1311
1337
  property_printParentChapterLevel: "@printParentChapterLevel",
1338
+ property_printOnRequestCustomerId: "@printOnRequestCustomerId",
1339
+ property_printOnRequestProductId: "@printOnRequestProductId",
1312
1340
  property_pageNo: "@pageNo",
1313
1341
  property_partialAnswer: "@partialAnswer",
1314
1342
  property_partner: "@partner",
@@ -1384,6 +1412,7 @@ var propertyKeys = {
1384
1412
  property_siteName: "@siteName",
1385
1413
  property_size: "@size",
1386
1414
  property_slug: "@slug",
1415
+ property_sourceBB: "@sourceBB",
1387
1416
  property_sourceDocument: "@sourceDocument",
1388
1417
  property_sourceRL: "@sourceRL",
1389
1418
  property_spaceId: "@spaceId",
@@ -2128,25 +2157,29 @@ var CARDSETS = {
2128
2157
  //
2129
2158
  [CardSetConfigKey.flashcard]: {
2130
2159
  jsonKey: "cards",
2160
+ exportJsonKey: { cards: "$" },
2131
2161
  sides: [
2132
2162
  {
2133
2163
  name: "question",
2134
2164
  variants: [
2135
2165
  {
2136
2166
  jsonKey: "question.text",
2167
+ exportJsonKey: { question: { text: "$" } },
2137
2168
  tags: [
2138
2169
  {
2139
2170
  key: ConfigKey.group_standardTags,
2140
2171
  description: "Standard tags for the flashcard."
2141
2172
  },
2142
2173
  {
2174
+ exportJsonKey: { title: "$" },
2143
2175
  key: ConfigKey.tag_title,
2144
2176
  description: "Title of the flashcard."
2145
2177
  },
2146
2178
  {
2147
2179
  key: ConfigKey.group_resourceIcon,
2148
2180
  description: "Icon resource for the flashcard.",
2149
- jsonKey: "question.icon"
2181
+ jsonKey: "question.icon|resource(type=image, key=image)",
2182
+ exportJsonKey: { question: { icon: { type: "image", image: { src: "$" } } } }
2150
2183
  }
2151
2184
  ]
2152
2185
  }
@@ -2157,36 +2190,45 @@ var CARDSETS = {
2157
2190
  variants: [
2158
2191
  {
2159
2192
  jsonKey: "answer.text",
2193
+ exportJsonKey: { answer: { text: "$" } },
2160
2194
  tags: [
2161
2195
  {
2162
2196
  key: ConfigKey.group_standardTags,
2163
2197
  description: "Standard tags for the flashcard."
2164
2198
  },
2165
2199
  {
2200
+ exportJsonKey: { title: "$" },
2166
2201
  key: ConfigKey.tag_title,
2167
2202
  description: "Title of the flashcard."
2168
2203
  },
2169
2204
  {
2170
2205
  key: ConfigKey.group_resourceIcon,
2171
2206
  description: "Icon resource for the flashcard.",
2172
- jsonKey: "answer.icon"
2207
+ jsonKey: "answer.icon|resource(type=image, key=image)",
2208
+ exportJsonKey: { answer: { icon: { type: "image", image: { src: "$" } } } }
2173
2209
  }
2174
2210
  ]
2175
2211
  },
2176
2212
  {
2177
2213
  jsonKey: "alternativeAnswers[].text",
2214
+ exportJsonKey: { alternativeAnswers: [{ text: "$" }] },
2178
2215
  tags: [
2179
2216
  {
2180
2217
  key: ConfigKey.group_standardTags,
2181
2218
  description: "Standard tags for the flashcard."
2182
2219
  },
2183
2220
  {
2221
+ exportJsonKey: { title: "$" },
2184
2222
  key: ConfigKey.tag_title,
2185
2223
  description: "Title of the flashcard."
2186
2224
  },
2187
2225
  {
2188
2226
  key: ConfigKey.group_resourceIcon,
2189
- description: "Icon resource for the flashcard."
2227
+ description: "Icon resource for the flashcard.",
2228
+ jsonKey: "alternativeAnswers[].icon|resource(type=image, key=image)",
2229
+ exportJsonKey: {
2230
+ alternativeAnswers: [{ icon: { type: "image", image: { src: "$" } } }]
2231
+ }
2190
2232
  }
2191
2233
  ],
2192
2234
  repeatCount: Count.infinity
@@ -2200,12 +2242,14 @@ var CARDSETS = {
2200
2242
  //
2201
2243
  [CardSetConfigKey.definitionList]: {
2202
2244
  jsonKey: "definitions",
2245
+ exportJsonKey: { definitions: "$" },
2203
2246
  sides: [
2204
2247
  {
2205
2248
  name: "term",
2206
2249
  variants: [
2207
2250
  {
2208
2251
  jsonKey: "term.text",
2252
+ exportJsonKey: { term: { text: "$" } },
2209
2253
  tags: [
2210
2254
  {
2211
2255
  key: ConfigKey.group_standardTags,
@@ -2214,12 +2258,16 @@ var CARDSETS = {
2214
2258
  {
2215
2259
  key: ConfigKey.tag_title,
2216
2260
  description: "Title of the definition.",
2217
- jsonKey: "^heading.forKeys"
2261
+ format: TagFormat.plainText,
2262
+ jsonKey: "^heading.forKeys",
2263
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2218
2264
  },
2219
2265
  {
2220
2266
  key: ConfigKey.group_resourceIcon,
2221
2267
  description: "Icon resource for the definition.",
2222
- jsonKey: "term.icon"
2268
+ format: TagFormat.plainText,
2269
+ jsonKey: "term.icon|resource(type=image, key=image)",
2270
+ exportJsonKey: { term: { icon: { type: "image", image: { src: "$" } } } }
2223
2271
  }
2224
2272
  ]
2225
2273
  }
@@ -2230,6 +2278,7 @@ var CARDSETS = {
2230
2278
  variants: [
2231
2279
  {
2232
2280
  jsonKey: "definition.text",
2281
+ exportJsonKey: { definition: { text: "$" } },
2233
2282
  tags: [
2234
2283
  {
2235
2284
  key: ConfigKey.group_standardTags,
@@ -2238,29 +2287,38 @@ var CARDSETS = {
2238
2287
  {
2239
2288
  key: ConfigKey.tag_title,
2240
2289
  description: "Title of the definition.",
2241
- jsonKey: "^heading.forValues"
2290
+ format: TagFormat.plainText,
2291
+ jsonKey: "^heading.forValues",
2292
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2242
2293
  },
2243
2294
  {
2244
2295
  key: ConfigKey.group_resourceIcon,
2245
2296
  description: "Icon resource for the definition.",
2246
- jsonKey: "definition.icon"
2297
+ jsonKey: "definition.icon|resource(type=image, key=image)",
2298
+ exportJsonKey: { definition: { icon: { type: "image", image: { src: "$" } } } }
2247
2299
  }
2248
2300
  ]
2249
2301
  },
2250
2302
  {
2251
2303
  jsonKey: "alternativeDefinitions[].text",
2304
+ exportJsonKey: { alternativeDefinitions: [{ text: "$" }] },
2252
2305
  tags: [
2253
2306
  {
2254
2307
  key: ConfigKey.group_standardTags,
2255
2308
  description: "Standard tags for the definition."
2256
2309
  },
2257
2310
  {
2311
+ exportJsonKey: { title: "$" },
2258
2312
  key: ConfigKey.tag_title,
2259
2313
  description: "Title of the definition."
2260
2314
  },
2261
2315
  {
2262
2316
  key: ConfigKey.group_resourceIcon,
2263
- description: "Icon resource for the definition."
2317
+ description: "Icon resource for the definition.",
2318
+ jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)",
2319
+ exportJsonKey: {
2320
+ alternativeDefinitions: [{ icon: { type: "image", image: { src: "$" } } }]
2321
+ }
2264
2322
  }
2265
2323
  ],
2266
2324
  repeatCount: Count.infinity
@@ -2274,12 +2332,14 @@ var CARDSETS = {
2274
2332
  //
2275
2333
  [CardSetConfigKey.matchPairs]: {
2276
2334
  jsonKey: "pairs",
2335
+ exportJsonKey: { pairs: "$" },
2277
2336
  sides: [
2278
2337
  {
2279
2338
  name: "key",
2280
2339
  variants: [
2281
2340
  {
2282
2341
  jsonKey: "key",
2342
+ exportJsonKey: { key: "$" },
2283
2343
  tags: [
2284
2344
  {
2285
2345
  key: ConfigKey.group_standardTags,
@@ -2288,22 +2348,30 @@ var CARDSETS = {
2288
2348
  {
2289
2349
  key: ConfigKey.tag_title,
2290
2350
  description: "Title of the match pair.",
2291
- jsonKey: "^heading.forKeys"
2351
+ format: TagFormat.plainText,
2352
+ jsonKey: "^heading.forKeys",
2353
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2292
2354
  },
2293
2355
  {
2294
2356
  key: ConfigKey.property_isCaseSensitive,
2357
+ exportJsonKey: [
2358
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2359
+ { isCaseSensitive: "$" }
2360
+ ],
2295
2361
  description: "Property to indicate if the match is case sensitive.",
2296
2362
  format: TagFormat.boolean
2297
2363
  },
2298
2364
  {
2299
2365
  key: ConfigKey.resource_audio,
2300
2366
  description: "Audio resource for the match pair.",
2301
- jsonKey: "keyAudio"
2367
+ jsonKey: "keyAudio",
2368
+ exportJsonKey: { keyAudio: "$" }
2302
2369
  },
2303
2370
  {
2304
2371
  key: ConfigKey.resource_image,
2305
2372
  description: "Image resource for the match pair.",
2306
- jsonKey: "keyImage"
2373
+ jsonKey: "keyImage",
2374
+ exportJsonKey: { keyImage: "$" }
2307
2375
  }
2308
2376
  ]
2309
2377
  }
@@ -2315,6 +2383,7 @@ var CARDSETS = {
2315
2383
  variants: [
2316
2384
  {
2317
2385
  jsonKey: "values[]",
2386
+ exportJsonKey: { values: ["$"] },
2318
2387
  tags: [
2319
2388
  {
2320
2389
  key: ConfigKey.group_standardTags,
@@ -2323,10 +2392,16 @@ var CARDSETS = {
2323
2392
  {
2324
2393
  key: ConfigKey.tag_title,
2325
2394
  description: "Title of the match pair.",
2326
- jsonKey: "^heading.forValues"
2395
+ format: TagFormat.plainText,
2396
+ jsonKey: "^heading.forValues",
2397
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2327
2398
  },
2328
2399
  {
2329
2400
  key: ConfigKey.property_isCaseSensitive,
2401
+ exportJsonKey: [
2402
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2403
+ { isCaseSensitive: "$" }
2404
+ ],
2330
2405
  description: "Property to indicate if the match is case sensitive.",
2331
2406
  format: TagFormat.boolean
2332
2407
  }
@@ -2342,12 +2417,14 @@ var CARDSETS = {
2342
2417
  //
2343
2418
  [CardSetConfigKey.matchAudioPairs]: {
2344
2419
  jsonKey: "pairs",
2420
+ exportJsonKey: { pairs: "$" },
2345
2421
  sides: [
2346
2422
  {
2347
2423
  name: "key",
2348
2424
  variants: [
2349
2425
  {
2350
2426
  jsonKey: "key",
2427
+ exportJsonKey: { key: "$" },
2351
2428
  tags: [
2352
2429
  {
2353
2430
  key: ConfigKey.group_standardTags,
@@ -2356,12 +2433,15 @@ var CARDSETS = {
2356
2433
  {
2357
2434
  key: ConfigKey.tag_title,
2358
2435
  description: "Title of the audio match pair.",
2359
- jsonKey: "^heading.forKeys"
2436
+ format: TagFormat.plainText,
2437
+ jsonKey: "^heading.forKeys",
2438
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2360
2439
  },
2361
2440
  {
2362
2441
  key: ConfigKey.resource_audio,
2363
2442
  description: "Audio resource for the match pair.",
2364
- jsonKey: "keyAudio"
2443
+ jsonKey: "keyAudio",
2444
+ exportJsonKey: { keyAudio: "$" }
2365
2445
  }
2366
2446
  ]
2367
2447
  }
@@ -2373,6 +2453,7 @@ var CARDSETS = {
2373
2453
  variants: [
2374
2454
  {
2375
2455
  jsonKey: "values[]",
2456
+ exportJsonKey: { values: ["$"] },
2376
2457
  tags: [
2377
2458
  {
2378
2459
  key: ConfigKey.group_standardTags,
@@ -2381,7 +2462,9 @@ var CARDSETS = {
2381
2462
  {
2382
2463
  key: ConfigKey.tag_title,
2383
2464
  description: "Title of the audio match pair.",
2384
- jsonKey: "^heading.forValues"
2465
+ format: TagFormat.plainText,
2466
+ jsonKey: "^heading.forValues",
2467
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2385
2468
  },
2386
2469
  {
2387
2470
  key: ConfigKey.resource_audio,
@@ -2399,12 +2482,14 @@ var CARDSETS = {
2399
2482
  //
2400
2483
  [CardSetConfigKey.matchImagePairs]: {
2401
2484
  jsonKey: "pairs",
2485
+ exportJsonKey: { pairs: "$" },
2402
2486
  sides: [
2403
2487
  {
2404
2488
  name: "key",
2405
2489
  variants: [
2406
2490
  {
2407
2491
  jsonKey: "key",
2492
+ exportJsonKey: { key: "$" },
2408
2493
  tags: [
2409
2494
  {
2410
2495
  key: ConfigKey.group_standardTags,
@@ -2413,12 +2498,15 @@ var CARDSETS = {
2413
2498
  {
2414
2499
  key: ConfigKey.tag_title,
2415
2500
  description: "Title of the image match pair.",
2416
- jsonKey: "^heading.forKeys"
2501
+ format: TagFormat.plainText,
2502
+ jsonKey: "^heading.forKeys",
2503
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2417
2504
  },
2418
2505
  {
2419
2506
  key: ConfigKey.resource_image,
2420
2507
  description: "Image resource for the match pair.",
2421
- jsonKey: "keyImage"
2508
+ jsonKey: "keyImage",
2509
+ exportJsonKey: { keyImage: "$" }
2422
2510
  }
2423
2511
  ]
2424
2512
  }
@@ -2430,6 +2518,7 @@ var CARDSETS = {
2430
2518
  variants: [
2431
2519
  {
2432
2520
  jsonKey: "values[]",
2521
+ exportJsonKey: { values: ["$"] },
2433
2522
  tags: [
2434
2523
  {
2435
2524
  key: ConfigKey.group_standardTags,
@@ -2438,7 +2527,9 @@ var CARDSETS = {
2438
2527
  {
2439
2528
  key: ConfigKey.tag_title,
2440
2529
  description: "Title of the image match pair.",
2441
- jsonKey: "^heading.forValues"
2530
+ format: TagFormat.plainText,
2531
+ jsonKey: "^heading.forValues",
2532
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2442
2533
  },
2443
2534
  {
2444
2535
  key: ConfigKey.resource_image,
@@ -2456,12 +2547,14 @@ var CARDSETS = {
2456
2547
  //
2457
2548
  [CardSetConfigKey.matchMatrix]: {
2458
2549
  jsonKey: "matrix",
2550
+ exportJsonKey: { matrix: "$" },
2459
2551
  sides: [
2460
2552
  {
2461
2553
  name: "key",
2462
2554
  variants: [
2463
2555
  {
2464
2556
  jsonKey: "key",
2557
+ exportJsonKey: { key: "$" },
2465
2558
  tags: [
2466
2559
  {
2467
2560
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2469,16 +2562,27 @@ var CARDSETS = {
2469
2562
  },
2470
2563
  {
2471
2564
  key: ConfigKey.property_example,
2565
+ exportJsonKey: [
2566
+ { "@keyonly": { isExample: true, "@bit": { isExample: true } } },
2567
+ { "@absent": { isExample: true, "@bit": { isExample: true } } },
2568
+ { isExample: true, example: "$", "@bit": { isExample: true } }
2569
+ ],
2472
2570
  description: "Example text for the match matrix.",
2473
2571
  format: TagFormat.plainText
2474
2572
  },
2475
2573
  {
2476
2574
  key: ConfigKey.tag_title,
2477
2575
  description: "Title of the match matrix.",
2478
- jsonKey: "^heading.forKeys"
2576
+ format: TagFormat.plainText,
2577
+ jsonKey: "^heading.forKeys",
2578
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2479
2579
  },
2480
2580
  {
2481
2581
  key: ConfigKey.property_isCaseSensitive,
2582
+ exportJsonKey: [
2583
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2584
+ { isCaseSensitive: "$" }
2585
+ ],
2482
2586
  description: "Property to indicate if the match is case sensitive.",
2483
2587
  format: TagFormat.boolean
2484
2588
  }
@@ -2492,6 +2596,7 @@ var CARDSETS = {
2492
2596
  variants: [
2493
2597
  {
2494
2598
  jsonKey: "cells[{s}].values[]",
2599
+ exportJsonKey: { cells: { $s: { values: ["$"] } } },
2495
2600
  tags: [
2496
2601
  {
2497
2602
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2499,16 +2604,34 @@ var CARDSETS = {
2499
2604
  },
2500
2605
  {
2501
2606
  key: ConfigKey.property_example,
2607
+ exportJsonKey: [
2608
+ {
2609
+ "@keyonly": {
2610
+ cells: { $s: { isExample: true, example: "$parent.values[0]" } },
2611
+ "@bit": { isExample: true }
2612
+ }
2613
+ },
2614
+ {
2615
+ "@absent": { cells: { $s: { isExample: true, example: "$parent.values[0]" } } }
2616
+ },
2617
+ { cells: { $s: { isExample: true, example: "$" } }, "@bit": { isExample: true } }
2618
+ ],
2502
2619
  description: "Example text for the match matrix.",
2503
2620
  format: TagFormat.plainText
2504
2621
  },
2505
2622
  {
2506
2623
  key: ConfigKey.tag_title,
2507
2624
  description: "Title of the match matrix.",
2508
- jsonKey: "^heading.forValues"
2625
+ format: TagFormat.plainText,
2626
+ jsonKey: "^heading.forValues",
2627
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2509
2628
  },
2510
2629
  {
2511
2630
  key: ConfigKey.property_isCaseSensitive,
2631
+ exportJsonKey: [
2632
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2633
+ { isCaseSensitive: "$" }
2634
+ ],
2512
2635
  description: "Property to indicate if the match is case sensitive.",
2513
2636
  format: TagFormat.boolean
2514
2637
  }
@@ -2524,23 +2647,27 @@ var CARDSETS = {
2524
2647
  //
2525
2648
  [CardSetConfigKey.statements]: {
2526
2649
  jsonKey: "statements",
2650
+ exportJsonKey: { statements: "$" },
2527
2651
  sides: [
2528
2652
  {
2529
2653
  name: "statement",
2530
2654
  variants: [
2531
2655
  {
2532
2656
  jsonKey: "statement",
2657
+ exportJsonKey: { statement: "$" },
2533
2658
  tags: [
2534
2659
  {
2535
2660
  key: ConfigKey.tag_true,
2536
2661
  description: "Tag for true statements.",
2537
2662
  jsonKey: "statement|set(isCorrect=true)",
2663
+ exportJsonKey: { statement: "$", isCorrect: true },
2538
2664
  maxCount: 1
2539
2665
  },
2540
2666
  {
2541
2667
  key: ConfigKey.tag_false,
2542
2668
  description: "Tag for false statements.",
2543
2669
  jsonKey: "statement|set(isCorrect=false)",
2670
+ exportJsonKey: { statement: "$", isCorrect: false },
2544
2671
  maxCount: 1
2545
2672
  },
2546
2673
  {
@@ -2559,6 +2686,7 @@ var CARDSETS = {
2559
2686
  //
2560
2687
  [CardSetConfigKey.quiz]: {
2561
2688
  jsonKey: "quizzes",
2689
+ exportJsonKey: { quizzes: "$" },
2562
2690
  sides: [
2563
2691
  {
2564
2692
  name: "choices",
@@ -2586,6 +2714,7 @@ var CARDSETS = {
2586
2714
  //
2587
2715
  [CardSetConfigKey.feedback]: {
2588
2716
  jsonKey: "feedbacks",
2717
+ exportJsonKey: { feedbacks: "$" },
2589
2718
  sides: [
2590
2719
  {
2591
2720
  name: "choices",
@@ -2604,7 +2733,9 @@ var CARDSETS = {
2604
2733
  {
2605
2734
  key: ConfigKey.tag_title,
2606
2735
  description: "Title of the feedback.",
2607
- jsonKey: "^heading.forKeys"
2736
+ format: TagFormat.plainText,
2737
+ jsonKey: "^heading.forKeys",
2738
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2608
2739
  }
2609
2740
  ],
2610
2741
  bodyAllowed: false
@@ -2616,6 +2747,7 @@ var CARDSETS = {
2616
2747
  variants: [
2617
2748
  {
2618
2749
  jsonKey: "reason.text",
2750
+ exportJsonKey: { reason: { text: "$" } },
2619
2751
  tags: [
2620
2752
  {
2621
2753
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2623,18 +2755,29 @@ var CARDSETS = {
2623
2755
  },
2624
2756
  {
2625
2757
  key: ConfigKey.property_reasonableNumOfChars,
2758
+ exportJsonKey: [
2759
+ { "@absent": { reasonableNumOfChars: "$ancestor" } },
2760
+ { reasonableNumOfChars: "$" }
2761
+ ],
2626
2762
  description: "Property for reasonable number of characters.",
2627
2763
  format: TagFormat.number
2628
2764
  },
2629
2765
  {
2630
2766
  key: ConfigKey.property_example,
2767
+ exportJsonKey: [
2768
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
2769
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
2770
+ { isExample: true, example: "$", "@bit": { isExample: true } }
2771
+ ],
2631
2772
  description: "Example text for the feedback.",
2632
2773
  format: TagFormat.plainText
2633
2774
  },
2634
2775
  {
2635
2776
  key: ConfigKey.tag_title,
2636
2777
  description: "Title of the feedback.",
2637
- jsonKey: "^heading.forValues"
2778
+ format: TagFormat.plainText,
2779
+ jsonKey: "^heading.forValues",
2780
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2638
2781
  }
2639
2782
  ],
2640
2783
  bodyAllowed: true
@@ -2648,21 +2791,29 @@ var CARDSETS = {
2648
2791
  //
2649
2792
  [CardSetConfigKey.questions]: {
2650
2793
  jsonKey: "questions",
2794
+ exportJsonKey: { questions: "$" },
2651
2795
  sides: [
2652
2796
  {
2653
2797
  name: "question",
2654
2798
  variants: [
2655
2799
  {
2656
2800
  jsonKey: "question",
2801
+ exportJsonKey: { question: "$" },
2657
2802
  tags: [
2658
2803
  {
2659
2804
  key: ConfigKey.property_reasonableNumOfChars,
2805
+ exportJsonKey: [
2806
+ { "@absent": { reasonableNumOfChars: "$ancestor" } },
2807
+ { reasonableNumOfChars: "$" }
2808
+ ],
2660
2809
  description: "Property for reasonable number of characters.",
2661
2810
  format: TagFormat.number
2662
2811
  },
2663
2812
  {
2813
+ exportJsonKey: { sampleSolution: "$" },
2664
2814
  key: ConfigKey.tag_sampleSolution,
2665
- description: "Sample solution for the question."
2815
+ description: "Sample solution for the question.",
2816
+ format: TagFormat.plainText
2666
2817
  },
2667
2818
  {
2668
2819
  key: ConfigKey.property_sampleSolution,
@@ -2702,6 +2853,7 @@ var CARDSETS = {
2702
2853
  variants: [
2703
2854
  {
2704
2855
  jsonKey: "elements[]",
2856
+ exportJsonKey: { elements: ["$"] },
2705
2857
  tags: [
2706
2858
  {
2707
2859
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2709,6 +2861,11 @@ var CARDSETS = {
2709
2861
  },
2710
2862
  {
2711
2863
  key: ConfigKey.property_example,
2864
+ exportJsonKey: [
2865
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
2866
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
2867
+ { isExample: true, example: "$", "@bit": { isExample: true } }
2868
+ ],
2712
2869
  description: "Example text for the element.",
2713
2870
  format: TagFormat.plainText
2714
2871
  }
@@ -2724,6 +2881,7 @@ var CARDSETS = {
2724
2881
  //
2725
2882
  [CardSetConfigKey.table]: {
2726
2883
  jsonKey: "table.data",
2884
+ exportJsonKey: { table: { data: "$" } },
2727
2885
  sides: [
2728
2886
  {
2729
2887
  name: "cell",
@@ -2739,6 +2897,7 @@ var CARDSETS = {
2739
2897
  {
2740
2898
  key: ConfigKey.tag_title,
2741
2899
  jsonKey: "^table.columns[]",
2900
+ exportJsonKey: { "@bit": { table: { columns: ["$"] } } },
2742
2901
  description: "Title of the table."
2743
2902
  },
2744
2903
  {
@@ -2779,18 +2938,34 @@ var CARDSETS = {
2779
2938
  [CardSetConfigKey.tableExtended]: {
2780
2939
  jsonKey: null,
2781
2940
  sections: {
2782
- "table-header": { jsonKey: "table.header.rows", sideJsonKey: "cells[{s}]|set(title=true)" },
2783
- "table-body": { jsonKey: "table.body.rows", isDefault: true },
2784
- "table-footer": { jsonKey: "table.footer.rows", sideJsonKey: "cells[{s}]|set(title=true)" }
2941
+ "table-header": {
2942
+ jsonKey: "table.header.rows",
2943
+ exportJsonKey: { table: { header: { rows: "$" } } },
2944
+ sideJsonKey: "cells[{s}]|set(title=true)",
2945
+ sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } }
2946
+ },
2947
+ "table-body": {
2948
+ jsonKey: "table.body.rows",
2949
+ exportJsonKey: { table: { body: { rows: "$" } } },
2950
+ isDefault: true
2951
+ },
2952
+ "table-footer": {
2953
+ jsonKey: "table.footer.rows",
2954
+ exportJsonKey: { table: { footer: { rows: "$" } } },
2955
+ sideJsonKey: "cells[{s}]|set(title=true)",
2956
+ sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } }
2957
+ }
2785
2958
  },
2786
2959
  sides: [
2787
2960
  {
2788
2961
  name: "cell",
2789
2962
  repeat: true,
2790
2963
  jsonKey: "cells[{s}]",
2964
+ exportJsonKey: { cells: { $s: "$" } },
2791
2965
  variants: [
2792
2966
  {
2793
2967
  jsonKey: "content",
2968
+ exportJsonKey: { content: "$" },
2794
2969
  tags: [
2795
2970
  {
2796
2971
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2799,29 +2974,38 @@ var CARDSETS = {
2799
2974
  {
2800
2975
  key: ConfigKey.tag_title,
2801
2976
  jsonKey: ".",
2977
+ exportJsonKey: {
2978
+ "@bit": {
2979
+ table: { header: { rows: { cells: { cells: { $s: { content: "$" } } } } } }
2980
+ }
2981
+ },
2802
2982
  description: "Title of the table cell."
2803
2983
  },
2804
2984
  {
2805
2985
  key: ConfigKey.property_tableCellType,
2806
2986
  jsonKey: "title|bool(th)",
2987
+ exportJsonKey: [{ "@value=th": { title: true } }],
2807
2988
  description: "Table cell type (th/td).",
2808
2989
  format: TagFormat.plainText
2809
2990
  },
2810
2991
  {
2811
2992
  key: ConfigKey.property_tableRowSpan,
2812
2993
  jsonKey: "rowspan",
2994
+ exportJsonKey: { rowspan: "$" },
2813
2995
  description: "Number of rows the cell spans.",
2814
2996
  format: TagFormat.number
2815
2997
  },
2816
2998
  {
2817
2999
  key: ConfigKey.property_tableColSpan,
2818
3000
  jsonKey: "colspan",
3001
+ exportJsonKey: { colspan: "$" },
2819
3002
  description: "Number of columns the cell spans.",
2820
3003
  format: TagFormat.number
2821
3004
  },
2822
3005
  {
2823
3006
  key: ConfigKey.property_tableScope,
2824
3007
  jsonKey: "scope",
3008
+ exportJsonKey: { scope: "$" },
2825
3009
  description: "Scope attribute for header cells.",
2826
3010
  format: TagFormat.plainText
2827
3011
  },
@@ -2842,6 +3026,7 @@ var CARDSETS = {
2842
3026
  //
2843
3027
  [CardSetConfigKey.pronunciationTable]: {
2844
3028
  jsonKey: "pronunciationTable.data",
3029
+ exportJsonKey: { pronunciationTable: { data: "$" } },
2845
3030
  sides: [
2846
3031
  {
2847
3032
  name: "cell",
@@ -2849,12 +3034,14 @@ var CARDSETS = {
2849
3034
  variants: [
2850
3035
  {
2851
3036
  jsonKey: "body",
3037
+ exportJsonKey: { body: "$" },
2852
3038
  tags: [
2853
3039
  {
2854
3040
  key: ConfigKey.group_standardItemLeadInstructionHint,
2855
3041
  description: "Standard tags for lead, instruction, and hint."
2856
3042
  },
2857
3043
  {
3044
+ exportJsonKey: { title: "$" },
2858
3045
  key: ConfigKey.tag_title,
2859
3046
  description: "Title of the pronunciation table."
2860
3047
  },
@@ -2875,12 +3062,15 @@ var CARDSETS = {
2875
3062
  //
2876
3063
  [CardSetConfigKey.botActionResponses]: {
2877
3064
  jsonKey: "responses",
3065
+ exportJsonKey: { responses: "$" },
2878
3066
  sides: [
2879
3067
  {
2880
3068
  name: "response",
2881
3069
  variants: [
2882
3070
  {
2883
3071
  jsonKey: "feedback",
3072
+ exportJsonKey: { feedback: "$" },
3073
+ format: TextFormat.plainText,
2884
3074
  tags: [
2885
3075
  {
2886
3076
  key: ConfigKey.property_reaction,
@@ -2888,16 +3078,53 @@ var CARDSETS = {
2888
3078
  format: TagFormat.plainText
2889
3079
  },
2890
3080
  {
2891
- key: ConfigKey.group_standardItemLead,
2892
- description: "Item, lead, page number, and margin number for the bot action response."
3081
+ key: ConfigKey.tag_item,
3082
+ jsonKey: "item",
3083
+ exportJsonKey: { item: "$" },
3084
+ format: TagFormat.plainText,
3085
+ description: "The item for the bit",
3086
+ chain: [
3087
+ {
3088
+ key: ConfigKey.tag_item,
3089
+ jsonKey: "lead",
3090
+ exportJsonKey: { lead: "$" },
3091
+ description: "The lead for the bit",
3092
+ maxCount: 1,
3093
+ chain: [
3094
+ {
3095
+ key: ConfigKey.tag_item,
3096
+ jsonKey: "pageNumber",
3097
+ exportJsonKey: { pageNumber: "$" },
3098
+ description: "The page number for the bit",
3099
+ maxCount: 1,
3100
+ chain: [
3101
+ {
3102
+ key: ConfigKey.tag_item,
3103
+ jsonKey: "marginNumber",
3104
+ exportJsonKey: { marginNumber: "$" },
3105
+ description: "The margin number for the bit",
3106
+ maxCount: 1
3107
+ }
3108
+ ]
3109
+ }
3110
+ ]
3111
+ }
3112
+ ]
2893
3113
  },
2894
3114
  {
2895
3115
  key: ConfigKey.tag_instruction,
2896
3116
  description: "The response label for the bot action.",
2897
- jsonKey: "response"
3117
+ jsonKey: "response",
3118
+ exportJsonKey: { response: "$" },
3119
+ format: TagFormat.plainText
2898
3120
  },
2899
3121
  {
2900
3122
  key: ConfigKey.property_example,
3123
+ exportJsonKey: [
3124
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
3125
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
3126
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3127
+ ],
2901
3128
  description: "Example text for the bot action response.",
2902
3129
  format: TagFormat.plainText
2903
3130
  }
@@ -2912,12 +3139,14 @@ var CARDSETS = {
2912
3139
  //
2913
3140
  [CardSetConfigKey.clozeList]: {
2914
3141
  jsonKey: "listItems",
3142
+ exportJsonKey: { listItems: "$" },
2915
3143
  sides: [
2916
3144
  {
2917
3145
  name: "content",
2918
3146
  variants: [
2919
3147
  {
2920
3148
  jsonKey: "body",
3149
+ exportJsonKey: { body: "$" },
2921
3150
  tags: [
2922
3151
  {
2923
3152
  key: ConfigKey.group_standardTags,
@@ -2938,18 +3167,21 @@ var CARDSETS = {
2938
3167
  //
2939
3168
  [CardSetConfigKey.exampleBitList]: {
2940
3169
  jsonKey: "listItems",
3170
+ exportJsonKey: { listItems: "$" },
2941
3171
  sides: [
2942
3172
  {
2943
3173
  name: "item",
2944
3174
  variants: [
2945
3175
  {
2946
3176
  jsonKey: "body",
3177
+ exportJsonKey: { body: "$" },
2947
3178
  tags: [
2948
3179
  {
2949
3180
  key: ConfigKey.group_standardTags,
2950
3181
  description: "Standard tags for example bits."
2951
3182
  },
2952
3183
  {
3184
+ exportJsonKey: { title: "$" },
2953
3185
  key: ConfigKey.tag_title,
2954
3186
  description: "Title of the example bit."
2955
3187
  }
@@ -2964,28 +3196,35 @@ var CARDSETS = {
2964
3196
  //
2965
3197
  [CardSetConfigKey.ingredients]: {
2966
3198
  jsonKey: "ingredients",
3199
+ exportJsonKey: { ingredients: "$" },
2967
3200
  sides: [
2968
3201
  {
2969
3202
  name: "ingredient",
2970
3203
  variants: [
2971
3204
  {
2972
3205
  jsonKey: "ingredient",
3206
+ exportJsonKey: { ingredient: "$" },
2973
3207
  tags: [
2974
3208
  {
3209
+ exportJsonKey: { title: "$" },
2975
3210
  key: ConfigKey.tag_title,
2976
3211
  description: "Title of the ingredient."
2977
3212
  },
2978
3213
  {
2979
3214
  key: ConfigKey.tag_true,
2980
3215
  description: "Checked state for the ingredient.",
2981
- jsonKey: "ingredient|set(checked=true)",
3216
+ jsonKey: "|set(checked=true)",
3217
+ exportJsonKey: { checked: true, $: "$" },
2982
3218
  maxCount: 1
3219
+ // nullable: true,
2983
3220
  },
2984
3221
  {
2985
3222
  key: ConfigKey.tag_false,
2986
3223
  description: "Unchecked state for the ingredient.",
2987
- jsonKey: "ingredient|set(checked=false)",
3224
+ jsonKey: "|set(checked=false)",
3225
+ exportJsonKey: { checked: false, $: "$" },
2988
3226
  maxCount: 1
3227
+ // nullable: true,
2989
3228
  },
2990
3229
  {
2991
3230
  key: ConfigKey.group_standardItemLead,
@@ -2994,9 +3233,12 @@ var CARDSETS = {
2994
3233
  {
2995
3234
  key: ConfigKey.tag_instruction,
2996
3235
  description: "The quantity of the ingredient.",
2997
- jsonKey: "quantity"
3236
+ jsonKey: "quantity",
3237
+ exportJsonKey: { quantity: "$" },
3238
+ format: TagFormat.number
2998
3239
  },
2999
3240
  {
3241
+ exportJsonKey: { hint: "$" },
3000
3242
  key: ConfigKey.tag_hint,
3001
3243
  description: "The hint for the ingredient."
3002
3244
  },
@@ -3032,6 +3274,7 @@ var CARDSETS = {
3032
3274
  //
3033
3275
  [CardSetConfigKey.bookReferenceList]: {
3034
3276
  jsonKey: "bookReferences",
3277
+ exportJsonKey: { bookReferences: "$" },
3035
3278
  sides: [
3036
3279
  {
3037
3280
  name: "reference",
@@ -3091,6 +3334,11 @@ var GROUPS = {
3091
3334
  format: TagFormat.plainText,
3092
3335
  maxCount: Count.infinity
3093
3336
  },
3337
+ {
3338
+ key: ConfigKey.property_gUri,
3339
+ description: "Global URI for the bit",
3340
+ format: TagFormat.plainText
3341
+ },
3094
3342
  {
3095
3343
  key: ConfigKey.property_customerId,
3096
3344
  description: "The customer-specific identifier for the bit",
@@ -3274,12 +3522,14 @@ var GROUPS = {
3274
3522
  {
3275
3523
  key: ConfigKey.property_groupTag,
3276
3524
  jsonKey: "groupTag.name",
3525
+ exportJsonKey: { groupTag: { name: "$" } },
3277
3526
  description: "The group tag(s) for the bit",
3278
3527
  format: TagFormat.plainText,
3279
3528
  maxCount: Count.infinity,
3280
3529
  chain: [
3281
3530
  {
3282
3531
  key: ConfigKey.property_tag,
3532
+ exportJsonKey: { tags: ["$"] },
3283
3533
  description: "The tag(s) for the group",
3284
3534
  format: TagFormat.plainText,
3285
3535
  maxCount: Count.infinity
@@ -3310,6 +3560,12 @@ var GROUPS = {
3310
3560
  format: TagFormat.plainText,
3311
3561
  maxCount: Count.infinity
3312
3562
  },
3563
+ {
3564
+ key: ConfigKey.property_sourceBB,
3565
+ description: "The source bounding box(es) for the bit (x, y, x1, y1)",
3566
+ format: TagFormat.coordinates,
3567
+ maxCount: Count.infinity
3568
+ },
3313
3569
  {
3314
3570
  key: ConfigKey.property_levelCEFRp,
3315
3571
  description: "The CEFRp level for the bit",
@@ -3347,8 +3603,10 @@ var GROUPS = {
3347
3603
  maxCount: Count.infinity
3348
3604
  },
3349
3605
  {
3606
+ exportJsonKey: { anchor: "$" },
3350
3607
  key: ConfigKey.tag_anchor,
3351
3608
  name: "Anchor",
3609
+ format: TagFormat.plainText,
3352
3610
  description: "The anchor for the bit"
3353
3611
  },
3354
3612
  {
@@ -3383,23 +3641,27 @@ var GROUPS = {
3383
3641
  {
3384
3642
  key: ConfigKey.tag_item,
3385
3643
  jsonKey: "item",
3644
+ exportJsonKey: { item: "$" },
3386
3645
  description: "The item for the bit",
3387
3646
  chain: [
3388
3647
  {
3389
3648
  key: ConfigKey.tag_item,
3390
3649
  jsonKey: "lead",
3650
+ exportJsonKey: { lead: "$" },
3391
3651
  description: "The lead for the bit",
3392
3652
  maxCount: 1,
3393
3653
  chain: [
3394
3654
  {
3395
3655
  key: ConfigKey.tag_item,
3396
3656
  jsonKey: "pageNumber",
3657
+ exportJsonKey: { pageNumber: "$" },
3397
3658
  description: "The page number for the bit",
3398
3659
  maxCount: 1,
3399
3660
  chain: [
3400
3661
  {
3401
3662
  key: ConfigKey.tag_item,
3402
3663
  jsonKey: "marginNumber",
3664
+ exportJsonKey: { marginNumber: "$" },
3403
3665
  description: "The margin number for the bit",
3404
3666
  maxCount: 1
3405
3667
  }
@@ -3420,11 +3682,13 @@ var GROUPS = {
3420
3682
  description: "Item, lead, page number, and margin number tags"
3421
3683
  },
3422
3684
  {
3685
+ exportJsonKey: { instruction: "$" },
3423
3686
  key: ConfigKey.tag_instruction,
3424
3687
  name: "Instruction",
3425
3688
  description: "The instruction for the bit"
3426
3689
  },
3427
3690
  {
3691
+ exportJsonKey: { hint: "$" },
3428
3692
  key: ConfigKey.tag_hint,
3429
3693
  name: "Hint",
3430
3694
  description: "The hint for the bit"
@@ -3444,9 +3708,17 @@ var GROUPS = {
3444
3708
  description: "Item, lead, page number, margin number, instruction and hint tags"
3445
3709
  },
3446
3710
  {
3711
+ // Bit-level example tag: bare/synthesized records the marker only;
3712
+ // valued [@example:text] emits `isExample: true` and `example` as
3713
+ // PM-rendered rich text (bitmark+ format).
3447
3714
  key: ConfigKey.property_example,
3715
+ exportJsonKey: [
3716
+ { "@keyonly": { isExample: true } },
3717
+ { "@absent": { isExample: true } },
3718
+ { isExample: true, example: "$" }
3719
+ ],
3448
3720
  description: "The example(s) for the bit",
3449
- format: TagFormat.plainText
3721
+ format: TagFormat.bitmarkText
3450
3722
  }
3451
3723
  ]
3452
3724
  },
@@ -3457,6 +3729,7 @@ var GROUPS = {
3457
3729
  {
3458
3730
  key: ConfigKey.property_imageSource,
3459
3731
  jsonKey: "imageSource.url",
3732
+ exportJsonKey: { imageSource: { url: "$" } },
3460
3733
  description: "The source of an image",
3461
3734
  format: TagFormat.plainText,
3462
3735
  chain: [
@@ -3491,6 +3764,7 @@ var GROUPS = {
3491
3764
  {
3492
3765
  key: ConfigKey.property_technicalTerm,
3493
3766
  jsonKey: "technicalTerm.technicalTerm",
3767
+ exportJsonKey: { technicalTerm: { technicalTerm: "$" } },
3494
3768
  description: "The technical term",
3495
3769
  format: TagFormat.plainText,
3496
3770
  chain: [
@@ -3509,7 +3783,8 @@ var GROUPS = {
3509
3783
  tags: [
3510
3784
  {
3511
3785
  key: ConfigKey.property_person,
3512
- jsonKey: "person.name",
3786
+ jsonKey: "partner.name",
3787
+ exportJsonKey: { partner: { name: "$" } },
3513
3788
  description: "A person",
3514
3789
  format: TagFormat.plainText,
3515
3790
  chain: [
@@ -3520,6 +3795,8 @@ var GROUPS = {
3520
3795
  },
3521
3796
  {
3522
3797
  key: ConfigKey.group_resourceImage,
3798
+ jsonKey: "avatarImage|resource(type=image, key=image)",
3799
+ exportJsonKey: { avatarImage: { type: "image", image: { src: "$" } } },
3523
3800
  description: "The image of the person"
3524
3801
  }
3525
3802
  ]
@@ -3528,6 +3805,7 @@ var GROUPS = {
3528
3805
  // Deprecated (parter renamed to person)
3529
3806
  key: ConfigKey.property_partner,
3530
3807
  jsonKey: "partner.name",
3808
+ exportJsonKey: { partner: { name: "$" } },
3531
3809
  description: "A partner",
3532
3810
  format: TagFormat.plainText,
3533
3811
  chain: [
@@ -3538,6 +3816,8 @@ var GROUPS = {
3538
3816
  },
3539
3817
  {
3540
3818
  key: ConfigKey.group_resourceImage,
3819
+ jsonKey: "avatarImage|resource(type=image, key=image)",
3820
+ exportJsonKey: { avatarImage: { type: "image", image: { src: "$" } } },
3541
3821
  description: "The image of the partner"
3542
3822
  }
3543
3823
  ]
@@ -3549,15 +3829,19 @@ var GROUPS = {
3549
3829
  description: "Gap chain",
3550
3830
  tags: [
3551
3831
  {
3832
+ exportJsonKey: { solutions: [["$"]] },
3552
3833
  key: ConfigKey.tag_gap,
3553
3834
  description: "The value of a gap in the content",
3554
3835
  maxCount: Count.infinity,
3836
+ format: TagFormat.plainText,
3555
3837
  chain: [
3556
3838
  {
3557
3839
  key: ConfigKey.tag_gap,
3558
3840
  jsonKey: "solutions[]",
3841
+ exportJsonKey: { solutions: ["$"] },
3559
3842
  description: "Alternative values for the gaps in the content",
3560
- maxCount: Count.infinity
3843
+ maxCount: Count.infinity,
3844
+ format: TagFormat.plainText
3561
3845
  },
3562
3846
  {
3563
3847
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3566,12 +3850,33 @@ var GROUPS = {
3566
3850
  {
3567
3851
  key: ConfigKey.property_example,
3568
3852
  jsonKey: "example",
3853
+ exportJsonKey: [
3854
+ {
3855
+ "@keyonly": {
3856
+ isExample: true,
3857
+ example: "$parent.solutions[0]",
3858
+ "@bit": { isExample: true }
3859
+ }
3860
+ },
3861
+ {
3862
+ "@absent": {
3863
+ isExample: true,
3864
+ example: "$parent.solutions[0]",
3865
+ "@bit": { isExample: true }
3866
+ }
3867
+ },
3868
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3869
+ ],
3569
3870
  description: "An example for the gap",
3570
- format: TagFormat.plainText
3871
+ format: TagFormat.bitmarkText
3571
3872
  },
3572
3873
  {
3573
3874
  key: ConfigKey.property_isCaseSensitive,
3574
3875
  jsonKey: "isCaseSensitive",
3876
+ exportJsonKey: [
3877
+ { "@absent": { isCaseSensitive: "$ancestor" } },
3878
+ { isCaseSensitive: "$" }
3879
+ ],
3575
3880
  description: "If true, the gap text is case sensitive",
3576
3881
  format: TagFormat.boolean,
3577
3882
  defaultValue: "true"
@@ -3585,21 +3890,27 @@ var GROUPS = {
3585
3890
  description: "True/False chain",
3586
3891
  tags: [
3587
3892
  {
3893
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3588
3894
  key: ConfigKey.tag_true,
3589
3895
  description: "True value for a true/false statement/question",
3590
3896
  maxCount: Count.infinity,
3897
+ format: TagFormat.plainText,
3591
3898
  chain: [
3592
3899
  {
3593
3900
  key: ConfigKey.tag_true,
3594
3901
  jsonKey: "choices[]|set(isCorrect=true)",
3902
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3595
3903
  description: "True values for a true/false statement/question",
3596
- maxCount: Count.infinity
3904
+ maxCount: Count.infinity,
3905
+ format: TagFormat.plainText
3597
3906
  },
3598
3907
  {
3599
3908
  key: ConfigKey.tag_false,
3600
3909
  jsonKey: "choices[]|set(isCorrect=false)",
3910
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3601
3911
  description: "False values for a true/false statement/question",
3602
- maxCount: Count.infinity
3912
+ maxCount: Count.infinity,
3913
+ format: TagFormat.plainText
3603
3914
  },
3604
3915
  {
3605
3916
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3608,27 +3919,50 @@ var GROUPS = {
3608
3919
  {
3609
3920
  key: ConfigKey.property_example,
3610
3921
  jsonKey: "example",
3922
+ exportJsonKey: [
3923
+ {
3924
+ "@keyonly": {
3925
+ isExample: true,
3926
+ example: "$parent.isCorrect",
3927
+ "@bit": { isExample: true }
3928
+ }
3929
+ },
3930
+ {
3931
+ "@absent": {
3932
+ isExample: true,
3933
+ example: "$parent.isCorrect",
3934
+ "@bit": { isExample: true }
3935
+ }
3936
+ },
3937
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3938
+ ],
3611
3939
  description: "An example for the true/false statement/question",
3612
- format: TagFormat.plainText
3940
+ format: TagFormat.bitmarkText
3613
3941
  }
3614
3942
  ]
3615
3943
  },
3616
3944
  {
3945
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3617
3946
  key: ConfigKey.tag_false,
3618
3947
  description: "False value for a true/false statement/question",
3619
3948
  maxCount: Count.infinity,
3949
+ format: TagFormat.plainText,
3620
3950
  chain: [
3621
3951
  {
3622
3952
  key: ConfigKey.tag_true,
3623
3953
  jsonKey: "choices[]|set(isCorrect=true)",
3954
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3624
3955
  description: "True values for a true/false statement/question",
3625
- maxCount: Count.infinity
3956
+ maxCount: Count.infinity,
3957
+ format: TagFormat.plainText
3626
3958
  },
3627
3959
  {
3628
3960
  key: ConfigKey.tag_false,
3629
3961
  jsonKey: "choices[]|set(isCorrect=false)",
3962
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3630
3963
  description: "False values for a true/false statement/question",
3631
- maxCount: Count.infinity
3964
+ maxCount: Count.infinity,
3965
+ format: TagFormat.plainText
3632
3966
  },
3633
3967
  {
3634
3968
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3637,8 +3971,25 @@ var GROUPS = {
3637
3971
  {
3638
3972
  key: ConfigKey.property_example,
3639
3973
  jsonKey: "example",
3974
+ exportJsonKey: [
3975
+ {
3976
+ "@keyonly": {
3977
+ isExample: true,
3978
+ example: "$parent.isCorrect",
3979
+ "@bit": { isExample: true }
3980
+ }
3981
+ },
3982
+ {
3983
+ "@absent": {
3984
+ isExample: true,
3985
+ example: "$parent.isCorrect",
3986
+ "@bit": { isExample: true }
3987
+ }
3988
+ },
3989
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3990
+ ],
3640
3991
  description: "An example for the true/false statement/question",
3641
- format: TagFormat.plainText
3992
+ format: TagFormat.bitmarkText
3642
3993
  }
3643
3994
  ]
3644
3995
  }
@@ -3651,6 +4002,7 @@ var GROUPS = {
3651
4002
  {
3652
4003
  key: ConfigKey.property_mark,
3653
4004
  jsonKey: "marks.mark",
4005
+ exportJsonKey: { marks: { mark: ["$"] } },
3654
4006
  description: "The mark configuration",
3655
4007
  format: TagFormat.plainText,
3656
4008
  maxCount: Count.infinity,
@@ -3674,9 +4026,11 @@ var GROUPS = {
3674
4026
  description: "Mark chain",
3675
4027
  tags: [
3676
4028
  {
4029
+ exportJsonKey: { solution: ["$"] },
3677
4030
  key: ConfigKey.tag_mark,
3678
4031
  description: "The marked content",
3679
4032
  maxCount: Count.infinity,
4033
+ format: TagFormat.plainText,
3680
4034
  chain: [
3681
4035
  {
3682
4036
  key: ConfigKey.property_mark,
@@ -3687,8 +4041,13 @@ var GROUPS = {
3687
4041
  {
3688
4042
  key: ConfigKey.property_example,
3689
4043
  jsonKey: "example",
4044
+ exportJsonKey: [
4045
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
4046
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
4047
+ { isExample: true, example: "$", "@bit": { isExample: true } }
4048
+ ],
3690
4049
  description: "An example for the marked content",
3691
- format: TagFormat.plainText
4050
+ format: TagFormat.bitmarkText
3692
4051
  }
3693
4052
  ]
3694
4053
  }
@@ -3776,7 +4135,9 @@ var GROUPS = {
3776
4135
  key: ConfigKey.tag_title,
3777
4136
  name: "Title",
3778
4137
  description: "The title of the book",
3779
- maxCount: 2
4138
+ maxCount: 2,
4139
+ jsonKey: "title|multi(count=2, key=subtitle)",
4140
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
3780
4141
  },
3781
4142
  {
3782
4143
  key: ConfigKey.property_subtype,
@@ -3791,6 +4152,8 @@ var GROUPS = {
3791
4152
  },
3792
4153
  {
3793
4154
  key: ConfigKey.resource_coverImage,
4155
+ jsonKey: "coverImage|resource(type=image, key=image)",
4156
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
3794
4157
  description: "The cover image of the book",
3795
4158
  chain: [
3796
4159
  {
@@ -3807,6 +4170,8 @@ var GROUPS = {
3807
4170
  },
3808
4171
  {
3809
4172
  key: ConfigKey.resource_backgroundImage,
4173
+ jsonKey: "backgroundImage|resource(type=image, key=image)",
4174
+ exportJsonKey: { backgroundImage: { type: "image", image: { src: "$" } } },
3810
4175
  description: "The background image of the book",
3811
4176
  chain: [
3812
4177
  {
@@ -3966,9 +4331,21 @@ var GROUPS = {
3966
4331
  format: TagFormat.plainText,
3967
4332
  chain: [
3968
4333
  {
4334
+ exportJsonKey: { reference: "$" },
3969
4335
  key: ConfigKey.tag_reference,
3970
- description: "The reference(s) for the book(s) in the learning path",
3971
- maxCount: 2
4336
+ format: TagFormat.plainText,
4337
+ description: "The reference for the book(s) in the learning path",
4338
+ maxCount: 1,
4339
+ chain: [
4340
+ {
4341
+ key: ConfigKey.tag_reference,
4342
+ jsonKey: "referenceEnd",
4343
+ exportJsonKey: { referenceEnd: "$" },
4344
+ format: TagFormat.plainText,
4345
+ description: "The referenceEnd for the book(s) in the learning path",
4346
+ maxCount: 1
4347
+ }
4348
+ ]
3972
4349
  }
3973
4350
  ]
3974
4351
  }
@@ -4108,6 +4485,8 @@ var GROUPS = {
4108
4485
  tags: [
4109
4486
  {
4110
4487
  key: ConfigKey.resource_imagePlaceholder,
4488
+ jsonKey: "imagePlaceholder|resource(type=image, key=image)",
4489
+ exportJsonKey: { imagePlaceholder: { type: "image", image: { src: "$" } } },
4111
4490
  description: "Placeholder image for the resource",
4112
4491
  chain: [
4113
4492
  {
@@ -4292,6 +4671,7 @@ var GROUPS = {
4292
4671
  {
4293
4672
  key: ConfigKey.property_posterImage,
4294
4673
  jsonKey: "posterImage.src",
4674
+ exportJsonKey: { posterImage: { src: "$" } },
4295
4675
  description: "The poster image for the video",
4296
4676
  format: TagFormat.plainText,
4297
4677
  chain: [
@@ -4348,6 +4728,7 @@ var GROUPS = {
4348
4728
  tags: [
4349
4729
  {
4350
4730
  key: ConfigKey.resource_image,
4731
+ exportJsonKey: { resource: { type: "image", image: { src: "$" } } },
4351
4732
  description: "The image resource",
4352
4733
  chain: [
4353
4734
  {
@@ -4412,6 +4793,7 @@ var GROUPS = {
4412
4793
  tags: [
4413
4794
  {
4414
4795
  key: ConfigKey.resource_imageLink,
4796
+ exportJsonKey: { resource: { type: "image-link", imageLink: { url: "$" } } },
4415
4797
  description: "The link to the image resource",
4416
4798
  chain: [
4417
4799
  {
@@ -4428,6 +4810,7 @@ var GROUPS = {
4428
4810
  tags: [
4429
4811
  {
4430
4812
  key: ConfigKey.resource_audio,
4813
+ exportJsonKey: { resource: { type: "audio", audio: { src: "$" } } },
4431
4814
  description: "The audio resource",
4432
4815
  chain: [
4433
4816
  {
@@ -4444,6 +4827,7 @@ var GROUPS = {
4444
4827
  tags: [
4445
4828
  {
4446
4829
  key: ConfigKey.resource_audioEmbed,
4830
+ exportJsonKey: { resource: { type: "audio-embed", audioEmbed: { src: "$" } } },
4447
4831
  description: "The embedded audio resource",
4448
4832
  chain: [
4449
4833
  {
@@ -4460,6 +4844,7 @@ var GROUPS = {
4460
4844
  tags: [
4461
4845
  {
4462
4846
  key: ConfigKey.resource_audioLink,
4847
+ exportJsonKey: { resource: { type: "audio-link", audioLink: { url: "$" } } },
4463
4848
  description: "The link to the audio resource",
4464
4849
  chain: [
4465
4850
  {
@@ -4476,6 +4861,7 @@ var GROUPS = {
4476
4861
  tags: [
4477
4862
  {
4478
4863
  key: ConfigKey.resource_video,
4864
+ exportJsonKey: { resource: { type: "video", video: { src: "$" } } },
4479
4865
  description: "The video resource",
4480
4866
  chain: [
4481
4867
  {
@@ -4492,6 +4878,7 @@ var GROUPS = {
4492
4878
  tags: [
4493
4879
  {
4494
4880
  key: ConfigKey.resource_videoEmbed,
4881
+ exportJsonKey: { resource: { type: "video-embed", videoEmbed: { url: "$" } } },
4495
4882
  description: "The embedded video resource",
4496
4883
  chain: [
4497
4884
  {
@@ -4508,6 +4895,7 @@ var GROUPS = {
4508
4895
  tags: [
4509
4896
  {
4510
4897
  key: ConfigKey.resource_videoLink,
4898
+ exportJsonKey: { resource: { type: "video-link", videoLink: { url: "$" } } },
4511
4899
  description: "The link to the video resource",
4512
4900
  chain: [
4513
4901
  {
@@ -4524,6 +4912,9 @@ var GROUPS = {
4524
4912
  tags: [
4525
4913
  {
4526
4914
  key: ConfigKey.resource_stillImageFilmEmbed,
4915
+ exportJsonKey: {
4916
+ resource: { type: "still-image-film-embed", stillImageFilmEmbed: { url: "$" } }
4917
+ },
4527
4918
  description: "The embedded still image film resource",
4528
4919
  chain: [
4529
4920
  {
@@ -4540,6 +4931,9 @@ var GROUPS = {
4540
4931
  tags: [
4541
4932
  {
4542
4933
  key: ConfigKey.resource_stillImageFilmLink,
4934
+ exportJsonKey: {
4935
+ resource: { type: "still-image-film-link", stillImageFilmLink: { url: "$" } }
4936
+ },
4543
4937
  description: "The link to the still image film resource",
4544
4938
  chain: [
4545
4939
  {
@@ -4604,6 +4998,7 @@ var GROUPS = {
4604
4998
  tags: [
4605
4999
  {
4606
5000
  key: ConfigKey.resource_document,
5001
+ exportJsonKey: { resource: { type: "document", document: { url: "$" } } },
4607
5002
  description: "The document resource",
4608
5003
  chain: [
4609
5004
  {
@@ -4620,6 +5015,7 @@ var GROUPS = {
4620
5015
  tags: [
4621
5016
  {
4622
5017
  key: ConfigKey.resource_documentEmbed,
5018
+ exportJsonKey: { resource: { type: "document-embed", documentEmbed: { url: "$" } } },
4623
5019
  description: "The embedded document resource",
4624
5020
  chain: [
4625
5021
  {
@@ -4636,6 +5032,7 @@ var GROUPS = {
4636
5032
  tags: [
4637
5033
  {
4638
5034
  key: ConfigKey.resource_documentLink,
5035
+ exportJsonKey: { resource: { type: "document-link", documentLink: { url: "$" } } },
4639
5036
  description: "The link to the document resource",
4640
5037
  chain: [
4641
5038
  {
@@ -4652,6 +5049,7 @@ var GROUPS = {
4652
5049
  tags: [
4653
5050
  {
4654
5051
  key: ConfigKey.resource_documentDownload,
5052
+ exportJsonKey: { resource: { type: "document-download", documentDownload: { url: "$" } } },
4655
5053
  description: "The downloadable document resource",
4656
5054
  chain: [
4657
5055
  {
@@ -4668,6 +5066,7 @@ var GROUPS = {
4668
5066
  tags: [
4669
5067
  {
4670
5068
  key: ConfigKey.resource_appLink,
5069
+ exportJsonKey: { resource: { type: "app-link", appLink: { url: "$" } } },
4671
5070
  description: "The link to the app resource",
4672
5071
  chain: [
4673
5072
  {
@@ -4684,6 +5083,7 @@ var GROUPS = {
4684
5083
  tags: [
4685
5084
  {
4686
5085
  key: ConfigKey.resource_websiteLink,
5086
+ exportJsonKey: { resource: { type: "website-link", websiteLink: { url: "$" } } },
4687
5087
  description: "The link to the website resource",
4688
5088
  chain: [
4689
5089
  {
@@ -4741,6 +5141,8 @@ var GROUPS = {
4741
5141
  tags: [
4742
5142
  {
4743
5143
  key: ConfigKey.resource_previewImage,
5144
+ jsonKey: "previewImage|resource(type=image, key=image)",
5145
+ exportJsonKey: { previewImage: { type: "image", image: { src: "$" } } },
4744
5146
  description: "The preview image resource",
4745
5147
  chain: [
4746
5148
  {
@@ -4757,6 +5159,8 @@ var GROUPS = {
4757
5159
  tags: [
4758
5160
  {
4759
5161
  key: ConfigKey.resource_previewVideo,
5162
+ jsonKey: "previewVideo|resource(type=video, key=video)",
5163
+ exportJsonKey: { previewVideo: { type: "video", video: { src: "$" } } },
4760
5164
  description: "The preview video resource",
4761
5165
  chain: [
4762
5166
  {
@@ -4821,20 +5225,48 @@ var ConfigHydrator = class {
4821
5225
  _side.name,
4822
5226
  _side.repeat ?? false,
4823
5227
  variantsOfSide,
4824
- _side.jsonKey
5228
+ _side.jsonKey,
5229
+ _side.exportJsonKey,
5230
+ Object.prototype.hasOwnProperty.call(_side, "exportJsonKey")
4825
5231
  );
4826
5232
  sides.push(sideConfig);
4827
5233
  }
4828
5234
  const cardSetConfig = new CardSetConfig(
4829
5235
  _cardSet,
4830
5236
  _cardSetConfig.jsonKey,
4831
- _cardSetConfig.sections,
5237
+ _cardSetConfig.exportJsonKey,
5238
+ Object.prototype.hasOwnProperty.call(_cardSetConfig, "exportJsonKey"),
5239
+ this.hydrateCardSections(_cardSetConfig.sections),
4832
5240
  sides
4833
5241
  );
4834
5242
  return cardSetConfig;
4835
5243
  }
5244
+ hydrateCardSections(sections) {
5245
+ if (!sections) return void 0;
5246
+ const out = {};
5247
+ for (const [k, v] of Object.entries(sections)) {
5248
+ out[k] = {
5249
+ jsonKey: v.jsonKey,
5250
+ exportJsonKey: v.exportJsonKey,
5251
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(v, "exportJsonKey"),
5252
+ isDefault: v.isDefault,
5253
+ sideJsonKey: v.sideJsonKey,
5254
+ sideExportJsonKey: v.sideExportJsonKey,
5255
+ hasSideExportJsonKey: Object.prototype.hasOwnProperty.call(v, "sideExportJsonKey")
5256
+ };
5257
+ }
5258
+ return out;
5259
+ }
4836
5260
  hydrateTagConfig(_tag) {
4837
- const { key: _configKey, maxCount, minCount, chain: _chain, deprecated } = _tag;
5261
+ const {
5262
+ key: _configKey,
5263
+ maxCount,
5264
+ minCount,
5265
+ chain: _chain,
5266
+ deprecated,
5267
+ jsonKey,
5268
+ exportJsonKey
5269
+ } = _tag;
4838
5270
  const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4839
5271
  if (!configKey) throw new Error(`No tag key found for config key '${configKey}'`);
4840
5272
  const tag = Enum(Tag).fromValue(configKey);
@@ -4849,6 +5281,9 @@ var ConfigHydrator = class {
4849
5281
  maxCount: maxCount ?? MAX_COUNT_DEFAULT,
4850
5282
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4851
5283
  chain,
5284
+ jsonKey,
5285
+ exportJsonKey,
5286
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4852
5287
  deprecated
4853
5288
  });
4854
5289
  return {
@@ -4867,7 +5302,8 @@ var ConfigHydrator = class {
4867
5302
  format,
4868
5303
  values,
4869
5304
  defaultValue,
4870
- jsonKey
5305
+ jsonKey,
5306
+ exportJsonKey
4871
5307
  } = _tag;
4872
5308
  const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4873
5309
  if (!configKey) throw new Error(`No property key found for config key '${configKey}'`);
@@ -4883,6 +5319,8 @@ var ConfigHydrator = class {
4883
5319
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4884
5320
  chain,
4885
5321
  jsonKey,
5322
+ exportJsonKey,
5323
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4886
5324
  format,
4887
5325
  values,
4888
5326
  defaultValue,
@@ -4895,7 +5333,15 @@ var ConfigHydrator = class {
4895
5333
  };
4896
5334
  }
4897
5335
  hydrateResourceTagConfig(_tag) {
4898
- const { key: _configKey, maxCount, minCount, chain: _chain, deprecated, jsonKey } = _tag;
5336
+ const {
5337
+ key: _configKey,
5338
+ maxCount,
5339
+ minCount,
5340
+ chain: _chain,
5341
+ deprecated,
5342
+ jsonKey,
5343
+ exportJsonKey
5344
+ } = _tag;
4899
5345
  const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4900
5346
  if (!configKey) throw new Error(`No resource key found for config key '${configKey}'`);
4901
5347
  const tag = _configKey.substring(1);
@@ -4910,6 +5356,8 @@ var ConfigHydrator = class {
4910
5356
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4911
5357
  chain,
4912
5358
  jsonKey,
5359
+ exportJsonKey,
5360
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4913
5361
  deprecated
4914
5362
  });
4915
5363
  return {
@@ -4941,14 +5389,25 @@ var ConfigHydrator = class {
4941
5389
  };
4942
5390
  }
4943
5391
  hydrateCardVariantConfig(_variant) {
4944
- const { tags: _tags, bodyAllowed, bodyRequired, repeatCount, jsonKey } = _variant;
5392
+ const {
5393
+ tags: _tags,
5394
+ bodyAllowed,
5395
+ bodyRequired,
5396
+ repeatCount,
5397
+ jsonKey,
5398
+ exportJsonKey,
5399
+ format
5400
+ } = _variant;
4945
5401
  const tags2 = this.hydrateTagsConfig(_tags);
4946
5402
  const cardSetConfig = new CardVariantConfig(
4947
5403
  tags2.tags,
4948
5404
  bodyAllowed,
4949
5405
  bodyRequired,
4950
5406
  repeatCount,
4951
- jsonKey
5407
+ jsonKey,
5408
+ exportJsonKey,
5409
+ Object.prototype.hasOwnProperty.call(_variant, "exportJsonKey"),
5410
+ format
4952
5411
  );
4953
5412
  return cardSetConfig;
4954
5413
  }
@@ -4986,6 +5445,7 @@ var BITS = {
4986
5445
  description: "Common tags for quiz bits"
4987
5446
  },
4988
5447
  {
5448
+ exportJsonKey: { title: "$" },
4989
5449
  key: ConfigKey.tag_title,
4990
5450
  description: "The title of the flashcard quiz"
4991
5451
  },
@@ -4994,6 +5454,20 @@ var BITS = {
4994
5454
  description: "The flashcard set to use for the app flashcards",
4995
5455
  format: TagFormat.plainText,
4996
5456
  maxCount: Count.infinity
5457
+ },
5458
+ {
5459
+ // Override inherited @example from group_standardTags: string root
5460
+ // example. Bare/synthesized emits `example: "true"` (a text literal
5461
+ // that field-coerces to a paragraph "true" in bitmark+ contexts);
5462
+ // valued [@example:text] emits the user's text via `$`.
5463
+ key: ConfigKey.property_example,
5464
+ exportJsonKey: [
5465
+ { "@keyonly": { isExample: true, example: "true" } },
5466
+ { "@absent": { isExample: true, example: "true" } },
5467
+ { isExample: true, example: "$" }
5468
+ ],
5469
+ description: "The example text for the bit",
5470
+ format: TagFormat.plainText
4997
5471
  }
4998
5472
  ],
4999
5473
  rootExampleType: ExampleType.string
@@ -5075,6 +5549,7 @@ var BITS = {
5075
5549
  description: "Article bit, used for articles / paragraphs",
5076
5550
  tags: [
5077
5551
  {
5552
+ exportJsonKey: { title: "$" },
5078
5553
  key: ConfigKey.tag_title,
5079
5554
  description: "The title of the article"
5080
5555
  }
@@ -5181,7 +5656,9 @@ var BITS = {
5181
5656
  {
5182
5657
  key: ConfigKey.tag_title,
5183
5658
  description: "Title and subtitle of the catalog item",
5184
- maxCount: 2
5659
+ maxCount: 2,
5660
+ jsonKey: "title|multi(count=2, key=subtitle)",
5661
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5185
5662
  },
5186
5663
  {
5187
5664
  key: ConfigKey.property_coverImage,
@@ -5190,6 +5667,8 @@ var BITS = {
5190
5667
  },
5191
5668
  {
5192
5669
  key: ConfigKey.resource_coverImage,
5670
+ jsonKey: "coverImage|resource(type=image, key=image)",
5671
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
5193
5672
  description: "Cover image of the catalog item",
5194
5673
  chain: [
5195
5674
  {
@@ -5317,6 +5796,17 @@ var BITS = {
5317
5796
  key: ConfigKey.group_previewVideos,
5318
5797
  description: "Array of preview videos for the catalog item",
5319
5798
  maxCount: Count.infinity
5799
+ },
5800
+ {
5801
+ // Override inherited @example from group_standardTags: string root example.
5802
+ key: ConfigKey.property_example,
5803
+ exportJsonKey: [
5804
+ { "@keyonly": { isExample: true, example: "true" } },
5805
+ { "@absent": { isExample: true, example: "true" } },
5806
+ { isExample: true, example: "$" }
5807
+ ],
5808
+ description: "The example text for the bit",
5809
+ format: TagFormat.plainText
5320
5810
  }
5321
5811
  ],
5322
5812
  rootExampleType: ExampleType.string
@@ -5329,7 +5819,9 @@ var BITS = {
5329
5819
  {
5330
5820
  key: ConfigKey.tag_title,
5331
5821
  description: "Title and subtitle of the catalog item",
5332
- maxCount: 2
5822
+ maxCount: 2,
5823
+ jsonKey: "title|multi(count=2, key=subtitle)",
5824
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5333
5825
  },
5334
5826
  {
5335
5827
  key: ConfigKey.property_coverImage,
@@ -5338,6 +5830,8 @@ var BITS = {
5338
5830
  },
5339
5831
  {
5340
5832
  key: ConfigKey.resource_coverImage,
5833
+ jsonKey: "coverImage|resource(type=image, key=image)",
5834
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
5341
5835
  description: "Cover image of the catalog item",
5342
5836
  chain: [
5343
5837
  {
@@ -5465,6 +5959,17 @@ var BITS = {
5465
5959
  key: ConfigKey.group_previewVideos,
5466
5960
  description: "Array of preview videos for the catalog item",
5467
5961
  maxCount: Count.infinity
5962
+ },
5963
+ {
5964
+ // Override inherited @example from group_standardTags: string root example.
5965
+ key: ConfigKey.property_example,
5966
+ exportJsonKey: [
5967
+ { "@keyonly": { isExample: true, example: "true" } },
5968
+ { "@absent": { isExample: true, example: "true" } },
5969
+ { isExample: true, example: "$" }
5970
+ ],
5971
+ description: "The example text for the bit",
5972
+ format: TagFormat.plainText
5468
5973
  }
5469
5974
  ],
5470
5975
  rootExampleType: ExampleType.string
@@ -5477,7 +5982,9 @@ var BITS = {
5477
5982
  {
5478
5983
  key: ConfigKey.tag_title,
5479
5984
  description: "Title and subtitle of the catalog item",
5480
- maxCount: 2
5985
+ maxCount: 2,
5986
+ jsonKey: "title|multi(count=2, key=subtitle)",
5987
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5481
5988
  },
5482
5989
  {
5483
5990
  key: ConfigKey.property_coverImage,
@@ -5603,6 +6110,17 @@ var BITS = {
5603
6110
  key: ConfigKey.group_previewVideos,
5604
6111
  description: "Array of preview videos for the catalog item",
5605
6112
  maxCount: Count.infinity
6113
+ },
6114
+ {
6115
+ // Override inherited @example from group_standardTags: string root example.
6116
+ key: ConfigKey.property_example,
6117
+ exportJsonKey: [
6118
+ { "@keyonly": { isExample: true, example: "true" } },
6119
+ { "@absent": { isExample: true, example: "true" } },
6120
+ { isExample: true, example: "$" }
6121
+ ],
6122
+ description: "The example text for the bit",
6123
+ format: TagFormat.plainText
5606
6124
  }
5607
6125
  ],
5608
6126
  rootExampleType: ExampleType.string
@@ -5804,11 +6322,15 @@ var BITS = {
5804
6322
  description: "Bit alias, used to create an alias for a bit",
5805
6323
  tags: [
5806
6324
  {
6325
+ exportJsonKey: { reference: "$" },
5807
6326
  key: ConfigKey.tag_reference,
6327
+ format: TagFormat.plainText,
5808
6328
  description: "The reference to the bit that this alias points to"
5809
6329
  },
5810
6330
  {
6331
+ exportJsonKey: { anchor: "$" },
5811
6332
  key: ConfigKey.tag_anchor,
6333
+ format: TagFormat.plainText,
5812
6334
  description: "The anchor for the bit alias, used for linking"
5813
6335
  }
5814
6336
  ]
@@ -6006,8 +6528,10 @@ var BITS = {
6006
6528
  {
6007
6529
  key: ConfigKey.tag_title,
6008
6530
  description: "The title of the book cover",
6009
- maxCount: 2
6531
+ maxCount: 2,
6010
6532
  // title & subtitle
6533
+ jsonKey: "title|multi(count=2, key=subtitle)",
6534
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
6011
6535
  },
6012
6536
  {
6013
6537
  key: ConfigKey.property_coverColor,
@@ -6151,12 +6675,16 @@ var BITS = {
6151
6675
  description: "Chapter bit, used to define chapters in books or articles",
6152
6676
  tags: [
6153
6677
  {
6678
+ exportJsonKey: { anchor: "$" },
6154
6679
  key: ConfigKey.tag_anchor,
6680
+ format: TagFormat.plainText,
6155
6681
  description: "The anchor for the chapter, used for linking"
6156
6682
  },
6157
6683
  {
6158
6684
  key: ConfigKey.tag_title,
6159
- description: "The title of the chapter"
6685
+ description: "The title of the chapter",
6686
+ jsonKey: "title|setMulti(level)",
6687
+ exportJsonKey: { title: "$", level: "$level" }
6160
6688
  },
6161
6689
  {
6162
6690
  key: ConfigKey.property_toc,
@@ -6209,6 +6737,7 @@ var BITS = {
6209
6737
  },
6210
6738
  {
6211
6739
  key: ConfigKey.property_isCaseSensitive,
6740
+ exportJsonKey: {},
6212
6741
  description: "If the cloze answers are case sensitive",
6213
6742
  format: TagFormat.boolean,
6214
6743
  defaultValue: "true"
@@ -6306,6 +6835,11 @@ var BITS = {
6306
6835
  description: "Formula bit, used for mathematical formulas in articles or documents",
6307
6836
  textFormatDefault: TextFormat.latex
6308
6837
  },
6838
+ [BitType.formulaImage]: {
6839
+ since: "5.23.0",
6840
+ baseBitType: BitType.formula,
6841
+ description: "Formula image bit, used for mathematical formulas rendered as images"
6842
+ },
6309
6843
  [BitType.smartStandardFormula]: {
6310
6844
  since: "3.11.0",
6311
6845
  baseBitType: BitType.formula,
@@ -6658,6 +7192,7 @@ var BITS = {
6658
7192
  {
6659
7193
  key: ConfigKey.property_servings,
6660
7194
  jsonKey: "servings.servings",
7195
+ exportJsonKey: { servings: { servings: "$" } },
6661
7196
  description: "The number of servings for the ingredients",
6662
7197
  format: TagFormat.number,
6663
7198
  chain: [
@@ -6683,8 +7218,10 @@ var BITS = {
6683
7218
  format: TagFormat.boolean
6684
7219
  },
6685
7220
  {
7221
+ exportJsonKey: { hint: "$" },
6686
7222
  key: ConfigKey.tag_hint,
6687
- description: "Hint for the ingredient, used to provide additional information"
7223
+ description: "Hint for the ingredient, used to provide additional information",
7224
+ format: TagFormat.plainText
6688
7225
  }
6689
7226
  ]
6690
7227
  }
@@ -6859,6 +7396,17 @@ var BITS = {
6859
7396
  description: "Reference for the essay, used to link to external resources",
6860
7397
  format: TagFormat.plainText,
6861
7398
  maxCount: Count.infinity
7399
+ },
7400
+ {
7401
+ // Override inherited @example from group_standardTags: string root example.
7402
+ key: ConfigKey.property_example,
7403
+ exportJsonKey: [
7404
+ { "@keyonly": { isExample: true, example: "true" } },
7405
+ { "@absent": { isExample: true, example: "true" } },
7406
+ { isExample: true, example: "$" }
7407
+ ],
7408
+ description: "The example text for the essay bit",
7409
+ format: TagFormat.plainText
6862
7410
  }
6863
7411
  ],
6864
7412
  rootExampleType: ExampleType.string
@@ -6879,8 +7427,20 @@ var BITS = {
6879
7427
  description: "Example bit, used to provide examples in articles or books",
6880
7428
  tags: [
6881
7429
  {
7430
+ exportJsonKey: { title: "$" },
6882
7431
  key: ConfigKey.tag_title,
6883
7432
  description: "The title of the example"
7433
+ },
7434
+ {
7435
+ // Override inherited @example from group_standardTags: string root example.
7436
+ key: ConfigKey.property_example,
7437
+ exportJsonKey: [
7438
+ { "@keyonly": { isExample: true, example: "true" } },
7439
+ { "@absent": { isExample: true, example: "true" } },
7440
+ { isExample: true, example: "$" }
7441
+ ],
7442
+ description: "The example text for the example bit",
7443
+ format: TagFormat.plainText
6884
7444
  }
6885
7445
  ],
6886
7446
  rootExampleType: ExampleType.string
@@ -7746,6 +8306,7 @@ var BITS = {
7746
8306
  // Image resource
7747
8307
  key: ConfigKey.group_resourceImage,
7748
8308
  description: "Resource image tags for logo grave images, used to attach images",
8309
+ exportJsonKey: { images: "$" },
7749
8310
  minCount: 1,
7750
8311
  maxCount: Count.infinity
7751
8312
  }
@@ -7909,15 +8470,29 @@ var BITS = {
7909
8470
  format: TagFormat.plainText,
7910
8471
  chain: [
7911
8472
  {
8473
+ exportJsonKey: { reference: "$" },
7912
8474
  key: ConfigKey.tag_reference,
8475
+ format: TagFormat.plainText,
7913
8476
  description: "Reference tag for the book, used to link to the book in the system",
7914
- maxCount: 2
8477
+ maxCount: 1,
8478
+ chain: [
8479
+ {
8480
+ key: ConfigKey.tag_reference,
8481
+ jsonKey: "referenceEnd",
8482
+ exportJsonKey: { referenceEnd: "$" },
8483
+ format: TagFormat.plainText,
8484
+ description: "End reference tag for the book, used to specify a range",
8485
+ maxCount: 1
8486
+ }
8487
+ ]
7915
8488
  }
7916
8489
  ]
7917
8490
  },
7918
8491
  {
7919
8492
  /* Allow incorrectly chained reference tag */
8493
+ exportJsonKey: { reference: "$" },
7920
8494
  key: ConfigKey.tag_reference,
8495
+ format: TagFormat.plainText,
7921
8496
  description: "Reference tag for the book, used to link to the book in the system"
7922
8497
  },
7923
8498
  {
@@ -7962,16 +8537,41 @@ var BITS = {
7962
8537
  format: TagFormat.plainText,
7963
8538
  chain: [
7964
8539
  {
8540
+ exportJsonKey: { reference: "$" },
7965
8541
  key: ConfigKey.tag_reference,
8542
+ format: TagFormat.plainText,
7966
8543
  description: "Reference tag for the book, used to link to the book in the system",
7967
- maxCount: 2
8544
+ maxCount: 1,
8545
+ chain: [
8546
+ {
8547
+ key: ConfigKey.tag_reference,
8548
+ jsonKey: "referenceEnd",
8549
+ exportJsonKey: { referenceEnd: "$" },
8550
+ format: TagFormat.plainText,
8551
+ description: "End reference tag for the book, used to specify a range",
8552
+ maxCount: 1
8553
+ }
8554
+ ]
7968
8555
  }
7969
8556
  ]
7970
8557
  },
7971
8558
  {
7972
8559
  /* Allow incorrectly chained reference tag */
8560
+ exportJsonKey: { reference: "$" },
7973
8561
  key: ConfigKey.tag_reference,
7974
- description: "Reference tag for the book, used to link to the book in the system"
8562
+ format: TagFormat.plainText,
8563
+ description: "Reference tag for the book, used to link to the book in the system",
8564
+ maxCount: 1,
8565
+ chain: [
8566
+ {
8567
+ key: ConfigKey.tag_reference,
8568
+ jsonKey: "referenceEnd",
8569
+ exportJsonKey: { referenceEnd: "$" },
8570
+ format: TagFormat.plainText,
8571
+ description: "End reference tag for the book, used to specify a range",
8572
+ maxCount: 1
8573
+ }
8574
+ ]
7975
8575
  },
7976
8576
  {
7977
8577
  key: ConfigKey.property_buttonCaption,
@@ -8000,9 +8600,21 @@ var BITS = {
8000
8600
  maxCount: Count.infinity,
8001
8601
  chain: [
8002
8602
  {
8603
+ exportJsonKey: { reference: "$" },
8003
8604
  key: ConfigKey.tag_reference,
8605
+ format: TagFormat.plainText,
8004
8606
  description: "Reference tag for the book, used to link to the book in the system",
8005
- maxCount: 2
8607
+ maxCount: 1,
8608
+ chain: [
8609
+ {
8610
+ key: ConfigKey.tag_reference,
8611
+ jsonKey: "referenceEnd",
8612
+ exportJsonKey: { referenceEnd: "$" },
8613
+ format: TagFormat.plainText,
8614
+ description: "End reference tag for the book, used to specify a range",
8615
+ maxCount: 1
8616
+ }
8617
+ ]
8006
8618
  }
8007
8619
  ]
8008
8620
  },
@@ -8169,6 +8781,7 @@ var BITS = {
8169
8781
  tags: [
8170
8782
  {
8171
8783
  key: ConfigKey.resource_backgroundWallpaper,
8784
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
8172
8785
  description: "Background wallpaper for the image, used to set a background for the image",
8173
8786
  chain: [
8174
8787
  {
@@ -8351,6 +8964,7 @@ var BITS = {
8351
8964
  },
8352
8965
  {
8353
8966
  key: ConfigKey.resource_backgroundWallpaper,
8967
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
8354
8968
  description: "Background wallpaper for the image, used to set a background for the image",
8355
8969
  chain: [
8356
8970
  {
@@ -8503,6 +9117,7 @@ var BITS = {
8503
9117
  // Image resource
8504
9118
  key: ConfigKey.group_resourceImage,
8505
9119
  description: "Resource image tags for logo grave images, used to attach images",
9120
+ exportJsonKey: { logos: "$" },
8506
9121
  minCount: 1,
8507
9122
  maxCount: Count.infinity
8508
9123
  }
@@ -8520,7 +9135,9 @@ var BITS = {
8520
9135
  description: "Internal link bit, used to create links to other bits in articles or books",
8521
9136
  tags: [
8522
9137
  {
9138
+ exportJsonKey: { reference: "$" },
8523
9139
  key: ConfigKey.tag_reference,
9140
+ format: TagFormat.plainText,
8524
9141
  description: "Reference tag for the internal link, used to link to the target bit"
8525
9142
  }
8526
9143
  ]
@@ -8537,6 +9154,7 @@ var BITS = {
8537
9154
  },
8538
9155
  {
8539
9156
  key: ConfigKey.property_reasonableNumOfChars,
9157
+ exportJsonKey: {},
8540
9158
  description: "Reasonable number of characters for the interview, used to limit input size",
8541
9159
  format: TagFormat.number
8542
9160
  }
@@ -8912,6 +9530,7 @@ var BITS = {
8912
9530
  },
8913
9531
  {
8914
9532
  key: ConfigKey.property_isCaseSensitive,
9533
+ exportJsonKey: {},
8915
9534
  description: "Case sensitivity for matching pairs, used to define if matches are case-sensitive",
8916
9535
  format: TagFormat.boolean,
8917
9536
  defaultValue: "true"
@@ -8964,6 +9583,7 @@ var BITS = {
8964
9583
  tags: [
8965
9584
  {
8966
9585
  key: ConfigKey.property_reasonableNumOfChars,
9586
+ exportJsonKey: {},
8967
9587
  description: "Reasonable number of characters for feedback, used to limit input size",
8968
9588
  format: TagFormat.number
8969
9589
  }
@@ -9105,6 +9725,7 @@ var BITS = {
9105
9725
  description: "Page bit, used to create pages in articles or books",
9106
9726
  tags: [
9107
9727
  {
9728
+ exportJsonKey: { title: "$" },
9108
9729
  key: ConfigKey.tag_title,
9109
9730
  description: "Title of the page, used to display the page title"
9110
9731
  },
@@ -9463,6 +10084,8 @@ var BITS = {
9463
10084
  },
9464
10085
  {
9465
10086
  key: ConfigKey.resource_platformBackgroundImage,
10087
+ jsonKey: "platformBackgroundImage|resource(type=image, key=image)",
10088
+ exportJsonKey: { platformBackgroundImage: { type: "image", image: { src: "$" } } },
9466
10089
  description: "The platform section chat background image",
9467
10090
  chain: [
9468
10091
  {
@@ -9556,6 +10179,7 @@ var BITS = {
9556
10179
  description: "Review note bit, used to create review notes in articles or books",
9557
10180
  tags: [
9558
10181
  {
10182
+ exportJsonKey: { title: "$" },
9559
10183
  key: ConfigKey.tag_title,
9560
10184
  description: "Title of the review note, used to display the note title"
9561
10185
  },
@@ -9574,6 +10198,17 @@ var BITS = {
9574
10198
  key: ConfigKey.property_resolvedBy,
9575
10199
  description: "Resolved by for the review note, used to define who resolved the note",
9576
10200
  format: TagFormat.plainText
10201
+ },
10202
+ {
10203
+ // Override inherited @example from group_standardTags: string root example.
10204
+ key: ConfigKey.property_example,
10205
+ exportJsonKey: [
10206
+ { "@keyonly": { isExample: true, example: "true" } },
10207
+ { "@absent": { isExample: true, example: "true" } },
10208
+ { isExample: true, example: "$" }
10209
+ ],
10210
+ description: "The example text for the review note bit",
10211
+ format: TagFormat.plainText
9577
10212
  }
9578
10213
  ],
9579
10214
  rootExampleType: ExampleType.string
@@ -9626,11 +10261,15 @@ var BITS = {
9626
10261
  tags: [
9627
10262
  // Not sure if these are actually valid here, but include them as they are in the test bit.
9628
10263
  {
10264
+ exportJsonKey: { anchor: "$" },
9629
10265
  key: ConfigKey.tag_anchor,
10266
+ format: TagFormat.plainText,
9630
10267
  description: "Anchor for the sample solution, used to link to the solution"
9631
10268
  },
9632
10269
  {
10270
+ exportJsonKey: { reference: "$" },
9633
10271
  key: ConfigKey.tag_reference,
10272
+ format: TagFormat.plainText,
9634
10273
  description: "Reference for the sample solution, used to link to the source of the solution"
9635
10274
  }
9636
10275
  ]
@@ -9644,6 +10283,19 @@ var BITS = {
9644
10283
  {
9645
10284
  key: ConfigKey.group_quizCommon,
9646
10285
  description: "Common quiz tags for sequences"
10286
+ },
10287
+ {
10288
+ // Override inherited @example from group_standardTags: this bit has
10289
+ // a boolean root example (rootExampleType: boolean), so bit-level
10290
+ // [@example] writes `example: true` in addition to `isExample: true`.
10291
+ key: ConfigKey.property_example,
10292
+ exportJsonKey: [
10293
+ { "@keyonly": { isExample: true, example: true } },
10294
+ { "@absent": { isExample: true, example: true } },
10295
+ { isExample: true, example: "$" }
10296
+ ],
10297
+ description: "The example flag for the bit (boolean)",
10298
+ format: TagFormat.plainText
9647
10299
  }
9648
10300
  ],
9649
10301
  cardSet: CardSetConfigKey.elements,
@@ -9751,6 +10403,7 @@ var BITS = {
9751
10403
  {
9752
10404
  key: ConfigKey.property_ratingLevelStart,
9753
10405
  jsonKey: "ratingLevelStart.level",
10406
+ exportJsonKey: { ratingLevelStart: { level: "$" } },
9754
10407
  description: "Start level for the rating survey, used to define the lowest rating",
9755
10408
  format: TagFormat.number,
9756
10409
  chain: [
@@ -9764,6 +10417,7 @@ var BITS = {
9764
10417
  {
9765
10418
  key: ConfigKey.property_ratingLevelEnd,
9766
10419
  jsonKey: "ratingLevelEnd.level",
10420
+ exportJsonKey: { ratingLevelEnd: { level: "$" } },
9767
10421
  description: "End level for the rating survey, used to define the highest rating",
9768
10422
  format: TagFormat.number,
9769
10423
  chain: [
@@ -9916,6 +10570,7 @@ var BITS = {
9916
10570
  },
9917
10571
  {
9918
10572
  key: ConfigKey.resource_backgroundWallpaper,
10573
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
9919
10574
  description: "Background wallpaper for the image, used to set a background for the image",
9920
10575
  chain: [
9921
10576
  {
@@ -10299,12 +10954,34 @@ var BITS = {
10299
10954
  format: TagFormat.plainText
10300
10955
  },
10301
10956
  {
10957
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
10302
10958
  key: ConfigKey.tag_true,
10303
- description: "Tag for the true option in the true/false question"
10959
+ description: "Tag for the true option in the true/false question",
10960
+ format: TagFormat.plainText
10304
10961
  },
10305
10962
  {
10963
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
10306
10964
  key: ConfigKey.tag_false,
10307
- description: "Tag for the false option in the true/false question"
10965
+ description: "Tag for the false option in the true/false question",
10966
+ format: TagFormat.plainText
10967
+ },
10968
+ {
10969
+ // Override inherited @example from group_standardTags: boolean root
10970
+ // example. Note: the legacy reference parser ties the bare-form
10971
+ // example value to `statement.isCorrect`, but the statement is not
10972
+ // yet emitted when this tag fires at bit-header. The pattern below
10973
+ // emits a literal `true` for bare/synthesized and `$` for valued —
10974
+ // sufficient for `[+...]` (correct) statements which dominate the
10975
+ // fixtures; `[-...]` (incorrect) bits with bare `[@example]` would
10976
+ // need either a runtime extension or an explicit `[@example:false]`.
10977
+ key: ConfigKey.property_example,
10978
+ exportJsonKey: [
10979
+ { "@keyonly": { isExample: true, example: true } },
10980
+ { "@absent": { isExample: true, example: true } },
10981
+ { isExample: true, example: "$" }
10982
+ ],
10983
+ description: "The example flag for the bit (boolean)",
10984
+ format: TagFormat.plainText
10308
10985
  }
10309
10986
  ],
10310
10987
  rootExampleType: ExampleType.boolean
@@ -10512,6 +11189,25 @@ var BITS = {
10512
11189
  baseBitType: BitType.vendorStripePricingTable,
10513
11190
  description: "External Stripe pricing table bit, used to embed external Stripe pricing tables in articles or books"
10514
11191
  },
11192
+ [BitType.vendorStripePricingTablePrintOnRequest]: {
11193
+ since: "5.21.0",
11194
+ baseBitType: BitType.vendorStripePricingTable,
11195
+ description: "Stripe pricing table bit with print-on-request customer/product IDs, used to embed Stripe pricing tables tied to a specific print-on-request customer and product",
11196
+ tags: [
11197
+ {
11198
+ key: ConfigKey.property_printOnRequestCustomerId,
11199
+ description: "Print-on-request customer ID, used to identify the customer for the print-on-request flow",
11200
+ format: TagFormat.plainText,
11201
+ minCount: 1
11202
+ },
11203
+ {
11204
+ key: ConfigKey.property_printOnRequestProductId,
11205
+ description: "Print-on-request product ID, used to identify the product for the print-on-request flow",
11206
+ format: TagFormat.plainText,
11207
+ minCount: 1
11208
+ }
11209
+ ]
11210
+ },
10515
11211
  [BitType.video]: {
10516
11212
  since: "1.3.0",
10517
11213
  baseBitType: BitType._standard,
@@ -10868,6 +11564,8 @@ var Config = class {
10868
11564
  maxCount: 1,
10869
11565
  chain: tag.chain,
10870
11566
  jsonKey: tag.jsonKey,
11567
+ exportJsonKey: tag.exportJsonKey,
11568
+ hasExportJsonKey: tag.hasExportJsonKey,
10871
11569
  deprecated: tag.deprecated
10872
11570
  });
10873
11571
  finalResourceTags[k] = newTag;
@@ -10972,7 +11670,7 @@ var instance2 = new Config();
10972
11670
  // src/generated/package_info.ts
10973
11671
  var PACKAGE_INFO = {
10974
11672
  "name": "@gmb/bitmark-parser-generator",
10975
- "version": "5.21.0",
11673
+ "version": "5.23.0",
10976
11674
  "license": "ISC"};
10977
11675
  var Environment = {
10978
11676
  unknown: "",
@@ -11534,6 +12232,8 @@ var NodeType = {
11534
12232
  gmbExternalShopItems: "gmbExternalShopItems",
11535
12233
  groupTag: "groupTag",
11536
12234
  groupTagValue: "groupTagValue",
12235
+ gUri: "gUri",
12236
+ gUriValue: "gUriValue",
11537
12237
  handInAcceptFileType: "handInAcceptFileType",
11538
12238
  handInAcceptFileTypeValue: "handInAcceptFileTypeValue",
11539
12239
  handInInstruction: "handInInstruction",
@@ -11755,6 +12455,10 @@ var NodeType = {
11755
12455
  previewVideoValue: "previewVideoValue",
11756
12456
  printParentChapterLevel: "printParentChapterLevel",
11757
12457
  printParentChapterLevelValue: "printParentChapterLevelValue",
12458
+ printOnRequestCustomerId: "printOnRequestCustomerId",
12459
+ printOnRequestCustomerIdValue: "printOnRequestCustomerIdValue",
12460
+ printOnRequestProductId: "printOnRequestProductId",
12461
+ printOnRequestProductIdValue: "printOnRequestProductIdValue",
11758
12462
  processHandIn: "processHandIn",
11759
12463
  processHandInLocation: "processHandInLocation",
11760
12464
  processHandInLocationValue: "processHandInLocationValue",
@@ -11872,6 +12576,8 @@ var NodeType = {
11872
12576
  solution: "solution",
11873
12577
  solutions: "solutions",
11874
12578
  solutionsValue: "solutionsValue",
12579
+ sourceBB: "sourceBB",
12580
+ sourceBBValue: "sourceBBValue",
11875
12581
  sourceDocument: "sourceDocument",
11876
12582
  sourceDocumentValue: "sourceDocumentValue",
11877
12583
  sourceRL: "sourceRL",
@@ -12493,6 +13199,17 @@ function convertBasicToExtendedTableFormat(table) {
12493
13199
  }))
12494
13200
  };
12495
13201
  }
13202
+ if (Array.isArray(table.columnWidths) && table.columnWidths.length > 0) {
13203
+ const targetCells = tableExtended.header?.rows[0]?.cells ?? tableExtended.body?.rows[0]?.cells;
13204
+ if (targetCells) {
13205
+ for (let i = 0; i < table.columnWidths.length; i++) {
13206
+ const width = table.columnWidths[i];
13207
+ if (typeof width === "number" && width > 0 && targetCells[i]) {
13208
+ targetCells[i].colwidth = width;
13209
+ }
13210
+ }
13211
+ }
13212
+ }
12496
13213
  return tableExtended;
12497
13214
  }
12498
13215
  function convertExtendedToBasicTableFormat(tableExtended) {
@@ -12504,7 +13221,23 @@ function convertExtendedToBasicTableFormat(tableExtended) {
12504
13221
  return row.cells.map((cell) => cell?.content).filter((content) => content !== void 0);
12505
13222
  };
12506
13223
  const dataRows = [];
13224
+ const widths = [];
13225
+ let hasAnyWidth = false;
13226
+ let maxCellCount = 0;
13227
+ const collectWidths = (cells) => {
13228
+ if (!cells) return;
13229
+ if (cells.length > maxCellCount) maxCellCount = cells.length;
13230
+ cells.forEach((cell, idx) => {
13231
+ if (cell && typeof cell.colwidth === "number" && cell.colwidth > 0) {
13232
+ widths[idx] = cell.colwidth;
13233
+ hasAnyWidth = true;
13234
+ }
13235
+ });
13236
+ };
12507
13237
  const headRows = tableExtended.header?.rows ?? [];
13238
+ headRows.forEach((row) => collectWidths(row?.cells));
13239
+ (tableExtended.body?.rows ?? []).forEach((row) => collectWidths(row?.cells));
13240
+ (tableExtended.footer?.rows ?? []).forEach((row) => collectWidths(row?.cells));
12508
13241
  if (headRows.length > 0) {
12509
13242
  const primaryHeader = extractRowCells(headRows[0]);
12510
13243
  if (primaryHeader.length > 0) {
@@ -12534,6 +13267,15 @@ function convertExtendedToBasicTableFormat(tableExtended) {
12534
13267
  if (dataRows.length > 0) {
12535
13268
  table.data = dataRows;
12536
13269
  }
13270
+ if (hasAnyWidth) {
13271
+ const columnCount = table.columns?.length ?? maxCellCount;
13272
+ const columnWidths = new Array(columnCount).fill(null);
13273
+ for (let i = 0; i < columnCount; i++) {
13274
+ const w = widths[i];
13275
+ if (typeof w === "number") columnWidths[i] = w;
13276
+ }
13277
+ table.columnWidths = columnWidths;
13278
+ }
12537
13279
  return table;
12538
13280
  }
12539
13281
  function normalizeTableFormat(bitType, table) {
@@ -24532,6 +25274,7 @@ var Builder = class extends BaseBuilder {
24532
25274
  isCommented: data.isCommented,
24533
25275
  // Properties
24534
25276
  id: this.toAstProperty(bitType, ConfigKey.property_id, data.id, options),
25277
+ gUri: this.toAstProperty(bitType, ConfigKey.property_gUri, data.gUri, options),
24535
25278
  internalComment: this.toAstProperty(
24536
25279
  bitType,
24537
25280
  ConfigKey.property_internalComment,
@@ -24743,6 +25486,7 @@ var Builder = class extends BaseBuilder {
24743
25486
  data.extractorInternal,
24744
25487
  options
24745
25488
  ),
25489
+ sourceBB: this.normaliseSourceBB(data.sourceBB),
24746
25490
  levelCEFRp: this.toAstProperty(
24747
25491
  bitType,
24748
25492
  ConfigKey.property_levelCEFRp,
@@ -25387,6 +26131,18 @@ var Builder = class extends BaseBuilder {
25387
26131
  data.printParentChapterLevel,
25388
26132
  options
25389
26133
  ),
26134
+ printOnRequestCustomerId: this.toAstProperty(
26135
+ bitType,
26136
+ ConfigKey.property_printOnRequestCustomerId,
26137
+ data.printOnRequestCustomerId,
26138
+ options
26139
+ ),
26140
+ printOnRequestProductId: this.toAstProperty(
26141
+ bitType,
26142
+ ConfigKey.property_printOnRequestProductId,
26143
+ data.printOnRequestProductId,
26144
+ options
26145
+ ),
25390
26146
  platformBrandTarget: this.toAstProperty(
25391
26147
  bitType,
25392
26148
  ConfigKey.property_platformBrandTarget,
@@ -25751,6 +26507,19 @@ var Builder = class extends BaseBuilder {
25751
26507
  nodes = Object.values(combinedNodes);
25752
26508
  return nodes.length > 0 ? nodes : void 0;
25753
26509
  }
26510
+ /**
26511
+ * Normalise a sourceBB input into the AST shape (always number[][]).
26512
+ * Accepts a single 4-number tuple or an array of tuples; returns undefined when empty.
26513
+ */
26514
+ normaliseSourceBB(data) {
26515
+ if (data == null) return void 0;
26516
+ if (!Array.isArray(data) || data.length === 0) return void 0;
26517
+ const isNested = data.some(Array.isArray);
26518
+ const tuples = (isNested ? data : [data]).filter(
26519
+ (t) => Array.isArray(t) && t.length === 4 && t.every((n) => typeof n === "number")
26520
+ );
26521
+ return tuples.length > 0 ? tuples : void 0;
26522
+ }
25754
26523
  /**
25755
26524
  * Build groupTag node
25756
26525
  *
@@ -26219,6 +26988,17 @@ var Builder = class extends BaseBuilder {
26219
26988
  (row) => (row || []).map((cell) => this.handleJsonText(context, TextLocation.tag, cell))
26220
26989
  );
26221
26990
  }
26991
+ if (Array.isArray(nodeTable.columnWidths)) {
26992
+ const columnCount = Array.isArray(nodeTable.columns) ? nodeTable.columns.length : void 0;
26993
+ const source = columnCount != null ? nodeTable.columnWidths.slice(0, columnCount) : nodeTable.columnWidths;
26994
+ const normalized = source.map((w) => typeof w === "number" && w > 0 ? w : null);
26995
+ const hasAny = normalized.some((w) => w != null);
26996
+ if (hasAny) {
26997
+ nodeTable.columnWidths = normalized;
26998
+ } else {
26999
+ delete nodeTable.columnWidths;
27000
+ }
27001
+ }
26222
27002
  const buildSection = (section) => {
26223
27003
  if (!section || !Array.isArray(section.rows)) return void 0;
26224
27004
  const rows = section.rows.map((row) => {
@@ -28046,6 +28826,23 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
28046
28826
  format: TagFormat.plainText
28047
28827
  });
28048
28828
  }
28829
+ // bitmarkAst -> bits -> bitsValue -> sourceBB
28830
+ enter_sourceBB(node, route) {
28831
+ const parent = this.getParentNode(route);
28832
+ if (parent?.key !== NodeType.bitsValue) return false;
28833
+ const tuples = node.value;
28834
+ if (!Array.isArray(tuples) || tuples.length === 0) return false;
28835
+ this.writeProperty(
28836
+ "sourceBB",
28837
+ tuples.map((t) => t.join(", ")),
28838
+ route,
28839
+ {
28840
+ format: TagFormat.plainText,
28841
+ array: true
28842
+ }
28843
+ );
28844
+ return false;
28845
+ }
28049
28846
  // bitmarkAst -> bits -> bitsValue -> questions -> questionsValue -> additionalSolutions -> additionalSolutionsValue
28050
28847
  leaf_additionalSolutionsValue(node, route) {
28051
28848
  const parent = this.getParentNode(route, 2);
@@ -30159,6 +30956,16 @@ var JsonGenerator = class extends AstWalkerGenerator {
30159
30956
  enter_ratingLevelEnd(node, route) {
30160
30957
  return this.standardHandler(node, route, NodeType.bitsValue, { array: false });
30161
30958
  }
30959
+ // bitmarkAst -> bits -> bitsValue -> sourceBB
30960
+ enter_sourceBB(node, route) {
30961
+ const tuples = node.value;
30962
+ const parent = this.getParentNode(route);
30963
+ if (parent?.key !== NodeType.bitsValue) return false;
30964
+ if (tuples && tuples.length > 0) {
30965
+ this.bitJson.sourceBB = tuples.length === 1 ? tuples[0] : tuples;
30966
+ }
30967
+ return false;
30968
+ }
30162
30969
  // bitmarkAst -> bits -> bitsValue -> productId
30163
30970
  enter_productId(node, route) {
30164
30971
  const productIds = node.value;
@@ -31184,6 +31991,10 @@ var JsonGenerator = class extends AstWalkerGenerator {
31184
31991
  if (instance2.isOfBitType(bitType, BitType.vendorStripePricingTable)) {
31185
31992
  if (bitJson.stripePricingTableId == null) bitJson.stripePricingTableId = "";
31186
31993
  if (bitJson.stripePublishableKey == null) bitJson.stripePublishableKey = "";
31994
+ if (instance2.isOfBitType(bitType, BitType.vendorStripePricingTablePrintOnRequest)) {
31995
+ if (bitJson.printOnRequestCustomerId == null) bitJson.printOnRequestCustomerId = "";
31996
+ if (bitJson.printOnRequestProductId == null) bitJson.printOnRequestProductId = "";
31997
+ }
31187
31998
  }
31188
31999
  if (instance2.isOfBitType(bitType, BitType.callToAction)) {
31189
32000
  if (bitJson.buttonCaption == null) bitJson.buttonCaption = "";
@@ -34754,6 +35565,17 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
34754
35565
  format: TextFormat.bitmarkText,
34755
35566
  location: TextLocation.tag
34756
35567
  });
35568
+ case TagFormat.coordinates:
35569
+ const coordRaw = instance3.unbreakscape(v2, {
35570
+ format: TextFormat.plainText,
35571
+ location: TextLocation.tag
35572
+ });
35573
+ if (coordRaw == null) return void 0;
35574
+ const coordParts = coordRaw.split(",").map((p) => instance6.asNumber(p.trim()));
35575
+ if (coordParts.length !== 4 || coordParts.some((n) => n == null)) {
35576
+ return void 0;
35577
+ }
35578
+ return coordParts;
34757
35579
  }
34758
35580
  }
34759
35581
  return instance3.unbreakscape(v2, {
@@ -34790,6 +35612,8 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
34790
35612
  minCount: 1,
34791
35613
  chain: void 0,
34792
35614
  jsonKey: void 0,
35615
+ exportJsonKey: void 0,
35616
+ hasExportJsonKey: false,
34793
35617
  format: TagFormat.bitmarkText,
34794
35618
  values: void 0,
34795
35619
  defaultValue: void 0,
@@ -34800,19 +35624,18 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
34800
35624
  }
34801
35625
 
34802
35626
  // src/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.ts
34803
- function referenceTagContentProcessor(_context, _contentDepth, _tagsConfig, content, target, isReferenceEnd) {
34804
- const { value } = content;
35627
+ function referenceTagContentProcessor(context, _contentDepth, tagsConfig, content, target) {
35628
+ const { value, chain } = content;
34805
35629
  const trimmedStringValue = stringUtils.trimmedString(value);
34806
- if (isReferenceEnd) {
34807
- target.referenceEnd = instance3.unbreakscape(trimmedStringValue, {
34808
- format: TextFormat.bitmarkText,
34809
- location: TextLocation.tag
34810
- });
34811
- } else {
34812
- target.reference = instance3.unbreakscape(trimmedStringValue, {
34813
- format: TextFormat.bitmarkText,
34814
- location: TextLocation.tag
34815
- });
35630
+ target.reference = instance3.unbreakscape(trimmedStringValue, {
35631
+ format: TextFormat.bitmarkText,
35632
+ location: TextLocation.tag
35633
+ });
35634
+ if (Array.isArray(chain) && chain.length > 0) {
35635
+ const sub = context.bitContentProcessor(ContentDepth.Chain, tagsConfig, chain);
35636
+ if (sub.reference != null) {
35637
+ target.referenceEnd = sub.reference;
35638
+ }
34816
35639
  }
34817
35640
  }
34818
35641
  var resourceBuilder = new ResourceBuilder();
@@ -35493,7 +36316,6 @@ var BitmarkPegParserProcessor = class {
35493
36316
  result.markConfig = [];
35494
36317
  result.extraProperties = {};
35495
36318
  result.internalComments = [];
35496
- let seenReference = false;
35497
36319
  let inFooter = false;
35498
36320
  const bodyParts = [];
35499
36321
  let bodyTextPart = instance3.EMPTY_STRING;
@@ -35529,15 +36351,7 @@ var BitmarkPegParserProcessor = class {
35529
36351
  defaultTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
35530
36352
  break;
35531
36353
  case TypeKey.Reference:
35532
- referenceTagContentProcessor(
35533
- this.context,
35534
- contentDepth,
35535
- tagsConfig,
35536
- content,
35537
- result,
35538
- seenReference
35539
- );
35540
- seenReference = true;
36354
+ referenceTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
35541
36355
  break;
35542
36356
  case TypeKey.Title:
35543
36357
  titleTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
@@ -39783,58 +40597,44 @@ var ConfigBuilder = class {
39783
40597
  BitTagConfigKeyType.group,
39784
40598
  BitTagConfigKeyType.unknown
39785
40599
  ];
40600
+ const exportJsonKeyErrors = [];
39786
40601
  const resolveGroupReferences = (groupKey) => {
39787
40602
  if (squashedGroups.has(groupKey)) {
39788
40603
  const replacements = squashedGroups.get(groupKey);
39789
- return replacements.flatMap((r) => resolveGroupReferences(r));
40604
+ return replacements.flatMap(
40605
+ (r) => squashedGroups.has(r.key) ? resolveGroupReferences(r.key) : [r]
40606
+ );
39790
40607
  }
39791
- return [groupKey];
40608
+ return [{ key: groupKey }];
39792
40609
  };
39793
- const keyToJsonKey = (key, tagNameChain) => {
39794
- let jsonKey = key;
39795
- if (key === "%") {
39796
- jsonKey = "item";
39797
- } else if (key === "!") {
39798
- jsonKey = "instruction";
39799
- } else if (key === "?") {
39800
- jsonKey = "hint";
39801
- } else if (key === "#") {
39802
- jsonKey = "title";
39803
- } else if (key === "##") {
39804
- jsonKey = "subTitle";
39805
- } else if (key === "\u25BC") {
39806
- jsonKey = "anchor";
39807
- } else if (key === "\u25BA") {
39808
- jsonKey = "reference";
39809
- } else if (key === "$") {
39810
- jsonKey = "sampleSolution";
39811
- } else if (key === "+") {
39812
- jsonKey = "choices[]|set(isCorrect=true)";
39813
- } else if (key === "-") {
39814
- jsonKey = "choices[]|set(isCorrect=false)";
39815
- } else if (key === "_") {
39816
- jsonKey = "solutions[]";
39817
- } else if (key === "=") {
39818
- jsonKey = "solution";
39819
- } else if (key.startsWith("@")) {
39820
- jsonKey = key.substring(1);
39821
- } else if (key.startsWith("&")) {
39822
- jsonKey = key.substring(1);
39823
- }
39824
- const thisChain = [...tagNameChain, jsonKey];
39825
- jsonKey = thisChain.join(".");
39826
- return jsonKey;
40610
+ const bareKeyForProperty = (key) => {
40611
+ if (key.startsWith("@") || key.startsWith("&")) return key.substring(1);
40612
+ return void 0;
40613
+ };
40614
+ const legacyIsTrivialDefault = (tag) => {
40615
+ const bare = bareKeyForProperty(tag.key);
40616
+ if (bare == null) return false;
40617
+ return tag.jsonKey == null || tag.jsonKey === bare;
39827
40618
  };
39828
- const processTagEntries = (tag, tagNameChain) => {
40619
+ const processTagEntries = (tag, pathStack) => {
39829
40620
  const tags2 = [];
39830
40621
  let tagName = tag.key;
39831
- const jsonKey = tag.jsonKey ?? keyToJsonKey(tagName, tagNameChain);
39832
40622
  const tagType = typeFromConfigKey(tag.key);
39833
40623
  let format = "";
39834
40624
  let chain = void 0;
39835
40625
  if (tagType === BitTagConfigKeyType.tag) {
39836
40626
  tagName = tag.key;
39837
- format = "bitmark--";
40627
+ if (tag.format === TagFormat.plainText) {
40628
+ format = "string";
40629
+ } else if (tag.format === TagFormat.boolean) {
40630
+ format = "bool";
40631
+ } else if (tag.format === TagFormat.bitmarkText) {
40632
+ format = "bitmark";
40633
+ } else if (tag.format === TagFormat.number) {
40634
+ format = "number";
40635
+ } else {
40636
+ format = "bitmark--";
40637
+ }
39838
40638
  } else if (tagType === BitTagConfigKeyType.property) {
39839
40639
  tagName = tag.key;
39840
40640
  if (tag.format === TagFormat.plainText) {
@@ -39851,48 +40651,88 @@ var ConfigBuilder = class {
39851
40651
  } else if (tagType === BitTagConfigKeyType.group) {
39852
40652
  let k = tag.key;
39853
40653
  if (k.startsWith("group_")) k = k.substring(6);
39854
- k = /*'_' +*/
39855
- stringUtils.camelToKebab(k);
40654
+ k = stringUtils.camelToKebab(k);
39856
40655
  const resolvedGroups = resolveGroupReferences(k);
39857
- for (const groupKey of resolvedGroups) {
40656
+ const hasOuterExport = Object.prototype.hasOwnProperty.call(tag, "exportJsonKey");
40657
+ if (!hasOuterExport && tag.jsonKey != null) {
40658
+ const headingPath = [...pathStack, `tags.${tag.key}`].join(" / ");
40659
+ exportJsonKeyErrors.push(
40660
+ `Missing exportJsonKey for non-default jsonKey at ${headingPath} (legacy: \`${tag.jsonKey}\`)`
40661
+ );
40662
+ }
40663
+ for (const ref of resolvedGroups) {
40664
+ const exportJsonKeyChosen = hasOuterExport ? tag.exportJsonKey : ref.exportJsonKey;
40665
+ const hasExportChosen = hasOuterExport || !!ref.hasExportJsonKey;
40666
+ const min = tag.minCount != null ? tag.minCount : ref.min;
40667
+ const max = tag.maxCount != null ? tag.maxCount : ref.max;
40668
+ const description = tag.description ? tag.description : ref.description;
39858
40669
  tags2.push({
39859
40670
  type: "group",
39860
- key: groupKey,
39861
- ...tag.jsonKey ? { jsonKey: tag.jsonKey } : {}
40671
+ key: ref.key,
40672
+ ...hasExportChosen ? { jsonKey: exportJsonKeyChosen } : {},
40673
+ ...min != null ? { min } : {},
40674
+ ...max != null ? { max } : {},
40675
+ ...description ? { description } : {}
39862
40676
  });
39863
40677
  }
39864
40678
  return tags2;
39865
40679
  }
39866
40680
  if (Array.isArray(tag.chain) && tag.chain.length > 0) {
39867
40681
  const chainTags = [];
39868
- for (const [_tagKey, chainTag] of tag.chain.entries()) {
39869
- chainTags.push(...processTagEntries(chainTag, []));
40682
+ const childPathStack = [...pathStack, `tags.${tag.key}`];
40683
+ for (const [, chainTag] of tag.chain.entries()) {
40684
+ chainTags.push(...processTagEntries(chainTag, childPathStack));
39870
40685
  }
39871
40686
  chain = chainTags;
39872
40687
  }
40688
+ const hasExport = Object.prototype.hasOwnProperty.call(tag, "exportJsonKey");
40689
+ let exportJsonKeyField;
40690
+ if (hasExport) {
40691
+ exportJsonKeyField = { jsonKey: tag.exportJsonKey };
40692
+ } else if (legacyIsTrivialDefault(tag)) {
40693
+ exportJsonKeyField = {};
40694
+ } else {
40695
+ const headingPath = [...pathStack, `tags.${tag.key}`].join(" / ");
40696
+ exportJsonKeyErrors.push(
40697
+ `Missing exportJsonKey for non-default jsonKey at ${headingPath}` + (tag.jsonKey ? ` (legacy: \`${tag.jsonKey}\`)` : ` (symbol-mapped tag \`${tag.key}\`)`)
40698
+ );
40699
+ exportJsonKeyField = {};
40700
+ }
39873
40701
  const t = {
39874
40702
  type: "tag",
39875
40703
  key: tagName,
39876
- jsonKey,
40704
+ ...exportJsonKeyField,
39877
40705
  format,
39878
40706
  default: tag.defaultValue ?? null,
40707
+ ...tag.nullable ? { nullable: true } : {},
39879
40708
  min: tag.minCount == null ? 0 : tag.minCount,
39880
40709
  max: tag.maxCount == null ? 1 : tag.maxCount,
39881
40710
  description: tag.description ?? "",
39882
40711
  tags: chain
39883
- // raw: {
39884
- // ...tag,
39885
- // },
39886
40712
  };
39887
40713
  tags2.push(t);
39888
40714
  return tags2;
39889
40715
  };
40716
+ const cardJsonKeyField = (container, legacyKey, exportKey, pathHeading) => {
40717
+ const c = container;
40718
+ const hasExport = Object.prototype.hasOwnProperty.call(c, exportKey);
40719
+ if (hasExport) return { jsonKey: c[exportKey] };
40720
+ const legacy = c[legacyKey];
40721
+ if (legacy == null) return {};
40722
+ exportJsonKeyErrors.push(
40723
+ `Missing exportJsonKey for non-default jsonKey at ${pathHeading} (legacy: \`${legacy}\`)`
40724
+ );
40725
+ return {};
40726
+ };
39890
40727
  const serializeCardSet = (cardSetKey) => {
40728
+ const variantBodyFormat = (variant) => variant.format ?? TextFormat.bitmarkText;
39891
40729
  const cardSetConfig = CARDSETS[cardSetKey];
39892
40730
  if (!cardSetConfig) return void 0;
39893
40731
  const normalizedKey = normalizeCardKey(cardSetKey);
39894
- const sides = cardSetConfig.sides.map((side) => {
39895
- const variants = side.variants.map((variant) => {
40732
+ const sides = cardSetConfig.sides.map((side, sideIdx) => {
40733
+ const sidePath = `cardSets.${normalizedKey} / sides.${side.name ?? `[${sideIdx}]`}`;
40734
+ const variants = side.variants.map((variant, variantIdx) => {
40735
+ const variantPath = `${sidePath} / variants.[${variantIdx}]`;
39896
40736
  const variantTags = [];
39897
40737
  const variantTagEntries = Object.entries(variant.tags ?? []).sort((a, b) => {
39898
40738
  const tagA = a[1];
@@ -39903,10 +40743,11 @@ var ConfigBuilder = class {
39903
40743
  return typeOrder;
39904
40744
  });
39905
40745
  for (const [, variantTag] of variantTagEntries) {
39906
- variantTags.push(...processTagEntries(variantTag, []));
40746
+ variantTags.push(...processTagEntries(variantTag, [variantPath]));
39907
40747
  }
39908
40748
  return {
39909
- ...variant.jsonKey !== void 0 ? { jsonKey: variant.jsonKey } : {},
40749
+ ...cardJsonKeyField(variant, "jsonKey", "exportJsonKey", variantPath),
40750
+ format: variantBodyFormat(variant),
39910
40751
  tags: variantTags,
39911
40752
  repeatCount: variant.repeatCount ?? 1,
39912
40753
  ...variant.bodyRequired ? { bodyRequired: true } : {},
@@ -39916,41 +40757,41 @@ var ConfigBuilder = class {
39916
40757
  return {
39917
40758
  name: side.name,
39918
40759
  ...side.repeat ? { repeat: side.repeat } : {},
39919
- ...side.jsonKey != null ? { jsonKey: side.jsonKey } : {},
40760
+ ...cardJsonKeyField(side, "jsonKey", "exportJsonKey", sidePath),
39920
40761
  variants
39921
40762
  };
39922
40763
  });
39923
40764
  if (cardSetConfig.sections) {
39924
40765
  const cards = Object.entries(cardSetConfig.sections).map(([sectionName, section]) => {
39925
- let cardSides = section.sideJsonKey ? sides.map((s) => ({ ...s, jsonKey: section.sideJsonKey })) : sides;
39926
- if (normalizedKey === "table-extended" && sectionName !== "table-header") {
39927
- cardSides = JSON.parse(JSON.stringify(cardSides));
39928
- for (const side of cardSides) {
39929
- for (const variant of side.variants) {
39930
- for (const tag of variant.tags) {
39931
- if (tag.type === "tag" && tag.key === "#" && tag.jsonKey === ".") {
39932
- tag.jsonKey = "^table.header.rows.cells[{s}].content";
39933
- }
39934
- }
39935
- }
39936
- }
40766
+ const sectionPath = `cardSets.${normalizedKey} / cards.${sectionName}`;
40767
+ const hasSideExport = Object.prototype.hasOwnProperty.call(section, "sideExportJsonKey");
40768
+ let cardSides = sides;
40769
+ if (hasSideExport || section.sideJsonKey != null) {
40770
+ const sideOverride = cardJsonKeyField(
40771
+ section,
40772
+ "sideJsonKey",
40773
+ "sideExportJsonKey",
40774
+ `${sectionPath} / sides.*`
40775
+ );
40776
+ cardSides = sides.map((s) => ({ ...s, ...sideOverride }));
39937
40777
  }
39938
40778
  return {
39939
40779
  name: sectionName,
39940
40780
  ...section.isDefault ? { isDefault: true } : {},
39941
- jsonKey: section.jsonKey,
40781
+ ...cardJsonKeyField(section, "jsonKey", "exportJsonKey", sectionPath),
39942
40782
  sides: cardSides
39943
40783
  };
39944
40784
  });
39945
40785
  return { name: normalizedKey, cards };
39946
40786
  }
40787
+ const cardSetPath = `cardSets.${normalizedKey} / cards.default`;
39947
40788
  return {
39948
40789
  name: normalizedKey,
39949
40790
  cards: [
39950
40791
  {
39951
40792
  name: "default",
39952
40793
  isDefault: true,
39953
- jsonKey: cardSetConfig.jsonKey,
40794
+ ...cardJsonKeyField(cardSetConfig, "jsonKey", "exportJsonKey", cardSetPath),
39954
40795
  sides
39955
40796
  }
39956
40797
  ]
@@ -39977,10 +40818,20 @@ var ConfigBuilder = class {
39977
40818
  if (allAreGroups && processedTags.length > 0) {
39978
40819
  const replacements = [];
39979
40820
  if (b.baseBitType) {
39980
- replacements.push(`group-${b.baseBitType}`);
40821
+ replacements.push({ key: `group-${b.baseBitType}` });
39981
40822
  }
39982
40823
  for (const t of processedTags) {
39983
- replacements.push(t.key);
40824
+ const ref = {
40825
+ key: t.key,
40826
+ ...t.min != null ? { min: t.min } : {},
40827
+ ...t.max != null ? { max: t.max } : {},
40828
+ ...t.description ? { description: t.description } : {}
40829
+ };
40830
+ if (Object.prototype.hasOwnProperty.call(t, "jsonKey")) {
40831
+ ref.exportJsonKey = t.jsonKey;
40832
+ ref.hasExportJsonKey = true;
40833
+ }
40834
+ replacements.push(ref);
39984
40835
  }
39985
40836
  squashedGroups.set(groupKey, replacements);
39986
40837
  }
@@ -39999,19 +40850,27 @@ var ConfigBuilder = class {
39999
40850
  const isInheritedFrom = bitGroupConfigKeys.has(b.bitType);
40000
40851
  if (isInheritedFrom) {
40001
40852
  const resolvedGroups = resolveGroupReferences(`group-${b.bitType}`);
40002
- for (const groupKey of resolvedGroups) {
40853
+ for (const ref of resolvedGroups) {
40003
40854
  tags2.push({
40004
40855
  type: "group",
40005
- key: groupKey
40856
+ key: ref.key,
40857
+ ...ref.hasExportJsonKey ? { jsonKey: ref.exportJsonKey } : {},
40858
+ ...ref.min != null ? { min: ref.min } : {},
40859
+ ...ref.max != null ? { max: ref.max } : {},
40860
+ ...ref.description ? { description: ref.description } : {}
40006
40861
  });
40007
40862
  }
40008
40863
  } else {
40009
40864
  if (b.baseBitType) {
40010
40865
  const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
40011
- for (const groupKey of resolvedGroups) {
40866
+ for (const ref of resolvedGroups) {
40012
40867
  tags2.push({
40013
40868
  type: "group",
40014
- key: groupKey
40869
+ key: ref.key,
40870
+ ...ref.hasExportJsonKey ? { jsonKey: ref.exportJsonKey } : {},
40871
+ ...ref.min != null ? { min: ref.min } : {},
40872
+ ...ref.max != null ? { max: ref.max } : {},
40873
+ ...ref.description ? { description: ref.description } : {}
40015
40874
  });
40016
40875
  }
40017
40876
  }
@@ -40131,10 +40990,14 @@ var ConfigBuilder = class {
40131
40990
  const tags2 = [];
40132
40991
  if (b.baseBitType) {
40133
40992
  const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
40134
- for (const gk of resolvedGroups) {
40993
+ for (const ref of resolvedGroups) {
40135
40994
  tags2.push({
40136
40995
  type: "group",
40137
- key: gk
40996
+ key: ref.key,
40997
+ ...ref.hasExportJsonKey ? { jsonKey: ref.exportJsonKey } : {},
40998
+ ...ref.min != null ? { min: ref.min } : {},
40999
+ ...ref.max != null ? { max: ref.max } : {},
41000
+ ...ref.description ? { description: ref.description } : {}
40138
41001
  });
40139
41002
  }
40140
41003
  }
@@ -40169,6 +41032,13 @@ var ConfigBuilder = class {
40169
41032
  };
40170
41033
  writeBitsAsGroupConfigs(bitGroupConfigs);
40171
41034
  writeCardConfigs();
41035
+ if (exportJsonKeyErrors.length > 0) {
41036
+ console.error("\n\u26A0\uFE0F exportJsonKey validation errors:");
41037
+ for (const e of exportJsonKeyErrors) console.error(` - ${e}`);
41038
+ throw new Error(
41039
+ `exportJsonKey validation failed: ${exportJsonKeyErrors.length} entr${exportJsonKeyErrors.length === 1 ? "y" : "ies"} with non-default jsonKey but no exportJsonKey companion.`
41040
+ );
41041
+ }
40172
41042
  Promise.all(fileWrites).then(() => {
40173
41043
  const validationErrors = this.validateConfigTree(outputFolder);
40174
41044
  if (validationErrors.length > 0) {