@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.
@@ -278,6 +278,7 @@ var BitType2 = {
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",
@@ -702,8 +703,10 @@ var TagFormat = {
702
703
  // If the value is treated as a boolean
703
704
  invertedBoolean: "invertedBoolean",
704
705
  // If the value is treated as a boolean with the value inverted (e.g. isLongAnswer ==> isShortAnswer = false)
705
- enumeration: "enumeration"
706
+ enumeration: "enumeration",
706
707
  // If the value is treated as an enumeration (the value is a string that must be one of a predefined set of values)
708
+ coordinates: "coordinates"
709
+ // Comma-separated list of 4 numbers (e.g. bounding-box x, y, x1, y1)
707
710
  };
708
711
 
709
712
  // src/model/enum/TextFormat.ts
@@ -788,7 +791,11 @@ var AbstractTagConfig = class {
788
791
  // Default: 0
789
792
  __publicField(this, "chain");
790
793
  __publicField(this, "jsonKey");
791
- // If the json key is different from the tag
794
+ // Legacy string-form jsonKey
795
+ __publicField(this, "exportJsonKey");
796
+ // New JSON-pattern jsonKey (export-only)
797
+ __publicField(this, "hasExportJsonKey");
798
+ // True iff exportJsonKey was explicitly set
792
799
  __publicField(this, "deprecated");
793
800
  this.type = params.type;
794
801
  this.configKey = params.configKey;
@@ -797,6 +804,8 @@ var AbstractTagConfig = class {
797
804
  this.minCount = params.minCount;
798
805
  this.chain = params.chain;
799
806
  this.jsonKey = params.jsonKey;
807
+ this.exportJsonKey = params.exportJsonKey;
808
+ this.hasExportJsonKey = params.hasExportJsonKey;
800
809
  this.deprecated = params.deprecated;
801
810
  }
802
811
  };
@@ -806,7 +815,6 @@ var MarkupTagConfig = class extends AbstractTagConfig {
806
815
  constructor(params) {
807
816
  super({
808
817
  type: BitTagConfigKeyType.tag,
809
- jsonKey: void 0,
810
818
  ...params
811
819
  });
812
820
  __publicField(this, "type", BitTagConfigKeyType.tag);
@@ -918,8 +926,8 @@ var ResourceTagConfig = class extends AbstractTagConfig {
918
926
 
919
927
  // src/model/config/CardVariantConfig.ts
920
928
  var CardVariantConfig = class {
921
- // JSON path for body text
922
- constructor(tags2, bodyAllowed, bodyRequired, repeatCount, jsonKey) {
929
+ // Body text format. Default: bitmark++
930
+ constructor(tags2, bodyAllowed, bodyRequired, repeatCount, jsonKey, exportJsonKey, hasExportJsonKey = false, format) {
923
931
  __publicField(this, "tags");
924
932
  __publicField(this, "bodyAllowed");
925
933
  // Default: true
@@ -929,11 +937,19 @@ var CardVariantConfig = class {
929
937
  // Default: 1
930
938
  // JSON mapping fields
931
939
  __publicField(this, "jsonKey");
940
+ // JSON path for body text (legacy)
941
+ __publicField(this, "exportJsonKey");
942
+ // New JSON-pattern jsonKey
943
+ __publicField(this, "hasExportJsonKey");
944
+ __publicField(this, "format");
932
945
  this.tags = tags2;
933
946
  this.bodyAllowed = bodyAllowed == null ? true : bodyAllowed;
934
947
  this.bodyRequired = bodyRequired;
935
948
  this.repeatCount = repeatCount;
936
949
  this.jsonKey = jsonKey;
950
+ this.exportJsonKey = exportJsonKey;
951
+ this.hasExportJsonKey = hasExportJsonKey;
952
+ this.format = format;
937
953
  }
938
954
  toString(options) {
939
955
  const opts = Object.assign({}, options);
@@ -957,14 +973,18 @@ ${tag.toString(opts)}`;
957
973
 
958
974
  // src/model/config/CardSideConfig.ts
959
975
  var CardSideConfig = class {
960
- constructor(name, repeat, variants, jsonKey) {
976
+ constructor(name, repeat, variants, jsonKey, exportJsonKey, hasExportJsonKey = false) {
961
977
  __publicField(this, "name");
962
978
  __publicField(this, "repeat");
963
979
  __publicField(this, "jsonKey");
980
+ __publicField(this, "exportJsonKey");
981
+ __publicField(this, "hasExportJsonKey");
964
982
  __publicField(this, "variants");
965
983
  this.name = name;
966
984
  this.repeat = repeat;
967
985
  this.jsonKey = jsonKey;
986
+ this.exportJsonKey = exportJsonKey;
987
+ this.hasExportJsonKey = hasExportJsonKey;
968
988
  this.variants = variants;
969
989
  }
970
990
  toString(options) {
@@ -986,13 +1006,17 @@ var CardSideConfig = class {
986
1006
 
987
1007
  // src/model/config/CardSetConfig.ts
988
1008
  var CardSetConfig = class {
989
- constructor(configKey, jsonKey, sections, sides) {
1009
+ constructor(configKey, jsonKey, exportJsonKey, hasExportJsonKey, sections, sides) {
990
1010
  __publicField(this, "configKey");
991
1011
  __publicField(this, "jsonKey");
1012
+ __publicField(this, "exportJsonKey");
1013
+ __publicField(this, "hasExportJsonKey");
992
1014
  __publicField(this, "sections");
993
1015
  __publicField(this, "sides");
994
1016
  this.configKey = configKey;
995
1017
  this.jsonKey = jsonKey;
1018
+ this.exportJsonKey = exportJsonKey;
1019
+ this.hasExportJsonKey = hasExportJsonKey;
996
1020
  this.sections = sections;
997
1021
  this.sides = sides;
998
1022
  }
@@ -1287,6 +1311,7 @@ var propertyKeys = {
1287
1311
  property_formula: "@formula",
1288
1312
  property_fullName: "@fullName",
1289
1313
  property_groupTag: "@groupTag",
1314
+ property_gUri: "@gUri",
1290
1315
  property_handInAcceptFileType: "@handInAcceptFileType",
1291
1316
  property_handInInstruction: "@handInInstruction",
1292
1317
  property_handInRequirement: "@handInRequirement",
@@ -1422,6 +1447,7 @@ var propertyKeys = {
1422
1447
  property_siteName: "@siteName",
1423
1448
  property_size: "@size",
1424
1449
  property_slug: "@slug",
1450
+ property_sourceBB: "@sourceBB",
1425
1451
  property_sourceDocument: "@sourceDocument",
1426
1452
  property_sourceRL: "@sourceRL",
1427
1453
  property_spaceId: "@spaceId",
@@ -2175,25 +2201,29 @@ var CARDSETS = {
2175
2201
  //
2176
2202
  [CardSetConfigKey.flashcard]: {
2177
2203
  jsonKey: "cards",
2204
+ exportJsonKey: { cards: "$" },
2178
2205
  sides: [
2179
2206
  {
2180
2207
  name: "question",
2181
2208
  variants: [
2182
2209
  {
2183
2210
  jsonKey: "question.text",
2211
+ exportJsonKey: { question: { text: "$" } },
2184
2212
  tags: [
2185
2213
  {
2186
2214
  key: ConfigKey.group_standardTags,
2187
2215
  description: "Standard tags for the flashcard."
2188
2216
  },
2189
2217
  {
2218
+ exportJsonKey: { title: "$" },
2190
2219
  key: ConfigKey.tag_title,
2191
2220
  description: "Title of the flashcard."
2192
2221
  },
2193
2222
  {
2194
2223
  key: ConfigKey.group_resourceIcon,
2195
2224
  description: "Icon resource for the flashcard.",
2196
- jsonKey: "question.icon|resource(type=image, key=image)"
2225
+ jsonKey: "question.icon|resource(type=image, key=image)",
2226
+ exportJsonKey: { question: { icon: { type: "image", image: { src: "$" } } } }
2197
2227
  }
2198
2228
  ]
2199
2229
  }
@@ -2204,37 +2234,45 @@ var CARDSETS = {
2204
2234
  variants: [
2205
2235
  {
2206
2236
  jsonKey: "answer.text",
2237
+ exportJsonKey: { answer: { text: "$" } },
2207
2238
  tags: [
2208
2239
  {
2209
2240
  key: ConfigKey.group_standardTags,
2210
2241
  description: "Standard tags for the flashcard."
2211
2242
  },
2212
2243
  {
2244
+ exportJsonKey: { title: "$" },
2213
2245
  key: ConfigKey.tag_title,
2214
2246
  description: "Title of the flashcard."
2215
2247
  },
2216
2248
  {
2217
2249
  key: ConfigKey.group_resourceIcon,
2218
2250
  description: "Icon resource for the flashcard.",
2219
- jsonKey: "answer.icon|resource(type=image, key=image)"
2251
+ jsonKey: "answer.icon|resource(type=image, key=image)",
2252
+ exportJsonKey: { answer: { icon: { type: "image", image: { src: "$" } } } }
2220
2253
  }
2221
2254
  ]
2222
2255
  },
2223
2256
  {
2224
2257
  jsonKey: "alternativeAnswers[].text",
2258
+ exportJsonKey: { alternativeAnswers: [{ text: "$" }] },
2225
2259
  tags: [
2226
2260
  {
2227
2261
  key: ConfigKey.group_standardTags,
2228
2262
  description: "Standard tags for the flashcard."
2229
2263
  },
2230
2264
  {
2265
+ exportJsonKey: { title: "$" },
2231
2266
  key: ConfigKey.tag_title,
2232
2267
  description: "Title of the flashcard."
2233
2268
  },
2234
2269
  {
2235
2270
  key: ConfigKey.group_resourceIcon,
2236
2271
  description: "Icon resource for the flashcard.",
2237
- jsonKey: "alternativeAnswers[].icon|resource(type=image, key=image)"
2272
+ jsonKey: "alternativeAnswers[].icon|resource(type=image, key=image)",
2273
+ exportJsonKey: {
2274
+ alternativeAnswers: [{ icon: { type: "image", image: { src: "$" } } }]
2275
+ }
2238
2276
  }
2239
2277
  ],
2240
2278
  repeatCount: Count.infinity
@@ -2248,12 +2286,14 @@ var CARDSETS = {
2248
2286
  //
2249
2287
  [CardSetConfigKey.definitionList]: {
2250
2288
  jsonKey: "definitions",
2289
+ exportJsonKey: { definitions: "$" },
2251
2290
  sides: [
2252
2291
  {
2253
2292
  name: "term",
2254
2293
  variants: [
2255
2294
  {
2256
2295
  jsonKey: "term.text",
2296
+ exportJsonKey: { term: { text: "$" } },
2257
2297
  tags: [
2258
2298
  {
2259
2299
  key: ConfigKey.group_standardTags,
@@ -2263,13 +2303,15 @@ var CARDSETS = {
2263
2303
  key: ConfigKey.tag_title,
2264
2304
  description: "Title of the definition.",
2265
2305
  format: TagFormat.plainText,
2266
- jsonKey: "^heading.forKeys"
2306
+ jsonKey: "^heading.forKeys",
2307
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2267
2308
  },
2268
2309
  {
2269
2310
  key: ConfigKey.group_resourceIcon,
2270
2311
  description: "Icon resource for the definition.",
2271
2312
  format: TagFormat.plainText,
2272
- jsonKey: "term.icon|resource(type=image, key=image)"
2313
+ jsonKey: "term.icon|resource(type=image, key=image)",
2314
+ exportJsonKey: { term: { icon: { type: "image", image: { src: "$" } } } }
2273
2315
  }
2274
2316
  ]
2275
2317
  }
@@ -2280,6 +2322,7 @@ var CARDSETS = {
2280
2322
  variants: [
2281
2323
  {
2282
2324
  jsonKey: "definition.text",
2325
+ exportJsonKey: { definition: { text: "$" } },
2283
2326
  tags: [
2284
2327
  {
2285
2328
  key: ConfigKey.group_standardTags,
@@ -2289,30 +2332,37 @@ var CARDSETS = {
2289
2332
  key: ConfigKey.tag_title,
2290
2333
  description: "Title of the definition.",
2291
2334
  format: TagFormat.plainText,
2292
- jsonKey: "^heading.forValues"
2335
+ jsonKey: "^heading.forValues",
2336
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2293
2337
  },
2294
2338
  {
2295
2339
  key: ConfigKey.group_resourceIcon,
2296
2340
  description: "Icon resource for the definition.",
2297
- jsonKey: "definition.icon|resource(type=image, key=image)"
2341
+ jsonKey: "definition.icon|resource(type=image, key=image)",
2342
+ exportJsonKey: { definition: { icon: { type: "image", image: { src: "$" } } } }
2298
2343
  }
2299
2344
  ]
2300
2345
  },
2301
2346
  {
2302
2347
  jsonKey: "alternativeDefinitions[].text",
2348
+ exportJsonKey: { alternativeDefinitions: [{ text: "$" }] },
2303
2349
  tags: [
2304
2350
  {
2305
2351
  key: ConfigKey.group_standardTags,
2306
2352
  description: "Standard tags for the definition."
2307
2353
  },
2308
2354
  {
2355
+ exportJsonKey: { title: "$" },
2309
2356
  key: ConfigKey.tag_title,
2310
2357
  description: "Title of the definition."
2311
2358
  },
2312
2359
  {
2313
2360
  key: ConfigKey.group_resourceIcon,
2314
2361
  description: "Icon resource for the definition.",
2315
- jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)"
2362
+ jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)",
2363
+ exportJsonKey: {
2364
+ alternativeDefinitions: [{ icon: { type: "image", image: { src: "$" } } }]
2365
+ }
2316
2366
  }
2317
2367
  ],
2318
2368
  repeatCount: Count.infinity
@@ -2326,12 +2376,14 @@ var CARDSETS = {
2326
2376
  //
2327
2377
  [CardSetConfigKey.matchPairs]: {
2328
2378
  jsonKey: "pairs",
2379
+ exportJsonKey: { pairs: "$" },
2329
2380
  sides: [
2330
2381
  {
2331
2382
  name: "key",
2332
2383
  variants: [
2333
2384
  {
2334
2385
  jsonKey: "key",
2386
+ exportJsonKey: { key: "$" },
2335
2387
  tags: [
2336
2388
  {
2337
2389
  key: ConfigKey.group_standardTags,
@@ -2341,22 +2393,29 @@ var CARDSETS = {
2341
2393
  key: ConfigKey.tag_title,
2342
2394
  description: "Title of the match pair.",
2343
2395
  format: TagFormat.plainText,
2344
- jsonKey: "^heading.forKeys"
2396
+ jsonKey: "^heading.forKeys",
2397
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2345
2398
  },
2346
2399
  {
2347
2400
  key: ConfigKey.property_isCaseSensitive,
2401
+ exportJsonKey: [
2402
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2403
+ { isCaseSensitive: "$" }
2404
+ ],
2348
2405
  description: "Property to indicate if the match is case sensitive.",
2349
2406
  format: TagFormat.boolean
2350
2407
  },
2351
2408
  {
2352
2409
  key: ConfigKey.resource_audio,
2353
2410
  description: "Audio resource for the match pair.",
2354
- jsonKey: "keyAudio"
2411
+ jsonKey: "keyAudio",
2412
+ exportJsonKey: { keyAudio: "$" }
2355
2413
  },
2356
2414
  {
2357
2415
  key: ConfigKey.resource_image,
2358
2416
  description: "Image resource for the match pair.",
2359
- jsonKey: "keyImage"
2417
+ jsonKey: "keyImage",
2418
+ exportJsonKey: { keyImage: "$" }
2360
2419
  }
2361
2420
  ]
2362
2421
  }
@@ -2368,6 +2427,7 @@ var CARDSETS = {
2368
2427
  variants: [
2369
2428
  {
2370
2429
  jsonKey: "values[]",
2430
+ exportJsonKey: { values: ["$"] },
2371
2431
  tags: [
2372
2432
  {
2373
2433
  key: ConfigKey.group_standardTags,
@@ -2377,10 +2437,15 @@ var CARDSETS = {
2377
2437
  key: ConfigKey.tag_title,
2378
2438
  description: "Title of the match pair.",
2379
2439
  format: TagFormat.plainText,
2380
- jsonKey: "^heading.forValues"
2440
+ jsonKey: "^heading.forValues",
2441
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2381
2442
  },
2382
2443
  {
2383
2444
  key: ConfigKey.property_isCaseSensitive,
2445
+ exportJsonKey: [
2446
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2447
+ { isCaseSensitive: "$" }
2448
+ ],
2384
2449
  description: "Property to indicate if the match is case sensitive.",
2385
2450
  format: TagFormat.boolean
2386
2451
  }
@@ -2396,12 +2461,14 @@ var CARDSETS = {
2396
2461
  //
2397
2462
  [CardSetConfigKey.matchAudioPairs]: {
2398
2463
  jsonKey: "pairs",
2464
+ exportJsonKey: { pairs: "$" },
2399
2465
  sides: [
2400
2466
  {
2401
2467
  name: "key",
2402
2468
  variants: [
2403
2469
  {
2404
2470
  jsonKey: "key",
2471
+ exportJsonKey: { key: "$" },
2405
2472
  tags: [
2406
2473
  {
2407
2474
  key: ConfigKey.group_standardTags,
@@ -2411,12 +2478,14 @@ var CARDSETS = {
2411
2478
  key: ConfigKey.tag_title,
2412
2479
  description: "Title of the audio match pair.",
2413
2480
  format: TagFormat.plainText,
2414
- jsonKey: "^heading.forKeys"
2481
+ jsonKey: "^heading.forKeys",
2482
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2415
2483
  },
2416
2484
  {
2417
2485
  key: ConfigKey.resource_audio,
2418
2486
  description: "Audio resource for the match pair.",
2419
- jsonKey: "keyAudio"
2487
+ jsonKey: "keyAudio",
2488
+ exportJsonKey: { keyAudio: "$" }
2420
2489
  }
2421
2490
  ]
2422
2491
  }
@@ -2428,6 +2497,7 @@ var CARDSETS = {
2428
2497
  variants: [
2429
2498
  {
2430
2499
  jsonKey: "values[]",
2500
+ exportJsonKey: { values: ["$"] },
2431
2501
  tags: [
2432
2502
  {
2433
2503
  key: ConfigKey.group_standardTags,
@@ -2437,7 +2507,8 @@ var CARDSETS = {
2437
2507
  key: ConfigKey.tag_title,
2438
2508
  description: "Title of the audio match pair.",
2439
2509
  format: TagFormat.plainText,
2440
- jsonKey: "^heading.forValues"
2510
+ jsonKey: "^heading.forValues",
2511
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2441
2512
  },
2442
2513
  {
2443
2514
  key: ConfigKey.resource_audio,
@@ -2455,12 +2526,14 @@ var CARDSETS = {
2455
2526
  //
2456
2527
  [CardSetConfigKey.matchImagePairs]: {
2457
2528
  jsonKey: "pairs",
2529
+ exportJsonKey: { pairs: "$" },
2458
2530
  sides: [
2459
2531
  {
2460
2532
  name: "key",
2461
2533
  variants: [
2462
2534
  {
2463
2535
  jsonKey: "key",
2536
+ exportJsonKey: { key: "$" },
2464
2537
  tags: [
2465
2538
  {
2466
2539
  key: ConfigKey.group_standardTags,
@@ -2470,12 +2543,14 @@ var CARDSETS = {
2470
2543
  key: ConfigKey.tag_title,
2471
2544
  description: "Title of the image match pair.",
2472
2545
  format: TagFormat.plainText,
2473
- jsonKey: "^heading.forKeys"
2546
+ jsonKey: "^heading.forKeys",
2547
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2474
2548
  },
2475
2549
  {
2476
2550
  key: ConfigKey.resource_image,
2477
2551
  description: "Image resource for the match pair.",
2478
- jsonKey: "keyImage"
2552
+ jsonKey: "keyImage",
2553
+ exportJsonKey: { keyImage: "$" }
2479
2554
  }
2480
2555
  ]
2481
2556
  }
@@ -2487,6 +2562,7 @@ var CARDSETS = {
2487
2562
  variants: [
2488
2563
  {
2489
2564
  jsonKey: "values[]",
2565
+ exportJsonKey: { values: ["$"] },
2490
2566
  tags: [
2491
2567
  {
2492
2568
  key: ConfigKey.group_standardTags,
@@ -2496,7 +2572,8 @@ var CARDSETS = {
2496
2572
  key: ConfigKey.tag_title,
2497
2573
  description: "Title of the image match pair.",
2498
2574
  format: TagFormat.plainText,
2499
- jsonKey: "^heading.forValues"
2575
+ jsonKey: "^heading.forValues",
2576
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2500
2577
  },
2501
2578
  {
2502
2579
  key: ConfigKey.resource_image,
@@ -2514,12 +2591,14 @@ var CARDSETS = {
2514
2591
  //
2515
2592
  [CardSetConfigKey.matchMatrix]: {
2516
2593
  jsonKey: "matrix",
2594
+ exportJsonKey: { matrix: "$" },
2517
2595
  sides: [
2518
2596
  {
2519
2597
  name: "key",
2520
2598
  variants: [
2521
2599
  {
2522
2600
  jsonKey: "key",
2601
+ exportJsonKey: { key: "$" },
2523
2602
  tags: [
2524
2603
  {
2525
2604
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2527,6 +2606,11 @@ var CARDSETS = {
2527
2606
  },
2528
2607
  {
2529
2608
  key: ConfigKey.property_example,
2609
+ exportJsonKey: [
2610
+ { "@keyonly": { isExample: true, "@bit": { isExample: true } } },
2611
+ { "@absent": { isExample: true, "@bit": { isExample: true } } },
2612
+ { isExample: true, example: "$", "@bit": { isExample: true } }
2613
+ ],
2530
2614
  description: "Example text for the match matrix.",
2531
2615
  format: TagFormat.plainText
2532
2616
  },
@@ -2534,10 +2618,15 @@ var CARDSETS = {
2534
2618
  key: ConfigKey.tag_title,
2535
2619
  description: "Title of the match matrix.",
2536
2620
  format: TagFormat.plainText,
2537
- jsonKey: "^heading.forKeys"
2621
+ jsonKey: "^heading.forKeys",
2622
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2538
2623
  },
2539
2624
  {
2540
2625
  key: ConfigKey.property_isCaseSensitive,
2626
+ exportJsonKey: [
2627
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2628
+ { isCaseSensitive: "$" }
2629
+ ],
2541
2630
  description: "Property to indicate if the match is case sensitive.",
2542
2631
  format: TagFormat.boolean
2543
2632
  }
@@ -2551,6 +2640,7 @@ var CARDSETS = {
2551
2640
  variants: [
2552
2641
  {
2553
2642
  jsonKey: "cells[{s}].values[]",
2643
+ exportJsonKey: { cells: { $s: { values: ["$"] } } },
2554
2644
  tags: [
2555
2645
  {
2556
2646
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2558,6 +2648,18 @@ var CARDSETS = {
2558
2648
  },
2559
2649
  {
2560
2650
  key: ConfigKey.property_example,
2651
+ exportJsonKey: [
2652
+ {
2653
+ "@keyonly": {
2654
+ cells: { $s: { isExample: true, example: "$parent.values[0]" } },
2655
+ "@bit": { isExample: true }
2656
+ }
2657
+ },
2658
+ {
2659
+ "@absent": { cells: { $s: { isExample: true, example: "$parent.values[0]" } } }
2660
+ },
2661
+ { cells: { $s: { isExample: true, example: "$" } }, "@bit": { isExample: true } }
2662
+ ],
2561
2663
  description: "Example text for the match matrix.",
2562
2664
  format: TagFormat.plainText
2563
2665
  },
@@ -2565,10 +2667,15 @@ var CARDSETS = {
2565
2667
  key: ConfigKey.tag_title,
2566
2668
  description: "Title of the match matrix.",
2567
2669
  format: TagFormat.plainText,
2568
- jsonKey: "^heading.forValues"
2670
+ jsonKey: "^heading.forValues",
2671
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2569
2672
  },
2570
2673
  {
2571
2674
  key: ConfigKey.property_isCaseSensitive,
2675
+ exportJsonKey: [
2676
+ { "@absent": { isCaseSensitive: "$ancestor" } },
2677
+ { isCaseSensitive: "$" }
2678
+ ],
2572
2679
  description: "Property to indicate if the match is case sensitive.",
2573
2680
  format: TagFormat.boolean
2574
2681
  }
@@ -2584,23 +2691,27 @@ var CARDSETS = {
2584
2691
  //
2585
2692
  [CardSetConfigKey.statements]: {
2586
2693
  jsonKey: "statements",
2694
+ exportJsonKey: { statements: "$" },
2587
2695
  sides: [
2588
2696
  {
2589
2697
  name: "statement",
2590
2698
  variants: [
2591
2699
  {
2592
2700
  jsonKey: "statement",
2701
+ exportJsonKey: { statement: "$" },
2593
2702
  tags: [
2594
2703
  {
2595
2704
  key: ConfigKey.tag_true,
2596
2705
  description: "Tag for true statements.",
2597
2706
  jsonKey: "statement|set(isCorrect=true)",
2707
+ exportJsonKey: { statement: "$", isCorrect: true },
2598
2708
  maxCount: 1
2599
2709
  },
2600
2710
  {
2601
2711
  key: ConfigKey.tag_false,
2602
2712
  description: "Tag for false statements.",
2603
2713
  jsonKey: "statement|set(isCorrect=false)",
2714
+ exportJsonKey: { statement: "$", isCorrect: false },
2604
2715
  maxCount: 1
2605
2716
  },
2606
2717
  {
@@ -2619,6 +2730,7 @@ var CARDSETS = {
2619
2730
  //
2620
2731
  [CardSetConfigKey.quiz]: {
2621
2732
  jsonKey: "quizzes",
2733
+ exportJsonKey: { quizzes: "$" },
2622
2734
  sides: [
2623
2735
  {
2624
2736
  name: "choices",
@@ -2646,6 +2758,7 @@ var CARDSETS = {
2646
2758
  //
2647
2759
  [CardSetConfigKey.feedback]: {
2648
2760
  jsonKey: "feedbacks",
2761
+ exportJsonKey: { feedbacks: "$" },
2649
2762
  sides: [
2650
2763
  {
2651
2764
  name: "choices",
@@ -2665,7 +2778,8 @@ var CARDSETS = {
2665
2778
  key: ConfigKey.tag_title,
2666
2779
  description: "Title of the feedback.",
2667
2780
  format: TagFormat.plainText,
2668
- jsonKey: "^heading.forKeys"
2781
+ jsonKey: "^heading.forKeys",
2782
+ exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
2669
2783
  }
2670
2784
  ],
2671
2785
  bodyAllowed: false
@@ -2677,6 +2791,7 @@ var CARDSETS = {
2677
2791
  variants: [
2678
2792
  {
2679
2793
  jsonKey: "reason.text",
2794
+ exportJsonKey: { reason: { text: "$" } },
2680
2795
  tags: [
2681
2796
  {
2682
2797
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2684,11 +2799,20 @@ var CARDSETS = {
2684
2799
  },
2685
2800
  {
2686
2801
  key: ConfigKey.property_reasonableNumOfChars,
2802
+ exportJsonKey: [
2803
+ { "@absent": { reasonableNumOfChars: "$ancestor" } },
2804
+ { reasonableNumOfChars: "$" }
2805
+ ],
2687
2806
  description: "Property for reasonable number of characters.",
2688
2807
  format: TagFormat.number
2689
2808
  },
2690
2809
  {
2691
2810
  key: ConfigKey.property_example,
2811
+ exportJsonKey: [
2812
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
2813
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
2814
+ { isExample: true, example: "$", "@bit": { isExample: true } }
2815
+ ],
2692
2816
  description: "Example text for the feedback.",
2693
2817
  format: TagFormat.plainText
2694
2818
  },
@@ -2696,7 +2820,8 @@ var CARDSETS = {
2696
2820
  key: ConfigKey.tag_title,
2697
2821
  description: "Title of the feedback.",
2698
2822
  format: TagFormat.plainText,
2699
- jsonKey: "^heading.forValues"
2823
+ jsonKey: "^heading.forValues",
2824
+ exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
2700
2825
  }
2701
2826
  ],
2702
2827
  bodyAllowed: true
@@ -2710,21 +2835,29 @@ var CARDSETS = {
2710
2835
  //
2711
2836
  [CardSetConfigKey.questions]: {
2712
2837
  jsonKey: "questions",
2838
+ exportJsonKey: { questions: "$" },
2713
2839
  sides: [
2714
2840
  {
2715
2841
  name: "question",
2716
2842
  variants: [
2717
2843
  {
2718
2844
  jsonKey: "question",
2845
+ exportJsonKey: { question: "$" },
2719
2846
  tags: [
2720
2847
  {
2721
2848
  key: ConfigKey.property_reasonableNumOfChars,
2849
+ exportJsonKey: [
2850
+ { "@absent": { reasonableNumOfChars: "$ancestor" } },
2851
+ { reasonableNumOfChars: "$" }
2852
+ ],
2722
2853
  description: "Property for reasonable number of characters.",
2723
2854
  format: TagFormat.number
2724
2855
  },
2725
2856
  {
2857
+ exportJsonKey: { sampleSolution: "$" },
2726
2858
  key: ConfigKey.tag_sampleSolution,
2727
- description: "Sample solution for the question."
2859
+ description: "Sample solution for the question.",
2860
+ format: TagFormat.plainText
2728
2861
  },
2729
2862
  {
2730
2863
  key: ConfigKey.property_sampleSolution,
@@ -2764,6 +2897,7 @@ var CARDSETS = {
2764
2897
  variants: [
2765
2898
  {
2766
2899
  jsonKey: "elements[]",
2900
+ exportJsonKey: { elements: ["$"] },
2767
2901
  tags: [
2768
2902
  {
2769
2903
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2771,6 +2905,11 @@ var CARDSETS = {
2771
2905
  },
2772
2906
  {
2773
2907
  key: ConfigKey.property_example,
2908
+ exportJsonKey: [
2909
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
2910
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
2911
+ { isExample: true, example: "$", "@bit": { isExample: true } }
2912
+ ],
2774
2913
  description: "Example text for the element.",
2775
2914
  format: TagFormat.plainText
2776
2915
  }
@@ -2786,6 +2925,7 @@ var CARDSETS = {
2786
2925
  //
2787
2926
  [CardSetConfigKey.table]: {
2788
2927
  jsonKey: "table.data",
2928
+ exportJsonKey: { table: { data: "$" } },
2789
2929
  sides: [
2790
2930
  {
2791
2931
  name: "cell",
@@ -2801,6 +2941,7 @@ var CARDSETS = {
2801
2941
  {
2802
2942
  key: ConfigKey.tag_title,
2803
2943
  jsonKey: "^table.columns[]",
2944
+ exportJsonKey: { "@bit": { table: { columns: ["$"] } } },
2804
2945
  description: "Title of the table."
2805
2946
  },
2806
2947
  {
@@ -2841,18 +2982,34 @@ var CARDSETS = {
2841
2982
  [CardSetConfigKey.tableExtended]: {
2842
2983
  jsonKey: null,
2843
2984
  sections: {
2844
- "table-header": { jsonKey: "table.header.rows", sideJsonKey: "cells[{s}]|set(title=true)" },
2845
- "table-body": { jsonKey: "table.body.rows", isDefault: true },
2846
- "table-footer": { jsonKey: "table.footer.rows", sideJsonKey: "cells[{s}]|set(title=true)" }
2985
+ "table-header": {
2986
+ jsonKey: "table.header.rows",
2987
+ exportJsonKey: { table: { header: { rows: "$" } } },
2988
+ sideJsonKey: "cells[{s}]|set(title=true)",
2989
+ sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } }
2990
+ },
2991
+ "table-body": {
2992
+ jsonKey: "table.body.rows",
2993
+ exportJsonKey: { table: { body: { rows: "$" } } },
2994
+ isDefault: true
2995
+ },
2996
+ "table-footer": {
2997
+ jsonKey: "table.footer.rows",
2998
+ exportJsonKey: { table: { footer: { rows: "$" } } },
2999
+ sideJsonKey: "cells[{s}]|set(title=true)",
3000
+ sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } }
3001
+ }
2847
3002
  },
2848
3003
  sides: [
2849
3004
  {
2850
3005
  name: "cell",
2851
3006
  repeat: true,
2852
3007
  jsonKey: "cells[{s}]",
3008
+ exportJsonKey: { cells: { $s: "$" } },
2853
3009
  variants: [
2854
3010
  {
2855
3011
  jsonKey: "content",
3012
+ exportJsonKey: { content: "$" },
2856
3013
  tags: [
2857
3014
  {
2858
3015
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -2861,29 +3018,38 @@ var CARDSETS = {
2861
3018
  {
2862
3019
  key: ConfigKey.tag_title,
2863
3020
  jsonKey: ".",
3021
+ exportJsonKey: {
3022
+ "@bit": {
3023
+ table: { header: { rows: { cells: { cells: { $s: { content: "$" } } } } } }
3024
+ }
3025
+ },
2864
3026
  description: "Title of the table cell."
2865
3027
  },
2866
3028
  {
2867
3029
  key: ConfigKey.property_tableCellType,
2868
3030
  jsonKey: "title|bool(th)",
3031
+ exportJsonKey: [{ "@value=th": { title: true } }],
2869
3032
  description: "Table cell type (th/td).",
2870
3033
  format: TagFormat.plainText
2871
3034
  },
2872
3035
  {
2873
3036
  key: ConfigKey.property_tableRowSpan,
2874
3037
  jsonKey: "rowspan",
3038
+ exportJsonKey: { rowspan: "$" },
2875
3039
  description: "Number of rows the cell spans.",
2876
3040
  format: TagFormat.number
2877
3041
  },
2878
3042
  {
2879
3043
  key: ConfigKey.property_tableColSpan,
2880
3044
  jsonKey: "colspan",
3045
+ exportJsonKey: { colspan: "$" },
2881
3046
  description: "Number of columns the cell spans.",
2882
3047
  format: TagFormat.number
2883
3048
  },
2884
3049
  {
2885
3050
  key: ConfigKey.property_tableScope,
2886
3051
  jsonKey: "scope",
3052
+ exportJsonKey: { scope: "$" },
2887
3053
  description: "Scope attribute for header cells.",
2888
3054
  format: TagFormat.plainText
2889
3055
  },
@@ -2904,6 +3070,7 @@ var CARDSETS = {
2904
3070
  //
2905
3071
  [CardSetConfigKey.pronunciationTable]: {
2906
3072
  jsonKey: "pronunciationTable.data",
3073
+ exportJsonKey: { pronunciationTable: { data: "$" } },
2907
3074
  sides: [
2908
3075
  {
2909
3076
  name: "cell",
@@ -2911,12 +3078,14 @@ var CARDSETS = {
2911
3078
  variants: [
2912
3079
  {
2913
3080
  jsonKey: "body",
3081
+ exportJsonKey: { body: "$" },
2914
3082
  tags: [
2915
3083
  {
2916
3084
  key: ConfigKey.group_standardItemLeadInstructionHint,
2917
3085
  description: "Standard tags for lead, instruction, and hint."
2918
3086
  },
2919
3087
  {
3088
+ exportJsonKey: { title: "$" },
2920
3089
  key: ConfigKey.tag_title,
2921
3090
  description: "Title of the pronunciation table."
2922
3091
  },
@@ -2937,12 +3106,15 @@ var CARDSETS = {
2937
3106
  //
2938
3107
  [CardSetConfigKey.botActionResponses]: {
2939
3108
  jsonKey: "responses",
3109
+ exportJsonKey: { responses: "$" },
2940
3110
  sides: [
2941
3111
  {
2942
3112
  name: "response",
2943
3113
  variants: [
2944
3114
  {
2945
3115
  jsonKey: "feedback",
3116
+ exportJsonKey: { feedback: "$" },
3117
+ format: TextFormat2.plainText,
2946
3118
  tags: [
2947
3119
  {
2948
3120
  key: ConfigKey.property_reaction,
@@ -2950,16 +3122,53 @@ var CARDSETS = {
2950
3122
  format: TagFormat.plainText
2951
3123
  },
2952
3124
  {
2953
- key: ConfigKey.group_standardItemLead,
2954
- description: "Item, lead, page number, and margin number for the bot action response."
3125
+ key: ConfigKey.tag_item,
3126
+ jsonKey: "item",
3127
+ exportJsonKey: { item: "$" },
3128
+ format: TagFormat.plainText,
3129
+ description: "The item for the bit",
3130
+ chain: [
3131
+ {
3132
+ key: ConfigKey.tag_item,
3133
+ jsonKey: "lead",
3134
+ exportJsonKey: { lead: "$" },
3135
+ description: "The lead for the bit",
3136
+ maxCount: 1,
3137
+ chain: [
3138
+ {
3139
+ key: ConfigKey.tag_item,
3140
+ jsonKey: "pageNumber",
3141
+ exportJsonKey: { pageNumber: "$" },
3142
+ description: "The page number for the bit",
3143
+ maxCount: 1,
3144
+ chain: [
3145
+ {
3146
+ key: ConfigKey.tag_item,
3147
+ jsonKey: "marginNumber",
3148
+ exportJsonKey: { marginNumber: "$" },
3149
+ description: "The margin number for the bit",
3150
+ maxCount: 1
3151
+ }
3152
+ ]
3153
+ }
3154
+ ]
3155
+ }
3156
+ ]
2955
3157
  },
2956
3158
  {
2957
3159
  key: ConfigKey.tag_instruction,
2958
3160
  description: "The response label for the bot action.",
2959
- jsonKey: "response"
3161
+ jsonKey: "response",
3162
+ exportJsonKey: { response: "$" },
3163
+ format: TagFormat.plainText
2960
3164
  },
2961
3165
  {
2962
3166
  key: ConfigKey.property_example,
3167
+ exportJsonKey: [
3168
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
3169
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
3170
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3171
+ ],
2963
3172
  description: "Example text for the bot action response.",
2964
3173
  format: TagFormat.plainText
2965
3174
  }
@@ -2974,12 +3183,14 @@ var CARDSETS = {
2974
3183
  //
2975
3184
  [CardSetConfigKey.clozeList]: {
2976
3185
  jsonKey: "listItems",
3186
+ exportJsonKey: { listItems: "$" },
2977
3187
  sides: [
2978
3188
  {
2979
3189
  name: "content",
2980
3190
  variants: [
2981
3191
  {
2982
3192
  jsonKey: "body",
3193
+ exportJsonKey: { body: "$" },
2983
3194
  tags: [
2984
3195
  {
2985
3196
  key: ConfigKey.group_standardTags,
@@ -3000,18 +3211,21 @@ var CARDSETS = {
3000
3211
  //
3001
3212
  [CardSetConfigKey.exampleBitList]: {
3002
3213
  jsonKey: "listItems",
3214
+ exportJsonKey: { listItems: "$" },
3003
3215
  sides: [
3004
3216
  {
3005
3217
  name: "item",
3006
3218
  variants: [
3007
3219
  {
3008
3220
  jsonKey: "body",
3221
+ exportJsonKey: { body: "$" },
3009
3222
  tags: [
3010
3223
  {
3011
3224
  key: ConfigKey.group_standardTags,
3012
3225
  description: "Standard tags for example bits."
3013
3226
  },
3014
3227
  {
3228
+ exportJsonKey: { title: "$" },
3015
3229
  key: ConfigKey.tag_title,
3016
3230
  description: "Title of the example bit."
3017
3231
  }
@@ -3026,14 +3240,17 @@ var CARDSETS = {
3026
3240
  //
3027
3241
  [CardSetConfigKey.ingredients]: {
3028
3242
  jsonKey: "ingredients",
3243
+ exportJsonKey: { ingredients: "$" },
3029
3244
  sides: [
3030
3245
  {
3031
3246
  name: "ingredient",
3032
3247
  variants: [
3033
3248
  {
3034
3249
  jsonKey: "ingredient",
3250
+ exportJsonKey: { ingredient: "$" },
3035
3251
  tags: [
3036
3252
  {
3253
+ exportJsonKey: { title: "$" },
3037
3254
  key: ConfigKey.tag_title,
3038
3255
  description: "Title of the ingredient."
3039
3256
  },
@@ -3041,6 +3258,7 @@ var CARDSETS = {
3041
3258
  key: ConfigKey.tag_true,
3042
3259
  description: "Checked state for the ingredient.",
3043
3260
  jsonKey: "|set(checked=true)",
3261
+ exportJsonKey: { checked: true, $: "$" },
3044
3262
  maxCount: 1
3045
3263
  // nullable: true,
3046
3264
  },
@@ -3048,6 +3266,7 @@ var CARDSETS = {
3048
3266
  key: ConfigKey.tag_false,
3049
3267
  description: "Unchecked state for the ingredient.",
3050
3268
  jsonKey: "|set(checked=false)",
3269
+ exportJsonKey: { checked: false, $: "$" },
3051
3270
  maxCount: 1
3052
3271
  // nullable: true,
3053
3272
  },
@@ -3059,9 +3278,11 @@ var CARDSETS = {
3059
3278
  key: ConfigKey.tag_instruction,
3060
3279
  description: "The quantity of the ingredient.",
3061
3280
  jsonKey: "quantity",
3281
+ exportJsonKey: { quantity: "$" },
3062
3282
  format: TagFormat.number
3063
3283
  },
3064
3284
  {
3285
+ exportJsonKey: { hint: "$" },
3065
3286
  key: ConfigKey.tag_hint,
3066
3287
  description: "The hint for the ingredient."
3067
3288
  },
@@ -3097,6 +3318,7 @@ var CARDSETS = {
3097
3318
  //
3098
3319
  [CardSetConfigKey.bookReferenceList]: {
3099
3320
  jsonKey: "bookReferences",
3321
+ exportJsonKey: { bookReferences: "$" },
3100
3322
  sides: [
3101
3323
  {
3102
3324
  name: "reference",
@@ -3156,6 +3378,11 @@ var GROUPS = {
3156
3378
  format: TagFormat.plainText,
3157
3379
  maxCount: Count.infinity
3158
3380
  },
3381
+ {
3382
+ key: ConfigKey.property_gUri,
3383
+ description: "Global URI for the bit",
3384
+ format: TagFormat.plainText
3385
+ },
3159
3386
  {
3160
3387
  key: ConfigKey.property_customerId,
3161
3388
  description: "The customer-specific identifier for the bit",
@@ -3339,12 +3566,14 @@ var GROUPS = {
3339
3566
  {
3340
3567
  key: ConfigKey.property_groupTag,
3341
3568
  jsonKey: "groupTag.name",
3569
+ exportJsonKey: { groupTag: { name: "$" } },
3342
3570
  description: "The group tag(s) for the bit",
3343
3571
  format: TagFormat.plainText,
3344
3572
  maxCount: Count.infinity,
3345
3573
  chain: [
3346
3574
  {
3347
3575
  key: ConfigKey.property_tag,
3576
+ exportJsonKey: { tags: ["$"] },
3348
3577
  description: "The tag(s) for the group",
3349
3578
  format: TagFormat.plainText,
3350
3579
  maxCount: Count.infinity
@@ -3375,6 +3604,12 @@ var GROUPS = {
3375
3604
  format: TagFormat.plainText,
3376
3605
  maxCount: Count.infinity
3377
3606
  },
3607
+ {
3608
+ key: ConfigKey.property_sourceBB,
3609
+ description: "The source bounding box(es) for the bit (x, y, x1, y1)",
3610
+ format: TagFormat.coordinates,
3611
+ maxCount: Count.infinity
3612
+ },
3378
3613
  {
3379
3614
  key: ConfigKey.property_levelCEFRp,
3380
3615
  description: "The CEFRp level for the bit",
@@ -3412,6 +3647,7 @@ var GROUPS = {
3412
3647
  maxCount: Count.infinity
3413
3648
  },
3414
3649
  {
3650
+ exportJsonKey: { anchor: "$" },
3415
3651
  key: ConfigKey.tag_anchor,
3416
3652
  name: "Anchor",
3417
3653
  format: TagFormat.plainText,
@@ -3449,23 +3685,27 @@ var GROUPS = {
3449
3685
  {
3450
3686
  key: ConfigKey.tag_item,
3451
3687
  jsonKey: "item",
3688
+ exportJsonKey: { item: "$" },
3452
3689
  description: "The item for the bit",
3453
3690
  chain: [
3454
3691
  {
3455
3692
  key: ConfigKey.tag_item,
3456
3693
  jsonKey: "lead",
3694
+ exportJsonKey: { lead: "$" },
3457
3695
  description: "The lead for the bit",
3458
3696
  maxCount: 1,
3459
3697
  chain: [
3460
3698
  {
3461
3699
  key: ConfigKey.tag_item,
3462
3700
  jsonKey: "pageNumber",
3701
+ exportJsonKey: { pageNumber: "$" },
3463
3702
  description: "The page number for the bit",
3464
3703
  maxCount: 1,
3465
3704
  chain: [
3466
3705
  {
3467
3706
  key: ConfigKey.tag_item,
3468
3707
  jsonKey: "marginNumber",
3708
+ exportJsonKey: { marginNumber: "$" },
3469
3709
  description: "The margin number for the bit",
3470
3710
  maxCount: 1
3471
3711
  }
@@ -3486,11 +3726,13 @@ var GROUPS = {
3486
3726
  description: "Item, lead, page number, and margin number tags"
3487
3727
  },
3488
3728
  {
3729
+ exportJsonKey: { instruction: "$" },
3489
3730
  key: ConfigKey.tag_instruction,
3490
3731
  name: "Instruction",
3491
3732
  description: "The instruction for the bit"
3492
3733
  },
3493
3734
  {
3735
+ exportJsonKey: { hint: "$" },
3494
3736
  key: ConfigKey.tag_hint,
3495
3737
  name: "Hint",
3496
3738
  description: "The hint for the bit"
@@ -3510,9 +3752,17 @@ var GROUPS = {
3510
3752
  description: "Item, lead, page number, margin number, instruction and hint tags"
3511
3753
  },
3512
3754
  {
3755
+ // Bit-level example tag: bare/synthesized records the marker only;
3756
+ // valued [@example:text] emits `isExample: true` and `example` as
3757
+ // PM-rendered rich text (bitmark+ format).
3513
3758
  key: ConfigKey.property_example,
3759
+ exportJsonKey: [
3760
+ { "@keyonly": { isExample: true } },
3761
+ { "@absent": { isExample: true } },
3762
+ { isExample: true, example: "$" }
3763
+ ],
3514
3764
  description: "The example(s) for the bit",
3515
- format: TagFormat.plainText
3765
+ format: TagFormat.bitmarkText
3516
3766
  }
3517
3767
  ]
3518
3768
  },
@@ -3523,6 +3773,7 @@ var GROUPS = {
3523
3773
  {
3524
3774
  key: ConfigKey.property_imageSource,
3525
3775
  jsonKey: "imageSource.url",
3776
+ exportJsonKey: { imageSource: { url: "$" } },
3526
3777
  description: "The source of an image",
3527
3778
  format: TagFormat.plainText,
3528
3779
  chain: [
@@ -3557,6 +3808,7 @@ var GROUPS = {
3557
3808
  {
3558
3809
  key: ConfigKey.property_technicalTerm,
3559
3810
  jsonKey: "technicalTerm.technicalTerm",
3811
+ exportJsonKey: { technicalTerm: { technicalTerm: "$" } },
3560
3812
  description: "The technical term",
3561
3813
  format: TagFormat.plainText,
3562
3814
  chain: [
@@ -3576,6 +3828,7 @@ var GROUPS = {
3576
3828
  {
3577
3829
  key: ConfigKey.property_person,
3578
3830
  jsonKey: "partner.name",
3831
+ exportJsonKey: { partner: { name: "$" } },
3579
3832
  description: "A person",
3580
3833
  format: TagFormat.plainText,
3581
3834
  chain: [
@@ -3587,6 +3840,7 @@ var GROUPS = {
3587
3840
  {
3588
3841
  key: ConfigKey.group_resourceImage,
3589
3842
  jsonKey: "avatarImage|resource(type=image, key=image)",
3843
+ exportJsonKey: { avatarImage: { type: "image", image: { src: "$" } } },
3590
3844
  description: "The image of the person"
3591
3845
  }
3592
3846
  ]
@@ -3595,6 +3849,7 @@ var GROUPS = {
3595
3849
  // Deprecated (parter renamed to person)
3596
3850
  key: ConfigKey.property_partner,
3597
3851
  jsonKey: "partner.name",
3852
+ exportJsonKey: { partner: { name: "$" } },
3598
3853
  description: "A partner",
3599
3854
  format: TagFormat.plainText,
3600
3855
  chain: [
@@ -3606,6 +3861,7 @@ var GROUPS = {
3606
3861
  {
3607
3862
  key: ConfigKey.group_resourceImage,
3608
3863
  jsonKey: "avatarImage|resource(type=image, key=image)",
3864
+ exportJsonKey: { avatarImage: { type: "image", image: { src: "$" } } },
3609
3865
  description: "The image of the partner"
3610
3866
  }
3611
3867
  ]
@@ -3617,15 +3873,19 @@ var GROUPS = {
3617
3873
  description: "Gap chain",
3618
3874
  tags: [
3619
3875
  {
3876
+ exportJsonKey: { solutions: [["$"]] },
3620
3877
  key: ConfigKey.tag_gap,
3621
3878
  description: "The value of a gap in the content",
3622
3879
  maxCount: Count.infinity,
3880
+ format: TagFormat.plainText,
3623
3881
  chain: [
3624
3882
  {
3625
3883
  key: ConfigKey.tag_gap,
3626
3884
  jsonKey: "solutions[]",
3885
+ exportJsonKey: { solutions: ["$"] },
3627
3886
  description: "Alternative values for the gaps in the content",
3628
- maxCount: Count.infinity
3887
+ maxCount: Count.infinity,
3888
+ format: TagFormat.plainText
3629
3889
  },
3630
3890
  {
3631
3891
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3634,12 +3894,33 @@ var GROUPS = {
3634
3894
  {
3635
3895
  key: ConfigKey.property_example,
3636
3896
  jsonKey: "example",
3897
+ exportJsonKey: [
3898
+ {
3899
+ "@keyonly": {
3900
+ isExample: true,
3901
+ example: "$parent.solutions[0]",
3902
+ "@bit": { isExample: true }
3903
+ }
3904
+ },
3905
+ {
3906
+ "@absent": {
3907
+ isExample: true,
3908
+ example: "$parent.solutions[0]",
3909
+ "@bit": { isExample: true }
3910
+ }
3911
+ },
3912
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3913
+ ],
3637
3914
  description: "An example for the gap",
3638
- format: TagFormat.plainText
3915
+ format: TagFormat.bitmarkText
3639
3916
  },
3640
3917
  {
3641
3918
  key: ConfigKey.property_isCaseSensitive,
3642
3919
  jsonKey: "isCaseSensitive",
3920
+ exportJsonKey: [
3921
+ { "@absent": { isCaseSensitive: "$ancestor" } },
3922
+ { isCaseSensitive: "$" }
3923
+ ],
3643
3924
  description: "If true, the gap text is case sensitive",
3644
3925
  format: TagFormat.boolean,
3645
3926
  defaultValue: "true"
@@ -3653,21 +3934,27 @@ var GROUPS = {
3653
3934
  description: "True/False chain",
3654
3935
  tags: [
3655
3936
  {
3937
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3656
3938
  key: ConfigKey.tag_true,
3657
3939
  description: "True value for a true/false statement/question",
3658
3940
  maxCount: Count.infinity,
3941
+ format: TagFormat.plainText,
3659
3942
  chain: [
3660
3943
  {
3661
3944
  key: ConfigKey.tag_true,
3662
3945
  jsonKey: "choices[]|set(isCorrect=true)",
3946
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3663
3947
  description: "True values for a true/false statement/question",
3664
- maxCount: Count.infinity
3948
+ maxCount: Count.infinity,
3949
+ format: TagFormat.plainText
3665
3950
  },
3666
3951
  {
3667
3952
  key: ConfigKey.tag_false,
3668
3953
  jsonKey: "choices[]|set(isCorrect=false)",
3954
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3669
3955
  description: "False values for a true/false statement/question",
3670
- maxCount: Count.infinity
3956
+ maxCount: Count.infinity,
3957
+ format: TagFormat.plainText
3671
3958
  },
3672
3959
  {
3673
3960
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3676,27 +3963,50 @@ var GROUPS = {
3676
3963
  {
3677
3964
  key: ConfigKey.property_example,
3678
3965
  jsonKey: "example",
3966
+ exportJsonKey: [
3967
+ {
3968
+ "@keyonly": {
3969
+ isExample: true,
3970
+ example: "$parent.isCorrect",
3971
+ "@bit": { isExample: true }
3972
+ }
3973
+ },
3974
+ {
3975
+ "@absent": {
3976
+ isExample: true,
3977
+ example: "$parent.isCorrect",
3978
+ "@bit": { isExample: true }
3979
+ }
3980
+ },
3981
+ { isExample: true, example: "$", "@bit": { isExample: true } }
3982
+ ],
3679
3983
  description: "An example for the true/false statement/question",
3680
- format: TagFormat.plainText
3984
+ format: TagFormat.bitmarkText
3681
3985
  }
3682
3986
  ]
3683
3987
  },
3684
3988
  {
3989
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3685
3990
  key: ConfigKey.tag_false,
3686
3991
  description: "False value for a true/false statement/question",
3687
3992
  maxCount: Count.infinity,
3993
+ format: TagFormat.plainText,
3688
3994
  chain: [
3689
3995
  {
3690
3996
  key: ConfigKey.tag_true,
3691
3997
  jsonKey: "choices[]|set(isCorrect=true)",
3998
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
3692
3999
  description: "True values for a true/false statement/question",
3693
- maxCount: Count.infinity
4000
+ maxCount: Count.infinity,
4001
+ format: TagFormat.plainText
3694
4002
  },
3695
4003
  {
3696
4004
  key: ConfigKey.tag_false,
3697
4005
  jsonKey: "choices[]|set(isCorrect=false)",
4006
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
3698
4007
  description: "False values for a true/false statement/question",
3699
- maxCount: Count.infinity
4008
+ maxCount: Count.infinity,
4009
+ format: TagFormat.plainText
3700
4010
  },
3701
4011
  {
3702
4012
  key: ConfigKey.group_standardItemLeadInstructionHint,
@@ -3705,8 +4015,25 @@ var GROUPS = {
3705
4015
  {
3706
4016
  key: ConfigKey.property_example,
3707
4017
  jsonKey: "example",
4018
+ exportJsonKey: [
4019
+ {
4020
+ "@keyonly": {
4021
+ isExample: true,
4022
+ example: "$parent.isCorrect",
4023
+ "@bit": { isExample: true }
4024
+ }
4025
+ },
4026
+ {
4027
+ "@absent": {
4028
+ isExample: true,
4029
+ example: "$parent.isCorrect",
4030
+ "@bit": { isExample: true }
4031
+ }
4032
+ },
4033
+ { isExample: true, example: "$", "@bit": { isExample: true } }
4034
+ ],
3708
4035
  description: "An example for the true/false statement/question",
3709
- format: TagFormat.plainText
4036
+ format: TagFormat.bitmarkText
3710
4037
  }
3711
4038
  ]
3712
4039
  }
@@ -3719,6 +4046,7 @@ var GROUPS = {
3719
4046
  {
3720
4047
  key: ConfigKey.property_mark,
3721
4048
  jsonKey: "marks.mark",
4049
+ exportJsonKey: { marks: { mark: ["$"] } },
3722
4050
  description: "The mark configuration",
3723
4051
  format: TagFormat.plainText,
3724
4052
  maxCount: Count.infinity,
@@ -3742,9 +4070,11 @@ var GROUPS = {
3742
4070
  description: "Mark chain",
3743
4071
  tags: [
3744
4072
  {
4073
+ exportJsonKey: { solution: ["$"] },
3745
4074
  key: ConfigKey.tag_mark,
3746
4075
  description: "The marked content",
3747
4076
  maxCount: Count.infinity,
4077
+ format: TagFormat.plainText,
3748
4078
  chain: [
3749
4079
  {
3750
4080
  key: ConfigKey.property_mark,
@@ -3755,8 +4085,13 @@ var GROUPS = {
3755
4085
  {
3756
4086
  key: ConfigKey.property_example,
3757
4087
  jsonKey: "example",
4088
+ exportJsonKey: [
4089
+ { "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
4090
+ { "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
4091
+ { isExample: true, example: "$", "@bit": { isExample: true } }
4092
+ ],
3758
4093
  description: "An example for the marked content",
3759
- format: TagFormat.plainText
4094
+ format: TagFormat.bitmarkText
3760
4095
  }
3761
4096
  ]
3762
4097
  }
@@ -3845,7 +4180,8 @@ var GROUPS = {
3845
4180
  name: "Title",
3846
4181
  description: "The title of the book",
3847
4182
  maxCount: 2,
3848
- jsonKey: "title|multi(count=2, key=subtitle)"
4183
+ jsonKey: "title|multi(count=2, key=subtitle)",
4184
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
3849
4185
  },
3850
4186
  {
3851
4187
  key: ConfigKey.property_subtype,
@@ -3861,6 +4197,7 @@ var GROUPS = {
3861
4197
  {
3862
4198
  key: ConfigKey.resource_coverImage,
3863
4199
  jsonKey: "coverImage|resource(type=image, key=image)",
4200
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
3864
4201
  description: "The cover image of the book",
3865
4202
  chain: [
3866
4203
  {
@@ -3878,6 +4215,7 @@ var GROUPS = {
3878
4215
  {
3879
4216
  key: ConfigKey.resource_backgroundImage,
3880
4217
  jsonKey: "backgroundImage|resource(type=image, key=image)",
4218
+ exportJsonKey: { backgroundImage: { type: "image", image: { src: "$" } } },
3881
4219
  description: "The background image of the book",
3882
4220
  chain: [
3883
4221
  {
@@ -4037,10 +4375,21 @@ var GROUPS = {
4037
4375
  format: TagFormat.plainText,
4038
4376
  chain: [
4039
4377
  {
4378
+ exportJsonKey: { reference: "$" },
4040
4379
  key: ConfigKey.tag_reference,
4041
4380
  format: TagFormat.plainText,
4042
- description: "The reference(s) for the book(s) in the learning path",
4043
- maxCount: 2
4381
+ description: "The reference for the book(s) in the learning path",
4382
+ maxCount: 1,
4383
+ chain: [
4384
+ {
4385
+ key: ConfigKey.tag_reference,
4386
+ jsonKey: "referenceEnd",
4387
+ exportJsonKey: { referenceEnd: "$" },
4388
+ format: TagFormat.plainText,
4389
+ description: "The referenceEnd for the book(s) in the learning path",
4390
+ maxCount: 1
4391
+ }
4392
+ ]
4044
4393
  }
4045
4394
  ]
4046
4395
  }
@@ -4180,6 +4529,8 @@ var GROUPS = {
4180
4529
  tags: [
4181
4530
  {
4182
4531
  key: ConfigKey.resource_imagePlaceholder,
4532
+ jsonKey: "imagePlaceholder|resource(type=image, key=image)",
4533
+ exportJsonKey: { imagePlaceholder: { type: "image", image: { src: "$" } } },
4183
4534
  description: "Placeholder image for the resource",
4184
4535
  chain: [
4185
4536
  {
@@ -4364,6 +4715,7 @@ var GROUPS = {
4364
4715
  {
4365
4716
  key: ConfigKey.property_posterImage,
4366
4717
  jsonKey: "posterImage.src",
4718
+ exportJsonKey: { posterImage: { src: "$" } },
4367
4719
  description: "The poster image for the video",
4368
4720
  format: TagFormat.plainText,
4369
4721
  chain: [
@@ -4420,6 +4772,7 @@ var GROUPS = {
4420
4772
  tags: [
4421
4773
  {
4422
4774
  key: ConfigKey.resource_image,
4775
+ exportJsonKey: { resource: { type: "image", image: { src: "$" } } },
4423
4776
  description: "The image resource",
4424
4777
  chain: [
4425
4778
  {
@@ -4484,6 +4837,7 @@ var GROUPS = {
4484
4837
  tags: [
4485
4838
  {
4486
4839
  key: ConfigKey.resource_imageLink,
4840
+ exportJsonKey: { resource: { type: "image-link", imageLink: { url: "$" } } },
4487
4841
  description: "The link to the image resource",
4488
4842
  chain: [
4489
4843
  {
@@ -4500,6 +4854,7 @@ var GROUPS = {
4500
4854
  tags: [
4501
4855
  {
4502
4856
  key: ConfigKey.resource_audio,
4857
+ exportJsonKey: { resource: { type: "audio", audio: { src: "$" } } },
4503
4858
  description: "The audio resource",
4504
4859
  chain: [
4505
4860
  {
@@ -4516,6 +4871,7 @@ var GROUPS = {
4516
4871
  tags: [
4517
4872
  {
4518
4873
  key: ConfigKey.resource_audioEmbed,
4874
+ exportJsonKey: { resource: { type: "audio-embed", audioEmbed: { src: "$" } } },
4519
4875
  description: "The embedded audio resource",
4520
4876
  chain: [
4521
4877
  {
@@ -4532,6 +4888,7 @@ var GROUPS = {
4532
4888
  tags: [
4533
4889
  {
4534
4890
  key: ConfigKey.resource_audioLink,
4891
+ exportJsonKey: { resource: { type: "audio-link", audioLink: { url: "$" } } },
4535
4892
  description: "The link to the audio resource",
4536
4893
  chain: [
4537
4894
  {
@@ -4548,6 +4905,7 @@ var GROUPS = {
4548
4905
  tags: [
4549
4906
  {
4550
4907
  key: ConfigKey.resource_video,
4908
+ exportJsonKey: { resource: { type: "video", video: { src: "$" } } },
4551
4909
  description: "The video resource",
4552
4910
  chain: [
4553
4911
  {
@@ -4564,6 +4922,7 @@ var GROUPS = {
4564
4922
  tags: [
4565
4923
  {
4566
4924
  key: ConfigKey.resource_videoEmbed,
4925
+ exportJsonKey: { resource: { type: "video-embed", videoEmbed: { url: "$" } } },
4567
4926
  description: "The embedded video resource",
4568
4927
  chain: [
4569
4928
  {
@@ -4580,6 +4939,7 @@ var GROUPS = {
4580
4939
  tags: [
4581
4940
  {
4582
4941
  key: ConfigKey.resource_videoLink,
4942
+ exportJsonKey: { resource: { type: "video-link", videoLink: { url: "$" } } },
4583
4943
  description: "The link to the video resource",
4584
4944
  chain: [
4585
4945
  {
@@ -4596,6 +4956,9 @@ var GROUPS = {
4596
4956
  tags: [
4597
4957
  {
4598
4958
  key: ConfigKey.resource_stillImageFilmEmbed,
4959
+ exportJsonKey: {
4960
+ resource: { type: "still-image-film-embed", stillImageFilmEmbed: { url: "$" } }
4961
+ },
4599
4962
  description: "The embedded still image film resource",
4600
4963
  chain: [
4601
4964
  {
@@ -4612,6 +4975,9 @@ var GROUPS = {
4612
4975
  tags: [
4613
4976
  {
4614
4977
  key: ConfigKey.resource_stillImageFilmLink,
4978
+ exportJsonKey: {
4979
+ resource: { type: "still-image-film-link", stillImageFilmLink: { url: "$" } }
4980
+ },
4615
4981
  description: "The link to the still image film resource",
4616
4982
  chain: [
4617
4983
  {
@@ -4676,6 +5042,7 @@ var GROUPS = {
4676
5042
  tags: [
4677
5043
  {
4678
5044
  key: ConfigKey.resource_document,
5045
+ exportJsonKey: { resource: { type: "document", document: { url: "$" } } },
4679
5046
  description: "The document resource",
4680
5047
  chain: [
4681
5048
  {
@@ -4692,6 +5059,7 @@ var GROUPS = {
4692
5059
  tags: [
4693
5060
  {
4694
5061
  key: ConfigKey.resource_documentEmbed,
5062
+ exportJsonKey: { resource: { type: "document-embed", documentEmbed: { url: "$" } } },
4695
5063
  description: "The embedded document resource",
4696
5064
  chain: [
4697
5065
  {
@@ -4708,6 +5076,7 @@ var GROUPS = {
4708
5076
  tags: [
4709
5077
  {
4710
5078
  key: ConfigKey.resource_documentLink,
5079
+ exportJsonKey: { resource: { type: "document-link", documentLink: { url: "$" } } },
4711
5080
  description: "The link to the document resource",
4712
5081
  chain: [
4713
5082
  {
@@ -4724,6 +5093,7 @@ var GROUPS = {
4724
5093
  tags: [
4725
5094
  {
4726
5095
  key: ConfigKey.resource_documentDownload,
5096
+ exportJsonKey: { resource: { type: "document-download", documentDownload: { url: "$" } } },
4727
5097
  description: "The downloadable document resource",
4728
5098
  chain: [
4729
5099
  {
@@ -4740,6 +5110,7 @@ var GROUPS = {
4740
5110
  tags: [
4741
5111
  {
4742
5112
  key: ConfigKey.resource_appLink,
5113
+ exportJsonKey: { resource: { type: "app-link", appLink: { url: "$" } } },
4743
5114
  description: "The link to the app resource",
4744
5115
  chain: [
4745
5116
  {
@@ -4756,6 +5127,7 @@ var GROUPS = {
4756
5127
  tags: [
4757
5128
  {
4758
5129
  key: ConfigKey.resource_websiteLink,
5130
+ exportJsonKey: { resource: { type: "website-link", websiteLink: { url: "$" } } },
4759
5131
  description: "The link to the website resource",
4760
5132
  chain: [
4761
5133
  {
@@ -4814,6 +5186,7 @@ var GROUPS = {
4814
5186
  {
4815
5187
  key: ConfigKey.resource_previewImage,
4816
5188
  jsonKey: "previewImage|resource(type=image, key=image)",
5189
+ exportJsonKey: { previewImage: { type: "image", image: { src: "$" } } },
4817
5190
  description: "The preview image resource",
4818
5191
  chain: [
4819
5192
  {
@@ -4831,6 +5204,7 @@ var GROUPS = {
4831
5204
  {
4832
5205
  key: ConfigKey.resource_previewVideo,
4833
5206
  jsonKey: "previewVideo|resource(type=video, key=video)",
5207
+ exportJsonKey: { previewVideo: { type: "video", video: { src: "$" } } },
4834
5208
  description: "The preview video resource",
4835
5209
  chain: [
4836
5210
  {
@@ -4895,20 +5269,48 @@ var ConfigHydrator = class {
4895
5269
  _side.name,
4896
5270
  _side.repeat ?? false,
4897
5271
  variantsOfSide,
4898
- _side.jsonKey
5272
+ _side.jsonKey,
5273
+ _side.exportJsonKey,
5274
+ Object.prototype.hasOwnProperty.call(_side, "exportJsonKey")
4899
5275
  );
4900
5276
  sides.push(sideConfig);
4901
5277
  }
4902
5278
  const cardSetConfig = new CardSetConfig(
4903
5279
  _cardSet,
4904
5280
  _cardSetConfig.jsonKey,
4905
- _cardSetConfig.sections,
5281
+ _cardSetConfig.exportJsonKey,
5282
+ Object.prototype.hasOwnProperty.call(_cardSetConfig, "exportJsonKey"),
5283
+ this.hydrateCardSections(_cardSetConfig.sections),
4906
5284
  sides
4907
5285
  );
4908
5286
  return cardSetConfig;
4909
5287
  }
5288
+ hydrateCardSections(sections) {
5289
+ if (!sections) return void 0;
5290
+ const out = {};
5291
+ for (const [k, v] of Object.entries(sections)) {
5292
+ out[k] = {
5293
+ jsonKey: v.jsonKey,
5294
+ exportJsonKey: v.exportJsonKey,
5295
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(v, "exportJsonKey"),
5296
+ isDefault: v.isDefault,
5297
+ sideJsonKey: v.sideJsonKey,
5298
+ sideExportJsonKey: v.sideExportJsonKey,
5299
+ hasSideExportJsonKey: Object.prototype.hasOwnProperty.call(v, "sideExportJsonKey")
5300
+ };
5301
+ }
5302
+ return out;
5303
+ }
4910
5304
  hydrateTagConfig(_tag) {
4911
- const { key: _configKey, maxCount, minCount, chain: _chain, deprecated } = _tag;
5305
+ const {
5306
+ key: _configKey,
5307
+ maxCount,
5308
+ minCount,
5309
+ chain: _chain,
5310
+ deprecated,
5311
+ jsonKey,
5312
+ exportJsonKey
5313
+ } = _tag;
4912
5314
  const configKey = Enum2(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4913
5315
  if (!configKey) throw new Error(`No tag key found for config key '${configKey}'`);
4914
5316
  const tag = Enum2(Tag).fromValue(configKey);
@@ -4923,6 +5325,9 @@ var ConfigHydrator = class {
4923
5325
  maxCount: maxCount ?? MAX_COUNT_DEFAULT,
4924
5326
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4925
5327
  chain,
5328
+ jsonKey,
5329
+ exportJsonKey,
5330
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4926
5331
  deprecated
4927
5332
  });
4928
5333
  return {
@@ -4941,7 +5346,8 @@ var ConfigHydrator = class {
4941
5346
  format,
4942
5347
  values,
4943
5348
  defaultValue,
4944
- jsonKey
5349
+ jsonKey,
5350
+ exportJsonKey
4945
5351
  } = _tag;
4946
5352
  const configKey = Enum2(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4947
5353
  if (!configKey) throw new Error(`No property key found for config key '${configKey}'`);
@@ -4957,6 +5363,8 @@ var ConfigHydrator = class {
4957
5363
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4958
5364
  chain,
4959
5365
  jsonKey,
5366
+ exportJsonKey,
5367
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4960
5368
  format,
4961
5369
  values,
4962
5370
  defaultValue,
@@ -4969,7 +5377,15 @@ var ConfigHydrator = class {
4969
5377
  };
4970
5378
  }
4971
5379
  hydrateResourceTagConfig(_tag) {
4972
- const { key: _configKey, maxCount, minCount, chain: _chain, deprecated, jsonKey } = _tag;
5380
+ const {
5381
+ key: _configKey,
5382
+ maxCount,
5383
+ minCount,
5384
+ chain: _chain,
5385
+ deprecated,
5386
+ jsonKey,
5387
+ exportJsonKey
5388
+ } = _tag;
4973
5389
  const configKey = Enum2(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
4974
5390
  if (!configKey) throw new Error(`No resource key found for config key '${configKey}'`);
4975
5391
  const tag = _configKey.substring(1);
@@ -4984,6 +5400,8 @@ var ConfigHydrator = class {
4984
5400
  minCount: minCount ?? MIN_COUNT_DEFAULT,
4985
5401
  chain,
4986
5402
  jsonKey,
5403
+ exportJsonKey,
5404
+ hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
4987
5405
  deprecated
4988
5406
  });
4989
5407
  return {
@@ -5015,14 +5433,25 @@ var ConfigHydrator = class {
5015
5433
  };
5016
5434
  }
5017
5435
  hydrateCardVariantConfig(_variant) {
5018
- const { tags: _tags, bodyAllowed, bodyRequired, repeatCount, jsonKey } = _variant;
5436
+ const {
5437
+ tags: _tags,
5438
+ bodyAllowed,
5439
+ bodyRequired,
5440
+ repeatCount,
5441
+ jsonKey,
5442
+ exportJsonKey,
5443
+ format
5444
+ } = _variant;
5019
5445
  const tags2 = this.hydrateTagsConfig(_tags);
5020
5446
  const cardSetConfig = new CardVariantConfig(
5021
5447
  tags2.tags,
5022
5448
  bodyAllowed,
5023
5449
  bodyRequired,
5024
5450
  repeatCount,
5025
- jsonKey
5451
+ jsonKey,
5452
+ exportJsonKey,
5453
+ Object.prototype.hasOwnProperty.call(_variant, "exportJsonKey"),
5454
+ format
5026
5455
  );
5027
5456
  return cardSetConfig;
5028
5457
  }
@@ -5060,6 +5489,7 @@ var BITS = {
5060
5489
  description: "Common tags for quiz bits"
5061
5490
  },
5062
5491
  {
5492
+ exportJsonKey: { title: "$" },
5063
5493
  key: ConfigKey.tag_title,
5064
5494
  description: "The title of the flashcard quiz"
5065
5495
  },
@@ -5068,6 +5498,20 @@ var BITS = {
5068
5498
  description: "The flashcard set to use for the app flashcards",
5069
5499
  format: TagFormat.plainText,
5070
5500
  maxCount: Count.infinity
5501
+ },
5502
+ {
5503
+ // Override inherited @example from group_standardTags: string root
5504
+ // example. Bare/synthesized emits `example: "true"` (a text literal
5505
+ // that field-coerces to a paragraph "true" in bitmark+ contexts);
5506
+ // valued [@example:text] emits the user's text via `$`.
5507
+ key: ConfigKey.property_example,
5508
+ exportJsonKey: [
5509
+ { "@keyonly": { isExample: true, example: "true" } },
5510
+ { "@absent": { isExample: true, example: "true" } },
5511
+ { isExample: true, example: "$" }
5512
+ ],
5513
+ description: "The example text for the bit",
5514
+ format: TagFormat.plainText
5071
5515
  }
5072
5516
  ],
5073
5517
  rootExampleType: ExampleType.string
@@ -5149,6 +5593,7 @@ var BITS = {
5149
5593
  description: "Article bit, used for articles / paragraphs",
5150
5594
  tags: [
5151
5595
  {
5596
+ exportJsonKey: { title: "$" },
5152
5597
  key: ConfigKey.tag_title,
5153
5598
  description: "The title of the article"
5154
5599
  }
@@ -5256,7 +5701,8 @@ var BITS = {
5256
5701
  key: ConfigKey.tag_title,
5257
5702
  description: "Title and subtitle of the catalog item",
5258
5703
  maxCount: 2,
5259
- jsonKey: "title|multi(count=2, key=subtitle)"
5704
+ jsonKey: "title|multi(count=2, key=subtitle)",
5705
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5260
5706
  },
5261
5707
  {
5262
5708
  key: ConfigKey.property_coverImage,
@@ -5266,6 +5712,7 @@ var BITS = {
5266
5712
  {
5267
5713
  key: ConfigKey.resource_coverImage,
5268
5714
  jsonKey: "coverImage|resource(type=image, key=image)",
5715
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
5269
5716
  description: "Cover image of the catalog item",
5270
5717
  chain: [
5271
5718
  {
@@ -5393,6 +5840,17 @@ var BITS = {
5393
5840
  key: ConfigKey.group_previewVideos,
5394
5841
  description: "Array of preview videos for the catalog item",
5395
5842
  maxCount: Count.infinity
5843
+ },
5844
+ {
5845
+ // Override inherited @example from group_standardTags: string root example.
5846
+ key: ConfigKey.property_example,
5847
+ exportJsonKey: [
5848
+ { "@keyonly": { isExample: true, example: "true" } },
5849
+ { "@absent": { isExample: true, example: "true" } },
5850
+ { isExample: true, example: "$" }
5851
+ ],
5852
+ description: "The example text for the bit",
5853
+ format: TagFormat.plainText
5396
5854
  }
5397
5855
  ],
5398
5856
  rootExampleType: ExampleType.string
@@ -5406,7 +5864,8 @@ var BITS = {
5406
5864
  key: ConfigKey.tag_title,
5407
5865
  description: "Title and subtitle of the catalog item",
5408
5866
  maxCount: 2,
5409
- jsonKey: "title|multi(count=2, key=subtitle)"
5867
+ jsonKey: "title|multi(count=2, key=subtitle)",
5868
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5410
5869
  },
5411
5870
  {
5412
5871
  key: ConfigKey.property_coverImage,
@@ -5416,6 +5875,7 @@ var BITS = {
5416
5875
  {
5417
5876
  key: ConfigKey.resource_coverImage,
5418
5877
  jsonKey: "coverImage|resource(type=image, key=image)",
5878
+ exportJsonKey: { coverImage: { type: "image", image: { src: "$" } } },
5419
5879
  description: "Cover image of the catalog item",
5420
5880
  chain: [
5421
5881
  {
@@ -5543,6 +6003,17 @@ var BITS = {
5543
6003
  key: ConfigKey.group_previewVideos,
5544
6004
  description: "Array of preview videos for the catalog item",
5545
6005
  maxCount: Count.infinity
6006
+ },
6007
+ {
6008
+ // Override inherited @example from group_standardTags: string root example.
6009
+ key: ConfigKey.property_example,
6010
+ exportJsonKey: [
6011
+ { "@keyonly": { isExample: true, example: "true" } },
6012
+ { "@absent": { isExample: true, example: "true" } },
6013
+ { isExample: true, example: "$" }
6014
+ ],
6015
+ description: "The example text for the bit",
6016
+ format: TagFormat.plainText
5546
6017
  }
5547
6018
  ],
5548
6019
  rootExampleType: ExampleType.string
@@ -5556,7 +6027,8 @@ var BITS = {
5556
6027
  key: ConfigKey.tag_title,
5557
6028
  description: "Title and subtitle of the catalog item",
5558
6029
  maxCount: 2,
5559
- jsonKey: "title|multi(count=2, key=subtitle)"
6030
+ jsonKey: "title|multi(count=2, key=subtitle)",
6031
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
5560
6032
  },
5561
6033
  {
5562
6034
  key: ConfigKey.property_coverImage,
@@ -5682,6 +6154,17 @@ var BITS = {
5682
6154
  key: ConfigKey.group_previewVideos,
5683
6155
  description: "Array of preview videos for the catalog item",
5684
6156
  maxCount: Count.infinity
6157
+ },
6158
+ {
6159
+ // Override inherited @example from group_standardTags: string root example.
6160
+ key: ConfigKey.property_example,
6161
+ exportJsonKey: [
6162
+ { "@keyonly": { isExample: true, example: "true" } },
6163
+ { "@absent": { isExample: true, example: "true" } },
6164
+ { isExample: true, example: "$" }
6165
+ ],
6166
+ description: "The example text for the bit",
6167
+ format: TagFormat.plainText
5685
6168
  }
5686
6169
  ],
5687
6170
  rootExampleType: ExampleType.string
@@ -5883,11 +6366,13 @@ var BITS = {
5883
6366
  description: "Bit alias, used to create an alias for a bit",
5884
6367
  tags: [
5885
6368
  {
6369
+ exportJsonKey: { reference: "$" },
5886
6370
  key: ConfigKey.tag_reference,
5887
6371
  format: TagFormat.plainText,
5888
6372
  description: "The reference to the bit that this alias points to"
5889
6373
  },
5890
6374
  {
6375
+ exportJsonKey: { anchor: "$" },
5891
6376
  key: ConfigKey.tag_anchor,
5892
6377
  format: TagFormat.plainText,
5893
6378
  description: "The anchor for the bit alias, used for linking"
@@ -6089,7 +6574,8 @@ var BITS = {
6089
6574
  description: "The title of the book cover",
6090
6575
  maxCount: 2,
6091
6576
  // title & subtitle
6092
- jsonKey: "title|multi(count=2, key=subtitle)"
6577
+ jsonKey: "title|multi(count=2, key=subtitle)",
6578
+ exportJsonKey: [{ "@level=1": { title: "$" } }, { "@level=2": { subtitle: "$" } }]
6093
6579
  },
6094
6580
  {
6095
6581
  key: ConfigKey.property_coverColor,
@@ -6233,6 +6719,7 @@ var BITS = {
6233
6719
  description: "Chapter bit, used to define chapters in books or articles",
6234
6720
  tags: [
6235
6721
  {
6722
+ exportJsonKey: { anchor: "$" },
6236
6723
  key: ConfigKey.tag_anchor,
6237
6724
  format: TagFormat.plainText,
6238
6725
  description: "The anchor for the chapter, used for linking"
@@ -6240,7 +6727,8 @@ var BITS = {
6240
6727
  {
6241
6728
  key: ConfigKey.tag_title,
6242
6729
  description: "The title of the chapter",
6243
- jsonKey: "title|setMulti(level)"
6730
+ jsonKey: "title|setMulti(level)",
6731
+ exportJsonKey: { title: "$", level: "$level" }
6244
6732
  },
6245
6733
  {
6246
6734
  key: ConfigKey.property_toc,
@@ -6293,6 +6781,7 @@ var BITS = {
6293
6781
  },
6294
6782
  {
6295
6783
  key: ConfigKey.property_isCaseSensitive,
6784
+ exportJsonKey: {},
6296
6785
  description: "If the cloze answers are case sensitive",
6297
6786
  format: TagFormat.boolean,
6298
6787
  defaultValue: "true"
@@ -6390,6 +6879,11 @@ var BITS = {
6390
6879
  description: "Formula bit, used for mathematical formulas in articles or documents",
6391
6880
  textFormatDefault: TextFormat2.latex
6392
6881
  },
6882
+ [BitType2.formulaImage]: {
6883
+ since: "5.23.0",
6884
+ baseBitType: BitType2.formula,
6885
+ description: "Formula image bit, used for mathematical formulas rendered as images"
6886
+ },
6393
6887
  [BitType2.smartStandardFormula]: {
6394
6888
  since: "3.11.0",
6395
6889
  baseBitType: BitType2.formula,
@@ -6742,6 +7236,7 @@ var BITS = {
6742
7236
  {
6743
7237
  key: ConfigKey.property_servings,
6744
7238
  jsonKey: "servings.servings",
7239
+ exportJsonKey: { servings: { servings: "$" } },
6745
7240
  description: "The number of servings for the ingredients",
6746
7241
  format: TagFormat.number,
6747
7242
  chain: [
@@ -6767,6 +7262,7 @@ var BITS = {
6767
7262
  format: TagFormat.boolean
6768
7263
  },
6769
7264
  {
7265
+ exportJsonKey: { hint: "$" },
6770
7266
  key: ConfigKey.tag_hint,
6771
7267
  description: "Hint for the ingredient, used to provide additional information",
6772
7268
  format: TagFormat.plainText
@@ -6944,6 +7440,17 @@ var BITS = {
6944
7440
  description: "Reference for the essay, used to link to external resources",
6945
7441
  format: TagFormat.plainText,
6946
7442
  maxCount: Count.infinity
7443
+ },
7444
+ {
7445
+ // Override inherited @example from group_standardTags: string root example.
7446
+ key: ConfigKey.property_example,
7447
+ exportJsonKey: [
7448
+ { "@keyonly": { isExample: true, example: "true" } },
7449
+ { "@absent": { isExample: true, example: "true" } },
7450
+ { isExample: true, example: "$" }
7451
+ ],
7452
+ description: "The example text for the essay bit",
7453
+ format: TagFormat.plainText
6947
7454
  }
6948
7455
  ],
6949
7456
  rootExampleType: ExampleType.string
@@ -6964,8 +7471,20 @@ var BITS = {
6964
7471
  description: "Example bit, used to provide examples in articles or books",
6965
7472
  tags: [
6966
7473
  {
7474
+ exportJsonKey: { title: "$" },
6967
7475
  key: ConfigKey.tag_title,
6968
7476
  description: "The title of the example"
7477
+ },
7478
+ {
7479
+ // Override inherited @example from group_standardTags: string root example.
7480
+ key: ConfigKey.property_example,
7481
+ exportJsonKey: [
7482
+ { "@keyonly": { isExample: true, example: "true" } },
7483
+ { "@absent": { isExample: true, example: "true" } },
7484
+ { isExample: true, example: "$" }
7485
+ ],
7486
+ description: "The example text for the example bit",
7487
+ format: TagFormat.plainText
6969
7488
  }
6970
7489
  ],
6971
7490
  rootExampleType: ExampleType.string
@@ -7831,6 +8350,7 @@ var BITS = {
7831
8350
  // Image resource
7832
8351
  key: ConfigKey.group_resourceImage,
7833
8352
  description: "Resource image tags for logo grave images, used to attach images",
8353
+ exportJsonKey: { images: "$" },
7834
8354
  minCount: 1,
7835
8355
  maxCount: Count.infinity
7836
8356
  }
@@ -7994,15 +8514,27 @@ var BITS = {
7994
8514
  format: TagFormat.plainText,
7995
8515
  chain: [
7996
8516
  {
8517
+ exportJsonKey: { reference: "$" },
7997
8518
  key: ConfigKey.tag_reference,
7998
8519
  format: TagFormat.plainText,
7999
8520
  description: "Reference tag for the book, used to link to the book in the system",
8000
- maxCount: 2
8521
+ maxCount: 1,
8522
+ chain: [
8523
+ {
8524
+ key: ConfigKey.tag_reference,
8525
+ jsonKey: "referenceEnd",
8526
+ exportJsonKey: { referenceEnd: "$" },
8527
+ format: TagFormat.plainText,
8528
+ description: "End reference tag for the book, used to specify a range",
8529
+ maxCount: 1
8530
+ }
8531
+ ]
8001
8532
  }
8002
8533
  ]
8003
8534
  },
8004
8535
  {
8005
8536
  /* Allow incorrectly chained reference tag */
8537
+ exportJsonKey: { reference: "$" },
8006
8538
  key: ConfigKey.tag_reference,
8007
8539
  format: TagFormat.plainText,
8008
8540
  description: "Reference tag for the book, used to link to the book in the system"
@@ -8049,18 +8581,41 @@ var BITS = {
8049
8581
  format: TagFormat.plainText,
8050
8582
  chain: [
8051
8583
  {
8584
+ exportJsonKey: { reference: "$" },
8052
8585
  key: ConfigKey.tag_reference,
8053
8586
  format: TagFormat.plainText,
8054
8587
  description: "Reference tag for the book, used to link to the book in the system",
8055
- maxCount: 2
8588
+ maxCount: 1,
8589
+ chain: [
8590
+ {
8591
+ key: ConfigKey.tag_reference,
8592
+ jsonKey: "referenceEnd",
8593
+ exportJsonKey: { referenceEnd: "$" },
8594
+ format: TagFormat.plainText,
8595
+ description: "End reference tag for the book, used to specify a range",
8596
+ maxCount: 1
8597
+ }
8598
+ ]
8056
8599
  }
8057
8600
  ]
8058
8601
  },
8059
8602
  {
8060
8603
  /* Allow incorrectly chained reference tag */
8604
+ exportJsonKey: { reference: "$" },
8061
8605
  key: ConfigKey.tag_reference,
8062
8606
  format: TagFormat.plainText,
8063
- description: "Reference tag for the book, used to link to the book in the system"
8607
+ description: "Reference tag for the book, used to link to the book in the system",
8608
+ maxCount: 1,
8609
+ chain: [
8610
+ {
8611
+ key: ConfigKey.tag_reference,
8612
+ jsonKey: "referenceEnd",
8613
+ exportJsonKey: { referenceEnd: "$" },
8614
+ format: TagFormat.plainText,
8615
+ description: "End reference tag for the book, used to specify a range",
8616
+ maxCount: 1
8617
+ }
8618
+ ]
8064
8619
  },
8065
8620
  {
8066
8621
  key: ConfigKey.property_buttonCaption,
@@ -8089,10 +8644,21 @@ var BITS = {
8089
8644
  maxCount: Count.infinity,
8090
8645
  chain: [
8091
8646
  {
8647
+ exportJsonKey: { reference: "$" },
8092
8648
  key: ConfigKey.tag_reference,
8093
8649
  format: TagFormat.plainText,
8094
8650
  description: "Reference tag for the book, used to link to the book in the system",
8095
- maxCount: 2
8651
+ maxCount: 1,
8652
+ chain: [
8653
+ {
8654
+ key: ConfigKey.tag_reference,
8655
+ jsonKey: "referenceEnd",
8656
+ exportJsonKey: { referenceEnd: "$" },
8657
+ format: TagFormat.plainText,
8658
+ description: "End reference tag for the book, used to specify a range",
8659
+ maxCount: 1
8660
+ }
8661
+ ]
8096
8662
  }
8097
8663
  ]
8098
8664
  },
@@ -8259,6 +8825,7 @@ var BITS = {
8259
8825
  tags: [
8260
8826
  {
8261
8827
  key: ConfigKey.resource_backgroundWallpaper,
8828
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
8262
8829
  description: "Background wallpaper for the image, used to set a background for the image",
8263
8830
  chain: [
8264
8831
  {
@@ -8441,6 +9008,7 @@ var BITS = {
8441
9008
  },
8442
9009
  {
8443
9010
  key: ConfigKey.resource_backgroundWallpaper,
9011
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
8444
9012
  description: "Background wallpaper for the image, used to set a background for the image",
8445
9013
  chain: [
8446
9014
  {
@@ -8593,6 +9161,7 @@ var BITS = {
8593
9161
  // Image resource
8594
9162
  key: ConfigKey.group_resourceImage,
8595
9163
  description: "Resource image tags for logo grave images, used to attach images",
9164
+ exportJsonKey: { logos: "$" },
8596
9165
  minCount: 1,
8597
9166
  maxCount: Count.infinity
8598
9167
  }
@@ -8610,6 +9179,7 @@ var BITS = {
8610
9179
  description: "Internal link bit, used to create links to other bits in articles or books",
8611
9180
  tags: [
8612
9181
  {
9182
+ exportJsonKey: { reference: "$" },
8613
9183
  key: ConfigKey.tag_reference,
8614
9184
  format: TagFormat.plainText,
8615
9185
  description: "Reference tag for the internal link, used to link to the target bit"
@@ -8628,6 +9198,7 @@ var BITS = {
8628
9198
  },
8629
9199
  {
8630
9200
  key: ConfigKey.property_reasonableNumOfChars,
9201
+ exportJsonKey: {},
8631
9202
  description: "Reasonable number of characters for the interview, used to limit input size",
8632
9203
  format: TagFormat.number
8633
9204
  }
@@ -9003,6 +9574,7 @@ var BITS = {
9003
9574
  },
9004
9575
  {
9005
9576
  key: ConfigKey.property_isCaseSensitive,
9577
+ exportJsonKey: {},
9006
9578
  description: "Case sensitivity for matching pairs, used to define if matches are case-sensitive",
9007
9579
  format: TagFormat.boolean,
9008
9580
  defaultValue: "true"
@@ -9055,6 +9627,7 @@ var BITS = {
9055
9627
  tags: [
9056
9628
  {
9057
9629
  key: ConfigKey.property_reasonableNumOfChars,
9630
+ exportJsonKey: {},
9058
9631
  description: "Reasonable number of characters for feedback, used to limit input size",
9059
9632
  format: TagFormat.number
9060
9633
  }
@@ -9196,6 +9769,7 @@ var BITS = {
9196
9769
  description: "Page bit, used to create pages in articles or books",
9197
9770
  tags: [
9198
9771
  {
9772
+ exportJsonKey: { title: "$" },
9199
9773
  key: ConfigKey.tag_title,
9200
9774
  description: "Title of the page, used to display the page title"
9201
9775
  },
@@ -9555,6 +10129,7 @@ var BITS = {
9555
10129
  {
9556
10130
  key: ConfigKey.resource_platformBackgroundImage,
9557
10131
  jsonKey: "platformBackgroundImage|resource(type=image, key=image)",
10132
+ exportJsonKey: { platformBackgroundImage: { type: "image", image: { src: "$" } } },
9558
10133
  description: "The platform section chat background image",
9559
10134
  chain: [
9560
10135
  {
@@ -9648,6 +10223,7 @@ var BITS = {
9648
10223
  description: "Review note bit, used to create review notes in articles or books",
9649
10224
  tags: [
9650
10225
  {
10226
+ exportJsonKey: { title: "$" },
9651
10227
  key: ConfigKey.tag_title,
9652
10228
  description: "Title of the review note, used to display the note title"
9653
10229
  },
@@ -9666,6 +10242,17 @@ var BITS = {
9666
10242
  key: ConfigKey.property_resolvedBy,
9667
10243
  description: "Resolved by for the review note, used to define who resolved the note",
9668
10244
  format: TagFormat.plainText
10245
+ },
10246
+ {
10247
+ // Override inherited @example from group_standardTags: string root example.
10248
+ key: ConfigKey.property_example,
10249
+ exportJsonKey: [
10250
+ { "@keyonly": { isExample: true, example: "true" } },
10251
+ { "@absent": { isExample: true, example: "true" } },
10252
+ { isExample: true, example: "$" }
10253
+ ],
10254
+ description: "The example text for the review note bit",
10255
+ format: TagFormat.plainText
9669
10256
  }
9670
10257
  ],
9671
10258
  rootExampleType: ExampleType.string
@@ -9718,11 +10305,13 @@ var BITS = {
9718
10305
  tags: [
9719
10306
  // Not sure if these are actually valid here, but include them as they are in the test bit.
9720
10307
  {
10308
+ exportJsonKey: { anchor: "$" },
9721
10309
  key: ConfigKey.tag_anchor,
9722
10310
  format: TagFormat.plainText,
9723
10311
  description: "Anchor for the sample solution, used to link to the solution"
9724
10312
  },
9725
10313
  {
10314
+ exportJsonKey: { reference: "$" },
9726
10315
  key: ConfigKey.tag_reference,
9727
10316
  format: TagFormat.plainText,
9728
10317
  description: "Reference for the sample solution, used to link to the source of the solution"
@@ -9738,6 +10327,19 @@ var BITS = {
9738
10327
  {
9739
10328
  key: ConfigKey.group_quizCommon,
9740
10329
  description: "Common quiz tags for sequences"
10330
+ },
10331
+ {
10332
+ // Override inherited @example from group_standardTags: this bit has
10333
+ // a boolean root example (rootExampleType: boolean), so bit-level
10334
+ // [@example] writes `example: true` in addition to `isExample: true`.
10335
+ key: ConfigKey.property_example,
10336
+ exportJsonKey: [
10337
+ { "@keyonly": { isExample: true, example: true } },
10338
+ { "@absent": { isExample: true, example: true } },
10339
+ { isExample: true, example: "$" }
10340
+ ],
10341
+ description: "The example flag for the bit (boolean)",
10342
+ format: TagFormat.plainText
9741
10343
  }
9742
10344
  ],
9743
10345
  cardSet: CardSetConfigKey.elements,
@@ -9845,6 +10447,7 @@ var BITS = {
9845
10447
  {
9846
10448
  key: ConfigKey.property_ratingLevelStart,
9847
10449
  jsonKey: "ratingLevelStart.level",
10450
+ exportJsonKey: { ratingLevelStart: { level: "$" } },
9848
10451
  description: "Start level for the rating survey, used to define the lowest rating",
9849
10452
  format: TagFormat.number,
9850
10453
  chain: [
@@ -9858,6 +10461,7 @@ var BITS = {
9858
10461
  {
9859
10462
  key: ConfigKey.property_ratingLevelEnd,
9860
10463
  jsonKey: "ratingLevelEnd.level",
10464
+ exportJsonKey: { ratingLevelEnd: { level: "$" } },
9861
10465
  description: "End level for the rating survey, used to define the highest rating",
9862
10466
  format: TagFormat.number,
9863
10467
  chain: [
@@ -10010,6 +10614,7 @@ var BITS = {
10010
10614
  },
10011
10615
  {
10012
10616
  key: ConfigKey.resource_backgroundWallpaper,
10617
+ exportJsonKey: { backgroundWallpaper: { type: "image", image: { src: "$" } } },
10013
10618
  description: "Background wallpaper for the image, used to set a background for the image",
10014
10619
  chain: [
10015
10620
  {
@@ -10393,12 +10998,34 @@ var BITS = {
10393
10998
  format: TagFormat.plainText
10394
10999
  },
10395
11000
  {
11001
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: true }] },
10396
11002
  key: ConfigKey.tag_true,
10397
- description: "Tag for the true option in the true/false question"
11003
+ description: "Tag for the true option in the true/false question",
11004
+ format: TagFormat.plainText
10398
11005
  },
10399
11006
  {
11007
+ exportJsonKey: { choices: [{ choice: "$", isCorrect: false }] },
10400
11008
  key: ConfigKey.tag_false,
10401
- description: "Tag for the false option in the true/false question"
11009
+ description: "Tag for the false option in the true/false question",
11010
+ format: TagFormat.plainText
11011
+ },
11012
+ {
11013
+ // Override inherited @example from group_standardTags: boolean root
11014
+ // example. Note: the legacy reference parser ties the bare-form
11015
+ // example value to `statement.isCorrect`, but the statement is not
11016
+ // yet emitted when this tag fires at bit-header. The pattern below
11017
+ // emits a literal `true` for bare/synthesized and `$` for valued —
11018
+ // sufficient for `[+...]` (correct) statements which dominate the
11019
+ // fixtures; `[-...]` (incorrect) bits with bare `[@example]` would
11020
+ // need either a runtime extension or an explicit `[@example:false]`.
11021
+ key: ConfigKey.property_example,
11022
+ exportJsonKey: [
11023
+ { "@keyonly": { isExample: true, example: true } },
11024
+ { "@absent": { isExample: true, example: true } },
11025
+ { isExample: true, example: "$" }
11026
+ ],
11027
+ description: "The example flag for the bit (boolean)",
11028
+ format: TagFormat.plainText
10402
11029
  }
10403
11030
  ],
10404
11031
  rootExampleType: ExampleType.boolean
@@ -10981,6 +11608,8 @@ var Config = class {
10981
11608
  maxCount: 1,
10982
11609
  chain: tag.chain,
10983
11610
  jsonKey: tag.jsonKey,
11611
+ exportJsonKey: tag.exportJsonKey,
11612
+ hasExportJsonKey: tag.hasExportJsonKey,
10984
11613
  deprecated: tag.deprecated
10985
11614
  });
10986
11615
  finalResourceTags[k] = newTag;
@@ -11085,7 +11714,7 @@ var instance2 = new Config();
11085
11714
  // src/generated/package_info.ts
11086
11715
  var PACKAGE_INFO = {
11087
11716
  "name": "@gmb/bitmark-parser-generator",
11088
- "version": "5.22.0",
11717
+ "version": "5.23.0",
11089
11718
  "author": "Get More Brain Ltd",
11090
11719
  "license": "ISC",
11091
11720
  "description": "A bitmark parser and generator using Peggy.js"
@@ -11679,6 +12308,8 @@ var NodeType = {
11679
12308
  gmbExternalShopItems: "gmbExternalShopItems",
11680
12309
  groupTag: "groupTag",
11681
12310
  groupTagValue: "groupTagValue",
12311
+ gUri: "gUri",
12312
+ gUriValue: "gUriValue",
11682
12313
  handInAcceptFileType: "handInAcceptFileType",
11683
12314
  handInAcceptFileTypeValue: "handInAcceptFileTypeValue",
11684
12315
  handInInstruction: "handInInstruction",
@@ -12021,6 +12652,8 @@ var NodeType = {
12021
12652
  solution: "solution",
12022
12653
  solutions: "solutions",
12023
12654
  solutionsValue: "solutionsValue",
12655
+ sourceBB: "sourceBB",
12656
+ sourceBBValue: "sourceBBValue",
12024
12657
  sourceDocument: "sourceDocument",
12025
12658
  sourceDocumentValue: "sourceDocumentValue",
12026
12659
  sourceRL: "sourceRL",
@@ -24901,6 +25534,7 @@ var Builder = class extends BaseBuilder {
24901
25534
  isCommented: data.isCommented,
24902
25535
  // Properties
24903
25536
  id: this.toAstProperty(bitType, ConfigKey.property_id, data.id, options),
25537
+ gUri: this.toAstProperty(bitType, ConfigKey.property_gUri, data.gUri, options),
24904
25538
  internalComment: this.toAstProperty(
24905
25539
  bitType,
24906
25540
  ConfigKey.property_internalComment,
@@ -25112,6 +25746,7 @@ var Builder = class extends BaseBuilder {
25112
25746
  data.extractorInternal,
25113
25747
  options
25114
25748
  ),
25749
+ sourceBB: this.normaliseSourceBB(data.sourceBB),
25115
25750
  levelCEFRp: this.toAstProperty(
25116
25751
  bitType,
25117
25752
  ConfigKey.property_levelCEFRp,
@@ -26132,6 +26767,19 @@ var Builder = class extends BaseBuilder {
26132
26767
  nodes = Object.values(combinedNodes);
26133
26768
  return nodes.length > 0 ? nodes : void 0;
26134
26769
  }
26770
+ /**
26771
+ * Normalise a sourceBB input into the AST shape (always number[][]).
26772
+ * Accepts a single 4-number tuple or an array of tuples; returns undefined when empty.
26773
+ */
26774
+ normaliseSourceBB(data) {
26775
+ if (data == null) return void 0;
26776
+ if (!Array.isArray(data) || data.length === 0) return void 0;
26777
+ const isNested = data.some(Array.isArray);
26778
+ const tuples = (isNested ? data : [data]).filter(
26779
+ (t) => Array.isArray(t) && t.length === 4 && t.every((n) => typeof n === "number")
26780
+ );
26781
+ return tuples.length > 0 ? tuples : void 0;
26782
+ }
26135
26783
  /**
26136
26784
  * Build groupTag node
26137
26785
  *
@@ -28451,6 +29099,23 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
28451
29099
  format: TagFormat.plainText
28452
29100
  });
28453
29101
  }
29102
+ // bitmarkAst -> bits -> bitsValue -> sourceBB
29103
+ enter_sourceBB(node, route) {
29104
+ const parent = this.getParentNode(route);
29105
+ if (parent?.key !== NodeType.bitsValue) return false;
29106
+ const tuples = node.value;
29107
+ if (!Array.isArray(tuples) || tuples.length === 0) return false;
29108
+ this.writeProperty(
29109
+ "sourceBB",
29110
+ tuples.map((t) => t.join(", ")),
29111
+ route,
29112
+ {
29113
+ format: TagFormat.plainText,
29114
+ array: true
29115
+ }
29116
+ );
29117
+ return false;
29118
+ }
28454
29119
  // bitmarkAst -> bits -> bitsValue -> questions -> questionsValue -> additionalSolutions -> additionalSolutionsValue
28455
29120
  leaf_additionalSolutionsValue(node, route) {
28456
29121
  const parent = this.getParentNode(route, 2);
@@ -30574,6 +31239,16 @@ var JsonGenerator = class extends AstWalkerGenerator {
30574
31239
  enter_ratingLevelEnd(node, route) {
30575
31240
  return this.standardHandler(node, route, NodeType.bitsValue, { array: false });
30576
31241
  }
31242
+ // bitmarkAst -> bits -> bitsValue -> sourceBB
31243
+ enter_sourceBB(node, route) {
31244
+ const tuples = node.value;
31245
+ const parent = this.getParentNode(route);
31246
+ if (parent?.key !== NodeType.bitsValue) return false;
31247
+ if (tuples && tuples.length > 0) {
31248
+ this.bitJson.sourceBB = tuples.length === 1 ? tuples[0] : tuples;
31249
+ }
31250
+ return false;
31251
+ }
30577
31252
  // bitmarkAst -> bits -> bitsValue -> productId
30578
31253
  enter_productId(node, route) {
30579
31254
  const productIds = node.value;
@@ -35252,6 +35927,17 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
35252
35927
  format: TextFormat2.bitmarkText,
35253
35928
  location: TextLocation2.tag
35254
35929
  });
35930
+ case TagFormat.coordinates:
35931
+ const coordRaw = instance3.unbreakscape(v2, {
35932
+ format: TextFormat2.plainText,
35933
+ location: TextLocation2.tag
35934
+ });
35935
+ if (coordRaw == null) return void 0;
35936
+ const coordParts = coordRaw.split(",").map((p) => instance6.asNumber(p.trim()));
35937
+ if (coordParts.length !== 4 || coordParts.some((n) => n == null)) {
35938
+ return void 0;
35939
+ }
35940
+ return coordParts;
35255
35941
  }
35256
35942
  }
35257
35943
  return instance3.unbreakscape(v2, {
@@ -35288,6 +35974,8 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
35288
35974
  minCount: 1,
35289
35975
  chain: void 0,
35290
35976
  jsonKey: void 0,
35977
+ exportJsonKey: void 0,
35978
+ hasExportJsonKey: false,
35291
35979
  format: TagFormat.bitmarkText,
35292
35980
  values: void 0,
35293
35981
  defaultValue: void 0,
@@ -35298,19 +35986,18 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
35298
35986
  }
35299
35987
 
35300
35988
  // src/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.ts
35301
- function referenceTagContentProcessor(_context, _contentDepth, _tagsConfig, content, target, isReferenceEnd) {
35302
- const { value } = content;
35989
+ function referenceTagContentProcessor(context, _contentDepth, tagsConfig, content, target) {
35990
+ const { value, chain } = content;
35303
35991
  const trimmedStringValue = stringUtils.trimmedString(value);
35304
- if (isReferenceEnd) {
35305
- target.referenceEnd = instance3.unbreakscape(trimmedStringValue, {
35306
- format: TextFormat2.bitmarkText,
35307
- location: TextLocation2.tag
35308
- });
35309
- } else {
35310
- target.reference = instance3.unbreakscape(trimmedStringValue, {
35311
- format: TextFormat2.bitmarkText,
35312
- location: TextLocation2.tag
35313
- });
35992
+ target.reference = instance3.unbreakscape(trimmedStringValue, {
35993
+ format: TextFormat2.bitmarkText,
35994
+ location: TextLocation2.tag
35995
+ });
35996
+ if (Array.isArray(chain) && chain.length > 0) {
35997
+ const sub = context.bitContentProcessor(ContentDepth.Chain, tagsConfig, chain);
35998
+ if (sub.reference != null) {
35999
+ target.referenceEnd = sub.reference;
36000
+ }
35314
36001
  }
35315
36002
  }
35316
36003
 
@@ -35996,7 +36683,6 @@ var BitmarkPegParserProcessor = class {
35996
36683
  result.markConfig = [];
35997
36684
  result.extraProperties = {};
35998
36685
  result.internalComments = [];
35999
- let seenReference = false;
36000
36686
  let inFooter = false;
36001
36687
  const bodyParts = [];
36002
36688
  let bodyTextPart = instance3.EMPTY_STRING;
@@ -36032,15 +36718,7 @@ var BitmarkPegParserProcessor = class {
36032
36718
  defaultTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
36033
36719
  break;
36034
36720
  case TypeKey.Reference:
36035
- referenceTagContentProcessor(
36036
- this.context,
36037
- contentDepth,
36038
- tagsConfig,
36039
- content,
36040
- result,
36041
- seenReference
36042
- );
36043
- seenReference = true;
36721
+ referenceTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
36044
36722
  break;
36045
36723
  case TypeKey.Title:
36046
36724
  titleTagContentProcessor(this.context, contentDepth, tagsConfig, content, result);
@@ -40420,6 +41098,117 @@ var JsonStringGenerator = class {
40420
41098
  }
40421
41099
  };
40422
41100
 
41101
+ // src/utils/BoundingBox.ts
41102
+ function toBbox(arr) {
41103
+ if (!Array.isArray(arr) || arr.length !== 4) return null;
41104
+ if (!arr.every(Number.isFinite)) return null;
41105
+ return [arr[0], arr[1], arr[2], arr[3]];
41106
+ }
41107
+ function parseSourceBB(sourceBB) {
41108
+ if (sourceBB == null) return [];
41109
+ if (!Array.isArray(sourceBB) || sourceBB.length === 0) return [];
41110
+ const isNested = sourceBB.some(Array.isArray);
41111
+ const candidates = isNested ? sourceBB : [sourceBB];
41112
+ const out = [];
41113
+ for (const candidate of candidates) {
41114
+ const box = toBbox(candidate);
41115
+ if (box) out.push(box);
41116
+ }
41117
+ return out;
41118
+ }
41119
+ function boundingBoxIntersects(a, b) {
41120
+ return a[0] < b[2] && a[2] > b[0] && a[1] < b[3] && a[3] > b[1];
41121
+ }
41122
+ function boundingBoxUnion(boxes) {
41123
+ if (boxes.length === 0) return null;
41124
+ let [x0, y0, x1, y1] = boxes[0];
41125
+ for (let i = 1; i < boxes.length; i++) {
41126
+ const b = boxes[i];
41127
+ if (b[0] < x0) x0 = b[0];
41128
+ if (b[1] < y0) y0 = b[1];
41129
+ if (b[2] > x1) x1 = b[2];
41130
+ if (b[3] > y1) y1 = b[3];
41131
+ }
41132
+ return [x0, y0, x1, y1];
41133
+ }
41134
+ var BoundingBoxIndex = class _BoundingBoxIndex {
41135
+ constructor(entries) {
41136
+ __publicField(this, "_entries");
41137
+ __publicField(this, "bitmarkParser", new BitmarkParserGenerator());
41138
+ this._entries = entries;
41139
+ }
41140
+ /**
41141
+ * Build an index from already-parsed bits. Bits without a parseable
41142
+ * `sourceBB` are dropped. Order of the input is preserved.
41143
+ *
41144
+ * Pass `options.sourceRL` to scope the index to a single source page —
41145
+ * bits whose `sourceRL` doesn't match (or is absent) are excluded.
41146
+ */
41147
+ static fromBits(wrappers, options) {
41148
+ const filterSourceRL = options?.sourceRL;
41149
+ const entries = [];
41150
+ for (const wrapper of wrappers) {
41151
+ if (!wrapper?.bit) continue;
41152
+ if (filterSourceRL !== void 0 && wrapper.bit.sourceRL !== filterSourceRL) {
41153
+ continue;
41154
+ }
41155
+ const boxes = parseSourceBB(wrapper.bit.sourceBB);
41156
+ if (boxes.length === 0) continue;
41157
+ entries.push({ bit: wrapper.bit, wrapper, boxes });
41158
+ }
41159
+ return new _BoundingBoxIndex(entries);
41160
+ }
41161
+ /** All bits with at least one valid `sourceBB`, in input order. */
41162
+ get entries() {
41163
+ return this._entries;
41164
+ }
41165
+ /**
41166
+ * Bits whose ANY `sourceBB` box intersects `query` (strict overlap —
41167
+ * touching-only edges do NOT count as an intersection).
41168
+ */
41169
+ intersecting(query) {
41170
+ const matches = [];
41171
+ for (const entry of this._entries) {
41172
+ if (entry.boxes.some((box) => boundingBoxIntersects(query, box))) {
41173
+ matches.push(entry);
41174
+ }
41175
+ }
41176
+ return matches;
41177
+ }
41178
+ /**
41179
+ * Flat list of every individual `sourceBB` box that intersects `query`.
41180
+ * For a multi-box bit, only the boxes that themselves intersected are
41181
+ * returned.
41182
+ */
41183
+ intersectingBoxes(query) {
41184
+ const matches = [];
41185
+ for (const entry of this._entries) {
41186
+ for (const box of entry.boxes) {
41187
+ if (boundingBoxIntersects(query, box)) matches.push(box);
41188
+ }
41189
+ }
41190
+ return matches;
41191
+ }
41192
+ /**
41193
+ * Smallest axis-aligned box that fully encloses every individual `sourceBB`
41194
+ * box that intersected the query. For a multi-box bit, only the boxes that
41195
+ * themselves intersected contribute to the union — non-intersecting boxes
41196
+ * from the same bit are ignored. Returns `null` if no box matches.
41197
+ */
41198
+ enclosingBoundingBox(query) {
41199
+ return boundingBoxUnion(this.intersectingBoxes(query));
41200
+ }
41201
+ /** Render selected bits back to bitmark text. Empty input returns `''`. */
41202
+ toBitmark(entries) {
41203
+ if (entries.length === 0) return "";
41204
+ const wrappers = entries.map((e) => e.wrapper);
41205
+ return this.bitmarkParser.convert(wrappers, {
41206
+ outputFormat: Output.bitmark,
41207
+ bitmarkOptions: { prettifyJson: true }
41208
+ });
41209
+ }
41210
+ };
41211
+
40423
41212
  // src/index.ts
40424
41213
  init();
40425
41214
  export {
@@ -40432,6 +41221,7 @@ export {
40432
41221
  BitmarkStringGenerator,
40433
41222
  BitmarkVersion,
40434
41223
  BodyTextFormat,
41224
+ BoundingBoxIndex,
40435
41225
  Builder,
40436
41226
  CardSetVersion,
40437
41227
  InfoFormat,