@gmb/bitmark-parser 6.2.0 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { createRequire } from "module";
10
10
  // src/generated/package_info.ts
11
11
  var PACKAGE_INFO = {
12
12
  "name": "@gmb/bitmark-parser",
13
- "version": "6.2.0",
13
+ "version": "6.3.1",
14
14
  "author": "Get More Brain Ltd <info@getmorebrain.com>",
15
15
  "license": "ISC",
16
16
  "description": "A parser for bitmark text, powered by WebAssembly."
@@ -316,16 +316,14 @@ function validateVersionOptions(opts) {
316
316
  }
317
317
  function validateBitmarkOptions(o) {
318
318
  if (o.explicitTextFormat) unsupportedOption("bitmarkOptions.explicitTextFormat");
319
- if (o.prettifyJson !== void 0 && o.prettifyJson !== false) {
320
- unsupportedOption("bitmarkOptions.prettifyJson", "embedded-JSON body prettification is not supported");
319
+ if (o.cardSetVersion === 1) {
320
+ unsupportedOption("bitmarkOptions.cardSetVersion: 1", V3_ONLY);
321
321
  }
322
- if (o.cardSetVersion === 1) unsupportedOption("bitmarkOptions.cardSetVersion: 1", V3_ONLY);
323
322
  if (o.debugGenerationInline) unsupportedOption("bitmarkOptions.debugGenerationInline");
324
323
  if (o.noBreakscaping) unsupportedOption("bitmarkOptions.noBreakscaping");
325
324
  }
326
325
  function validateJsonOptions(o) {
327
326
  if (o.textAsPlainText) unsupportedOption("jsonOptions.textAsPlainText", V3_ONLY);
328
- if (o.excludeUnknownProperties) unsupportedOption("jsonOptions.excludeUnknownProperties");
329
327
  if (o.debugGenerationInline) unsupportedOption("jsonOptions.debugGenerationInline");
330
328
  }
331
329
  function prettyIndent(prettify) {
@@ -361,6 +359,14 @@ function isPseudoAst(v) {
361
359
  return v !== null && typeof v === "object" && (PSEUDO_AST_MARKER in v || Array.isArray(v.bits));
362
360
  }
363
361
 
362
+ // src/legacy/generated/resource-collection-keys.ts
363
+ var RESOURCE_COLLECTION_KEYS = {
364
+ "extractor-image": { key: "images", resourceType: "image" },
365
+ "extractor-image-collapsible": { key: "images", resourceType: "image" },
366
+ "images-logo-grave": { key: "logos", resourceType: "image" },
367
+ "prototype-images": { key: "images", resourceType: "image" }
368
+ };
369
+
364
370
  // src/legacy/builder.ts
365
371
  var BUILT_BIT_PARSER = /* @__PURE__ */ Symbol.for("@gmb/bitmark-parser/legacy-built-bit-parser");
366
372
  var DATA_KEY_TO_JSON_KEY = {
@@ -373,6 +379,13 @@ var DEPRECATED_TEXT_FORMATS = {
373
379
  "bitmark--": "bitmark++",
374
380
  "bitmark+": "bitmark++"
375
381
  };
382
+ var CONFIG_BODY_FORMAT_TO_TEXT_FORMAT = {
383
+ bitmark: "bitmark++",
384
+ text: "text",
385
+ json: "json",
386
+ latex: "latex",
387
+ xml: "xml"
388
+ };
376
389
  var TAG_TEXT_KEYS = [
377
390
  "title",
378
391
  "subtitle",
@@ -405,16 +418,20 @@ var Builder = class {
405
418
  * NOTE (documented divergences from bpg):
406
419
  * - the return value is bit JSON, not bpg's internal AST node model;
407
420
  * - `resourceType` (an inference hint in bpg) is not carried into the
408
- * JSON — the attached `resource` object is authoritative;
409
- * - more than one entry in `resources` passes through under a
410
- * `resources` key (kept visible, not silently dropped) — the canonical
411
- * single attachment is `resource`.
421
+ * JSON — the attached `resource` object is authoritative.
422
+ *
423
+ * `resources` follows bpg's JsonGenerator routing: on a bit whose config
424
+ * maps a repeatable resource tag group onto a collection key (e.g.
425
+ * `images` / `logos` — see the generated RESOURCE_COLLECTION_KEYS), the
426
+ * matching-type entries land under that key; on every other bit the first
427
+ * entry becomes the canonical single `resource` (as bpg: "if there is
428
+ * more than one resource, use the first one").
412
429
  */
413
430
  buildBit(data, _options) {
414
431
  const wasm2 = getLegacyWasm();
415
432
  const src = { ...data };
416
433
  const bitType = src.bitType;
417
- this.assertKnownBitType(bitType);
434
+ const bitConfig = this.getBitConfig(bitType);
418
435
  const bit = {};
419
436
  bit.type = bitType;
420
437
  if (src.isCommented) {
@@ -427,6 +444,8 @@ var Builder = class {
427
444
  if (textFormat !== void 0) {
428
445
  bit.format = DEPRECATED_TEXT_FORMATS[textFormat] ?? textFormat;
429
446
  delete src.textFormat;
447
+ } else {
448
+ bit.format = CONFIG_BODY_FORMAT_TO_TEXT_FORMAT[bitConfig.bodyFormat ?? ""] ?? "bitmark++";
430
449
  }
431
450
  delete src.resourceType;
432
451
  const body = src.body;
@@ -444,12 +463,15 @@ var Builder = class {
444
463
  delete src.__isDefaultExample;
445
464
  }
446
465
  const resources = src.resources;
447
- if (resources !== void 0) {
448
- if (Array.isArray(resources)) {
449
- if (resources.length === 1) bit.resource = resources[0];
450
- else if (resources.length > 1) bit.resources = resources;
451
- } else {
452
- bit.resource = resources;
466
+ if (resources !== void 0 && bitType !== void 0) {
467
+ const list = Array.isArray(resources) ? resources : [resources];
468
+ const collection = RESOURCE_COLLECTION_KEYS[bitType];
469
+ if (collection) {
470
+ bit[collection.key] = list.filter(
471
+ (r) => r !== null && typeof r === "object" && r.type === collection.resourceType
472
+ );
473
+ } else if (list.length >= 1) {
474
+ bit.resource = list[0];
453
475
  }
454
476
  delete src.resources;
455
477
  }
@@ -467,7 +489,7 @@ var Builder = class {
467
489
  }
468
490
  }
469
491
  this.parseStringTexts(bit);
470
- const out = wasm2.convert(JSON.stringify([{ bit }]), "json", "json", "optimized", false, 2, 1);
492
+ const out = wasm2.convert(JSON.stringify([{ bit }]), "json", "json", "optimized", false, 2, 1, false);
471
493
  if (out.startsWith("error:")) {
472
494
  throw new Error(out.slice("error:".length).trim());
473
495
  }
@@ -515,6 +537,12 @@ var Builder = class {
515
537
  * (inline marks become TextAst marks); the composer would otherwise treat
516
538
  * them as literal text. Converts top-level JsonText fields in place.
517
539
  * Nested (card-content) strings are left literal — documented divergence.
540
+ *
541
+ * A string body is dispatched on the bit's resolved text format, as bpg's
542
+ * buildBody: bitmark text is parsed to TextAst, `json` is JSON.parsed
543
+ * (unparseable → null), and plain-text formats (text/latex/xml) stay
544
+ * verbatim. Tag texts are always bitmark text, independent of body format
545
+ * (bpg TextParser.toAst ignores format; only location matters).
518
546
  */
519
547
  parseStringTexts(bit) {
520
548
  const wasm2 = getLegacyWasm();
@@ -529,29 +557,36 @@ var Builder = class {
529
557
  };
530
558
  const format = bit.format;
531
559
  const bitmarkBody = format === void 0 || format === "bitmark++" || format === "bitmark+";
532
- if (typeof bit.body === "string" && bitmarkBody) {
533
- bit.body = toAst(bit.body, "body");
560
+ if (typeof bit.body === "string") {
561
+ if (format === "json") {
562
+ try {
563
+ bit.body = JSON.parse(bit.body);
564
+ } catch {
565
+ bit.body = null;
566
+ }
567
+ } else if (bitmarkBody) {
568
+ bit.body = toAst(bit.body, "body");
569
+ }
534
570
  }
535
571
  for (const key of TAG_TEXT_KEYS) {
536
572
  const v = bit[key];
537
573
  if (typeof v === "string") bit[key] = toAst(v, "tag");
538
574
  }
539
575
  }
540
- /** Throw bpg's exact unknown-bit-type error (`Config.getBitConfig` parity). */
541
- assertKnownBitType(bitType) {
576
+ /**
577
+ * Look up the bit's config (`wasm.info`); throws bpg's exact
578
+ * unknown-bit-type error (`Config.getBitConfig` parity).
579
+ */
580
+ getBitConfig(bitType) {
542
581
  const wasm2 = getLegacyWasm();
543
- let known = false;
544
582
  if (bitType !== void 0) {
545
583
  try {
546
584
  const info2 = JSON.parse(wasm2.info("bit", "json", bitType, false, 2));
547
- known = info2.error === void 0;
585
+ if (info2.error === void 0) return info2;
548
586
  } catch {
549
- known = false;
550
587
  }
551
588
  }
552
- if (!known) {
553
- throw new Error(`No config found for bit: ${bitType}`);
554
- }
589
+ throw new Error(`No config found for bit: ${bitType}`);
555
590
  }
556
591
  };
557
592
  function stripUndefined(src, exclude) {
@@ -591,8 +626,10 @@ var BitmarkParserGenerator = class {
591
626
  const outputFormat = opts.outputFormat ?? (isBitmark ? "json" : "bitmark");
592
627
  const coreFormat = outputFormat === "ast" ? "json" : outputFormat;
593
628
  const { pretty, indent } = prettyIndent(jsonOptions.prettify);
629
+ const emit = coreFormat === "bitmark" ? prettyIndent(bitmarkOptions.prettifyJson) : { pretty, indent };
594
630
  const spaces = spacesAround(bitmarkOptions.spacesAroundValues);
595
- const out = wasm2.convert(source, isBitmark ? "bitmark" : "json", coreFormat, "optimized", pretty, indent, spaces);
631
+ const includeUnknown = !jsonOptions.excludeUnknownProperties;
632
+ const out = wasm2.convert(source, isBitmark ? "bitmark" : "json", coreFormat, "optimized", emit.pretty, emit.indent, spaces, includeUnknown);
596
633
  this.throwOnError(out);
597
634
  if (outputFormat === "bitmark" || outputFormat === "text") {
598
635
  return this.deliver(out, opts.outputFile, opts.fileOptions);
@@ -622,7 +659,9 @@ var BitmarkParserGenerator = class {
622
659
  this.checkBrowserFileWrite(opts.outputFile);
623
660
  const wasm2 = getLegacyWasm();
624
661
  const { source, isBitmark } = this.resolveInput(input, opts.inputFormat);
625
- const { pretty, indent } = prettyIndent(jsonOptions.prettify);
662
+ const { pretty, indent } = prettyIndent(
663
+ isBitmark ? bitmarkOptions.prettifyJson : jsonOptions.prettify
664
+ );
626
665
  const spaces = spacesAround(bitmarkOptions.spacesAroundValues);
627
666
  const out = wasm2.canonicalize(source, isBitmark ? "bitmark" : "json", "optimized", pretty, indent, spaces);
628
667
  this.throwOnError(out);
@@ -674,7 +713,7 @@ var BitmarkParserGenerator = class {
674
713
  const isHtmlInput = opts.inputFormat === "html" || opts.inputFormat === void 0 && typeof input === "string" && /<table[\s>]/iu.test(inStr);
675
714
  if (!isHtmlInput) {
676
715
  const { source, isBitmark } = this.resolveInput(input, void 0);
677
- const out2 = wasm2.convert(source, isBitmark ? "bitmark" : "json", "html", "optimized", false, 2, 1);
716
+ const out2 = wasm2.convert(source, isBitmark ? "bitmark" : "json", "html", "optimized", false, 2, 1, false);
678
717
  this.throwOnError(out2);
679
718
  return this.deliver(extractHtmlTables(out2).join("\n"), opts.outputFile, opts.fileOptions);
680
719
  }
@@ -684,12 +723,12 @@ var BitmarkParserGenerator = class {
684
723
  const { pretty, indent } = prettyIndent(jsonOptions.prettify);
685
724
  const spaces = spacesAround(bitmarkOptions.spacesAroundValues);
686
725
  if (outputFormat === "html") {
687
- const out2 = wasm2.convert(wrapped, "html", "html", "optimized", false, 2, 1);
726
+ const out2 = wasm2.convert(wrapped, "html", "html", "optimized", false, 2, 1, false);
688
727
  this.throwOnError(out2);
689
728
  return this.deliver(extractHtmlTables(out2).join("\n"), opts.outputFile, opts.fileOptions);
690
729
  }
691
730
  const coreFormat = outputFormat === "ast" ? "json" : outputFormat;
692
- const out = wasm2.convert(wrapped, "html", coreFormat, "optimized", pretty, indent, spaces);
731
+ const out = wasm2.convert(wrapped, "html", coreFormat, "optimized", pretty, indent, spaces, false);
693
732
  this.throwOnError(out);
694
733
  if (outputFormat === "bitmark" || outputFormat === "text") {
695
734
  return this.deliver(out, opts.outputFile, opts.fileOptions);
@@ -714,7 +753,7 @@ var BitmarkParserGenerator = class {
714
753
  const opts = Object.assign({}, options);
715
754
  const wasm2 = getLegacyWasm();
716
755
  const { source, isBitmark } = this.resolveInput(input, opts.inputFormat);
717
- const out = wasm2.convert(source, isBitmark ? "bitmark" : "json", "json", "optimized", false, 2, 1);
756
+ const out = wasm2.convert(source, isBitmark ? "bitmark" : "json", "json", "optimized", false, 2, 1, true);
718
757
  this.throwOnError(out);
719
758
  return makePseudoAst(JSON.parse(out));
720
759
  }
@@ -821,7 +860,7 @@ var BitmarkParserGenerator = class {
821
860
  }
822
861
  }
823
862
  const { source, isBitmark } = this.resolveInput(input, void 0);
824
- const out = wasm2.convert(source, isBitmark ? "bitmark" : "json", "text", "optimized", false, 2, 1);
863
+ const out = wasm2.convert(source, isBitmark ? "bitmark" : "json", "text", "optimized", false, 2, 1, false);
825
864
  this.throwOnError(out);
826
865
  return out;
827
866
  }
@@ -1306,19 +1345,25 @@ function version() {
1306
1345
  function lex(input, options = {}) {
1307
1346
  return wasm.lex(input, options.stage ?? "lex");
1308
1347
  }
1309
- function parse(input, options = {}) {
1310
- return wasm.parse(input, options.mode ?? "optimized");
1311
- }
1312
- function parseBits(input, options = {}) {
1313
- const out = wasm.convert(input, "auto", "json", options.mode ?? "optimized", false, 2, 1);
1348
+ function bitmarkToObjects(input, options = {}) {
1349
+ const out = wasm.convert(
1350
+ input,
1351
+ "bitmark",
1352
+ "json",
1353
+ options.mode ?? "optimized",
1354
+ false,
1355
+ 2,
1356
+ 1,
1357
+ options.includeUnknownProperties ?? false
1358
+ );
1314
1359
  if (out.startsWith("error:")) throw new Error(out.slice("error:".length).trim());
1315
1360
  return JSON.parse(out);
1316
1361
  }
1317
- function generateBits(bits, options = {}) {
1362
+ function objectsToBitmark(bits, options = {}) {
1318
1363
  const entries = bits.map(
1319
1364
  (b) => b !== null && typeof b === "object" && "bit" in b && typeof b.bit === "object" ? b : { bit: b }
1320
1365
  );
1321
- const out = wasm.convert(JSON.stringify(entries), "json", "bitmark", options.mode ?? "optimized", false, 2, 1);
1366
+ const out = wasm.convert(JSON.stringify(entries), "json", "bitmark", options.mode ?? "optimized", false, 2, 1, false);
1322
1367
  if (out.startsWith("error:")) throw new Error(out.slice("error:".length).trim());
1323
1368
  return out;
1324
1369
  }
@@ -1330,16 +1375,10 @@ function convert(input, options = {}) {
1330
1375
  options.mode ?? "optimized",
1331
1376
  options.pretty ?? false,
1332
1377
  options.indent ?? 2,
1333
- options.spacesAroundValues ?? 1
1378
+ options.spacesAroundValues ?? 1,
1379
+ options.includeUnknownProperties ?? false
1334
1380
  );
1335
1381
  }
1336
- function optimize(input, options = {}) {
1337
- return wasm.optimize(input, options.inputFormat ?? "auto", options.pretty ?? false, options.indent ?? 2);
1338
- }
1339
- function fullize(input, options = {}) {
1340
- return wasm.fullize(input, options.inputFormat ?? "auto", options.pretty ?? false, options.indent ?? 2);
1341
- }
1342
- var expand = fullize;
1343
1382
  function canonicalize(input, options = {}) {
1344
1383
  return wasm.canonicalize(
1345
1384
  input,
@@ -1395,24 +1434,16 @@ function info(options = {}) {
1395
1434
  const indent = options.indent ?? 2;
1396
1435
  return wasm.info(infoType, format, bit, pretty, indent);
1397
1436
  }
1398
- function generate(input, options = {}) {
1399
- return wasm.convert(input, "json", "bitmark", options.mode ?? "optimized", false, 2, 1);
1400
- }
1401
1437
  export {
1438
+ bitmarkToObjects,
1402
1439
  breakscapeText,
1403
1440
  canonicalize,
1404
1441
  convert,
1405
1442
  countBits,
1406
- expand,
1407
- fullize,
1408
- generate,
1409
- generateBits,
1410
1443
  info,
1411
1444
  legacy_exports as legacy,
1412
1445
  lex,
1413
- optimize,
1414
- parse,
1415
- parseBits,
1446
+ objectsToBitmark,
1416
1447
  patchEntry,
1417
1448
  splitBits,
1418
1449
  transform,