@gmb/bitmark-parser-generator 5.22.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",
@@ -688,8 +689,10 @@ var TagFormat = {
688
689
  // If the value is treated as a boolean
689
690
  invertedBoolean: "invertedBoolean",
690
691
  // If the value is treated as a boolean with the value inverted (e.g. isLongAnswer ==> isShortAnswer = false)
691
- enumeration: "enumeration"
692
+ enumeration: "enumeration",
692
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)
693
696
  };
694
697
  var TextFormat = {
695
698
  // plain text
@@ -760,7 +763,11 @@ var AbstractTagConfig = class {
760
763
  // Default: 0
761
764
  chain;
762
765
  jsonKey;
763
- // 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
764
771
  deprecated;
765
772
  // Deprecated version
766
773
  constructor(params) {
@@ -771,6 +778,8 @@ var AbstractTagConfig = class {
771
778
  this.minCount = params.minCount;
772
779
  this.chain = params.chain;
773
780
  this.jsonKey = params.jsonKey;
781
+ this.exportJsonKey = params.exportJsonKey;
782
+ this.hasExportJsonKey = params.hasExportJsonKey;
774
783
  this.deprecated = params.deprecated;
775
784
  }
776
785
  };
@@ -781,7 +790,6 @@ var MarkupTagConfig = class extends AbstractTagConfig {
781
790
  constructor(params) {
782
791
  super({
783
792
  type: BitTagConfigKeyType.tag,
784
- jsonKey: void 0,
785
793
  ...params
786
794
  });
787
795
  }
@@ -901,13 +909,21 @@ var CardVariantConfig = class {
901
909
  // Default: 1
902
910
  // JSON mapping fields
903
911
  jsonKey;
904
- // JSON path for body text
905
- 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) {
906
919
  this.tags = tags2;
907
920
  this.bodyAllowed = bodyAllowed == null ? true : bodyAllowed;
908
921
  this.bodyRequired = bodyRequired;
909
922
  this.repeatCount = repeatCount;
910
923
  this.jsonKey = jsonKey;
924
+ this.exportJsonKey = exportJsonKey;
925
+ this.hasExportJsonKey = hasExportJsonKey;
926
+ this.format = format;
911
927
  }
912
928
  toString(options) {
913
929
  const opts = Object.assign({}, options);
@@ -934,11 +950,15 @@ var CardSideConfig = class {
934
950
  name;
935
951
  repeat;
936
952
  jsonKey;
953
+ exportJsonKey;
954
+ hasExportJsonKey;
937
955
  variants;
938
- constructor(name, repeat, variants, jsonKey) {
956
+ constructor(name, repeat, variants, jsonKey, exportJsonKey, hasExportJsonKey = false) {
939
957
  this.name = name;
940
958
  this.repeat = repeat;
941
959
  this.jsonKey = jsonKey;
960
+ this.exportJsonKey = exportJsonKey;
961
+ this.hasExportJsonKey = hasExportJsonKey;
942
962
  this.variants = variants;
943
963
  }
944
964
  toString(options) {
@@ -962,6 +982,8 @@ var CardSideConfig = class {
962
982
  var CardSetConfig = class {
963
983
  configKey;
964
984
  jsonKey;
985
+ exportJsonKey;
986
+ hasExportJsonKey;
965
987
  sections;
966
988
  sides;
967
989
  // Legacy accessor — provides the same shape as the old `variants: CardVariantConfig[][]`
@@ -969,9 +991,11 @@ var CardSetConfig = class {
969
991
  get variants() {
970
992
  return this.sides.map((side) => side.variants);
971
993
  }
972
- constructor(configKey, jsonKey, sections, sides) {
994
+ constructor(configKey, jsonKey, exportJsonKey, hasExportJsonKey, sections, sides) {
973
995
  this.configKey = configKey;
974
996
  this.jsonKey = jsonKey;
997
+ this.exportJsonKey = exportJsonKey;
998
+ this.hasExportJsonKey = hasExportJsonKey;
975
999
  this.sections = sections;
976
1000
  this.sides = sides;
977
1001
  }
@@ -1252,6 +1276,7 @@ var propertyKeys = {
1252
1276
  property_formula: "@formula",
1253
1277
  property_fullName: "@fullName",
1254
1278
  property_groupTag: "@groupTag",
1279
+ property_gUri: "@gUri",
1255
1280
  property_handInAcceptFileType: "@handInAcceptFileType",
1256
1281
  property_handInInstruction: "@handInInstruction",
1257
1282
  property_handInRequirement: "@handInRequirement",
@@ -1387,6 +1412,7 @@ var propertyKeys = {
1387
1412
  property_siteName: "@siteName",
1388
1413
  property_size: "@size",
1389
1414
  property_slug: "@slug",
1415
+ property_sourceBB: "@sourceBB",
1390
1416
  property_sourceDocument: "@sourceDocument",
1391
1417
  property_sourceRL: "@sourceRL",
1392
1418
  property_spaceId: "@spaceId",
@@ -2131,25 +2157,29 @@ var CARDSETS = {
2131
2157
  //
2132
2158
  [CardSetConfigKey.flashcard]: {
2133
2159
  jsonKey: "cards",
2160
+ exportJsonKey: { cards: "$" },
2134
2161
  sides: [
2135
2162
  {
2136
2163
  name: "question",
2137
2164
  variants: [
2138
2165
  {
2139
2166
  jsonKey: "question.text",
2167
+ exportJsonKey: { question: { text: "$" } },
2140
2168
  tags: [
2141
2169
  {
2142
2170
  key: ConfigKey.group_standardTags,
2143
2171
  description: "Standard tags for the flashcard."
2144
2172
  },
2145
2173
  {
2174
+ exportJsonKey: { title: "$" },
2146
2175
  key: ConfigKey.tag_title,
2147
2176
  description: "Title of the flashcard."
2148
2177
  },
2149
2178
  {
2150
2179
  key: ConfigKey.group_resourceIcon,
2151
2180
  description: "Icon resource for the flashcard.",
2152
- jsonKey: "question.icon|resource(type=image, key=image)"
2181
+ jsonKey: "question.icon|resource(type=image, key=image)",
2182
+ exportJsonKey: { question: { icon: { type: "image", image: { src: "$" } } } }
2153
2183
  }
2154
2184
  ]
2155
2185
  }
@@ -2160,37 +2190,45 @@ var CARDSETS = {
2160
2190
  variants: [
2161
2191
  {
2162
2192
  jsonKey: "answer.text",
2193
+ exportJsonKey: { answer: { text: "$" } },
2163
2194
  tags: [
2164
2195
  {
2165
2196
  key: ConfigKey.group_standardTags,
2166
2197
  description: "Standard tags for the flashcard."
2167
2198
  },
2168
2199
  {
2200
+ exportJsonKey: { title: "$" },
2169
2201
  key: ConfigKey.tag_title,
2170
2202
  description: "Title of the flashcard."
2171
2203
  },
2172
2204
  {
2173
2205
  key: ConfigKey.group_resourceIcon,
2174
2206
  description: "Icon resource for the flashcard.",
2175
- jsonKey: "answer.icon|resource(type=image, key=image)"
2207
+ jsonKey: "answer.icon|resource(type=image, key=image)",
2208
+ exportJsonKey: { answer: { icon: { type: "image", image: { src: "$" } } } }
2176
2209
  }
2177
2210
  ]
2178
2211
  },
2179
2212
  {
2180
2213
  jsonKey: "alternativeAnswers[].text",
2214
+ exportJsonKey: { alternativeAnswers: [{ text: "$" }] },
2181
2215
  tags: [
2182
2216
  {
2183
2217
  key: ConfigKey.group_standardTags,
2184
2218
  description: "Standard tags for the flashcard."
2185
2219
  },
2186
2220
  {
2221
+ exportJsonKey: { title: "$" },
2187
2222
  key: ConfigKey.tag_title,
2188
2223
  description: "Title of the flashcard."
2189
2224
  },
2190
2225
  {
2191
2226
  key: ConfigKey.group_resourceIcon,
2192
2227
  description: "Icon resource for the flashcard.",
2193
- jsonKey: "alternativeAnswers[].icon|resource(type=image, key=image)"
2228
+ jsonKey: "alternativeAnswers[].icon|resource(type=image, key=image)",
2229
+ exportJsonKey: {
2230
+ alternativeAnswers: [{ icon: { type: "image", image: { src: "$" } } }]
2231
+ }
2194
2232
  }
2195
2233
  ],
2196
2234
  repeatCount: Count.infinity
@@ -2204,12 +2242,14 @@ var CARDSETS = {
2204
2242
  //
2205
2243
  [CardSetConfigKey.definitionList]: {
2206
2244
  jsonKey: "definitions",
2245
+ exportJsonKey: { definitions: "$" },
2207
2246
  sides: [
2208
2247
  {
2209
2248
  name: "term",
2210
2249
  variants: [
2211
2250
  {
2212
2251
  jsonKey: "term.text",
2252
+ exportJsonKey: { term: { text: "$" } },
2213
2253
  tags: [
2214
2254
  {
2215
2255
  key: ConfigKey.group_standardTags,
@@ -2219,13 +2259,15 @@ var CARDSETS = {
2219
2259
  key: ConfigKey.tag_title,
2220
2260
  description: "Title of the definition.",
2221
2261
  format: TagFormat.plainText,
2222
- jsonKey: "^heading.forKeys"
2262
+ jsonKey: "^heading.forKeys",
2263
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2223
2264
  },
2224
2265
  {
2225
2266
  key: ConfigKey.group_resourceIcon,
2226
2267
  description: "Icon resource for the definition.",
2227
2268
  format: TagFormat.plainText,
2228
- jsonKey: "term.icon|resource(type=image, key=image)"
2269
+ jsonKey: "term.icon|resource(type=image, key=image)",
2270
+ exportJsonKey: { term: { icon: { type: "image", image: { src: "$" } } } }
2229
2271
  }
2230
2272
  ]
2231
2273
  }
@@ -2236,6 +2278,7 @@ var CARDSETS = {
2236
2278
  variants: [
2237
2279
  {
2238
2280
  jsonKey: "definition.text",
2281
+ exportJsonKey: { definition: { text: "$" } },
2239
2282
  tags: [
2240
2283
  {
2241
2284
  key: ConfigKey.group_standardTags,
@@ -2245,30 +2288,37 @@ var CARDSETS = {
2245
2288
  key: ConfigKey.tag_title,
2246
2289
  description: "Title of the definition.",
2247
2290
  format: TagFormat.plainText,
2248
- jsonKey: "^heading.forValues"
2291
+ jsonKey: "^heading.forValues",
2292
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2249
2293
  },
2250
2294
  {
2251
2295
  key: ConfigKey.group_resourceIcon,
2252
2296
  description: "Icon resource for the definition.",
2253
- jsonKey: "definition.icon|resource(type=image, key=image)"
2297
+ jsonKey: "definition.icon|resource(type=image, key=image)",
2298
+ exportJsonKey: { definition: { icon: { type: "image", image: { src: "$" } } } }
2254
2299
  }
2255
2300
  ]
2256
2301
  },
2257
2302
  {
2258
2303
  jsonKey: "alternativeDefinitions[].text",
2304
+ exportJsonKey: { alternativeDefinitions: [{ text: "$" }] },
2259
2305
  tags: [
2260
2306
  {
2261
2307
  key: ConfigKey.group_standardTags,
2262
2308
  description: "Standard tags for the definition."
2263
2309
  },
2264
2310
  {
2311
+ exportJsonKey: { title: "$" },
2265
2312
  key: ConfigKey.tag_title,
2266
2313
  description: "Title of the definition."
2267
2314
  },
2268
2315
  {
2269
2316
  key: ConfigKey.group_resourceIcon,
2270
2317
  description: "Icon resource for the definition.",
2271
- jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)"
2318
+ jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)",
2319
+ exportJsonKey: {
2320
+ alternativeDefinitions: [{ icon: { type: "image", image: { src: "$" } } }]
2321
+ }
2272
2322
  }
2273
2323
  ],
2274
2324
  repeatCount: Count.infinity
@@ -2282,12 +2332,14 @@ var CARDSETS = {
2282
2332
  //
2283
2333
  [CardSetConfigKey.matchPairs]: {
2284
2334
  jsonKey: "pairs",
2335
+ exportJsonKey: { pairs: "$" },
2285
2336
  sides: [
2286
2337
  {
2287
2338
  name: "key",
2288
2339
  variants: [
2289
2340
  {
2290
2341
  jsonKey: "key",
2342
+ exportJsonKey: { key: "$" },
2291
2343
  tags: [
2292
2344
  {
2293
2345
  key: ConfigKey.group_standardTags,
@@ -2297,22 +2349,29 @@ var CARDSETS = {
2297
2349
  key: ConfigKey.tag_title,
2298
2350
  description: "Title of the match pair.",
2299
2351
  format: TagFormat.plainText,
2300
- jsonKey: "^heading.forKeys"
2352
+ jsonKey: "^heading.forKeys",
2353
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2301
2354
  },
2302
2355
  {
2303
2356
  key: ConfigKey.property_isCaseSensitive,
2357
+ exportJsonKey: [
2358
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2359
+ { isCaseSensitive: "$" }
2360
+ ],
2304
2361
  description: "Property to indicate if the match is case sensitive.",
2305
2362
  format: TagFormat.boolean
2306
2363
  },
2307
2364
  {
2308
2365
  key: ConfigKey.resource_audio,
2309
2366
  description: "Audio resource for the match pair.",
2310
- jsonKey: "keyAudio"
2367
+ jsonKey: "keyAudio",
2368
+ exportJsonKey: { keyAudio: "$" }
2311
2369
  },
2312
2370
  {
2313
2371
  key: ConfigKey.resource_image,
2314
2372
  description: "Image resource for the match pair.",
2315
- jsonKey: "keyImage"
2373
+ jsonKey: "keyImage",
2374
+ exportJsonKey: { keyImage: "$" }
2316
2375
  }
2317
2376
  ]
2318
2377
  }
@@ -2324,6 +2383,7 @@ var CARDSETS = {
2324
2383
  variants: [
2325
2384
  {
2326
2385
  jsonKey: "values[]",
2386
+ exportJsonKey: { values: ["$"] },
2327
2387
  tags: [
2328
2388
  {
2329
2389
  key: ConfigKey.group_standardTags,
@@ -2333,10 +2393,15 @@ var CARDSETS = {
2333
2393
  key: ConfigKey.tag_title,
2334
2394
  description: "Title of the match pair.",
2335
2395
  format: TagFormat.plainText,
2336
- jsonKey: "^heading.forValues"
2396
+ jsonKey: "^heading.forValues",
2397
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2337
2398
  },
2338
2399
  {
2339
2400
  key: ConfigKey.property_isCaseSensitive,
2401
+ exportJsonKey: [
2402
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2403
+ { isCaseSensitive: "$" }
2404
+ ],
2340
2405
  description: "Property to indicate if the match is case sensitive.",
2341
2406
  format: TagFormat.boolean
2342
2407
  }
@@ -2352,12 +2417,14 @@ var CARDSETS = {
2352
2417
  //
2353
2418
  [CardSetConfigKey.matchAudioPairs]: {
2354
2419
  jsonKey: "pairs",
2420
+ exportJsonKey: { pairs: "$" },
2355
2421
  sides: [
2356
2422
  {
2357
2423
  name: "key",
2358
2424
  variants: [
2359
2425
  {
2360
2426
  jsonKey: "key",
2427
+ exportJsonKey: { key: "$" },
2361
2428
  tags: [
2362
2429
  {
2363
2430
  key: ConfigKey.group_standardTags,
@@ -2367,12 +2434,14 @@ var CARDSETS = {
2367
2434
  key: ConfigKey.tag_title,
2368
2435
  description: "Title of the audio match pair.",
2369
2436
  format: TagFormat.plainText,
2370
- jsonKey: "^heading.forKeys"
2437
+ jsonKey: "^heading.forKeys",
2438
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2371
2439
  },
2372
2440
  {
2373
2441
  key: ConfigKey.resource_audio,
2374
2442
  description: "Audio resource for the match pair.",
2375
- jsonKey: "keyAudio"
2443
+ jsonKey: "keyAudio",
2444
+ exportJsonKey: { keyAudio: "$" }
2376
2445
  }
2377
2446
  ]
2378
2447
  }
@@ -2384,6 +2453,7 @@ var CARDSETS = {
2384
2453
  variants: [
2385
2454
  {
2386
2455
  jsonKey: "values[]",
2456
+ exportJsonKey: { values: ["$"] },
2387
2457
  tags: [
2388
2458
  {
2389
2459
  key: ConfigKey.group_standardTags,
@@ -2393,7 +2463,8 @@ var CARDSETS = {
2393
2463
  key: ConfigKey.tag_title,
2394
2464
  description: "Title of the audio match pair.",
2395
2465
  format: TagFormat.plainText,
2396
- jsonKey: "^heading.forValues"
2466
+ jsonKey: "^heading.forValues",
2467
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2397
2468
  },
2398
2469
  {
2399
2470
  key: ConfigKey.resource_audio,
@@ -2411,12 +2482,14 @@ var CARDSETS = {
2411
2482
  //
2412
2483
  [CardSetConfigKey.matchImagePairs]: {
2413
2484
  jsonKey: "pairs",
2485
+ exportJsonKey: { pairs: "$" },
2414
2486
  sides: [
2415
2487
  {
2416
2488
  name: "key",
2417
2489
  variants: [
2418
2490
  {
2419
2491
  jsonKey: "key",
2492
+ exportJsonKey: { key: "$" },
2420
2493
  tags: [
2421
2494
  {
2422
2495
  key: ConfigKey.group_standardTags,
@@ -2426,12 +2499,14 @@ var CARDSETS = {
2426
2499
  key: ConfigKey.tag_title,
2427
2500
  description: "Title of the image match pair.",
2428
2501
  format: TagFormat.plainText,
2429
- jsonKey: "^heading.forKeys"
2502
+ jsonKey: "^heading.forKeys",
2503
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2430
2504
  },
2431
2505
  {
2432
2506
  key: ConfigKey.resource_image,
2433
2507
  description: "Image resource for the match pair.",
2434
- jsonKey: "keyImage"
2508
+ jsonKey: "keyImage",
2509
+ exportJsonKey: { keyImage: "$" }
2435
2510
  }
2436
2511
  ]
2437
2512
  }
@@ -2443,6 +2518,7 @@ var CARDSETS = {
2443
2518
  variants: [
2444
2519
  {
2445
2520
  jsonKey: "values[]",
2521
+ exportJsonKey: { values: ["$"] },
2446
2522
  tags: [
2447
2523
  {
2448
2524
  key: ConfigKey.group_standardTags,
@@ -2452,7 +2528,8 @@ var CARDSETS = {
2452
2528
  key: ConfigKey.tag_title,
2453
2529
  description: "Title of the image match pair.",
2454
2530
  format: TagFormat.plainText,
2455
- jsonKey: "^heading.forValues"
2531
+ jsonKey: "^heading.forValues",
2532
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2456
2533
  },
2457
2534
  {
2458
2535
  key: ConfigKey.resource_image,
@@ -2470,12 +2547,14 @@ var CARDSETS = {
2470
2547
  //
2471
2548
  [CardSetConfigKey.matchMatrix]: {
2472
2549
  jsonKey: "matrix",
2550
+ exportJsonKey: { matrix: "$" },
2473
2551
  sides: [
2474
2552
  {
2475
2553
  name: "key",
2476
2554
  variants: [
2477
2555
  {
2478
2556
  jsonKey: "key",
2557
+ exportJsonKey: { key: "$" },
2479
2558
  tags: [
2480
2559
  {
2481
2560
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2483,6 +2562,11 @@ var CARDSETS = {
2483
2562
  },
2484
2563
  {
2485
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
+ ],
2486
2570
  description: "Example text for the match matrix.",
2487
2571
  format: TagFormat.plainText
2488
2572
  },
@@ -2490,10 +2574,15 @@ var CARDSETS = {
2490
2574
  key: ConfigKey.tag_title,
2491
2575
  description: "Title of the match matrix.",
2492
2576
  format: TagFormat.plainText,
2493
- jsonKey: "^heading.forKeys"
2577
+ jsonKey: "^heading.forKeys",
2578
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2494
2579
  },
2495
2580
  {
2496
2581
  key: ConfigKey.property_isCaseSensitive,
2582
+ exportJsonKey: [
2583
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2584
+ { isCaseSensitive: "$" }
2585
+ ],
2497
2586
  description: "Property to indicate if the match is case sensitive.",
2498
2587
  format: TagFormat.boolean
2499
2588
  }
@@ -2507,6 +2596,7 @@ var CARDSETS = {
2507
2596
  variants: [
2508
2597
  {
2509
2598
  jsonKey: "cells[{s}].values[]",
2599
+ exportJsonKey: { cells: { $s: { values: ["$"] } } },
2510
2600
  tags: [
2511
2601
  {
2512
2602
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2514,6 +2604,18 @@ var CARDSETS = {
2514
2604
  },
2515
2605
  {
2516
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
+ ],
2517
2619
  description: "Example text for the match matrix.",
2518
2620
  format: TagFormat.plainText
2519
2621
  },
@@ -2521,10 +2623,15 @@ var CARDSETS = {
2521
2623
  key: ConfigKey.tag_title,
2522
2624
  description: "Title of the match matrix.",
2523
2625
  format: TagFormat.plainText,
2524
- jsonKey: "^heading.forValues"
2626
+ jsonKey: "^heading.forValues",
2627
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2525
2628
  },
2526
2629
  {
2527
2630
  key: ConfigKey.property_isCaseSensitive,
2631
+ exportJsonKey: [
2632
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2633
+ { isCaseSensitive: "$" }
2634
+ ],
2528
2635
  description: "Property to indicate if the match is case sensitive.",
2529
2636
  format: TagFormat.boolean
2530
2637
  }
@@ -2540,23 +2647,27 @@ var CARDSETS = {
2540
2647
  //
2541
2648
  [CardSetConfigKey.statements]: {
2542
2649
  jsonKey: "statements",
2650
+ exportJsonKey: { statements: "$" },
2543
2651
  sides: [
2544
2652
  {
2545
2653
  name: "statement",
2546
2654
  variants: [
2547
2655
  {
2548
2656
  jsonKey: "statement",
2657
+ exportJsonKey: { statement: "$" },
2549
2658
  tags: [
2550
2659
  {
2551
2660
  key: ConfigKey.tag_true,
2552
2661
  description: "Tag for true statements.",
2553
2662
  jsonKey: "statement|set(isCorrect=true)",
2663
+ exportJsonKey: { statement: "$", isCorrect: true },
2554
2664
  maxCount: 1
2555
2665
  },
2556
2666
  {
2557
2667
  key: ConfigKey.tag_false,
2558
2668
  description: "Tag for false statements.",
2559
2669
  jsonKey: "statement|set(isCorrect=false)",
2670
+ exportJsonKey: { statement: "$", isCorrect: false },
2560
2671
  maxCount: 1
2561
2672
  },
2562
2673
  {
@@ -2575,6 +2686,7 @@ var CARDSETS = {
2575
2686
  //
2576
2687
  [CardSetConfigKey.quiz]: {
2577
2688
  jsonKey: "quizzes",
2689
+ exportJsonKey: { quizzes: "$" },
2578
2690
  sides: [
2579
2691
  {
2580
2692
  name: "choices",
@@ -2602,6 +2714,7 @@ var CARDSETS = {
2602
2714
  //
2603
2715
  [CardSetConfigKey.feedback]: {
2604
2716
  jsonKey: "feedbacks",
2717
+ exportJsonKey: { feedbacks: "$" },
2605
2718
  sides: [
2606
2719
  {
2607
2720
  name: "choices",
@@ -2621,7 +2734,8 @@ var CARDSETS = {
2621
2734
  key: ConfigKey.tag_title,
2622
2735
  description: "Title of the feedback.",
2623
2736
  format: TagFormat.plainText,
2624
- jsonKey: "^heading.forKeys"
2737
+ jsonKey: "^heading.forKeys",
2738
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2625
2739
  }
2626
2740
  ],
2627
2741
  bodyAllowed: false
@@ -2633,6 +2747,7 @@ var CARDSETS = {
2633
2747
  variants: [
2634
2748
  {
2635
2749
  jsonKey: "reason.text",
2750
+ exportJsonKey: { reason: { text: "$" } },
2636
2751
  tags: [
2637
2752
  {
2638
2753
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2640,11 +2755,20 @@ var CARDSETS = {
2640
2755
  },
2641
2756
  {
2642
2757
  key: ConfigKey.property_reasonableNumOfChars,
2758
+ exportJsonKey: [
2759
+ { "@absent": { reasonableNumOfChars: "$ancestor" } },
2760
+ { reasonableNumOfChars: "$" }
2761
+ ],
2643
2762
  description: "Property for reasonable number of characters.",
2644
2763
  format: TagFormat.number
2645
2764
  },
2646
2765
  {
2647
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
+ ],
2648
2772
  description: "Example text for the feedback.",
2649
2773
  format: TagFormat.plainText
2650
2774
  },
@@ -2652,7 +2776,8 @@ var CARDSETS = {
2652
2776
  key: ConfigKey.tag_title,
2653
2777
  description: "Title of the feedback.",
2654
2778
  format: TagFormat.plainText,
2655
- jsonKey: "^heading.forValues"
2779
+ jsonKey: "^heading.forValues",
2780
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2656
2781
  }
2657
2782
  ],
2658
2783
  bodyAllowed: true
@@ -2666,21 +2791,29 @@ var CARDSETS = {
2666
2791
  //
2667
2792
  [CardSetConfigKey.questions]: {
2668
2793
  jsonKey: "questions",
2794
+ exportJsonKey: { questions: "$" },
2669
2795
  sides: [
2670
2796
  {
2671
2797
  name: "question",
2672
2798
  variants: [
2673
2799
  {
2674
2800
  jsonKey: "question",
2801
+ exportJsonKey: { question: "$" },
2675
2802
  tags: [
2676
2803
  {
2677
2804
  key: ConfigKey.property_reasonableNumOfChars,
2805
+ exportJsonKey: [
2806
+ { "@absent": { reasonableNumOfChars: "$ancestor" } },
2807
+ { reasonableNumOfChars: "$" }
2808
+ ],
2678
2809
  description: "Property for reasonable number of characters.",
2679
2810
  format: TagFormat.number
2680
2811
  },
2681
2812
  {
2813
+ exportJsonKey: { sampleSolution: "$" },
2682
2814
  key: ConfigKey.tag_sampleSolution,
2683
- description: "Sample solution for the question."
2815
+ description: "Sample solution for the question.",
2816
+ format: TagFormat.plainText
2684
2817
  },
2685
2818
  {
2686
2819
  key: ConfigKey.property_sampleSolution,
@@ -2720,6 +2853,7 @@ var CARDSETS = {
2720
2853
  variants: [
2721
2854
  {
2722
2855
  jsonKey: "elements[]",
2856
+ exportJsonKey: { elements: ["$"] },
2723
2857
  tags: [
2724
2858
  {
2725
2859
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2727,6 +2861,11 @@ var CARDSETS = {
2727
2861
  },
2728
2862
  {
2729
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
+ ],
2730
2869
  description: "Example text for the element.",
2731
2870
  format: TagFormat.plainText
2732
2871
  }
@@ -2742,6 +2881,7 @@ var CARDSETS = {
2742
2881
  //
2743
2882
  [CardSetConfigKey.table]: {
2744
2883
  jsonKey: "table.data",
2884
+ exportJsonKey: { table: { data: "$" } },
2745
2885
  sides: [
2746
2886
  {
2747
2887
  name: "cell",
@@ -2757,6 +2897,7 @@ var CARDSETS = {
2757
2897
  {
2758
2898
  key: ConfigKey.tag_title,
2759
2899
  jsonKey: "^table.columns[]",
2900
+ exportJsonKey: { "@bit": { table: { columns: ["$"] } } },
2760
2901
  description: "Title of the table."
2761
2902
  },
2762
2903
  {
@@ -2797,18 +2938,34 @@ var CARDSETS = {
2797
2938
  [CardSetConfigKey.tableExtended]: {
2798
2939
  jsonKey: null,
2799
2940
  sections: {
2800
- "table-header": { jsonKey: "table.header.rows", sideJsonKey: "cells[{s}]|set(title=true)" },
2801
- "table-body": { jsonKey: "table.body.rows", isDefault: true },
2802
- "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
+ }
2803
2958
  },
2804
2959
  sides: [
2805
2960
  {
2806
2961
  name: "cell",
2807
2962
  repeat: true,
2808
2963
  jsonKey: "cells[{s}]",
2964
+ exportJsonKey: { cells: { $s: "$" } },
2809
2965
  variants: [
2810
2966
  {
2811
2967
  jsonKey: "content",
2968
+ exportJsonKey: { content: "$" },
2812
2969
  tags: [
2813
2970
  {
2814
2971
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2817,29 +2974,38 @@ var CARDSETS = {
2817
2974
  {
2818
2975
  key: ConfigKey.tag_title,
2819
2976
  jsonKey: ".",
2977
+ exportJsonKey: {
2978
+ "@bit": {
2979
+ table: { header: { rows: { cells: { cells: { $s: { content: "$" } } } } } }
2980
+ }
2981
+ },
2820
2982
  description: "Title of the table cell."
2821
2983
  },
2822
2984
  {
2823
2985
  key: ConfigKey.property_tableCellType,
2824
2986
  jsonKey: "title|bool(th)",
2987
+ exportJsonKey: [{ "@value=th": { title: true } }],
2825
2988
  description: "Table cell type (th/td).",
2826
2989
  format: TagFormat.plainText
2827
2990
  },
2828
2991
  {
2829
2992
  key: ConfigKey.property_tableRowSpan,
2830
2993
  jsonKey: "rowspan",
2994
+ exportJsonKey: { rowspan: "$" },
2831
2995
  description: "Number of rows the cell spans.",
2832
2996
  format: TagFormat.number
2833
2997
  },
2834
2998
  {
2835
2999
  key: ConfigKey.property_tableColSpan,
2836
3000
  jsonKey: "colspan",
3001
+ exportJsonKey: { colspan: "$" },
2837
3002
  description: "Number of columns the cell spans.",
2838
3003
  format: TagFormat.number
2839
3004
  },
2840
3005
  {
2841
3006
  key: ConfigKey.property_tableScope,
2842
3007
  jsonKey: "scope",
3008
+ exportJsonKey: { scope: "$" },
2843
3009
  description: "Scope attribute for header cells.",
2844
3010
  format: TagFormat.plainText
2845
3011
  },
@@ -2860,6 +3026,7 @@ var CARDSETS = {
2860
3026
  //
2861
3027
  [CardSetConfigKey.pronunciationTable]: {
2862
3028
  jsonKey: "pronunciationTable.data",
3029
+ exportJsonKey: { pronunciationTable: { data: "$" } },
2863
3030
  sides: [
2864
3031
  {
2865
3032
  name: "cell",
@@ -2867,12 +3034,14 @@ var CARDSETS = {
2867
3034
  variants: [
2868
3035
  {
2869
3036
  jsonKey: "body",
3037
+ exportJsonKey: { body: "$" },
2870
3038
  tags: [
2871
3039
  {
2872
3040
  key: ConfigKey.group_standardItemLeadInstructionHint,
2873
3041
  description: "Standard tags for lead, instruction, and hint."
2874
3042
  },
2875
3043
  {
3044
+ exportJsonKey: { title: "$" },
2876
3045
  key: ConfigKey.tag_title,
2877
3046
  description: "Title of the pronunciation table."
2878
3047
  },
@@ -2893,12 +3062,15 @@ var CARDSETS = {
2893
3062
  //
2894
3063
  [CardSetConfigKey.botActionResponses]: {
2895
3064
  jsonKey: "responses",
3065
+ exportJsonKey: { responses: "$" },
2896
3066
  sides: [
2897
3067
  {
2898
3068
  name: "response",
2899
3069
  variants: [
2900
3070
  {
2901
3071
  jsonKey: "feedback",
3072
+ exportJsonKey: { feedback: "$" },
3073
+ format: TextFormat.plainText,
2902
3074
  tags: [
2903
3075
  {
2904
3076
  key: ConfigKey.property_reaction,
@@ -2906,16 +3078,53 @@ var CARDSETS = {
2906
3078
  format: TagFormat.plainText
2907
3079
  },
2908
3080
  {
2909
- key: ConfigKey.group_standardItemLead,
2910
- 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
+ ]
2911
3113
  },
2912
3114
  {
2913
3115
  key: ConfigKey.tag_instruction,
2914
3116
  description: "The response label for the bot action.",
2915
- jsonKey: "response"
3117
+ jsonKey: "response",
3118
+ exportJsonKey: { response: "$" },
3119
+ format: TagFormat.plainText
2916
3120
  },
2917
3121
  {
2918
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
+ ],
2919
3128
  description: "Example text for the bot action response.",
2920
3129
  format: TagFormat.plainText
2921
3130
  }
@@ -2930,12 +3139,14 @@ var CARDSETS = {
2930
3139
  //
2931
3140
  [CardSetConfigKey.clozeList]: {
2932
3141
  jsonKey: "listItems",
3142
+ exportJsonKey: { listItems: "$" },
2933
3143
  sides: [
2934
3144
  {
2935
3145
  name: "content",
2936
3146
  variants: [
2937
3147
  {
2938
3148
  jsonKey: "body",
3149
+ exportJsonKey: { body: "$" },
2939
3150
  tags: [
2940
3151
  {
2941
3152
  key: ConfigKey.group_standardTags,
@@ -2956,18 +3167,21 @@ var CARDSETS = {
2956
3167
  //
2957
3168
  [CardSetConfigKey.exampleBitList]: {
2958
3169
  jsonKey: "listItems",
3170
+ exportJsonKey: { listItems: "$" },
2959
3171
  sides: [
2960
3172
  {
2961
3173
  name: "item",
2962
3174
  variants: [
2963
3175
  {
2964
3176
  jsonKey: "body",
3177
+ exportJsonKey: { body: "$" },
2965
3178
  tags: [
2966
3179
  {
2967
3180
  key: ConfigKey.group_standardTags,
2968
3181
  description: "Standard tags for example bits."
2969
3182
  },
2970
3183
  {
3184
+ exportJsonKey: { title: "$" },
2971
3185
  key: ConfigKey.tag_title,
2972
3186
  description: "Title of the example bit."
2973
3187
  }
@@ -2982,14 +3196,17 @@ var CARDSETS = {
2982
3196
  //
2983
3197
  [CardSetConfigKey.ingredients]: {
2984
3198
  jsonKey: "ingredients",
3199
+ exportJsonKey: { ingredients: "$" },
2985
3200
  sides: [
2986
3201
  {
2987
3202
  name: "ingredient",
2988
3203
  variants: [
2989
3204
  {
2990
3205
  jsonKey: "ingredient",
3206
+ exportJsonKey: { ingredient: "$" },
2991
3207
  tags: [
2992
3208
  {
3209
+ exportJsonKey: { title: "$" },
2993
3210
  key: ConfigKey.tag_title,
2994
3211
  description: "Title of the ingredient."
2995
3212
  },
@@ -2997,6 +3214,7 @@ var CARDSETS = {
2997
3214
  key: ConfigKey.tag_true,
2998
3215
  description: "Checked state for the ingredient.",
2999
3216
  jsonKey: "|set(checked=true)",
3217
+ exportJsonKey: { checked: true, $: "$" },
3000
3218
  maxCount: 1
3001
3219
  // nullable: true,
3002
3220
  },
@@ -3004,6 +3222,7 @@ var CARDSETS = {
3004
3222
  key: ConfigKey.tag_false,
3005
3223
  description: "Unchecked state for the ingredient.",
3006
3224
  jsonKey: "|set(checked=false)",
3225
+ exportJsonKey: { checked: false, $: "$" },
3007
3226
  maxCount: 1
3008
3227
  // nullable: true,
3009
3228
  },
@@ -3015,9 +3234,11 @@ var CARDSETS = {
3015
3234
  key: ConfigKey.tag_instruction,
3016
3235
  description: "The quantity of the ingredient.",
3017
3236
  jsonKey: "quantity",
3237
+ exportJsonKey: { quantity: "$" },
3018
3238
  format: TagFormat.number
3019
3239
  },
3020
3240
  {
3241
+ exportJsonKey: { hint: "$" },
3021
3242
  key: ConfigKey.tag_hint,
3022
3243
  description: "The hint for the ingredient."
3023
3244
  },
@@ -3053,6 +3274,7 @@ var CARDSETS = {
3053
3274
  //
3054
3275
  [CardSetConfigKey.bookReferenceList]: {
3055
3276
  jsonKey: "bookReferences",
3277
+ exportJsonKey: { bookReferences: "$" },
3056
3278
  sides: [
3057
3279
  {
3058
3280
  name: "reference",
@@ -3112,6 +3334,11 @@ var GROUPS = {
3112
3334
  format: TagFormat.plainText,
3113
3335
  maxCount: Count.infinity
3114
3336
  },
3337
+ {
3338
+ key: ConfigKey.property_gUri,
3339
+ description: "Global URI for the bit",
3340
+ format: TagFormat.plainText
3341
+ },
3115
3342
  {
3116
3343
  key: ConfigKey.property_customerId,
3117
3344
  description: "The customer-specific identifier for the bit",
@@ -3295,12 +3522,14 @@ var GROUPS = {
3295
3522
  {
3296
3523
  key: ConfigKey.property_groupTag,
3297
3524
  jsonKey: "groupTag.name",
3525
+ exportJsonKey: { groupTag: { name: "$" } },
3298
3526
  description: "The group tag(s) for the bit",
3299
3527
  format: TagFormat.plainText,
3300
3528
  maxCount: Count.infinity,
3301
3529
  chain: [
3302
3530
  {
3303
3531
  key: ConfigKey.property_tag,
3532
+ exportJsonKey: { tags: ["$"] },
3304
3533
  description: "The tag(s) for the group",
3305
3534
  format: TagFormat.plainText,
3306
3535
  maxCount: Count.infinity
@@ -3331,6 +3560,12 @@ var GROUPS = {
3331
3560
  format: TagFormat.plainText,
3332
3561
  maxCount: Count.infinity
3333
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
+ },
3334
3569
  {
3335
3570
  key: ConfigKey.property_levelCEFRp,
3336
3571
  description: "The CEFRp level for the bit",
@@ -3368,6 +3603,7 @@ var GROUPS = {
3368
3603
  maxCount: Count.infinity
3369
3604
  },
3370
3605
  {
3606
+ exportJsonKey: { anchor: "$" },
3371
3607
  key: ConfigKey.tag_anchor,
3372
3608
  name: "Anchor",
3373
3609
  format: TagFormat.plainText,
@@ -3405,23 +3641,27 @@ var GROUPS = {
3405
3641
  {
3406
3642
  key: ConfigKey.tag_item,
3407
3643
  jsonKey: "item",
3644
+ exportJsonKey: { item: "$" },
3408
3645
  description: "The item for the bit",
3409
3646
  chain: [
3410
3647
  {
3411
3648
  key: ConfigKey.tag_item,
3412
3649
  jsonKey: "lead",
3650
+ exportJsonKey: { lead: "$" },
3413
3651
  description: "The lead for the bit",
3414
3652
  maxCount: 1,
3415
3653
  chain: [
3416
3654
  {
3417
3655
  key: ConfigKey.tag_item,
3418
3656
  jsonKey: "pageNumber",
3657
+ exportJsonKey: { pageNumber: "$" },
3419
3658
  description: "The page number for the bit",
3420
3659
  maxCount: 1,
3421
3660
  chain: [
3422
3661
  {
3423
3662
  key: ConfigKey.tag_item,
3424
3663
  jsonKey: "marginNumber",
3664
+ exportJsonKey: { marginNumber: "$" },
3425
3665
  description: "The margin number for the bit",
3426
3666
  maxCount: 1
3427
3667
  }
@@ -3442,11 +3682,13 @@ var GROUPS = {
3442
3682
  description: "Item, lead, page number, and margin number tags"
3443
3683
  },
3444
3684
  {
3685
+ exportJsonKey: { instruction: "$" },
3445
3686
  key: ConfigKey.tag_instruction,
3446
3687
  name: "Instruction",
3447
3688
  description: "The instruction for the bit"
3448
3689
  },
3449
3690
  {
3691
+ exportJsonKey: { hint: "$" },
3450
3692
  key: ConfigKey.tag_hint,
3451
3693
  name: "Hint",
3452
3694
  description: "The hint for the bit"
@@ -3466,9 +3708,17 @@ var GROUPS = {
3466
3708
  description: "Item, lead, page number, margin number, instruction and hint tags"
3467
3709
  },
3468
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).
3469
3714
  key: ConfigKey.property_example,
3715
+ exportJsonKey: [
3716
+ { "@keyonly": { isExample: true } },
3717
+ { "@absent": { isExample: true } },
3718
+ { isExample: true, example: "$" }
3719
+ ],
3470
3720
  description: "The example(s) for the bit",
3471
- format: TagFormat.plainText
3721
+ format: TagFormat.bitmarkText
3472
3722
  }
3473
3723
  ]
3474
3724
  },
@@ -3479,6 +3729,7 @@ var GROUPS = {
3479
3729
  {
3480
3730
  key: ConfigKey.property_imageSource,
3481
3731
  jsonKey: "imageSource.url",
3732
+ exportJsonKey: { imageSource: { url: "$" } },
3482
3733
  description: "The source of an image",
3483
3734
  format: TagFormat.plainText,
3484
3735
  chain: [
@@ -3513,6 +3764,7 @@ var GROUPS = {
3513
3764
  {
3514
3765
  key: ConfigKey.property_technicalTerm,
3515
3766
  jsonKey: "technicalTerm.technicalTerm",
3767
+ exportJsonKey: { technicalTerm: { technicalTerm: "$" } },
3516
3768
  description: "The technical term",
3517
3769
  format: TagFormat.plainText,
3518
3770
  chain: [
@@ -3532,6 +3784,7 @@ var GROUPS = {
3532
3784
  {
3533
3785
  key: ConfigKey.property_person,
3534
3786
  jsonKey: "partner.name",
3787
+ exportJsonKey: { partner: { name: "$" } },
3535
3788
  description: "A person",
3536
3789
  format: TagFormat.plainText,
3537
3790
  chain: [
@@ -3543,6 +3796,7 @@ var GROUPS = {
3543
3796
  {
3544
3797
  key: ConfigKey.group_resourceImage,
3545
3798
  jsonKey: "avatarImage|resource(type=image, key=image)",
3799
+ exportJsonKey: { avatarImage: { type: "image", image: { src: "$" } } },
3546
3800
  description: "The image of the person"
3547
3801
  }
3548
3802
  ]
@@ -3551,6 +3805,7 @@ var GROUPS = {
3551
3805
  // Deprecated (parter renamed to person)
3552
3806
  key: ConfigKey.property_partner,
3553
3807
  jsonKey: "partner.name",
3808
+ exportJsonKey: { partner: { name: "$" } },
3554
3809
  description: "A partner",
3555
3810
  format: TagFormat.plainText,
3556
3811
  chain: [
@@ -3562,6 +3817,7 @@ var GROUPS = {
3562
3817
  {
3563
3818
  key: ConfigKey.group_resourceImage,
3564
3819
  jsonKey: "avatarImage|resource(type=image, key=image)",
3820
+ exportJsonKey: { avatarImage: { type: "image", image: { src: "$" } } },
3565
3821
  description: "The image of the partner"
3566
3822
  }
3567
3823
  ]
@@ -3573,15 +3829,19 @@ var GROUPS = {
3573
3829
  description: "Gap chain",
3574
3830
  tags: [
3575
3831
  {
3832
+ exportJsonKey: { solutions: [["$"]] },
3576
3833
  key: ConfigKey.tag_gap,
3577
3834
  description: "The value of a gap in the content",
3578
3835
  maxCount: Count.infinity,
3836
+ format: TagFormat.plainText,
3579
3837
  chain: [
3580
3838
  {
3581
3839
  key: ConfigKey.tag_gap,
3582
3840
  jsonKey: "solutions[]",
3841
+ exportJsonKey: { solutions: ["$"] },
3583
3842
  description: "Alternative values for the gaps in the content",
3584
- maxCount: Count.infinity
3843
+ maxCount: Count.infinity,
3844
+ format: TagFormat.plainText
3585
3845
  },
3586
3846
  {
3587
3847
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3590,12 +3850,33 @@ var GROUPS = {
3590
3850
  {
3591
3851
  key: ConfigKey.property_example,
3592
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
+ ],
3593
3870
  description: "An example for the gap",
3594
- format: TagFormat.plainText
3871
+ format: TagFormat.bitmarkText
3595
3872
  },
3596
3873
  {
3597
3874
  key: ConfigKey.property_isCaseSensitive,
3598
3875
  jsonKey: "isCaseSensitive",
3876
+ exportJsonKey: [
3877
+ { "@absent": { isCaseSensitive: "$ancestor" } },
3878
+ { isCaseSensitive: "$" }
3879
+ ],
3599
3880
  description: "If true, the gap text is case sensitive",
3600
3881
  format: TagFormat.boolean,
3601
3882
  defaultValue: "true"
@@ -3609,21 +3890,27 @@ var GROUPS = {
3609
3890
  description: "True/False chain",
3610
3891
  tags: [
3611
3892
  {
3893
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3612
3894
  key: ConfigKey.tag_true,
3613
3895
  description: "True value for a true/false statement/question",
3614
3896
  maxCount: Count.infinity,
3897
+ format: TagFormat.plainText,
3615
3898
  chain: [
3616
3899
  {
3617
3900
  key: ConfigKey.tag_true,
3618
3901
  jsonKey: "choices[]|set(isCorrect=true)",
3902
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3619
3903
  description: "True values for a true/false statement/question",
3620
- maxCount: Count.infinity
3904
+ maxCount: Count.infinity,
3905
+ format: TagFormat.plainText
3621
3906
  },
3622
3907
  {
3623
3908
  key: ConfigKey.tag_false,
3624
3909
  jsonKey: "choices[]|set(isCorrect=false)",
3910
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3625
3911
  description: "False values for a true/false statement/question",
3626
- maxCount: Count.infinity
3912
+ maxCount: Count.infinity,
3913
+ format: TagFormat.plainText
3627
3914
  },
3628
3915
  {
3629
3916
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3632,27 +3919,50 @@ var GROUPS = {
3632
3919
  {
3633
3920
  key: ConfigKey.property_example,
3634
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
+ ],
3635
3939
  description: "An example for the true/false statement/question",
3636
- format: TagFormat.plainText
3940
+ format: TagFormat.bitmarkText
3637
3941
  }
3638
3942
  ]
3639
3943
  },
3640
3944
  {
3945
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3641
3946
  key: ConfigKey.tag_false,
3642
3947
  description: "False value for a true/false statement/question",
3643
3948
  maxCount: Count.infinity,
3949
+ format: TagFormat.plainText,
3644
3950
  chain: [
3645
3951
  {
3646
3952
  key: ConfigKey.tag_true,
3647
3953
  jsonKey: "choices[]|set(isCorrect=true)",
3954
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3648
3955
  description: "True values for a true/false statement/question",
3649
- maxCount: Count.infinity
3956
+ maxCount: Count.infinity,
3957
+ format: TagFormat.plainText
3650
3958
  },
3651
3959
  {
3652
3960
  key: ConfigKey.tag_false,
3653
3961
  jsonKey: "choices[]|set(isCorrect=false)",
3962
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3654
3963
  description: "False values for a true/false statement/question",
3655
- maxCount: Count.infinity
3964
+ maxCount: Count.infinity,
3965
+ format: TagFormat.plainText
3656
3966
  },
3657
3967
  {
3658
3968
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3661,8 +3971,25 @@ var GROUPS = {
3661
3971
  {
3662
3972
  key: ConfigKey.property_example,
3663
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
+ ],
3664
3991
  description: "An example for the true/false statement/question",
3665
- format: TagFormat.plainText
3992
+ format: TagFormat.bitmarkText
3666
3993
  }
3667
3994
  ]
3668
3995
  }
@@ -3675,6 +4002,7 @@ var GROUPS = {
3675
4002
  {
3676
4003
  key: ConfigKey.property_mark,
3677
4004
  jsonKey: "marks.mark",
4005
+ exportJsonKey: { marks: { mark: ["$"] } },
3678
4006
  description: "The mark configuration",
3679
4007
  format: TagFormat.plainText,
3680
4008
  maxCount: Count.infinity,
@@ -3698,9 +4026,11 @@ var GROUPS = {
3698
4026
  description: "Mark chain",
3699
4027
  tags: [
3700
4028
  {
4029
+ exportJsonKey: { solution: ["$"] },
3701
4030
  key: ConfigKey.tag_mark,
3702
4031
  description: "The marked content",
3703
4032
  maxCount: Count.infinity,
4033
+ format: TagFormat.plainText,
3704
4034
  chain: [
3705
4035
  {
3706
4036
  key: ConfigKey.property_mark,
@@ -3711,8 +4041,13 @@ var GROUPS = {
3711
4041
  {
3712
4042
  key: ConfigKey.property_example,
3713
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
+ ],
3714
4049
  description: "An example for the marked content",
3715
- format: TagFormat.plainText
4050
+ format: TagFormat.bitmarkText
3716
4051
  }
3717
4052
  ]
3718
4053
  }
@@ -3801,7 +4136,8 @@ var GROUPS = {
3801
4136
  name: "Title",
3802
4137
  description: "The title of the book",
3803
4138
  maxCount: 2,
3804
- jsonKey: "title|multi(count=2, key=subtitle)"
4139
+ jsonKey: "title|multi(count=2, key=subtitle)",
4140
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
3805
4141
  },
3806
4142
  {
3807
4143
  key: ConfigKey.property_subtype,
@@ -3817,6 +4153,7 @@ var GROUPS = {
3817
4153
  {
3818
4154
  key: ConfigKey.resource_coverImage,
3819
4155
  jsonKey: "coverImage|resource(type=image, key=image)",
4156
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
3820
4157
  description: "The cover image of the book",
3821
4158
  chain: [
3822
4159
  {
@@ -3834,6 +4171,7 @@ var GROUPS = {
3834
4171
  {
3835
4172
  key: ConfigKey.resource_backgroundImage,
3836
4173
  jsonKey: "backgroundImage|resource(type=image, key=image)",
4174
+ exportJsonKey: { backgroundImage: { type: "image", image: { src: "$" } } },
3837
4175
  description: "The background image of the book",
3838
4176
  chain: [
3839
4177
  {
@@ -3993,10 +4331,21 @@ var GROUPS = {
3993
4331
  format: TagFormat.plainText,
3994
4332
  chain: [
3995
4333
  {
4334
+ exportJsonKey: { reference: "$" },
3996
4335
  key: ConfigKey.tag_reference,
3997
4336
  format: TagFormat.plainText,
3998
- description: "The reference(s) for the book(s) in the learning path",
3999
- maxCount: 2
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
+ ]
4000
4349
  }
4001
4350
  ]
4002
4351
  }
@@ -4136,6 +4485,8 @@ var GROUPS = {
4136
4485
  tags: [
4137
4486
  {
4138
4487
  key: ConfigKey.resource_imagePlaceholder,
4488
+ jsonKey: "imagePlaceholder|resource(type=image, key=image)",
4489
+ exportJsonKey: { imagePlaceholder: { type: "image", image: { src: "$" } } },
4139
4490
  description: "Placeholder image for the resource",
4140
4491
  chain: [
4141
4492
  {
@@ -4320,6 +4671,7 @@ var GROUPS = {
4320
4671
  {
4321
4672
  key: ConfigKey.property_posterImage,
4322
4673
  jsonKey: "posterImage.src",
4674
+ exportJsonKey: { posterImage: { src: "$" } },
4323
4675
  description: "The poster image for the video",
4324
4676
  format: TagFormat.plainText,
4325
4677
  chain: [
@@ -4376,6 +4728,7 @@ var GROUPS = {
4376
4728
  tags: [
4377
4729
  {
4378
4730
  key: ConfigKey.resource_image,
4731
+ exportJsonKey: { resource: { type: "image", image: { src: "$" } } },
4379
4732
  description: "The image resource",
4380
4733
  chain: [
4381
4734
  {
@@ -4440,6 +4793,7 @@ var GROUPS = {
4440
4793
  tags: [
4441
4794
  {
4442
4795
  key: ConfigKey.resource_imageLink,
4796
+ exportJsonKey: { resource: { type: "image-link", imageLink: { url: "$" } } },
4443
4797
  description: "The link to the image resource",
4444
4798
  chain: [
4445
4799
  {
@@ -4456,6 +4810,7 @@ var GROUPS = {
4456
4810
  tags: [
4457
4811
  {
4458
4812
  key: ConfigKey.resource_audio,
4813
+ exportJsonKey: { resource: { type: "audio", audio: { src: "$" } } },
4459
4814
  description: "The audio resource",
4460
4815
  chain: [
4461
4816
  {
@@ -4472,6 +4827,7 @@ var GROUPS = {
4472
4827
  tags: [
4473
4828
  {
4474
4829
  key: ConfigKey.resource_audioEmbed,
4830
+ exportJsonKey: { resource: { type: "audio-embed", audioEmbed: { src: "$" } } },
4475
4831
  description: "The embedded audio resource",
4476
4832
  chain: [
4477
4833
  {
@@ -4488,6 +4844,7 @@ var GROUPS = {
4488
4844
  tags: [
4489
4845
  {
4490
4846
  key: ConfigKey.resource_audioLink,
4847
+ exportJsonKey: { resource: { type: "audio-link", audioLink: { url: "$" } } },
4491
4848
  description: "The link to the audio resource",
4492
4849
  chain: [
4493
4850
  {
@@ -4504,6 +4861,7 @@ var GROUPS = {
4504
4861
  tags: [
4505
4862
  {
4506
4863
  key: ConfigKey.resource_video,
4864
+ exportJsonKey: { resource: { type: "video", video: { src: "$" } } },
4507
4865
  description: "The video resource",
4508
4866
  chain: [
4509
4867
  {
@@ -4520,6 +4878,7 @@ var GROUPS = {
4520
4878
  tags: [
4521
4879
  {
4522
4880
  key: ConfigKey.resource_videoEmbed,
4881
+ exportJsonKey: { resource: { type: "video-embed", videoEmbed: { url: "$" } } },
4523
4882
  description: "The embedded video resource",
4524
4883
  chain: [
4525
4884
  {
@@ -4536,6 +4895,7 @@ var GROUPS = {
4536
4895
  tags: [
4537
4896
  {
4538
4897
  key: ConfigKey.resource_videoLink,
4898
+ exportJsonKey: { resource: { type: "video-link", videoLink: { url: "$" } } },
4539
4899
  description: "The link to the video resource",
4540
4900
  chain: [
4541
4901
  {
@@ -4552,6 +4912,9 @@ var GROUPS = {
4552
4912
  tags: [
4553
4913
  {
4554
4914
  key: ConfigKey.resource_stillImageFilmEmbed,
4915
+ exportJsonKey: {
4916
+ resource: { type: "still-image-film-embed", stillImageFilmEmbed: { url: "$" } }
4917
+ },
4555
4918
  description: "The embedded still image film resource",
4556
4919
  chain: [
4557
4920
  {
@@ -4568,6 +4931,9 @@ var GROUPS = {
4568
4931
  tags: [
4569
4932
  {
4570
4933
  key: ConfigKey.resource_stillImageFilmLink,
4934
+ exportJsonKey: {
4935
+ resource: { type: "still-image-film-link", stillImageFilmLink: { url: "$" } }
4936
+ },
4571
4937
  description: "The link to the still image film resource",
4572
4938
  chain: [
4573
4939
  {
@@ -4632,6 +4998,7 @@ var GROUPS = {
4632
4998
  tags: [
4633
4999
  {
4634
5000
  key: ConfigKey.resource_document,
5001
+ exportJsonKey: { resource: { type: "document", document: { url: "$" } } },
4635
5002
  description: "The document resource",
4636
5003
  chain: [
4637
5004
  {
@@ -4648,6 +5015,7 @@ var GROUPS = {
4648
5015
  tags: [
4649
5016
  {
4650
5017
  key: ConfigKey.resource_documentEmbed,
5018
+ exportJsonKey: { resource: { type: "document-embed", documentEmbed: { url: "$" } } },
4651
5019
  description: "The embedded document resource",
4652
5020
  chain: [
4653
5021
  {
@@ -4664,6 +5032,7 @@ var GROUPS = {
4664
5032
  tags: [
4665
5033
  {
4666
5034
  key: ConfigKey.resource_documentLink,
5035
+ exportJsonKey: { resource: { type: "document-link", documentLink: { url: "$" } } },
4667
5036
  description: "The link to the document resource",
4668
5037
  chain: [
4669
5038
  {
@@ -4680,6 +5049,7 @@ var GROUPS = {
4680
5049
  tags: [
4681
5050
  {
4682
5051
  key: ConfigKey.resource_documentDownload,
5052
+ exportJsonKey: { resource: { type: "document-download", documentDownload: { url: "$" } } },
4683
5053
  description: "The downloadable document resource",
4684
5054
  chain: [
4685
5055
  {
@@ -4696,6 +5066,7 @@ var GROUPS = {
4696
5066
  tags: [
4697
5067
  {
4698
5068
  key: ConfigKey.resource_appLink,
5069
+ exportJsonKey: { resource: { type: "app-link", appLink: { url: "$" } } },
4699
5070
  description: "The link to the app resource",
4700
5071
  chain: [
4701
5072
  {
@@ -4712,6 +5083,7 @@ var GROUPS = {
4712
5083
  tags: [
4713
5084
  {
4714
5085
  key: ConfigKey.resource_websiteLink,
5086
+ exportJsonKey: { resource: { type: "website-link", websiteLink: { url: "$" } } },
4715
5087
  description: "The link to the website resource",
4716
5088
  chain: [
4717
5089
  {
@@ -4770,6 +5142,7 @@ var GROUPS = {
4770
5142
  {
4771
5143
  key: ConfigKey.resource_previewImage,
4772
5144
  jsonKey: "previewImage|resource(type=image, key=image)",
5145
+ exportJsonKey: { previewImage: { type: "image", image: { src: "$" } } },
4773
5146
  description: "The preview image resource",
4774
5147
  chain: [
4775
5148
  {
@@ -4787,6 +5160,7 @@ var GROUPS = {
4787
5160
  {
4788
5161
  key: ConfigKey.resource_previewVideo,
4789
5162
  jsonKey: "previewVideo|resource(type=video, key=video)",
5163
+ exportJsonKey: { previewVideo: { type: "video", video: { src: "$" } } },
4790
5164
  description: "The preview video resource",
4791
5165
  chain: [
4792
5166
  {
@@ -4851,20 +5225,48 @@ var ConfigHydrator = class {
4851
5225
  _side.name,
4852
5226
  _side.repeat ?? false,
4853
5227
  variantsOfSide,
4854
- _side.jsonKey
5228
+ _side.jsonKey,
5229
+ _side.exportJsonKey,
5230
+ Object.prototype.hasOwnProperty.call(_side, "exportJsonKey")
4855
5231
  );
4856
5232
  sides.push(sideConfig);
4857
5233
  }
4858
5234
  const cardSetConfig = new CardSetConfig(
4859
5235
  _cardSet,
4860
5236
  _cardSetConfig.jsonKey,
4861
- _cardSetConfig.sections,
5237
+ _cardSetConfig.exportJsonKey,
5238
+ Object.prototype.hasOwnProperty.call(_cardSetConfig, "exportJsonKey"),
5239
+ this.hydrateCardSections(_cardSetConfig.sections),
4862
5240
  sides
4863
5241
  );
4864
5242
  return cardSetConfig;
4865
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
+ }
4866
5260
  hydrateTagConfig(_tag) {
4867
- 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;
4868
5270
  const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4869
5271
  if (!configKey) throw new Error(`No tag key found for config key '${configKey}'`);
4870
5272
  const tag = Enum(Tag).fromValue(configKey);
@@ -4879,6 +5281,9 @@ var ConfigHydrator = class {
4879
5281
  maxCount: maxCount ?? MAX_COUNT_DEFAULT,
4880
5282
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4881
5283
  chain,
5284
+ jsonKey,
5285
+ exportJsonKey,
5286
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4882
5287
  deprecated
4883
5288
  });
4884
5289
  return {
@@ -4897,7 +5302,8 @@ var ConfigHydrator = class {
4897
5302
  format,
4898
5303
  values,
4899
5304
  defaultValue,
4900
- jsonKey
5305
+ jsonKey,
5306
+ exportJsonKey
4901
5307
  } = _tag;
4902
5308
  const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4903
5309
  if (!configKey) throw new Error(`No property key found for config key '${configKey}'`);
@@ -4913,6 +5319,8 @@ var ConfigHydrator = class {
4913
5319
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4914
5320
  chain,
4915
5321
  jsonKey,
5322
+ exportJsonKey,
5323
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4916
5324
  format,
4917
5325
  values,
4918
5326
  defaultValue,
@@ -4925,7 +5333,15 @@ var ConfigHydrator = class {
4925
5333
  };
4926
5334
  }
4927
5335
  hydrateResourceTagConfig(_tag) {
4928
- 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;
4929
5345
  const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4930
5346
  if (!configKey) throw new Error(`No resource key found for config key '${configKey}'`);
4931
5347
  const tag = _configKey.substring(1);
@@ -4940,6 +5356,8 @@ var ConfigHydrator = class {
4940
5356
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4941
5357
  chain,
4942
5358
  jsonKey,
5359
+ exportJsonKey,
5360
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4943
5361
  deprecated
4944
5362
  });
4945
5363
  return {
@@ -4971,14 +5389,25 @@ var ConfigHydrator = class {
4971
5389
  };
4972
5390
  }
4973
5391
  hydrateCardVariantConfig(_variant) {
4974
- 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;
4975
5401
  const tags2 = this.hydrateTagsConfig(_tags);
4976
5402
  const cardSetConfig = new CardVariantConfig(
4977
5403
  tags2.tags,
4978
5404
  bodyAllowed,
4979
5405
  bodyRequired,
4980
5406
  repeatCount,
4981
- jsonKey
5407
+ jsonKey,
5408
+ exportJsonKey,
5409
+ Object.prototype.hasOwnProperty.call(_variant, "exportJsonKey"),
5410
+ format
4982
5411
  );
4983
5412
  return cardSetConfig;
4984
5413
  }
@@ -5016,6 +5445,7 @@ var BITS = {
5016
5445
  description: "Common tags for quiz bits"
5017
5446
  },
5018
5447
  {
5448
+ exportJsonKey: { title: "$" },
5019
5449
  key: ConfigKey.tag_title,
5020
5450
  description: "The title of the flashcard quiz"
5021
5451
  },
@@ -5024,6 +5454,20 @@ var BITS = {
5024
5454
  description: "The flashcard set to use for the app flashcards",
5025
5455
  format: TagFormat.plainText,
5026
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
5027
5471
  }
5028
5472
  ],
5029
5473
  rootExampleType: ExampleType.string
@@ -5105,6 +5549,7 @@ var BITS = {
5105
5549
  description: "Article bit, used for articles / paragraphs",
5106
5550
  tags: [
5107
5551
  {
5552
+ exportJsonKey: { title: "$" },
5108
5553
  key: ConfigKey.tag_title,
5109
5554
  description: "The title of the article"
5110
5555
  }
@@ -5212,7 +5657,8 @@ var BITS = {
5212
5657
  key: ConfigKey.tag_title,
5213
5658
  description: "Title and subtitle of the catalog item",
5214
5659
  maxCount: 2,
5215
- jsonKey: "title|multi(count=2, key=subtitle)"
5660
+ jsonKey: "title|multi(count=2, key=subtitle)",
5661
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5216
5662
  },
5217
5663
  {
5218
5664
  key: ConfigKey.property_coverImage,
@@ -5222,6 +5668,7 @@ var BITS = {
5222
5668
  {
5223
5669
  key: ConfigKey.resource_coverImage,
5224
5670
  jsonKey: "coverImage|resource(type=image, key=image)",
5671
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
5225
5672
  description: "Cover image of the catalog item",
5226
5673
  chain: [
5227
5674
  {
@@ -5349,6 +5796,17 @@ var BITS = {
5349
5796
  key: ConfigKey.group_previewVideos,
5350
5797
  description: "Array of preview videos for the catalog item",
5351
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
5352
5810
  }
5353
5811
  ],
5354
5812
  rootExampleType: ExampleType.string
@@ -5362,7 +5820,8 @@ var BITS = {
5362
5820
  key: ConfigKey.tag_title,
5363
5821
  description: "Title and subtitle of the catalog item",
5364
5822
  maxCount: 2,
5365
- jsonKey: "title|multi(count=2, key=subtitle)"
5823
+ jsonKey: "title|multi(count=2, key=subtitle)",
5824
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5366
5825
  },
5367
5826
  {
5368
5827
  key: ConfigKey.property_coverImage,
@@ -5372,6 +5831,7 @@ var BITS = {
5372
5831
  {
5373
5832
  key: ConfigKey.resource_coverImage,
5374
5833
  jsonKey: "coverImage|resource(type=image, key=image)",
5834
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
5375
5835
  description: "Cover image of the catalog item",
5376
5836
  chain: [
5377
5837
  {
@@ -5499,6 +5959,17 @@ var BITS = {
5499
5959
  key: ConfigKey.group_previewVideos,
5500
5960
  description: "Array of preview videos for the catalog item",
5501
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
5502
5973
  }
5503
5974
  ],
5504
5975
  rootExampleType: ExampleType.string
@@ -5512,7 +5983,8 @@ var BITS = {
5512
5983
  key: ConfigKey.tag_title,
5513
5984
  description: "Title and subtitle of the catalog item",
5514
5985
  maxCount: 2,
5515
- jsonKey: "title|multi(count=2, key=subtitle)"
5986
+ jsonKey: "title|multi(count=2, key=subtitle)",
5987
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5516
5988
  },
5517
5989
  {
5518
5990
  key: ConfigKey.property_coverImage,
@@ -5638,6 +6110,17 @@ var BITS = {
5638
6110
  key: ConfigKey.group_previewVideos,
5639
6111
  description: "Array of preview videos for the catalog item",
5640
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
5641
6124
  }
5642
6125
  ],
5643
6126
  rootExampleType: ExampleType.string
@@ -5839,11 +6322,13 @@ var BITS = {
5839
6322
  description: "Bit alias, used to create an alias for a bit",
5840
6323
  tags: [
5841
6324
  {
6325
+ exportJsonKey: { reference: "$" },
5842
6326
  key: ConfigKey.tag_reference,
5843
6327
  format: TagFormat.plainText,
5844
6328
  description: "The reference to the bit that this alias points to"
5845
6329
  },
5846
6330
  {
6331
+ exportJsonKey: { anchor: "$" },
5847
6332
  key: ConfigKey.tag_anchor,
5848
6333
  format: TagFormat.plainText,
5849
6334
  description: "The anchor for the bit alias, used for linking"
@@ -6045,7 +6530,8 @@ var BITS = {
6045
6530
  description: "The title of the book cover",
6046
6531
  maxCount: 2,
6047
6532
  // title & subtitle
6048
- jsonKey: "title|multi(count=2, key=subtitle)"
6533
+ jsonKey: "title|multi(count=2, key=subtitle)",
6534
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
6049
6535
  },
6050
6536
  {
6051
6537
  key: ConfigKey.property_coverColor,
@@ -6189,6 +6675,7 @@ var BITS = {
6189
6675
  description: "Chapter bit, used to define chapters in books or articles",
6190
6676
  tags: [
6191
6677
  {
6678
+ exportJsonKey: { anchor: "$" },
6192
6679
  key: ConfigKey.tag_anchor,
6193
6680
  format: TagFormat.plainText,
6194
6681
  description: "The anchor for the chapter, used for linking"
@@ -6196,7 +6683,8 @@ var BITS = {
6196
6683
  {
6197
6684
  key: ConfigKey.tag_title,
6198
6685
  description: "The title of the chapter",
6199
- jsonKey: "title|setMulti(level)"
6686
+ jsonKey: "title|setMulti(level)",
6687
+ exportJsonKey: { title: "$", level: "$level" }
6200
6688
  },
6201
6689
  {
6202
6690
  key: ConfigKey.property_toc,
@@ -6249,6 +6737,7 @@ var BITS = {
6249
6737
  },
6250
6738
  {
6251
6739
  key: ConfigKey.property_isCaseSensitive,
6740
+ exportJsonKey: {},
6252
6741
  description: "If the cloze answers are case sensitive",
6253
6742
  format: TagFormat.boolean,
6254
6743
  defaultValue: "true"
@@ -6346,6 +6835,11 @@ var BITS = {
6346
6835
  description: "Formula bit, used for mathematical formulas in articles or documents",
6347
6836
  textFormatDefault: TextFormat.latex
6348
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
+ },
6349
6843
  [BitType.smartStandardFormula]: {
6350
6844
  since: "3.11.0",
6351
6845
  baseBitType: BitType.formula,
@@ -6698,6 +7192,7 @@ var BITS = {
6698
7192
  {
6699
7193
  key: ConfigKey.property_servings,
6700
7194
  jsonKey: "servings.servings",
7195
+ exportJsonKey: { servings: { servings: "$" } },
6701
7196
  description: "The number of servings for the ingredients",
6702
7197
  format: TagFormat.number,
6703
7198
  chain: [
@@ -6723,6 +7218,7 @@ var BITS = {
6723
7218
  format: TagFormat.boolean
6724
7219
  },
6725
7220
  {
7221
+ exportJsonKey: { hint: "$" },
6726
7222
  key: ConfigKey.tag_hint,
6727
7223
  description: "Hint for the ingredient, used to provide additional information",
6728
7224
  format: TagFormat.plainText
@@ -6900,6 +7396,17 @@ var BITS = {
6900
7396
  description: "Reference for the essay, used to link to external resources",
6901
7397
  format: TagFormat.plainText,
6902
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
6903
7410
  }
6904
7411
  ],
6905
7412
  rootExampleType: ExampleType.string
@@ -6920,8 +7427,20 @@ var BITS = {
6920
7427
  description: "Example bit, used to provide examples in articles or books",
6921
7428
  tags: [
6922
7429
  {
7430
+ exportJsonKey: { title: "$" },
6923
7431
  key: ConfigKey.tag_title,
6924
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
6925
7444
  }
6926
7445
  ],
6927
7446
  rootExampleType: ExampleType.string
@@ -7787,6 +8306,7 @@ var BITS = {
7787
8306
  // Image resource
7788
8307
  key: ConfigKey.group_resourceImage,
7789
8308
  description: "Resource image tags for logo grave images, used to attach images",
8309
+ exportJsonKey: { images: "$" },
7790
8310
  minCount: 1,
7791
8311
  maxCount: Count.infinity
7792
8312
  }
@@ -7950,15 +8470,27 @@ var BITS = {
7950
8470
  format: TagFormat.plainText,
7951
8471
  chain: [
7952
8472
  {
8473
+ exportJsonKey: { reference: "$" },
7953
8474
  key: ConfigKey.tag_reference,
7954
8475
  format: TagFormat.plainText,
7955
8476
  description: "Reference tag for the book, used to link to the book in the system",
7956
- 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
+ ]
7957
8488
  }
7958
8489
  ]
7959
8490
  },
7960
8491
  {
7961
8492
  /* Allow incorrectly chained reference tag */
8493
+ exportJsonKey: { reference: "$" },
7962
8494
  key: ConfigKey.tag_reference,
7963
8495
  format: TagFormat.plainText,
7964
8496
  description: "Reference tag for the book, used to link to the book in the system"
@@ -8005,18 +8537,41 @@ var BITS = {
8005
8537
  format: TagFormat.plainText,
8006
8538
  chain: [
8007
8539
  {
8540
+ exportJsonKey: { reference: "$" },
8008
8541
  key: ConfigKey.tag_reference,
8009
8542
  format: TagFormat.plainText,
8010
8543
  description: "Reference tag for the book, used to link to the book in the system",
8011
- 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
+ ]
8012
8555
  }
8013
8556
  ]
8014
8557
  },
8015
8558
  {
8016
8559
  /* Allow incorrectly chained reference tag */
8560
+ exportJsonKey: { reference: "$" },
8017
8561
  key: ConfigKey.tag_reference,
8018
8562
  format: TagFormat.plainText,
8019
- description: "Reference tag for the book, used to link to the book in the system"
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
+ ]
8020
8575
  },
8021
8576
  {
8022
8577
  key: ConfigKey.property_buttonCaption,
@@ -8045,10 +8600,21 @@ var BITS = {
8045
8600
  maxCount: Count.infinity,
8046
8601
  chain: [
8047
8602
  {
8603
+ exportJsonKey: { reference: "$" },
8048
8604
  key: ConfigKey.tag_reference,
8049
8605
  format: TagFormat.plainText,
8050
8606
  description: "Reference tag for the book, used to link to the book in the system",
8051
- 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
+ ]
8052
8618
  }
8053
8619
  ]
8054
8620
  },
@@ -8215,6 +8781,7 @@ var BITS = {
8215
8781
  tags: [
8216
8782
  {
8217
8783
  key: ConfigKey.resource_backgroundWallpaper,
8784
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
8218
8785
  description: "Background wallpaper for the image, used to set a background for the image",
8219
8786
  chain: [
8220
8787
  {
@@ -8397,6 +8964,7 @@ var BITS = {
8397
8964
  },
8398
8965
  {
8399
8966
  key: ConfigKey.resource_backgroundWallpaper,
8967
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
8400
8968
  description: "Background wallpaper for the image, used to set a background for the image",
8401
8969
  chain: [
8402
8970
  {
@@ -8549,6 +9117,7 @@ var BITS = {
8549
9117
  // Image resource
8550
9118
  key: ConfigKey.group_resourceImage,
8551
9119
  description: "Resource image tags for logo grave images, used to attach images",
9120
+ exportJsonKey: { logos: "$" },
8552
9121
  minCount: 1,
8553
9122
  maxCount: Count.infinity
8554
9123
  }
@@ -8566,6 +9135,7 @@ var BITS = {
8566
9135
  description: "Internal link bit, used to create links to other bits in articles or books",
8567
9136
  tags: [
8568
9137
  {
9138
+ exportJsonKey: { reference: "$" },
8569
9139
  key: ConfigKey.tag_reference,
8570
9140
  format: TagFormat.plainText,
8571
9141
  description: "Reference tag for the internal link, used to link to the target bit"
@@ -8584,6 +9154,7 @@ var BITS = {
8584
9154
  },
8585
9155
  {
8586
9156
  key: ConfigKey.property_reasonableNumOfChars,
9157
+ exportJsonKey: {},
8587
9158
  description: "Reasonable number of characters for the interview, used to limit input size",
8588
9159
  format: TagFormat.number
8589
9160
  }
@@ -8959,6 +9530,7 @@ var BITS = {
8959
9530
  },
8960
9531
  {
8961
9532
  key: ConfigKey.property_isCaseSensitive,
9533
+ exportJsonKey: {},
8962
9534
  description: "Case sensitivity for matching pairs, used to define if matches are case-sensitive",
8963
9535
  format: TagFormat.boolean,
8964
9536
  defaultValue: "true"
@@ -9011,6 +9583,7 @@ var BITS = {
9011
9583
  tags: [
9012
9584
  {
9013
9585
  key: ConfigKey.property_reasonableNumOfChars,
9586
+ exportJsonKey: {},
9014
9587
  description: "Reasonable number of characters for feedback, used to limit input size",
9015
9588
  format: TagFormat.number
9016
9589
  }
@@ -9152,6 +9725,7 @@ var BITS = {
9152
9725
  description: "Page bit, used to create pages in articles or books",
9153
9726
  tags: [
9154
9727
  {
9728
+ exportJsonKey: { title: "$" },
9155
9729
  key: ConfigKey.tag_title,
9156
9730
  description: "Title of the page, used to display the page title"
9157
9731
  },
@@ -9511,6 +10085,7 @@ var BITS = {
9511
10085
  {
9512
10086
  key: ConfigKey.resource_platformBackgroundImage,
9513
10087
  jsonKey: "platformBackgroundImage|resource(type=image, key=image)",
10088
+ exportJsonKey: { platformBackgroundImage: { type: "image", image: { src: "$" } } },
9514
10089
  description: "The platform section chat background image",
9515
10090
  chain: [
9516
10091
  {
@@ -9604,6 +10179,7 @@ var BITS = {
9604
10179
  description: "Review note bit, used to create review notes in articles or books",
9605
10180
  tags: [
9606
10181
  {
10182
+ exportJsonKey: { title: "$" },
9607
10183
  key: ConfigKey.tag_title,
9608
10184
  description: "Title of the review note, used to display the note title"
9609
10185
  },
@@ -9622,6 +10198,17 @@ var BITS = {
9622
10198
  key: ConfigKey.property_resolvedBy,
9623
10199
  description: "Resolved by for the review note, used to define who resolved the note",
9624
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
9625
10212
  }
9626
10213
  ],
9627
10214
  rootExampleType: ExampleType.string
@@ -9674,11 +10261,13 @@ var BITS = {
9674
10261
  tags: [
9675
10262
  // Not sure if these are actually valid here, but include them as they are in the test bit.
9676
10263
  {
10264
+ exportJsonKey: { anchor: "$" },
9677
10265
  key: ConfigKey.tag_anchor,
9678
10266
  format: TagFormat.plainText,
9679
10267
  description: "Anchor for the sample solution, used to link to the solution"
9680
10268
  },
9681
10269
  {
10270
+ exportJsonKey: { reference: "$" },
9682
10271
  key: ConfigKey.tag_reference,
9683
10272
  format: TagFormat.plainText,
9684
10273
  description: "Reference for the sample solution, used to link to the source of the solution"
@@ -9694,6 +10283,19 @@ var BITS = {
9694
10283
  {
9695
10284
  key: ConfigKey.group_quizCommon,
9696
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
9697
10299
  }
9698
10300
  ],
9699
10301
  cardSet: CardSetConfigKey.elements,
@@ -9801,6 +10403,7 @@ var BITS = {
9801
10403
  {
9802
10404
  key: ConfigKey.property_ratingLevelStart,
9803
10405
  jsonKey: "ratingLevelStart.level",
10406
+ exportJsonKey: { ratingLevelStart: { level: "$" } },
9804
10407
  description: "Start level for the rating survey, used to define the lowest rating",
9805
10408
  format: TagFormat.number,
9806
10409
  chain: [
@@ -9814,6 +10417,7 @@ var BITS = {
9814
10417
  {
9815
10418
  key: ConfigKey.property_ratingLevelEnd,
9816
10419
  jsonKey: "ratingLevelEnd.level",
10420
+ exportJsonKey: { ratingLevelEnd: { level: "$" } },
9817
10421
  description: "End level for the rating survey, used to define the highest rating",
9818
10422
  format: TagFormat.number,
9819
10423
  chain: [
@@ -9966,6 +10570,7 @@ var BITS = {
9966
10570
  },
9967
10571
  {
9968
10572
  key: ConfigKey.resource_backgroundWallpaper,
10573
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
9969
10574
  description: "Background wallpaper for the image, used to set a background for the image",
9970
10575
  chain: [
9971
10576
  {
@@ -10349,12 +10954,34 @@ var BITS = {
10349
10954
  format: TagFormat.plainText
10350
10955
  },
10351
10956
  {
10957
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
10352
10958
  key: ConfigKey.tag_true,
10353
- 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
10354
10961
  },
10355
10962
  {
10963
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
10356
10964
  key: ConfigKey.tag_false,
10357
- 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
10358
10985
  }
10359
10986
  ],
10360
10987
  rootExampleType: ExampleType.boolean
@@ -10937,6 +11564,8 @@ var Config = class {
10937
11564
  maxCount: 1,
10938
11565
  chain: tag.chain,
10939
11566
  jsonKey: tag.jsonKey,
11567
+ exportJsonKey: tag.exportJsonKey,
11568
+ hasExportJsonKey: tag.hasExportJsonKey,
10940
11569
  deprecated: tag.deprecated
10941
11570
  });
10942
11571
  finalResourceTags[k] = newTag;
@@ -11041,7 +11670,7 @@ var instance2 = new Config();
11041
11670
  // src/generated/package_info.ts
11042
11671
  var PACKAGE_INFO = {
11043
11672
  "name": "@gmb/bitmark-parser-generator",
11044
- "version": "5.22.0",
11673
+ "version": "5.23.0",
11045
11674
  "license": "ISC"};
11046
11675
  var Environment = {
11047
11676
  unknown: "",
@@ -11603,6 +12232,8 @@ var NodeType = {
11603
12232
  gmbExternalShopItems: "gmbExternalShopItems",
11604
12233
  groupTag: "groupTag",
11605
12234
  groupTagValue: "groupTagValue",
12235
+ gUri: "gUri",
12236
+ gUriValue: "gUriValue",
11606
12237
  handInAcceptFileType: "handInAcceptFileType",
11607
12238
  handInAcceptFileTypeValue: "handInAcceptFileTypeValue",
11608
12239
  handInInstruction: "handInInstruction",
@@ -11945,6 +12576,8 @@ var NodeType = {
11945
12576
  solution: "solution",
11946
12577
  solutions: "solutions",
11947
12578
  solutionsValue: "solutionsValue",
12579
+ sourceBB: "sourceBB",
12580
+ sourceBBValue: "sourceBBValue",
11948
12581
  sourceDocument: "sourceDocument",
11949
12582
  sourceDocumentValue: "sourceDocumentValue",
11950
12583
  sourceRL: "sourceRL",
@@ -24641,6 +25274,7 @@ var Builder = class extends BaseBuilder {
24641
25274
  isCommented: data.isCommented,
24642
25275
  // Properties
24643
25276
  id: this.toAstProperty(bitType, ConfigKey.property_id, data.id, options),
25277
+ gUri: this.toAstProperty(bitType, ConfigKey.property_gUri, data.gUri, options),
24644
25278
  internalComment: this.toAstProperty(
24645
25279
  bitType,
24646
25280
  ConfigKey.property_internalComment,
@@ -24852,6 +25486,7 @@ var Builder = class extends BaseBuilder {
24852
25486
  data.extractorInternal,
24853
25487
  options
24854
25488
  ),
25489
+ sourceBB: this.normaliseSourceBB(data.sourceBB),
24855
25490
  levelCEFRp: this.toAstProperty(
24856
25491
  bitType,
24857
25492
  ConfigKey.property_levelCEFRp,
@@ -25872,6 +26507,19 @@ var Builder = class extends BaseBuilder {
25872
26507
  nodes = Object.values(combinedNodes);
25873
26508
  return nodes.length > 0 ? nodes : void 0;
25874
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
+ }
25875
26523
  /**
25876
26524
  * Build groupTag node
25877
26525
  *
@@ -28178,6 +28826,23 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
28178
28826
  format: TagFormat.plainText
28179
28827
  });
28180
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
+ }
28181
28846
  // bitmarkAst -> bits -> bitsValue -> questions -> questionsValue -> additionalSolutions -> additionalSolutionsValue
28182
28847
  leaf_additionalSolutionsValue(node, route) {
28183
28848
  const parent = this.getParentNode(route, 2);
@@ -30291,6 +30956,16 @@ var JsonGenerator = class extends AstWalkerGenerator {
30291
30956
  enter_ratingLevelEnd(node, route) {
30292
30957
  return this.standardHandler(node, route, NodeType.bitsValue, { array: false });
30293
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
+ }
30294
30969
  // bitmarkAst -> bits -> bitsValue -> productId
30295
30970
  enter_productId(node, route) {
30296
30971
  const productIds = node.value;
@@ -34890,6 +35565,17 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
34890
35565
  format: TextFormat.bitmarkText,
34891
35566
  location: TextLocation.tag
34892
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;
34893
35579
  }
34894
35580
  }
34895
35581
  return instance3.unbreakscape(v2, {
@@ -34926,6 +35612,8 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
34926
35612
  minCount: 1,
34927
35613
  chain: void 0,
34928
35614
  jsonKey: void 0,
35615
+ exportJsonKey: void 0,
35616
+ hasExportJsonKey: false,
34929
35617
  format: TagFormat.bitmarkText,
34930
35618
  values: void 0,
34931
35619
  defaultValue: void 0,
@@ -34936,19 +35624,18 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
34936
35624
  }
34937
35625
 
34938
35626
  // src/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.ts
34939
- function referenceTagContentProcessor(_context, _contentDepth, _tagsConfig, content, target, isReferenceEnd) {
34940
- const { value } = content;
35627
+ function referenceTagContentProcessor(context, _contentDepth, tagsConfig, content, target) {
35628
+ const { value, chain } = content;
34941
35629
  const trimmedStringValue = stringUtils.trimmedString(value);
34942
- if (isReferenceEnd) {
34943
- target.referenceEnd = instance3.unbreakscape(trimmedStringValue, {
34944
- format: TextFormat.bitmarkText,
34945
- location: TextLocation.tag
34946
- });
34947
- } else {
34948
- target.reference = instance3.unbreakscape(trimmedStringValue, {
34949
- format: TextFormat.bitmarkText,
34950
- location: TextLocation.tag
34951
- });
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
+ }
34952
35639
  }
34953
35640
  }
34954
35641
  var resourceBuilder = new ResourceBuilder();
@@ -35629,7 +36316,6 @@ var BitmarkPegParserProcessor = class {
35629
36316
  result.markConfig = [];
35630
36317
  result.extraProperties = {};
35631
36318
  result.internalComments = [];
35632
- let seenReference = false;
35633
36319
  let inFooter = false;
35634
36320
  const bodyParts = [];
35635
36321
  let bodyTextPart = instance3.EMPTY_STRING;
@@ -35665,15 +36351,7 @@ var BitmarkPegParserProcessor = class {
35665
36351
  defaultTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
35666
36352
  break;
35667
36353
  case TypeKey.Reference:
35668
- referenceTagContentProcessor(
35669
- this.context,
35670
- contentDepth,
35671
- tagsConfig,
35672
- content,
35673
- result,
35674
- seenReference
35675
- );
35676
- seenReference = true;
36354
+ referenceTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
35677
36355
  break;
35678
36356
  case TypeKey.Title:
35679
36357
  titleTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
@@ -39919,52 +40597,28 @@ var ConfigBuilder = class {
39919
40597
  BitTagConfigKeyType.group,
39920
40598
  BitTagConfigKeyType.unknown
39921
40599
  ];
40600
+ const exportJsonKeyErrors = [];
39922
40601
  const resolveGroupReferences = (groupKey) => {
39923
40602
  if (squashedGroups.has(groupKey)) {
39924
40603
  const replacements = squashedGroups.get(groupKey);
39925
- return replacements.flatMap((r) => resolveGroupReferences(r));
40604
+ return replacements.flatMap(
40605
+ (r) => squashedGroups.has(r.key) ? resolveGroupReferences(r.key) : [r]
40606
+ );
39926
40607
  }
39927
- return [groupKey];
40608
+ return [{ key: groupKey }];
39928
40609
  };
39929
- const keyToJsonKey = (key, tagNameChain) => {
39930
- let jsonKey = key;
39931
- if (key === "%") {
39932
- jsonKey = "item";
39933
- } else if (key === "!") {
39934
- jsonKey = "instruction";
39935
- } else if (key === "?") {
39936
- jsonKey = "hint";
39937
- } else if (key === "#") {
39938
- jsonKey = "title";
39939
- } else if (key === "##") {
39940
- jsonKey = "subTitle";
39941
- } else if (key === "\u25BC") {
39942
- jsonKey = "anchor";
39943
- } else if (key === "\u25BA") {
39944
- jsonKey = "reference";
39945
- } else if (key === "$") {
39946
- jsonKey = "sampleSolution";
39947
- } else if (key === "+") {
39948
- jsonKey = "choices[]|set(isCorrect=true)";
39949
- } else if (key === "-") {
39950
- jsonKey = "choices[]|set(isCorrect=false)";
39951
- } else if (key === "_") {
39952
- jsonKey = "solutions[]";
39953
- } else if (key === "=") {
39954
- jsonKey = "solution";
39955
- } else if (key.startsWith("@")) {
39956
- jsonKey = key.substring(1);
39957
- } else if (key.startsWith("&")) {
39958
- jsonKey = key.substring(1);
39959
- }
39960
- const thisChain = [...tagNameChain, jsonKey];
39961
- jsonKey = thisChain.join(".");
39962
- return jsonKey;
40610
+ const bareKeyForProperty = (key) => {
40611
+ if (key.startsWith("@") || key.startsWith("&")) return key.substring(1);
40612
+ return void 0;
39963
40613
  };
39964
- const processTagEntries = (tag, tagNameChain) => {
40614
+ const legacyIsTrivialDefault = (tag) => {
40615
+ const bare = bareKeyForProperty(tag.key);
40616
+ if (bare == null) return false;
40617
+ return tag.jsonKey == null || tag.jsonKey === bare;
40618
+ };
40619
+ const processTagEntries = (tag, pathStack) => {
39965
40620
  const tags2 = [];
39966
40621
  let tagName = tag.key;
39967
- const jsonKey = tag.jsonKey ?? keyToJsonKey(tagName, tagNameChain);
39968
40622
  const tagType = typeFromConfigKey(tag.key);
39969
40623
  let format = "";
39970
40624
  let chain = void 0;
@@ -39997,32 +40651,57 @@ var ConfigBuilder = class {
39997
40651
  } else if (tagType === BitTagConfigKeyType.group) {
39998
40652
  let k = tag.key;
39999
40653
  if (k.startsWith("group_")) k = k.substring(6);
40000
- k = /*'_' +*/
40001
- stringUtils.camelToKebab(k);
40654
+ k = stringUtils.camelToKebab(k);
40002
40655
  const resolvedGroups = resolveGroupReferences(k);
40003
- 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;
40004
40669
  tags2.push({
40005
40670
  type: "group",
40006
- key: groupKey,
40007
- ...tag.jsonKey ? { jsonKey: tag.jsonKey } : {},
40008
- ...tag.minCount != null ? { min: tag.minCount } : {},
40009
- ...tag.maxCount != null ? { max: tag.maxCount } : {},
40010
- ...tag.description ? { description: tag.description } : {}
40671
+ key: ref.key,
40672
+ ...hasExportChosen ? { jsonKey: exportJsonKeyChosen } : {},
40673
+ ...min != null ? { min } : {},
40674
+ ...max != null ? { max } : {},
40675
+ ...description ? { description } : {}
40011
40676
  });
40012
40677
  }
40013
40678
  return tags2;
40014
40679
  }
40015
40680
  if (Array.isArray(tag.chain) && tag.chain.length > 0) {
40016
40681
  const chainTags = [];
40017
- for (const [_tagKey, chainTag] of tag.chain.entries()) {
40018
- 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));
40019
40685
  }
40020
40686
  chain = chainTags;
40021
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
+ }
40022
40701
  const t = {
40023
40702
  type: "tag",
40024
40703
  key: tagName,
40025
- jsonKey,
40704
+ ...exportJsonKeyField,
40026
40705
  format,
40027
40706
  default: tag.defaultValue ?? null,
40028
40707
  ...tag.nullable ? { nullable: true } : {},
@@ -40030,19 +40709,30 @@ var ConfigBuilder = class {
40030
40709
  max: tag.maxCount == null ? 1 : tag.maxCount,
40031
40710
  description: tag.description ?? "",
40032
40711
  tags: chain
40033
- // raw: {
40034
- // ...tag,
40035
- // },
40036
40712
  };
40037
40713
  tags2.push(t);
40038
40714
  return tags2;
40039
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
+ };
40040
40727
  const serializeCardSet = (cardSetKey) => {
40728
+ const variantBodyFormat = (variant) => variant.format ?? TextFormat.bitmarkText;
40041
40729
  const cardSetConfig = CARDSETS[cardSetKey];
40042
40730
  if (!cardSetConfig) return void 0;
40043
40731
  const normalizedKey = normalizeCardKey(cardSetKey);
40044
- const sides = cardSetConfig.sides.map((side) => {
40045
- 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}]`;
40046
40736
  const variantTags = [];
40047
40737
  const variantTagEntries = Object.entries(variant.tags ?? []).sort((a, b) => {
40048
40738
  const tagA = a[1];
@@ -40053,10 +40743,11 @@ var ConfigBuilder = class {
40053
40743
  return typeOrder;
40054
40744
  });
40055
40745
  for (const [, variantTag] of variantTagEntries) {
40056
- variantTags.push(...processTagEntries(variantTag, []));
40746
+ variantTags.push(...processTagEntries(variantTag, [variantPath]));
40057
40747
  }
40058
40748
  return {
40059
- ...variant.jsonKey !== void 0 ? { jsonKey: variant.jsonKey } : {},
40749
+ ...cardJsonKeyField(variant, "jsonKey", "exportJsonKey", variantPath),
40750
+ format: variantBodyFormat(variant),
40060
40751
  tags: variantTags,
40061
40752
  repeatCount: variant.repeatCount ?? 1,
40062
40753
  ...variant.bodyRequired ? { bodyRequired: true } : {},
@@ -40066,41 +40757,41 @@ var ConfigBuilder = class {
40066
40757
  return {
40067
40758
  name: side.name,
40068
40759
  ...side.repeat ? { repeat: side.repeat } : {},
40069
- ...side.jsonKey != null ? { jsonKey: side.jsonKey } : {},
40760
+ ...cardJsonKeyField(side, "jsonKey", "exportJsonKey", sidePath),
40070
40761
  variants
40071
40762
  };
40072
40763
  });
40073
40764
  if (cardSetConfig.sections) {
40074
40765
  const cards = Object.entries(cardSetConfig.sections).map(([sectionName, section]) => {
40075
- let cardSides = section.sideJsonKey ? sides.map((s) => ({ ...s, jsonKey: section.sideJsonKey })) : sides;
40076
- if (normalizedKey === "table-extended" && sectionName !== "table-header") {
40077
- cardSides = JSON.parse(JSON.stringify(cardSides));
40078
- for (const side of cardSides) {
40079
- for (const variant of side.variants) {
40080
- for (const tag of variant.tags) {
40081
- if (tag.type === "tag" && tag.key === "#" && tag.jsonKey === ".") {
40082
- tag.jsonKey = "^table.header.rows.cells[{s}].content";
40083
- }
40084
- }
40085
- }
40086
- }
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 }));
40087
40777
  }
40088
40778
  return {
40089
40779
  name: sectionName,
40090
40780
  ...section.isDefault ? { isDefault: true } : {},
40091
- jsonKey: section.jsonKey,
40781
+ ...cardJsonKeyField(section, "jsonKey", "exportJsonKey", sectionPath),
40092
40782
  sides: cardSides
40093
40783
  };
40094
40784
  });
40095
40785
  return { name: normalizedKey, cards };
40096
40786
  }
40787
+ const cardSetPath = `cardSets.${normalizedKey} / cards.default`;
40097
40788
  return {
40098
40789
  name: normalizedKey,
40099
40790
  cards: [
40100
40791
  {
40101
40792
  name: "default",
40102
40793
  isDefault: true,
40103
- jsonKey: cardSetConfig.jsonKey,
40794
+ ...cardJsonKeyField(cardSetConfig, "jsonKey", "exportJsonKey", cardSetPath),
40104
40795
  sides
40105
40796
  }
40106
40797
  ]
@@ -40127,10 +40818,20 @@ var ConfigBuilder = class {
40127
40818
  if (allAreGroups && processedTags.length > 0) {
40128
40819
  const replacements = [];
40129
40820
  if (b.baseBitType) {
40130
- replacements.push(`group-${b.baseBitType}`);
40821
+ replacements.push({ key: `group-${b.baseBitType}` });
40131
40822
  }
40132
40823
  for (const t of processedTags) {
40133
- 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);
40134
40835
  }
40135
40836
  squashedGroups.set(groupKey, replacements);
40136
40837
  }
@@ -40149,19 +40850,27 @@ var ConfigBuilder = class {
40149
40850
  const isInheritedFrom = bitGroupConfigKeys.has(b.bitType);
40150
40851
  if (isInheritedFrom) {
40151
40852
  const resolvedGroups = resolveGroupReferences(`group-${b.bitType}`);
40152
- for (const groupKey of resolvedGroups) {
40853
+ for (const ref of resolvedGroups) {
40153
40854
  tags2.push({
40154
40855
  type: "group",
40155
- 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 } : {}
40156
40861
  });
40157
40862
  }
40158
40863
  } else {
40159
40864
  if (b.baseBitType) {
40160
40865
  const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
40161
- for (const groupKey of resolvedGroups) {
40866
+ for (const ref of resolvedGroups) {
40162
40867
  tags2.push({
40163
40868
  type: "group",
40164
- 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 } : {}
40165
40874
  });
40166
40875
  }
40167
40876
  }
@@ -40281,10 +40990,14 @@ var ConfigBuilder = class {
40281
40990
  const tags2 = [];
40282
40991
  if (b.baseBitType) {
40283
40992
  const resolvedGroups = resolveGroupReferences(`group-${b.baseBitType}`);
40284
- for (const gk of resolvedGroups) {
40993
+ for (const ref of resolvedGroups) {
40285
40994
  tags2.push({
40286
40995
  type: "group",
40287
- 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 } : {}
40288
41001
  });
40289
41002
  }
40290
41003
  }
@@ -40319,6 +41032,13 @@ var ConfigBuilder = class {
40319
41032
  };
40320
41033
  writeBitsAsGroupConfigs(bitGroupConfigs);
40321
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
+ }
40322
41042
  Promise.all(fileWrites).then(() => {
40323
41043
  const validationErrors = this.validateConfigTree(outputFolder);
40324
41044
  if (validationErrors.length > 0) {