@gmb/bitmark-parser-generator 5.27.0 → 5.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/main.js CHANGED
@@ -1330,6 +1330,8 @@ var propertyKeys = {
1330
1330
  property_externalLinkText: "@externalLinkText",
1331
1331
  property_feedbackEngine: "@feedbackEngine",
1332
1332
  property_feedbackType: "@feedbackType",
1333
+ property_userFeedbackTranslationUrl: "@userFeedbackTranslationUrl",
1334
+ property_userFeedbackContentUrl: "@userFeedbackContentUrl",
1333
1335
  property_flashcardSet: "@flashcardSet",
1334
1336
  property_focusX: "@focusX",
1335
1337
  property_focusY: "@focusY",
@@ -3785,16 +3787,25 @@ var CARDSETS = {
3785
3787
  },
3786
3788
  {
3787
3789
  key: ConfigKey.property_tableRowSpan,
3790
+ // HTML-C2: contribute a `rowspan` attribute onto the enclosing
3791
+ // cell element (`<th>`/`<td>`).
3792
+ htmlKey: { "@el": { "@attr": { rowspan: "$" } } },
3788
3793
  description: "Number of rows the cell spans.",
3789
3794
  format: TagFormat.number
3790
3795
  },
3791
3796
  {
3792
3797
  key: ConfigKey.property_tableColSpan,
3798
+ // HTML-C2: contribute a `colspan` attribute onto the enclosing
3799
+ // cell element (`<th>`/`<td>`).
3800
+ htmlKey: { "@el": { "@attr": { colspan: "$" } } },
3793
3801
  description: "Number of columns the cell spans.",
3794
3802
  format: TagFormat.number
3795
3803
  },
3796
3804
  {
3797
3805
  key: ConfigKey.property_tableScope,
3806
+ // HTML-C2: contribute a `scope` attribute onto the enclosing
3807
+ // cell element (`<th>`/`<td>`).
3808
+ htmlKey: { "@el": { "@attr": { scope: "$" } } },
3798
3809
  description: "Scope attribute for header cells.",
3799
3810
  format: TagFormat.plainText
3800
3811
  },
@@ -3912,6 +3923,9 @@ var CARDSETS = {
3912
3923
  key: ConfigKey.property_tableRowSpan,
3913
3924
  jsonKey: "rowspan",
3914
3925
  exportJsonKey: { rowspan: "$" },
3926
+ // HTML-C2: contribute a `rowspan` attribute onto the enclosing
3927
+ // cell element (`<th>`/`<td>`).
3928
+ htmlKey: { "@el": { "@attr": { rowspan: "$" } } },
3915
3929
  description: "Number of rows the cell spans.",
3916
3930
  format: TagFormat.number
3917
3931
  },
@@ -3919,6 +3933,9 @@ var CARDSETS = {
3919
3933
  key: ConfigKey.property_tableColSpan,
3920
3934
  jsonKey: "colspan",
3921
3935
  exportJsonKey: { colspan: "$" },
3936
+ // HTML-C2: contribute a `colspan` attribute onto the enclosing
3937
+ // cell element (`<th>`/`<td>`).
3938
+ htmlKey: { "@el": { "@attr": { colspan: "$" } } },
3922
3939
  description: "Number of columns the cell spans.",
3923
3940
  format: TagFormat.number
3924
3941
  },
@@ -3926,6 +3943,9 @@ var CARDSETS = {
3926
3943
  key: ConfigKey.property_tableScope,
3927
3944
  jsonKey: "scope",
3928
3945
  exportJsonKey: { scope: "$" },
3946
+ // HTML-C2: contribute a `scope` attribute onto the enclosing
3947
+ // cell element (`<th>`/`<td>`).
3948
+ htmlKey: { "@el": { "@attr": { scope: "$" } } },
3929
3949
  description: "Scope attribute for header cells.",
3930
3950
  format: TagFormat.plainText
3931
3951
  },
@@ -5736,6 +5756,16 @@ var GROUPS = {
5736
5756
  description: "External Id of the translated book",
5737
5757
  format: TagFormat.plainText
5738
5758
  },
5759
+ {
5760
+ key: ConfigKey.property_userFeedbackTranslationUrl,
5761
+ description: "URL to an external feedback form for book translation feedback",
5762
+ format: TagFormat.plainText
5763
+ },
5764
+ {
5765
+ key: ConfigKey.property_userFeedbackContentUrl,
5766
+ description: "URL to an external feedback form for book content feedback",
5767
+ format: TagFormat.plainText
5768
+ },
5739
5769
  {
5740
5770
  key: ConfigKey.property_duration,
5741
5771
  description: "The duration of the book",
@@ -10838,7 +10868,9 @@ var BITS = {
10838
10868
  {
10839
10869
  key: ConfigKey.property_caption,
10840
10870
  description: "Caption for the table image, used to provide a description for the image",
10841
- format: TagFormat.bitmarkText
10871
+ format: TagFormat.bitmarkText,
10872
+ // HTML-10 / HTML-C2: render as the table's `<caption>` (see table bit).
10873
+ htmlKey: { "@el": "caption", "@children": "$" }
10842
10874
  },
10843
10875
  {
10844
10876
  key: ConfigKey.group_backgroundWallpaper,
@@ -12529,7 +12561,12 @@ var BITS = {
12529
12561
  {
12530
12562
  key: ConfigKey.property_caption,
12531
12563
  description: "Caption for the table, used to define the title of the table",
12532
- format: TagFormat.bitmarkText
12564
+ format: TagFormat.bitmarkText,
12565
+ // HTML-10 / HTML-C2: a bit-level caption renders as the table's
12566
+ // `<caption>` — placed inside the idiomatic `<table>` container as
12567
+ // its first child. Outside a table context it falls back to the
12568
+ // residual carrier.
12569
+ htmlKey: { "@el": "caption", "@children": "$" }
12533
12570
  },
12534
12571
  {
12535
12572
  key: ConfigKey.property_tableFixedHeader,
@@ -12614,7 +12651,9 @@ var BITS = {
12614
12651
  {
12615
12652
  key: ConfigKey.property_caption,
12616
12653
  description: "Caption for the table image, used to provide a description for the image",
12617
- format: TagFormat.bitmarkText
12654
+ format: TagFormat.bitmarkText,
12655
+ // HTML-10 / HTML-C2: render as the table's `<caption>` (see table bit).
12656
+ htmlKey: { "@el": "caption", "@children": "$" }
12618
12657
  },
12619
12658
  {
12620
12659
  key: ConfigKey.group_backgroundWallpaper,
@@ -13804,7 +13843,7 @@ var instance2 = new Config();
13804
13843
  // src/generated/package_info.ts
13805
13844
  var PACKAGE_INFO = {
13806
13845
  "name": "@gmb/bitmark-parser-generator",
13807
- "version": "5.27.0",
13846
+ "version": "5.28.0",
13808
13847
  "license": "ISC"};
13809
13848
  var Environment = {
13810
13849
  unknown: "",
@@ -14662,6 +14701,10 @@ var NodeType = {
14662
14701
  relatedBookValue: "relatedBookValue",
14663
14702
  translationOfBook: "translationOfBook",
14664
14703
  translationOfBookValue: "translationOfBookValue",
14704
+ userFeedbackTranslationUrl: "userFeedbackTranslationUrl",
14705
+ userFeedbackTranslationUrlValue: "userFeedbackTranslationUrlValue",
14706
+ userFeedbackContentUrl: "userFeedbackContentUrl",
14707
+ userFeedbackContentUrlValue: "userFeedbackContentUrlValue",
14665
14708
  releaseDate: "releaseDate",
14666
14709
  releaseDateValue: "releaseDateValue",
14667
14710
  releaseKind: "releaseKind",
@@ -27687,6 +27730,18 @@ var Builder = class extends BaseBuilder {
27687
27730
  data.translationOfBook,
27688
27731
  options
27689
27732
  ),
27733
+ userFeedbackTranslationUrl: this.toAstProperty(
27734
+ bitType,
27735
+ ConfigKey.property_userFeedbackTranslationUrl,
27736
+ data.userFeedbackTranslationUrl,
27737
+ options
27738
+ ),
27739
+ userFeedbackContentUrl: this.toAstProperty(
27740
+ bitType,
27741
+ ConfigKey.property_userFeedbackContentUrl,
27742
+ data.userFeedbackContentUrl,
27743
+ options
27744
+ ),
27690
27745
  author: this.toAstProperty(bitType, ConfigKey.property_author, data.author, options),
27691
27746
  subject: this.toAstProperty(bitType, ConfigKey.property_subject, data.subject, options),
27692
27747
  date: this.toAstProperty(bitType, ConfigKey.property_date, data.date, options),
@@ -31462,7 +31517,8 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
31462
31517
  this.writeNL();
31463
31518
  }
31464
31519
  const content = cell.content ?? instance3.EMPTY_STRING;
31465
- this.writeTextOrValue(content, this.textFormat, TextLocation.body);
31520
+ const options = this.options.noBreakscaping ? { noBreakscaping: true } : void 0;
31521
+ this.writeTextOrValue(content, this.textFormat, TextLocation.body, options);
31466
31522
  }
31467
31523
  writeTableCellProperty(name, value) {
31468
31524
  this.writeOPA();
@@ -32937,6 +32993,8 @@ var MARK_TO_TAG = {
32937
32993
  highlight: "mark",
32938
32994
  code: "code"
32939
32995
  };
32996
+ var INLINE_IMAGE_RE = /==([^=]*(?:=(?!=)[^=]*)*)==\|imageInline:([^|\s]+)((?:\|(?:@?[A-Za-z][A-Za-z0-9_-]*:[^|\s]+|#[^|\s]*))*)\|?/g;
32997
+ var MAX_IMAGE_DIMENSION = 9999;
32940
32998
  var HtmlTableGenerator = class {
32941
32999
  indentUnit = " ";
32942
33000
  /**
@@ -33053,6 +33111,8 @@ var HtmlTableGenerator = class {
33053
33111
  case "image":
33054
33112
  case "imageInline":
33055
33113
  return this.imageToHtml(node);
33114
+ case "latex":
33115
+ return this.latexToHtml(node);
33056
33116
  default:
33057
33117
  return this.inlineToHtml([node]);
33058
33118
  }
@@ -33063,8 +33123,9 @@ var HtmlTableGenerator = class {
33063
33123
  inlineNodeToHtml(node) {
33064
33124
  if (node.type === "hardBreak") return "<br>";
33065
33125
  if (node.type === "image" || node.type === "imageInline") return this.imageToHtml(node);
33126
+ if (node.type === "latex") return this.latexToHtml(node);
33066
33127
  if (node.type === "text") {
33067
- return this.wrapMarks(this.escapeText(node.text ?? ""), node.marks);
33128
+ return this.wrapMarks(this.textToHtml(node.text ?? ""), node.marks);
33068
33129
  }
33069
33130
  if (node.content) return this.inlineToHtml(node.content);
33070
33131
  return this.escapeText(node.text ?? "");
@@ -33142,6 +33203,44 @@ var HtmlTableGenerator = class {
33142
33203
  }
33143
33204
  return `<img ${parts.join(" ")}>`;
33144
33205
  }
33206
+ textToHtml(text) {
33207
+ let html = "";
33208
+ let lastIndex = 0;
33209
+ for (const match of text.matchAll(INLINE_IMAGE_RE)) {
33210
+ const index = match.index ?? 0;
33211
+ html += this.escapeText(text.slice(lastIndex, index));
33212
+ html += this.inlineImageTokenToHtml(match);
33213
+ lastIndex = index + match[0].length;
33214
+ }
33215
+ html += this.escapeText(text.slice(lastIndex));
33216
+ return html;
33217
+ }
33218
+ inlineImageTokenToHtml(match) {
33219
+ const attrs = {
33220
+ alt: match[1],
33221
+ src: match[2]
33222
+ };
33223
+ const rawAttrs = match[3] ?? "";
33224
+ for (const attr of rawAttrs.split("|")) {
33225
+ if (!attr || attr.startsWith("#")) continue;
33226
+ const colon = attr.indexOf(":");
33227
+ if (colon < 1) continue;
33228
+ const key = attr.slice(0, colon).replace(/^@/, "");
33229
+ const value = attr.slice(colon + 1);
33230
+ if (key === "width" || key === "height") {
33231
+ const n = Number.parseInt(value, 10);
33232
+ if (!Number.isNaN(n) && n > 0 && n <= MAX_IMAGE_DIMENSION) attrs[key] = n;
33233
+ } else if (key === "class" || key === "title") {
33234
+ attrs[key] = value;
33235
+ }
33236
+ }
33237
+ return this.imageToHtml({ type: "imageInline", attrs });
33238
+ }
33239
+ // --- formulas -------------------------------------------------------------
33240
+ latexToHtml(node) {
33241
+ const formula = node.attrs?.formula ?? "";
33242
+ return `<math alttext="${this.escapeAttr(formula)}"></math>`;
33243
+ }
33145
33244
  // --- escaping -------------------------------------------------------------
33146
33245
  escapeText(text) {
33147
33246
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -33450,6 +33549,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
33450
33549
  this.addProperty(this.bitJson, k, values, { array: true });
33451
33550
  }
33452
33551
  }
33552
+ return false;
33453
33553
  }
33454
33554
  // bitmarkAst -> bits -> bitsValue -> cardNode -> cardBits -> cardBitsValue
33455
33555
  enter_cardBitsValue(node, route) {
@@ -42381,7 +42481,7 @@ var IMPLIED_CLOSE = {
42381
42481
  p: /* @__PURE__ */ new Set(["p"]),
42382
42482
  option: /* @__PURE__ */ new Set(["option"])
42383
42483
  };
42384
- var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
42484
+ var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9:-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
42385
42485
  var ATTR_RE = /([a-zA-Z_:][a-zA-Z0-9:._-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
42386
42486
  function parseAttrs(raw) {
42387
42487
  const attrs = {};
@@ -42710,6 +42810,9 @@ var HtmlTableParser = class {
42710
42810
  if (name === "img") {
42711
42811
  return [this.imageNode(el, true)];
42712
42812
  }
42813
+ if (this.isMathTag(name)) {
42814
+ return [this.latexNode(el)];
42815
+ }
42713
42816
  const markType = MARK_TAGS[name];
42714
42817
  if (markType) {
42715
42818
  return this.inlineNodes(el.children, [...marks, { type: markType }]);
@@ -42826,6 +42929,43 @@ var HtmlTableParser = class {
42826
42929
  if (el.attrs.class) attrs.class = el.attrs.class;
42827
42930
  return { type: inline ? "imageInline" : "image", attrs };
42828
42931
  }
42932
+ // --- formulas -------------------------------------------------------------
42933
+ isMathTag(name) {
42934
+ return this.localName(name) === "math";
42935
+ }
42936
+ latexNode(el) {
42937
+ return {
42938
+ type: "latex",
42939
+ attrs: {
42940
+ formula: this.latexFromMath(el)
42941
+ }
42942
+ };
42943
+ }
42944
+ latexFromMath(el) {
42945
+ const alt = el.attrs.alttext ?? el.attrs.alt ?? el.attrs.title;
42946
+ if (alt != null) return decodeEntities(alt);
42947
+ const annotation = this.findLatexAnnotation(el);
42948
+ if (annotation) return this.textContent(annotation).trim();
42949
+ return this.textContent(el).trim();
42950
+ }
42951
+ findLatexAnnotation(el) {
42952
+ for (const child of el.children) {
42953
+ if (!isElement(child)) continue;
42954
+ const lowerEncoding = (child.attrs.encoding ?? "").toLowerCase();
42955
+ if (this.localName(child.name) === "annotation" && (/\btex\b/.test(lowerEncoding) || /\blatex\b/.test(lowerEncoding))) {
42956
+ return child;
42957
+ }
42958
+ const nested = this.findLatexAnnotation(child);
42959
+ if (nested) return nested;
42960
+ }
42961
+ return void 0;
42962
+ }
42963
+ textContent(el) {
42964
+ return el.children.map((child) => isElement(child) ? this.textContent(child) : decodeEntities(child.value)).join("").replace(/\s+/g, " ");
42965
+ }
42966
+ localName(name) {
42967
+ return name.includes(":") ? name.slice(name.indexOf(":") + 1) : name;
42968
+ }
42829
42969
  // --- whitespace -----------------------------------------------------------
42830
42970
  /** Trim leading/trailing whitespace from inline content (edges only). */
42831
42971
  trimInline(nodes) {
@@ -44723,7 +44863,10 @@ var BitmarkParserGenerator = class {
44723
44863
  outputFile: opts.outputFile,
44724
44864
  fileOptions: opts.fileOptions,
44725
44865
  jsonOptions: opts.jsonOptions,
44726
- bitmarkOptions: opts.bitmarkOptions
44866
+ bitmarkOptions: {
44867
+ ...opts.bitmarkOptions,
44868
+ ...opts.noBreakscaping ? { noBreakscaping: true } : {}
44869
+ }
44727
44870
  });
44728
44871
  }
44729
44872
  const outputFormat = opts.outputFormat ?? "html";
@@ -45085,7 +45228,7 @@ function createConvertHtmlTableCommand() {
45085
45228
  )
45086
45229
  ).addOption(
45087
45230
  new Option("--tableFormat <format>", "bit type to emit for HTML input").choices(TABLE_FORMAT_CHOICES).default("table-extended")
45088
- ).option("--keepUnknownTags", "keep unmappable HTML tags as literal text (HTML input only)").option("-p, --pretty", "prettify the JSON output with indent").option(
45231
+ ).option("--keepUnknownTags", "keep unmappable HTML tags as literal text (HTML input only)").option("--noBreakscaping", "do not breakscape generated bitmark table cell content").option("-p, --pretty", "prettify the JSON output with indent").option(
45089
45232
  "--indent <indent>",
45090
45233
  "prettify indent (default: 2 when --pretty is set)",
45091
45234
  (v) => Number.parseInt(v, 10)
@@ -45101,6 +45244,7 @@ function createConvertHtmlTableCommand() {
45101
45244
  options.tableFormat
45102
45245
  ),
45103
45246
  keepUnknownTags: options.keepUnknownTags,
45247
+ noBreakscaping: options.noBreakscaping,
45104
45248
  jsonOptions: {
45105
45249
  prettify
45106
45250
  }
@@ -45126,7 +45270,9 @@ Examples:
45126
45270
 
45127
45271
  $ bitmark-parser convertHtmlTable input.bitmark -o output.html
45128
45272
 
45129
- $ bitmark-parser convertHtmlTable --tableFormat table input.html`
45273
+ $ bitmark-parser convertHtmlTable --tableFormat table input.html
45274
+
45275
+ $ bitmark-parser convertHtmlTable --noBreakscaping input.html`
45130
45276
  );
45131
45277
  return cmd;
45132
45278
  }