@gmb/bitmark-parser-generator 5.39.0 → 5.41.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.
@@ -67,6 +67,8 @@ var BitType2 = {
67
67
  // Used to indicate a bit is commented out
68
68
  _standard: "_standard",
69
69
  // Not to be used as a bit, but as a base for other bit types
70
+ _standardLight: "_standard-light",
71
+ // PLAN-021: lightweight base (minimal tag set), not to be used as a bit
70
72
  advertising: "advertising",
71
73
  advertisingAdvertorial: "advertising-advertorial",
72
74
  advertisingAdvertorialPage: "advertising-advertorial-page",
@@ -354,6 +356,7 @@ var BitType2 = {
354
356
  handInSystemMedia: "hand-in-system-media",
355
357
  handInVideo: "hand-in-video",
356
358
  handInVoice: "hand-in-voice",
359
+ h: "h",
357
360
  help: "help",
358
361
  helpAlt: "help-alt",
359
362
  highlightText: "highlight-text",
@@ -439,6 +442,7 @@ var BitType2 = {
439
442
  leWatchVideoEmbed: "le-watch-video-embed",
440
443
  lifeSkillSticker: "life-skill-sticker",
441
444
  list: "list",
445
+ listAlt: "list-alt",
442
446
  listItem: "list-item",
443
447
  mark: "mark",
444
448
  match: "match",
@@ -469,6 +473,8 @@ var BitType2 = {
469
473
  notebookArticle: "notebook-article",
470
474
  noteCollapsible: "note-collapsible",
471
475
  output: "output",
476
+ p: "p",
477
+ pAlt: "p-alt",
472
478
  page: "page",
473
479
  pageAcademy: "page-academy",
474
480
  pageArticle: "page-article",
@@ -591,6 +597,7 @@ var BitType2 = {
591
597
  smartStandardNoteNonNormativeCollapsible: "smart-standard-note-non-normative-collapsible",
592
598
  smartStandardNoteNormative: "smart-standard-note-normative",
593
599
  smartStandardNoteNormativeCollapsible: "smart-standard-note-normative-collapsible",
600
+ smartStandardP: "smart-standard-p",
594
601
  smartStandardRemarkLegend: "smart-standard-remark-legend",
595
602
  smartStandardRemarkLegendNonNormative: "smart-standard-remark-legend-non-normative",
596
603
  smartStandardRemarkLegendNormative: "smart-standard-remark-legend-normative",
@@ -1560,6 +1567,8 @@ var import_superenum12 = require("@ncoderz/superenum");
1560
1567
  var groupKeys = {
1561
1568
  group_accessibilityDecorative: "group_accessibilityDecorative",
1562
1569
  group_standardAllBits: "group_standardAllBits",
1570
+ group_standardExample: "group_standardExample",
1571
+ group_standardItem: "group_standardItem",
1563
1572
  group_standardItemLead: "group_standardItemLead",
1564
1573
  group_standardItemLeadInstructionHint: "group_standardItemLeadInstructionHint",
1565
1574
  group_standardInstructionHint: "group_standardInstructionHint",
@@ -5059,6 +5068,34 @@ var GROUPS = {
5059
5068
  }
5060
5069
  ]
5061
5070
  },
5071
+ [ConfigKey.group_standardExample]: {
5072
+ type: GroupConfigType.standard,
5073
+ description: "PLAN-021: Standard group for the bit-level example property only. Mirror of the group_standardTags property_example entry, used by the lightweight bits (_standardLight).",
5074
+ tags: [
5075
+ {
5076
+ key: ConfigKey.property_example,
5077
+ exportJsonKey: [{ "@keyonly": {} }, { "@absent": { isExample: true } }, { example: "$" }],
5078
+ description: "The example(s) for the bit",
5079
+ format: TagFormat.bitmarkText,
5080
+ nullable: true
5081
+ }
5082
+ ]
5083
+ },
5084
+ [ConfigKey.group_standardItem]: {
5085
+ type: GroupConfigType.standard,
5086
+ description: "PLAN-021: Standard group for the item tag ONLY (no lead/pageNumber/marginNumber chain). Used by the lightweight bits (_standardLight).",
5087
+ tags: [
5088
+ {
5089
+ key: ConfigKey.tag_item,
5090
+ jsonKey: "item",
5091
+ exportJsonKey: { item: "$" },
5092
+ // PLAN-140 W3 (NISO import): the clause/note label of a mapped
5093
+ // source element ([%1], [%ANMERKUNG 1]) — same as group_standardItemLead.
5094
+ mappingKeys: { "xml-niso-iec": { "@el": "label", "@text": "$" } },
5095
+ description: "The item for the bit"
5096
+ }
5097
+ ]
5098
+ },
5062
5099
  [ConfigKey.group_standardItemLead]: {
5063
5100
  type: GroupConfigType.standard,
5064
5101
  description: "Standard group for item, lead, page number, and margin number tags",
@@ -7862,6 +7899,25 @@ var BITS = {
7862
7899
  }
7863
7900
  ]
7864
7901
  },
7902
+ [BitType2._standardLight]: {
7903
+ since: "5.40.0",
7904
+ description: "PLAN-021: Lightweight standard base bit with a minimal tag set (item + example only \u2014 no instruction/hint/lead, no resource attachments), used as a base for other bits, should not be used directly",
7905
+ resourceAttachmentAllowed: false,
7906
+ tags: [
7907
+ {
7908
+ key: ConfigKey.group_standardAllBits,
7909
+ description: "Standard tags for all bits"
7910
+ },
7911
+ {
7912
+ key: ConfigKey.group_standardItem,
7913
+ description: "The item tag (no lead/pageNumber/marginNumber chain)"
7914
+ },
7915
+ {
7916
+ key: ConfigKey.group_standardExample,
7917
+ description: "The bit-level example property"
7918
+ }
7919
+ ]
7920
+ },
7865
7921
  [BitType2.appFlashcards]: {
7866
7922
  since: "1.3.0",
7867
7923
  title: "Flashcards",
@@ -10689,6 +10745,23 @@ var BITS = {
10689
10745
  baseBitType: BitType2.article,
10690
10746
  description: "Glossary term bit, used to define glossary terms in articles or books"
10691
10747
  },
10748
+ [BitType2.h]: {
10749
+ since: "5.40.0",
10750
+ title: "Heading",
10751
+ bitGroups: [BitGroup.static],
10752
+ baseBitType: BitType2._standardLight,
10753
+ description: "Lightweight heading bit with chapter-style title levels 1-7; title/level + item only \u2014 no body, no footer",
10754
+ bodyAllowed: false,
10755
+ footerAllowed: false,
10756
+ tags: [
10757
+ {
10758
+ key: ConfigKey.tag_title,
10759
+ description: "The title of the heading",
10760
+ jsonKey: "title|setMulti(level)",
10761
+ exportJsonKey: { title: "$", level: "$level" }
10762
+ }
10763
+ ]
10764
+ },
10692
10765
  [BitType2.help]: {
10693
10766
  since: "1.3.0",
10694
10767
  title: "Help",
@@ -10875,13 +10948,22 @@ var BITS = {
10875
10948
  since: "1.22.0",
10876
10949
  title: "List",
10877
10950
  bitGroups: [BitGroup.static],
10878
- baseBitType: BitType2.article,
10951
+ // PLAN-021: rebased from article onto the lightweight base
10952
+ baseBitType: BitType2._standardLight,
10879
10953
  description: "List bit, used to create lists in articles or books"
10880
10954
  },
10955
+ [BitType2.listAlt]: {
10956
+ since: "5.40.0",
10957
+ title: "List Alt",
10958
+ bitGroups: [BitGroup.static],
10959
+ baseBitType: BitType2.list,
10960
+ description: "Lightweight list bit (alternative), based on list"
10961
+ },
10881
10962
  [BitType2.standardList]: {
10882
10963
  since: "1.22.0",
10883
10964
  bitGroups: [BitGroup.static],
10884
- baseBitType: BitType2.article,
10965
+ // PLAN-021: re-rooted from article onto the lightweight list
10966
+ baseBitType: BitType2.list,
10885
10967
  description: "Standard list bit, used to create standard lists in articles or books"
10886
10968
  },
10887
10969
  [BitType2.smartStandardList]: {
@@ -10897,6 +10979,13 @@ var BITS = {
10897
10979
  "xml-niso-iec": { "@el": "ref-list", "@attr": { id: "$customerId" }, "\u25BC": "$anchor" }
10898
10980
  }
10899
10981
  },
10982
+ [BitType2.smartStandardP]: {
10983
+ since: "5.40.0",
10984
+ title: "Smart Standard Paragraph",
10985
+ bitGroups: [BitGroup.static],
10986
+ baseBitType: BitType2.p,
10987
+ description: "Smart standard paragraph bit, based on p"
10988
+ },
10900
10989
  [BitType2.smartStandardListCollapsible]: {
10901
10990
  since: "1.28.0",
10902
10991
  deprecated: "5.37.0",
@@ -13478,7 +13567,8 @@ var BITS = {
13478
13567
  [BitType2.listItem]: {
13479
13568
  since: "1.22.0",
13480
13569
  bitGroups: [BitGroup.static],
13481
- baseBitType: BitType2.article,
13570
+ // PLAN-021: rebased from article onto the lightweight base
13571
+ baseBitType: BitType2._standardLight,
13482
13572
  description: "List item bit, used to create list items in articles or books",
13483
13573
  tags: [
13484
13574
  {
@@ -13883,6 +13973,20 @@ var BITS = {
13883
13973
  baseBitType: BitType2.multipleResponse,
13884
13974
  description: "Coach self-reflection multiple response bit, used for self-reflection in coaching"
13885
13975
  },
13976
+ [BitType2.p]: {
13977
+ since: "5.40.0",
13978
+ title: "Paragraph",
13979
+ bitGroups: [BitGroup.static],
13980
+ baseBitType: BitType2._standardLight,
13981
+ description: "Lightweight paragraph bit with a minimal tag set"
13982
+ },
13983
+ [BitType2.pAlt]: {
13984
+ since: "5.40.0",
13985
+ title: "Paragraph Alt",
13986
+ bitGroups: [BitGroup.static],
13987
+ baseBitType: BitType2.p,
13988
+ description: "Lightweight paragraph bit (alternative), based on p"
13989
+ },
13886
13990
  [BitType2.page]: {
13887
13991
  since: "1.3.0",
13888
13992
  title: "Page",
@@ -16613,7 +16717,7 @@ var instance2 = new Config();
16613
16717
  // src/generated/package_info.ts
16614
16718
  var PACKAGE_INFO = {
16615
16719
  "name": "@gmb/bitmark-parser-generator",
16616
- "version": "5.39.0",
16720
+ "version": "5.41.0",
16617
16721
  "author": "Get More Brain Ltd",
16618
16722
  "license": "ISC",
16619
16723
  "description": "A bitmark parser and generator using Peggy.js"
@@ -18467,6 +18571,752 @@ var AstWalkerGenerator = class {
18467
18571
  }
18468
18572
  };
18469
18573
 
18574
+ // src/generator/text/TextGrammarConstraints.ts
18575
+ var COLORS = [
18576
+ "aqua",
18577
+ "black",
18578
+ "blue",
18579
+ "brown",
18580
+ "fuchsia",
18581
+ "lightgrey",
18582
+ "gray",
18583
+ "darkgray",
18584
+ "green",
18585
+ "lime",
18586
+ "magenta",
18587
+ "maroon",
18588
+ "navy",
18589
+ "olive",
18590
+ "orange",
18591
+ "pink",
18592
+ "purple",
18593
+ "red",
18594
+ "silver",
18595
+ "teal",
18596
+ "violet",
18597
+ "white",
18598
+ "yellow"
18599
+ ];
18600
+ var HIGHLIGHT_COLORS = [
18601
+ "orange",
18602
+ "yellow",
18603
+ "green",
18604
+ "blue",
18605
+ "purple",
18606
+ "pink",
18607
+ "brown",
18608
+ "white",
18609
+ "black",
18610
+ "gray"
18611
+ ];
18612
+ var ALTERNATIVE_STYLE_TAGS = [
18613
+ "bold",
18614
+ "italic",
18615
+ "light",
18616
+ "highlightOrange",
18617
+ "highlightYellow",
18618
+ "highlightGreen",
18619
+ "highlightBlue",
18620
+ "highlightPurple",
18621
+ "highlightPink",
18622
+ "highlightBrown",
18623
+ "highlightBlack",
18624
+ "highlightWhite",
18625
+ "highlightGray",
18626
+ "highlight",
18627
+ "strike",
18628
+ "subscript",
18629
+ "superscript",
18630
+ "ins",
18631
+ "del",
18632
+ "underline",
18633
+ "doubleUnderline",
18634
+ "smallcaps",
18635
+ "circle",
18636
+ "languageEmRed",
18637
+ "languageEmOrange",
18638
+ "languageEmYellow",
18639
+ "languageEmGreen",
18640
+ "languageEmBlue",
18641
+ "languageEmPurple",
18642
+ "languageEmPink",
18643
+ "languageEmBrown",
18644
+ "languageEmBlack",
18645
+ "languageEmWhite",
18646
+ "languageEmGray",
18647
+ "languageEm",
18648
+ "userUnderline",
18649
+ "userDoubleUnderline",
18650
+ "userStrike",
18651
+ "userCircle",
18652
+ "userHighlight",
18653
+ "notranslate"
18654
+ ];
18655
+ var MEDIA_ALIGNMENTS = ["left", "center", "right"];
18656
+ var INLINE_MEDIA_ALIGNMENTS = [
18657
+ "top",
18658
+ "middle",
18659
+ "bottom",
18660
+ "baseline",
18661
+ "sub",
18662
+ "super",
18663
+ "text-bottom",
18664
+ "text-top"
18665
+ ];
18666
+ var INLINE_MEDIA_SIZES = [
18667
+ "line-height",
18668
+ "font-height",
18669
+ "super",
18670
+ "sub",
18671
+ "explicit"
18672
+ ];
18673
+ var LINE_TERMINATOR_REGEX = /[\n\r\u2028\u2029]/;
18674
+ var CHAIN_STRING_INVALID_REGEX = /[|\n\r\u2028\u2029]/;
18675
+ var URL_CHAR_CLASS = "a-zA-Z0-9!*'()=+,\\-./_?#@[\\]$&;%:{}~^";
18676
+ var URL_CHAR_REGEX = new RegExp(`^[${URL_CHAR_CLASS}]$`);
18677
+ var URL_HTTP_REGEX = new RegExp(`^https?://[${URL_CHAR_CLASS}]*$`);
18678
+ var URL_REGEX = new RegExp(`^(https?://|mailto:)[${URL_CHAR_CLASS}]*$`);
18679
+ function isChainString(v) {
18680
+ return typeof v === "string" && !CHAIN_STRING_INVALID_REGEX.test(v);
18681
+ }
18682
+ function isSingleLine(v) {
18683
+ return typeof v === "string" && !LINE_TERMINATOR_REGEX.test(v);
18684
+ }
18685
+ function hasLineTerminator(v) {
18686
+ return LINE_TERMINATOR_REGEX.test(v);
18687
+ }
18688
+ function isColor(v) {
18689
+ return typeof v === "string" && COLORS.indexOf(v) !== -1;
18690
+ }
18691
+ function isHighlightColor(v) {
18692
+ return typeof v === "string" && HIGHLIGHT_COLORS.indexOf(v) !== -1;
18693
+ }
18694
+ function isMediaAlignment(v) {
18695
+ return typeof v === "string" && MEDIA_ALIGNMENTS.indexOf(v) !== -1;
18696
+ }
18697
+ function isInlineMediaAlignment(v) {
18698
+ return typeof v === "string" && INLINE_MEDIA_ALIGNMENTS.indexOf(v) !== -1;
18699
+ }
18700
+ function isInlineMediaSize(v) {
18701
+ return typeof v === "string" && INLINE_MEDIA_SIZES.indexOf(v) !== -1;
18702
+ }
18703
+ function toUInt(v) {
18704
+ if (typeof v === "number") return Number.isInteger(v) && v >= 0 ? v : void 0;
18705
+ if (typeof v === "string" && /^[0-9]+$/.test(v)) return parseInt(v, 10);
18706
+ return void 0;
18707
+ }
18708
+ function toBoolean(v) {
18709
+ if (typeof v === "boolean") return v;
18710
+ if (v === "true") return true;
18711
+ if (v === "false") return false;
18712
+ return void 0;
18713
+ }
18714
+ function isDuration(v) {
18715
+ return isChainString(v) && v.trim().startsWith("P");
18716
+ }
18717
+ function isUrlHttp(v) {
18718
+ return typeof v === "string" && URL_HTTP_REGEX.test(v);
18719
+ }
18720
+ function isUrl(v) {
18721
+ return typeof v === "string" && URL_REGEX.test(v);
18722
+ }
18723
+ function isUrlChar(c) {
18724
+ return URL_CHAR_REGEX.test(c);
18725
+ }
18726
+ function bareUrlText(href) {
18727
+ return href.replace(/^(https?:\/\/|mailto:)/, "");
18728
+ }
18729
+ function isInlineAlt(v) {
18730
+ return typeof v === "string" && v.length > 0 && v.indexOf("==") === -1 && !v.startsWith("=") && !v.endsWith("=");
18731
+ }
18732
+ function isHeadingLevel(v) {
18733
+ return typeof v === "number" && Number.isInteger(v) && v >= 1 && v <= 3;
18734
+ }
18735
+ function normalizeInlineCodeLanguage(v) {
18736
+ if (!isChainString(v)) return void 0;
18737
+ return v.trim().toLowerCase();
18738
+ }
18739
+ function normalizeBlockCodeLanguage(v) {
18740
+ if (!isSingleLine(v)) return void 0;
18741
+ return v.trim().toLowerCase();
18742
+ }
18743
+
18744
+ // src/generator/text/TextMediaAttrs.ts
18745
+ var uint = (v) => toUInt(v);
18746
+ var bool = (v) => toBoolean(v);
18747
+ var alignment = (v) => isMediaAlignment(v) ? v : void 0;
18748
+ var chainString = (v) => isChainString(v) ? v.trim() : void 0;
18749
+ var inlineAlignment = (v) => isInlineMediaAlignment(v) ? v : void 0;
18750
+ var inlineSize = (v) => isInlineMediaSize(v) ? v : void 0;
18751
+ var VALIDATORS = {
18752
+ image: {
18753
+ alt: chainString,
18754
+ title: chainString,
18755
+ alignment,
18756
+ textAlign: alignment,
18757
+ zoomDisabled: bool,
18758
+ width: uint,
18759
+ height: uint,
18760
+ comment: chainString
18761
+ },
18762
+ imageInline: {
18763
+ srcAlt: chainString,
18764
+ alignmentVertical: inlineAlignment,
18765
+ size: inlineSize,
18766
+ width: uint,
18767
+ height: uint,
18768
+ comment: chainString
18769
+ },
18770
+ symbol: {
18771
+ alt: chainString,
18772
+ title: chainString,
18773
+ caption: chainString,
18774
+ alignment,
18775
+ textAlign: alignment,
18776
+ captionAlign: alignment,
18777
+ zoomDisabled: bool,
18778
+ width: uint,
18779
+ height: uint,
18780
+ comment: chainString
18781
+ }
18782
+ };
18783
+ var TAG_NAMES = {
18784
+ textAlign: "captionAlign",
18785
+ title: "caption"
18786
+ };
18787
+ var DEFAULTS = {
18788
+ image: { alignment: "center", textAlign: "left", zoomDisabled: true },
18789
+ imageInline: { alignmentVertical: "top", size: "line-height" },
18790
+ symbol: {}
18791
+ };
18792
+ function sanitizeMediaAttrs(kind, attrs) {
18793
+ const result = {};
18794
+ if (!attrs || typeof attrs !== "object") return result;
18795
+ const validators = VALIDATORS[kind];
18796
+ for (const [k, v] of Object.entries(attrs)) {
18797
+ const validator = validators[k];
18798
+ if (!validator || v == null) continue;
18799
+ const valid = validator(v);
18800
+ if (valid !== void 0) result[k] = valid;
18801
+ }
18802
+ if (kind === "symbol") {
18803
+ if ("caption" in result) delete result.title;
18804
+ if ("captionAlign" in result) delete result.textAlign;
18805
+ }
18806
+ return result;
18807
+ }
18808
+ function serializeMediaChain(kind, attrs) {
18809
+ const defaults = DEFAULTS[kind];
18810
+ let s = "";
18811
+ for (const k of Object.keys(VALIDATORS[kind])) {
18812
+ const v = attrs[k];
18813
+ if (v == null) continue;
18814
+ if (k in defaults && defaults[k] === v) continue;
18815
+ if (k === "comment") {
18816
+ if (v) s += `|#${v}`;
18817
+ } else if (typeof v === "string" && v === "") {
18818
+ continue;
18819
+ } else {
18820
+ s += `|${TAG_NAMES[k] ?? k}:${v}`;
18821
+ }
18822
+ }
18823
+ return s;
18824
+ }
18825
+
18826
+ // src/generator/text/TextMarkSanitizer.ts
18827
+ var STANDARD_SHORT_FORM_MARKS = [
18828
+ TextMarkType.bold,
18829
+ TextMarkType.italic,
18830
+ TextMarkType.light,
18831
+ TextMarkType.highlight
18832
+ ];
18833
+ function attrsOf(mark2) {
18834
+ const a = mark2.attrs;
18835
+ return a && typeof a === "object" && !Array.isArray(a) ? a : {};
18836
+ }
18837
+ function chainValue(v) {
18838
+ if (v == null) return "";
18839
+ return isChainString(v) ? v.trim() : void 0;
18840
+ }
18841
+ function mark(type, attrs) {
18842
+ return attrs ? { type, attrs } : { type };
18843
+ }
18844
+ function sanitizeMark(m, options) {
18845
+ const attrs = attrsOf(m);
18846
+ switch (m.type) {
18847
+ case TextMarkType.highlight:
18848
+ case TextMarkType.userHighlight: {
18849
+ const color = attrs.color;
18850
+ return isHighlightColor(color) ? mark(m.type, { color }) : mark(m.type);
18851
+ }
18852
+ case TextMarkType.textStyle:
18853
+ case TextMarkType.color: {
18854
+ const color = attrs.color;
18855
+ return isColor(color) ? mark(TextMarkType.textStyle, { color }) : void 0;
18856
+ }
18857
+ case TextMarkType.link: {
18858
+ const href = chainValue(attrs.href);
18859
+ return href === void 0 ? void 0 : mark(m.type, { href });
18860
+ }
18861
+ case TextMarkType.ref: {
18862
+ const reference = chainValue(attrs.reference);
18863
+ return reference === void 0 ? void 0 : mark(m.type, { reference });
18864
+ }
18865
+ case TextMarkType.xref: {
18866
+ const xref = chainValue(attrs.xref);
18867
+ if (xref === void 0) return void 0;
18868
+ const reference = chainValue(attrs.reference) ?? "";
18869
+ return mark(m.type, { xref, reference });
18870
+ }
18871
+ case TextMarkType.extref: {
18872
+ const extref = chainValue(attrs.extref);
18873
+ const provider = chainValue(attrs.provider);
18874
+ if (extref === void 0 || provider === void 0) return void 0;
18875
+ const refs = Array.isArray(attrs.references) ? attrs.references : [];
18876
+ const references = refs.map((r) => chainValue(r)).filter((r) => r !== void 0);
18877
+ return mark(m.type, { extref, references, provider });
18878
+ }
18879
+ case TextMarkType.footnote:
18880
+ case TextMarkType.footnoteStar: {
18881
+ const content = options.normalizeChainValue ? options.normalizeChainValue(attrs.content) : Array.isArray(attrs.content) ? attrs.content : [];
18882
+ return content === void 0 ? void 0 : mark(m.type, { content });
18883
+ }
18884
+ case TextMarkType.symbol: {
18885
+ const src = chainValue(attrs.src);
18886
+ if (src === void 0) return void 0;
18887
+ return mark(m.type, { src, ...sanitizeMediaAttrs("symbol", attrs) });
18888
+ }
18889
+ case TextMarkType.var: {
18890
+ const name = chainValue(attrs.name);
18891
+ return name === void 0 ? void 0 : mark(m.type, { name });
18892
+ }
18893
+ case TextMarkType.code: {
18894
+ const language = normalizeInlineCodeLanguage(attrs.language);
18895
+ return language === void 0 ? mark(m.type) : mark(m.type, { language });
18896
+ }
18897
+ case TextMarkType.timer: {
18898
+ const duration = attrs.duration;
18899
+ if (!isDuration(duration)) return void 0;
18900
+ const name = chainValue(attrs.name) ?? "";
18901
+ return mark(m.type, { name, duration: duration.trim() });
18902
+ }
18903
+ case TextMarkType.colorPicker: {
18904
+ const propertyRef = chainValue(attrs.propertyRef);
18905
+ return propertyRef === void 0 ? void 0 : mark(m.type, { propertyRef });
18906
+ }
18907
+ case TextMarkType.comment: {
18908
+ const comment = chainValue(m.comment);
18909
+ return comment === void 0 ? void 0 : { type: m.type, comment };
18910
+ }
18911
+ default:
18912
+ if (ALTERNATIVE_STYLE_TAGS.indexOf(m.type) !== -1) return mark(m.type);
18913
+ return void 0;
18914
+ }
18915
+ }
18916
+ function mergeLegacyTimer(marks) {
18917
+ const timer = marks.find((m) => m.type === TextMarkType.timer);
18918
+ const duration = marks.find((m) => m.type === TextMarkType.duration);
18919
+ if (!timer || !duration || attrsOf(timer).duration) return marks;
18920
+ return marks.map(
18921
+ (m) => m === timer ? { ...timer, attrs: { ...attrsOf(timer), duration: attrsOf(duration).duration } } : m
18922
+ );
18923
+ }
18924
+ function orderMarks(marks) {
18925
+ const a = (m) => m.attrs ?? {};
18926
+ const isBareHighlight = (m) => (m.type === TextMarkType.highlight || m.type === TextMarkType.userHighlight) && !a(m).color;
18927
+ const isHighlightColorStyle = (m) => m.type === TextMarkType.textStyle && isHighlightColor(a(m).color);
18928
+ const isEmptyXref = (m) => m.type === TextMarkType.xref && !a(m).reference;
18929
+ const result = [];
18930
+ for (const m of marks) {
18931
+ if (m.type === TextMarkType.ref) {
18932
+ const xrefIdx = result.findIndex(isEmptyXref);
18933
+ if (xrefIdx !== -1) {
18934
+ result.splice(xrefIdx, 0, m);
18935
+ continue;
18936
+ }
18937
+ }
18938
+ result.push(m);
18939
+ }
18940
+ for (let i = 0; i < result.length - 1; i++) {
18941
+ if (isBareHighlight(result[i]) && isHighlightColorStyle(result[i + 1])) {
18942
+ [result[i], result[i + 1]] = [result[i + 1], result[i]];
18943
+ }
18944
+ }
18945
+ const symbols = result.filter((m) => m.type === TextMarkType.symbol);
18946
+ if (symbols.length === 0) return result;
18947
+ return [...result.filter((m) => m.type !== TextMarkType.symbol), symbols[0]];
18948
+ }
18949
+ function sanitizeMarks(marks, options = {}) {
18950
+ if (!Array.isArray(marks)) return [];
18951
+ let loose = marks.filter(
18952
+ (m) => !!m && typeof m === "object" && typeof m.type === "string"
18953
+ );
18954
+ loose = mergeLegacyTimer(loose);
18955
+ const result = [];
18956
+ for (const m of loose) {
18957
+ const s = sanitizeMark(m, options);
18958
+ if (s) result.push(s);
18959
+ }
18960
+ if (options.chainValue) {
18961
+ if (result.length === 1 && STANDARD_SHORT_FORM_MARKS.indexOf(result[0].type) !== -1) {
18962
+ return [mark(result[0].type)];
18963
+ }
18964
+ if (result.length === 1 && result[0].type === TextMarkType.link) return result;
18965
+ return [];
18966
+ }
18967
+ return orderMarks(result);
18968
+ }
18969
+
18970
+ // src/generator/text/TextAstNormalizer.ts
18971
+ var LIST_TYPES = [
18972
+ TextNodeType.noBulletList,
18973
+ TextNodeType.bulletList,
18974
+ TextNodeType.orderedList,
18975
+ TextNodeType.orderedListRoman,
18976
+ TextNodeType.orderedListRomanLower,
18977
+ TextNodeType.letteredList,
18978
+ TextNodeType.letteredListLower,
18979
+ TextNodeType.taskList
18980
+ ];
18981
+ var ORDERED_LIST_TYPES = [
18982
+ TextNodeType.orderedList,
18983
+ TextNodeType.orderedListRoman,
18984
+ TextNodeType.orderedListRomanLower
18985
+ ];
18986
+ var BODY_BIT_TYPES = [
18987
+ TextNodeType.gap,
18988
+ TextNodeType.select,
18989
+ TextNodeType.highlight,
18990
+ TextNodeType.mark
18991
+ ];
18992
+ var LEADING_TAB_REGEX = /(^|[\n\r\u2028\u2029])\t+/g;
18993
+ var isList = (n) => LIST_TYPES.indexOf(n.type) !== -1;
18994
+ var isListItem = (n) => n.type === TextNodeType.listItem || n.type === TextNodeType.taskItem;
18995
+ var isBodyBit = (n) => BODY_BIT_TYPES.indexOf(n.type) !== -1;
18996
+ var isNode = (n) => !!n && typeof n === "object" && typeof n.type === "string";
18997
+ var contentOf = (n) => Array.isArray(n.content) ? n.content.filter(isNode) : [];
18998
+ var attrsOf2 = (n) => n.attrs && typeof n.attrs === "object" ? n.attrs : {};
18999
+ var asNode = (n) => n;
19000
+ var paragraph = (content) => asNode({ type: TextNodeType.paragraph, attrs: {}, content });
19001
+ var hardBreak = () => ({ type: TextNodeType.hardBreak });
19002
+ var isHardBreak = (n) => n?.type === TextNodeType.hardBreak;
19003
+ var hasText = (nodes) => nodes.some(
19004
+ (n) => n.type !== TextNodeType.hardBreak && (n.type !== TextNodeType.text || typeof n.text === "string" && n.text.trim() !== "")
19005
+ );
19006
+ function canFollowBareUrl(next) {
19007
+ if (!next) return true;
19008
+ if (next.type === TextNodeType.hardBreak) return true;
19009
+ if (next.type !== TextNodeType.text) return false;
19010
+ if (next.marks && next.marks.length > 0) return false;
19011
+ const first = (next.text ?? "").charAt(0);
19012
+ return first === "" || !isUrlChar(first);
19013
+ }
19014
+ function isSimpleLinkNode(node, next) {
19015
+ if (node.type !== TextNodeType.text || node.marks?.length !== 1) return false;
19016
+ const m = node.marks[0];
19017
+ if (m.type !== TextMarkType.link) return false;
19018
+ const href = m.attrs?.href;
19019
+ return isUrl(href) && bareUrlText(href) === node.text && canFollowBareUrl(next);
19020
+ }
19021
+ var FLATTENED_BLOCK_TYPES = [
19022
+ TextNodeType.paragraph,
19023
+ TextNodeType.heading,
19024
+ TextNodeType.section,
19025
+ TextNodeType.listItem,
19026
+ TextNodeType.taskItem,
19027
+ TextNodeType.codeBlock
19028
+ ];
19029
+ var TextAstNormalizer = class {
19030
+ constructor(options) {
19031
+ __publicField(this, "options");
19032
+ this.options = options;
19033
+ }
19034
+ normalize(ast) {
19035
+ if (!Array.isArray(ast)) return [];
19036
+ const nodes = ast.filter(isNode);
19037
+ if (this.options.chainValue) return this.inline(nodes, { plain: true, chainValue: true });
19038
+ if (this.options.location === TextLocation2.tag) {
19039
+ return nodes.flatMap((n) => this.inlineRootNode(n, {}));
19040
+ }
19041
+ return nodes.flatMap((n) => this.block(n));
19042
+ }
19043
+ //
19044
+ // Block context
19045
+ //
19046
+ block(n) {
19047
+ switch (n.type) {
19048
+ case TextNodeType.paragraph:
19049
+ return [{ ...n, content: this.inline(contentOf(n)) }];
19050
+ case TextNodeType.heading:
19051
+ return this.heading(n);
19052
+ case TextNodeType.section:
19053
+ return [paragraph(this.inline(contentOf(n)))];
19054
+ case TextNodeType.image: {
19055
+ const image = this.image(n);
19056
+ return image ? [image] : [];
19057
+ }
19058
+ case TextNodeType.codeBlock:
19059
+ return [{ ...n, content: this.code(contentOf(n)) }];
19060
+ case TextNodeType.text:
19061
+ case TextNodeType.hardBreak:
19062
+ case TextNodeType.imageInline:
19063
+ case TextNodeType.latex:
19064
+ return this.inline([n]);
19065
+ default:
19066
+ if (isList(n)) return this.list(n);
19067
+ if (isListItem(n)) return [paragraph(this.inline(contentOf(n)))];
19068
+ if (isBodyBit(n)) return [n];
19069
+ if (Array.isArray(n.content))
19070
+ return [{ ...n, content: this.blocks(contentOf(n)) }];
19071
+ return [n];
19072
+ }
19073
+ }
19074
+ blocks(nodes) {
19075
+ return nodes.flatMap((n) => this.block(n));
19076
+ }
19077
+ heading(n) {
19078
+ const level = attrsOf2(n).level;
19079
+ if (level != null && !isHeadingLevel(level)) {
19080
+ return [paragraph(this.inline(contentOf(n)))];
19081
+ }
19082
+ const content = this.inline(contentOf(n), { singleLine: true });
19083
+ if (!hasText(content)) return [];
19084
+ return [{ ...n, content }];
19085
+ }
19086
+ image(n) {
19087
+ const attrs = attrsOf2(n);
19088
+ if (!isUrlHttp(attrs.src)) return void 0;
19089
+ return asNode({ ...n, attrs: { src: attrs.src, ...sanitizeMediaAttrs("image", attrs) } });
19090
+ }
19091
+ code(nodes) {
19092
+ const result = [];
19093
+ for (const n of nodes) {
19094
+ if (n.type === TextNodeType.text) {
19095
+ if (typeof n.text === "string" && n.text) {
19096
+ result.push({ type: TextNodeType.text, text: n.text });
19097
+ }
19098
+ } else if (n.type === TextNodeType.hardBreak) {
19099
+ result.push(hardBreak());
19100
+ } else {
19101
+ result.push(...this.code(contentOf(n)));
19102
+ }
19103
+ }
19104
+ return result;
19105
+ }
19106
+ //
19107
+ // List context
19108
+ //
19109
+ list(n) {
19110
+ const attrs = attrsOf2(n);
19111
+ const ordered = ORDERED_LIST_TYPES.indexOf(n.type) !== -1;
19112
+ let start;
19113
+ if (ordered && attrs.start != null) {
19114
+ start = toUInt(attrs.start);
19115
+ if (start === void 0) {
19116
+ return contentOf(n).map(
19117
+ (item) => paragraph(this.inline([item], { stripLeadingTabs: true }))
19118
+ );
19119
+ }
19120
+ }
19121
+ const items = [];
19122
+ for (const child of contentOf(n)) {
19123
+ if (isListItem(child)) {
19124
+ items.push(...this.listItem(child));
19125
+ } else {
19126
+ items.push(...this.listItem({ type: TextNodeType.listItem, content: [child] }));
19127
+ }
19128
+ }
19129
+ if (items.length === 0) return [];
19130
+ const newAttrs = { ...attrs };
19131
+ if (ordered && start !== void 0) newAttrs.start = start;
19132
+ return [asNode({ ...n, attrs: newAttrs, content: items })];
19133
+ }
19134
+ /**
19135
+ * A list item holds a paragraph, then at most one sublist. Everything else is merged into the
19136
+ * paragraph; further sublists become new items (with an empty paragraph, which keeps them
19137
+ * attached). Returns the resulting item(s).
19138
+ */
19139
+ listItem(item) {
19140
+ const inlineOpts = { stripLeadingTabs: true };
19141
+ const acc = {};
19142
+ let sublist;
19143
+ const extraItems = [];
19144
+ const merge = (inline) => {
19145
+ if (!acc.para) acc.para = inline;
19146
+ else if (inline.length > 0) acc.para.push(hardBreak(), ...inline);
19147
+ };
19148
+ for (const child of contentOf(item)) {
19149
+ if (isList(child)) {
19150
+ for (const list of this.list(child)) {
19151
+ if (list.type === TextNodeType.paragraph) {
19152
+ merge(list.content ?? []);
19153
+ } else if (!sublist) {
19154
+ sublist = list;
19155
+ } else {
19156
+ extraItems.push({ ...item, content: [paragraph([]), list] });
19157
+ }
19158
+ }
19159
+ } else if (child.type === TextNodeType.image) {
19160
+ } else {
19161
+ merge(this.inline([child], inlineOpts));
19162
+ }
19163
+ }
19164
+ const paraContent = acc.para ?? [];
19165
+ if (!hasText(paraContent) && !sublist) return extraItems;
19166
+ const content = [paragraph(paraContent)];
19167
+ if (sublist) content.push(sublist);
19168
+ return [{ ...item, content }, ...extraItems];
19169
+ }
19170
+ //
19171
+ // Inline context
19172
+ //
19173
+ /** A root node at tag location: paragraphs of inline content only */
19174
+ inlineRootNode(n, opts) {
19175
+ switch (n.type) {
19176
+ case TextNodeType.text:
19177
+ case TextNodeType.hardBreak:
19178
+ case TextNodeType.imageInline:
19179
+ case TextNodeType.latex:
19180
+ return this.inline([n], opts);
19181
+ case TextNodeType.image:
19182
+ return [];
19183
+ default:
19184
+ if (isBodyBit(n)) return [n];
19185
+ if (isList(n)) {
19186
+ return contentOf(n).map(
19187
+ (item) => paragraph(this.inline([item], { ...opts, stripLeadingTabs: true }))
19188
+ );
19189
+ }
19190
+ return [paragraph(this.inline(contentOf(n), opts))];
19191
+ }
19192
+ }
19193
+ inline(nodes, opts = {}) {
19194
+ const result = [];
19195
+ const separator = () => opts.singleLine ? this.spaceText() : hardBreak();
19196
+ const separate = () => {
19197
+ if (result.length > 0 && !isHardBreak(result[result.length - 1])) result.push(separator());
19198
+ };
19199
+ for (const n of nodes) {
19200
+ switch (n.type) {
19201
+ case TextNodeType.text: {
19202
+ const text = this.text(n, opts);
19203
+ if (text) result.push(text);
19204
+ break;
19205
+ }
19206
+ case TextNodeType.hardBreak:
19207
+ result.push(separator());
19208
+ break;
19209
+ case TextNodeType.imageInline: {
19210
+ if (opts.plain) break;
19211
+ const image = this.imageInline(n);
19212
+ if (image) result.push(image);
19213
+ break;
19214
+ }
19215
+ case TextNodeType.latex:
19216
+ if (opts.plain) break;
19217
+ if (typeof attrsOf2(n).formula === "string") result.push(n);
19218
+ break;
19219
+ case TextNodeType.image:
19220
+ break;
19221
+ default:
19222
+ if (isBodyBit(n)) {
19223
+ result.push(n);
19224
+ } else if (isList(n)) {
19225
+ for (const item of contentOf(n)) {
19226
+ separate();
19227
+ result.push(...this.inline([item], opts));
19228
+ }
19229
+ } else if (FLATTENED_BLOCK_TYPES.indexOf(n.type) !== -1) {
19230
+ separate();
19231
+ result.push(...this.inline(contentOf(n), opts));
19232
+ } else if (Array.isArray(n.content)) {
19233
+ result.push({ ...n, content: this.inline(contentOf(n), opts) });
19234
+ } else {
19235
+ result.push(n);
19236
+ }
19237
+ }
19238
+ }
19239
+ return this.dropSymbolsBeforePipes(result);
19240
+ }
19241
+ /**
19242
+ * A symbol's media chain swallows every following `...|` segment on its line (even when sealed
19243
+ * with `^`), so a symbol mark has no representable form when the rest of the line contains `|`.
19244
+ */
19245
+ dropSymbolsBeforePipes(nodes) {
19246
+ for (let i = 0; i < nodes.length; i++) {
19247
+ const n = nodes[i];
19248
+ if (!n.marks?.some((m) => m.type === TextMarkType.symbol)) continue;
19249
+ let pipeFollows = false;
19250
+ for (let j = i + 1; j < nodes.length && !isHardBreak(nodes[j]); j++) {
19251
+ const text = nodes[j].text;
19252
+ if (typeof text !== "string") continue;
19253
+ const firstLine = text.split(/[\n\r\u2028\u2029]/, 1)[0];
19254
+ if (firstLine.indexOf("|") !== -1) pipeFollows = true;
19255
+ if (hasLineTerminator(text)) break;
19256
+ }
19257
+ if (pipeFollows) {
19258
+ const marks = n.marks.filter((m) => m.type !== TextMarkType.symbol);
19259
+ const { marks: _m, ...rest } = n;
19260
+ nodes[i] = marks.length > 0 ? { ...rest, marks } : rest;
19261
+ }
19262
+ }
19263
+ return nodes;
19264
+ }
19265
+ text(n, opts) {
19266
+ if (typeof n.text !== "string") return void 0;
19267
+ let text = n.text;
19268
+ if (opts.stripLeadingTabs) text = text.replace(LEADING_TAB_REGEX, "$1");
19269
+ if (opts.singleLine) text = text.replace(/[\n\r\u2028\u2029]+/g, " ");
19270
+ if (!text) return void 0;
19271
+ const marks = sanitizeMarks(n.marks, {
19272
+ chainValue: opts.chainValue,
19273
+ normalizeChainValue: (content) => this.chainValue(content)
19274
+ });
19275
+ const { marks: _m, ...rest } = n;
19276
+ return marks.length > 0 ? { ...rest, text, marks } : { ...rest, text };
19277
+ }
19278
+ spaceText() {
19279
+ return { type: TextNodeType.text, text: " " };
19280
+ }
19281
+ imageInline(n) {
19282
+ const attrs = attrsOf2(n);
19283
+ if (!isUrl(attrs.src)) return void 0;
19284
+ const alt = attrs.alt;
19285
+ if (!isInlineAlt(alt)) return void 0;
19286
+ return asNode({
19287
+ ...n,
19288
+ attrs: { src: attrs.src, alt, ...sanitizeMediaAttrs("imageInline", attrs) }
19289
+ });
19290
+ }
19291
+ /**
19292
+ * Footnote content: a `|`-free single line of plain text with short-form standard marks.
19293
+ * Returns undefined when the content cannot be represented.
19294
+ */
19295
+ chainValue(content) {
19296
+ if (!Array.isArray(content)) return [];
19297
+ const nodes = this.inline(content.filter(isNode), {
19298
+ plain: true,
19299
+ chainValue: true,
19300
+ singleLine: true
19301
+ });
19302
+ for (let i = 0; i < nodes.length; i++) {
19303
+ const n = nodes[i];
19304
+ const text = n.text;
19305
+ if (typeof text === "string" && (text.indexOf("|") !== -1 || hasLineTerminator(text))) {
19306
+ return void 0;
19307
+ }
19308
+ if (n.marks?.some((m) => m.type === TextMarkType.link) && !isSimpleLinkNode(n, nodes[i + 1])) {
19309
+ const { marks: _m, ...rest } = n;
19310
+ nodes[i] = rest;
19311
+ }
19312
+ }
19313
+ return nodes;
19314
+ }
19315
+ };
19316
+ function normalizeTextAst(ast, options) {
19317
+ return new TextAstNormalizer(options).normalize(ast);
19318
+ }
19319
+
18470
19320
  // src/generator/text/TextGenerator.ts
18471
19321
  var DEFAULT_OPTIONS = {
18472
19322
  bodyBitCallback: void 0,
@@ -18559,21 +19409,9 @@ var INLINE_MARK_TYPES = [
18559
19409
  TextMarkType.colorPicker,
18560
19410
  TextMarkType.comment
18561
19411
  ];
18562
- var HIGHLIGHT_COLORS = [
18563
- "orange",
18564
- "yellow",
18565
- "green",
18566
- "blue",
18567
- "purple",
18568
- "pink",
18569
- "brown",
18570
- "white",
18571
- "black",
18572
- "gray"
18573
- ];
18574
19412
  var INDENTATION_REGEX = new RegExp(/(\n|\r\n)/, "g");
18575
- var LINK_REGEX = new RegExp(/https?:\/\/|mailto:(.*)/, "g");
18576
19413
  var LINK_BREAKSCAPE_REGEX = new RegExp(/\]/, "g");
19414
+ var CHAIN_CONTINUATION_REGEX = /^[^\n\r\u2028\u2029]*\|/;
18577
19415
  var Stage = {
18578
19416
  enter: "enter",
18579
19417
  between: "between",
@@ -18610,6 +19448,8 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18610
19448
  __publicField(this, "textDepth", 0);
18611
19449
  __publicField(this, "placeholderIndex", 0);
18612
19450
  __publicField(this, "placeholders", {});
19451
+ __publicField(this, "chainJustClosed", false);
19452
+ __publicField(this, "simpleLinkAllowed", true);
18613
19453
  // For pre-text
18614
19454
  __publicField(this, "rootParagraphNodeContentIndex", 0);
18615
19455
  __publicField(this, "previousRootParagraphContextType", TextNodeType.text);
@@ -18655,6 +19495,11 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18655
19495
  generateSync(ast, textFormat, textLocation, options) {
18656
19496
  if (!ast || !Array.isArray(ast)) return "";
18657
19497
  this.generateOptions = Object.assign({}, options);
19498
+ ast = normalizeTextAst(ast, {
19499
+ format: textFormat ?? TextFormat2.bitmarkText,
19500
+ location: textLocation,
19501
+ chainValue: this.generateOptions.chainValueContext
19502
+ });
18658
19503
  this.validateGenerateOptions(ast);
18659
19504
  if (!this.generateOptions.plainTextDividerAllowed) {
18660
19505
  this.resetState(textFormat, textLocation);
@@ -18698,6 +19543,8 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18698
19543
  this.textDepth = 0;
18699
19544
  this.placeholderIndex = 0;
18700
19545
  this.placeholders = {};
19546
+ this.chainJustClosed = false;
19547
+ this.simpleLinkAllowed = true;
18701
19548
  this.rootParagraphNodeContentIndex = 0;
18702
19549
  this.previousRootParagraphContextType = TextNodeType.hardBreak;
18703
19550
  this.inPreText = false;
@@ -18763,6 +19610,7 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18763
19610
  this.writeHardBreak(node);
18764
19611
  break;
18765
19612
  case TextNodeType.text: {
19613
+ this.simpleLinkAllowed = this.isSimpleLinkAllowedAfter(route);
18766
19614
  this.writeMarks(node, Stage.enter);
18767
19615
  this.writeText(node);
18768
19616
  this.writeMarks(node, Stage.between);
@@ -18776,9 +19624,6 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18776
19624
  this.writeHeading(node);
18777
19625
  this.inHeading = true;
18778
19626
  break;
18779
- case TextNodeType.section:
18780
- this.writeSection(node);
18781
- break;
18782
19627
  case TextNodeType.listItem:
18783
19628
  case TextNodeType.taskItem:
18784
19629
  this.writeBullet(node, route);
@@ -18836,7 +19681,6 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18836
19681
  break;
18837
19682
  case TextNodeType.heading:
18838
19683
  this.inHeading = false;
18839
- case TextNodeType.section:
18840
19684
  case TextNodeType.image:
18841
19685
  if (!this.inParagraph) {
18842
19686
  this.writeNL();
@@ -18948,9 +19792,9 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
18948
19792
  */
18949
19793
  getLinkHref(node) {
18950
19794
  if (node.type === TextNodeType.text && node.marks) {
18951
- const href = node.marks.reduce((acc, mark) => {
18952
- if (mark.type === TextMarkType.link) {
18953
- const linkMark = mark;
19795
+ const href = node.marks.reduce((acc, mark2) => {
19796
+ if (mark2.type === TextMarkType.link) {
19797
+ const linkMark = mark2;
18954
19798
  const href2 = linkMark.attrs?.href;
18955
19799
  if (href2) return href2;
18956
19800
  }
@@ -19015,6 +19859,9 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19015
19859
  const indentationString = this.getIndentationString();
19016
19860
  s = s.replace(INDENTATION_REGEX, `$1${indentationString}`);
19017
19861
  }
19862
+ if (this.chainJustClosed && CHAIN_CONTINUATION_REGEX.test(s)) {
19863
+ s = `^${s}`;
19864
+ }
19018
19865
  if (this.havePreText && this.rootParagraphNodeContentIndex === this.preTextIndex) {
19019
19866
  this.writePlainTextDivider();
19020
19867
  this.writeNL();
@@ -19044,14 +19891,14 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19044
19891
  * @returns true if a simple link, otherwise false
19045
19892
  */
19046
19893
  isSimpleLink(node) {
19047
- if (node.text == null) return false;
19048
- if (node.marks?.length !== 1) return false;
19049
- const href = this.getLinkHref(node);
19050
- if (href) {
19051
- const hrefText = href.replace(LINK_REGEX, "$1");
19052
- return hrefText === node.text;
19053
- }
19054
- return false;
19894
+ return this.simpleLinkAllowed && isSimpleLinkNode(node, void 0);
19895
+ }
19896
+ /**
19897
+ * The bare-URL link short form is only safe when whatever is written next cannot be read as
19898
+ * part of the URL (the parser's Url rule consumes every following UrlChar).
19899
+ */
19900
+ isSimpleLinkAllowedAfter(route) {
19901
+ return canFollowBareUrl(this.getSiblingNodes(route).right);
19055
19902
  }
19056
19903
  /**
19057
19904
  * Get the link text if the node is a link, otherwise return false
@@ -19063,15 +19910,8 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19063
19910
  if (node.text == null) return false;
19064
19911
  const href = this.getLinkHref(node);
19065
19912
  if (href) {
19066
- let res;
19067
- const hrefText = href.replace(LINK_REGEX, "$1");
19068
- if (hrefText === node.text) {
19069
- res = href;
19070
- } else {
19071
- res = node.text;
19072
- }
19073
- res = (res ?? "").replace(LINK_BREAKSCAPE_REGEX, "^]");
19074
- return res;
19913
+ const res = this.isSimpleLink(node) ? href : node.text;
19914
+ return res.replace(LINK_BREAKSCAPE_REGEX, "^]");
19075
19915
  }
19076
19916
  return false;
19077
19917
  }
@@ -19128,22 +19968,17 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19128
19968
  writeMarks(node, stage) {
19129
19969
  if (node.marks) {
19130
19970
  const forceSingleMark = this.generateOptions.forceInline || !!(this.inInline || this.inHeading);
19131
- this.thisNodeIsPreText = false;
19132
- const emptyMarks = node.marks.length === 0;
19133
- if (emptyMarks) {
19134
- this.writeMarkTextWrapper(INLINE_MARK);
19135
- return;
19136
- }
19137
- const marks = this.getWritableMarks(node.marks);
19971
+ const marks = node.marks;
19138
19972
  if (marks.length === 0) return;
19973
+ this.thisNodeIsPreText = false;
19139
19974
  const singleMark = marks.length === 1 && forceSingleMark;
19140
19975
  const markStartEnd = marks.reduce(
19141
- (acc, mark) => {
19976
+ (acc, mark2) => {
19142
19977
  if (acc) return acc;
19143
- if (this.isStandardMark(mark)) {
19144
- if (singleMark) return STANDARD_MARKS[mark.type];
19978
+ if (this.isStandardMark(mark2)) {
19979
+ if (singleMark) return STANDARD_MARKS[mark2.type];
19145
19980
  return INLINE_MARK;
19146
- } else if (this.isInlineMark(mark)) {
19981
+ } else if (this.isInlineMark(mark2)) {
19147
19982
  return INLINE_MARK;
19148
19983
  } else {
19149
19984
  }
@@ -19158,56 +19993,59 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19158
19993
  this.writeMarkTextWrapper(markStartEnd);
19159
19994
  }
19160
19995
  if (stage == Stage.between) {
19161
- for (const mark of marks) {
19162
- if (this.isStandardMark(mark)) {
19996
+ for (const mark2 of marks) {
19997
+ if (this.isStandardMark(mark2)) {
19163
19998
  if (!singleMark) {
19164
19999
  this.writeInlineMarkStartEnd();
19165
- this.writeInlineMark(mark);
20000
+ this.writeInlineMark(mark2);
19166
20001
  }
19167
- } else if (TextMarkType.comment === mark.type) {
20002
+ } else if (TextMarkType.comment === mark2.type) {
19168
20003
  this.writeInlineMarkStartEnd();
19169
- this.writeCommentMark(mark);
19170
- } else if (TextMarkType.link === mark.type) {
20004
+ this.writeCommentMark(mark2);
20005
+ } else if (TextMarkType.link === mark2.type) {
19171
20006
  this.writeInlineMarkStartEnd();
19172
- this.writeLinkMark(mark);
19173
- } else if (TextMarkType.ref === mark.type) {
20007
+ this.writeLinkMark(mark2);
20008
+ } else if (TextMarkType.ref === mark2.type) {
19174
20009
  this.writeInlineMarkStartEnd();
19175
- this.writeRefMark(mark);
19176
- } else if (TextMarkType.xref === mark.type) {
20010
+ this.writeRefMark(mark2);
20011
+ } else if (TextMarkType.xref === mark2.type) {
19177
20012
  this.writeInlineMarkStartEnd();
19178
- this.writeXRefMark(mark);
19179
- } else if (TextMarkType.extref === mark.type) {
20013
+ this.writeXRefMark(mark2);
20014
+ } else if (TextMarkType.extref === mark2.type) {
19180
20015
  this.writeInlineMarkStartEnd();
19181
- this.writeExtRefMark(mark);
19182
- } else if (TextMarkType.footnote === mark.type) {
20016
+ this.writeExtRefMark(mark2);
20017
+ } else if (TextMarkType.footnote === mark2.type) {
19183
20018
  this.writeInlineMarkStartEnd();
19184
- this.writeFootnoteMark(mark);
19185
- } else if (TextMarkType.footnoteStar === mark.type) {
20019
+ this.writeFootnoteMark(mark2);
20020
+ } else if (TextMarkType.footnoteStar === mark2.type) {
19186
20021
  this.writeInlineMarkStartEnd();
19187
- this.writeFootnoteStarMark(mark);
19188
- } else if (TextMarkType.symbol === mark.type) {
20022
+ this.writeFootnoteStarMark(mark2);
20023
+ } else if (TextMarkType.symbol === mark2.type) {
19189
20024
  this.writeInlineMarkStartEnd();
19190
- this.writeSymbolMark(mark);
19191
- } else if (this.isInlineMark(mark)) {
20025
+ this.writeSymbolMark(mark2);
20026
+ } else if (this.isInlineMark(mark2)) {
19192
20027
  this.writeInlineMarkStartEnd();
19193
- this.writeInlineMark(mark);
20028
+ this.writeInlineMark(mark2);
19194
20029
  } else {
19195
20030
  }
19196
20031
  }
19197
20032
  }
19198
20033
  if (stage == Stage.exit) {
19199
20034
  let inlineMarkWritten = false;
19200
- for (const mark of marks) {
19201
- if (this.isStandardMark(mark)) {
20035
+ for (const mark2 of marks) {
20036
+ if (this.isStandardMark(mark2)) {
19202
20037
  if (!singleMark) {
19203
20038
  inlineMarkWritten = true;
19204
20039
  }
19205
- } else if (TextMarkType.comment === mark.type || TextMarkType.link === mark.type || TextMarkType.ref === mark.type || TextMarkType.xref === mark.type || TextMarkType.footnote === mark.type || TextMarkType.footnoteStar === mark.type || this.isInlineMark(mark)) {
20040
+ } else if (TextMarkType.comment === mark2.type || TextMarkType.link === mark2.type || TextMarkType.ref === mark2.type || TextMarkType.xref === mark2.type || TextMarkType.footnote === mark2.type || TextMarkType.footnoteStar === mark2.type || this.isInlineMark(mark2)) {
19206
20041
  inlineMarkWritten = true;
19207
20042
  } else {
19208
20043
  }
19209
20044
  }
19210
- if (inlineMarkWritten) this.writeInlineMarkStartEnd();
20045
+ if (inlineMarkWritten) {
20046
+ this.writeInlineMarkStartEnd();
20047
+ this.chainJustClosed = true;
20048
+ }
19211
20049
  }
19212
20050
  }
19213
20051
  }
@@ -19243,15 +20081,6 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19243
20081
  s += " ";
19244
20082
  this.write(s);
19245
20083
  }
19246
- writeSection(node) {
19247
- let s = "";
19248
- if (node.section) {
19249
- s = `|${node.section}: `;
19250
- } else {
19251
- s = "|";
19252
- }
19253
- this.write(s);
19254
- }
19255
20084
  writeBullet(node, route) {
19256
20085
  let bullet = this.getIndentationString();
19257
20086
  const listParent = this.getParentNode(route, 2);
@@ -19274,7 +20103,7 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19274
20103
  bullet += "\u2022a ";
19275
20104
  } else if (listType === TextNodeType.taskList) {
19276
20105
  const taskList = node;
19277
- const checked = taskList.attrs?.checked ?? false;
20106
+ const checked = taskList.attrs?.checked === true;
19278
20107
  bullet += checked ? "\u2022+ " : "\u2022- ";
19279
20108
  }
19280
20109
  if (bullet) this.write(bullet);
@@ -19283,28 +20112,20 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19283
20112
  if (node.attrs == null || !node.attrs.src) return;
19284
20113
  const attrs = node.attrs;
19285
20114
  const inlineImage = node.type === TextNodeType.imageInline;
19286
- let ignoreAttributes;
19287
- if (inlineImage) {
19288
- ignoreAttributes = /* @__PURE__ */ new Set(["alt", "zoomDisabled", "title"]);
19289
- const a = attrs;
19290
- if (a.alignmentVertical === "top") ignoreAttributes.add("alignmentVertical");
19291
- if (a.size === "line-height") ignoreAttributes.add("size");
19292
- }
19293
- const mediaAttrs = this.getMediaAttrs(inlineImage ? "imageInline" : "image", attrs, {
19294
- ignoreAttributes
19295
- });
20115
+ const kind = inlineImage ? "imageInline" : "image";
20116
+ const chain = serializeMediaChain(kind, attrs);
19296
20117
  let s = "";
19297
20118
  if (inlineImage) {
19298
20119
  s = `==${attrs.alt ?? ""}==`;
19299
20120
  }
19300
- s += mediaAttrs ? `|${mediaAttrs}|` : "";
20121
+ s += `|${kind}:${attrs.src}${chain}|`;
19301
20122
  this.write(s);
19302
20123
  }
19303
20124
  writeCodeBlock(node) {
19304
- if (node.attrs == null || !node.attrs.language) return;
19305
- const attrs = node.attrs;
19306
- const s = `|code:${attrs.language}
19307
- `;
20125
+ const raw = node.attrs?.language ?? node.language;
20126
+ const language = normalizeBlockCodeLanguage(raw) ?? "";
20127
+ const s = language ? `|code:${language}
20128
+ ` : "|code\n";
19308
20129
  this.write(s);
19309
20130
  }
19310
20131
  writeLatex(node) {
@@ -19320,10 +20141,10 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19320
20141
  writeMarkTextWrapper(s) {
19321
20142
  if (s) this.write(s);
19322
20143
  }
19323
- writeInlineMark(mark) {
19324
- const attrs = mark.attrs ?? {};
20144
+ writeInlineMark(mark2) {
20145
+ const attrs = mark2.attrs ?? {};
19325
20146
  let s;
19326
- switch (mark.type) {
20147
+ switch (mark2.type) {
19327
20148
  case TextMarkType.textStyle:
19328
20149
  case TextMarkType.color:
19329
20150
  s = `color:${attrs.color ?? ""}`;
@@ -19334,10 +20155,10 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19334
20155
  break;
19335
20156
  case TextMarkType.highlight:
19336
20157
  case TextMarkType.userHighlight:
19337
- s = attrs.color ? `${mark.type}|color:${attrs.color}` : `${mark.type}`;
20158
+ s = attrs.color ? `${mark2.type}|color:${attrs.color}` : `${mark2.type}`;
19338
20159
  break;
19339
20160
  default: {
19340
- s = `${mark.type}`;
20161
+ s = `${mark2.type}`;
19341
20162
  for (const [k, v] of Object.entries(attrs)) {
19342
20163
  if (k === "language" && v !== "plain text" || k === "propertyRef" || k === "name") {
19343
20164
  s = `${s}:${v}`;
@@ -19347,88 +20168,49 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19347
20168
  }
19348
20169
  this.write(s);
19349
20170
  }
19350
- /**
19351
- * Resolve the marks of a text node into the marks that will actually be written.
19352
- *
19353
- * - Merges a legacy standalone 'duration' mark into its sibling 'timer' mark.
19354
- * - Drops marks the current grammar cannot express (standalone 'duration', 'timer'
19355
- * without a duration).
19356
- * - Moves a 'textStyle'/'color' mark before a preceding bare 'highlight'/'userHighlight'
19357
- * mark when its color is a valid highlight color; written in the original order the
19358
- * output would re-parse as a highlight-with-color compound mark and change meaning.
19359
- */
19360
- getWritableMarks(nodeMarks) {
19361
- const attrsOf = (m) => m.attrs ?? {};
19362
- let marks = [...nodeMarks];
19363
- const timer = marks.find((m) => m.type === TextMarkType.timer);
19364
- const duration = marks.find((m) => m.type === TextMarkType.duration);
19365
- if (timer && duration && !attrsOf(timer).duration) {
19366
- marks = marks.map(
19367
- (m) => m === timer ? {
19368
- ...timer,
19369
- attrs: { ...attrsOf(timer), duration: attrsOf(duration).duration }
19370
- } : m
19371
- );
19372
- }
19373
- marks = marks.filter((m) => {
19374
- if (m.type === TextMarkType.duration) return false;
19375
- if (m.type === TextMarkType.timer) return !!attrsOf(m).duration;
19376
- return true;
19377
- });
19378
- const isBareHighlight = (m) => (m.type === TextMarkType.highlight || m.type === TextMarkType.userHighlight) && !attrsOf(m).color;
19379
- const isHighlightColorStyle = (m) => (m.type === TextMarkType.textStyle || m.type === TextMarkType.color) && HIGHLIGHT_COLORS.indexOf(attrsOf(m).color) !== -1;
19380
- for (let i = 0; i < marks.length - 1; i++) {
19381
- if (isBareHighlight(marks[i]) && isHighlightColorStyle(marks[i + 1])) {
19382
- const tmp = marks[i];
19383
- marks[i] = marks[i + 1];
19384
- marks[i + 1] = tmp;
19385
- }
19386
- }
19387
- return marks;
19388
- }
19389
20171
  /**
19390
20172
  * True if the mark is written using its standard form (e.g. **bold**, !!highlight!!)
19391
20173
  * when it is the only mark. A highlight mark with a color attribute is excluded - it
19392
20174
  * can only be expressed using the inline chain form (==text==|highlight|color:x|).
19393
20175
  */
19394
- isStandardMark(mark) {
19395
- if (STANDARD_MARK_TYPES.indexOf(mark.type) === -1) return false;
19396
- return !(mark.attrs && mark.attrs.color);
20176
+ isStandardMark(mark2) {
20177
+ if (STANDARD_MARK_TYPES.indexOf(mark2.type) === -1) return false;
20178
+ return !(mark2.attrs && mark2.attrs.color);
19397
20179
  }
19398
20180
  /**
19399
20181
  * True if the mark is written using the inline chain form (==text==|mark|).
19400
20182
  */
19401
- isInlineMark(mark) {
19402
- if (INLINE_MARK_TYPES.indexOf(mark.type) !== -1) return true;
19403
- return mark.type === TextMarkType.highlight && !!(mark.attrs && mark.attrs.color);
20183
+ isInlineMark(mark2) {
20184
+ if (INLINE_MARK_TYPES.indexOf(mark2.type) !== -1) return true;
20185
+ return mark2.type === TextMarkType.highlight && !!(mark2.attrs && mark2.attrs.color);
19404
20186
  }
19405
- writeCommentMark(mark) {
19406
- const comment = mark.comment || "";
20187
+ writeCommentMark(mark2) {
20188
+ const comment = mark2.comment || "";
19407
20189
  const s = `#${comment}`;
19408
20190
  this.write(s);
19409
20191
  }
19410
- writeLinkMark(mark) {
19411
- const href = mark.attrs?.href || "";
20192
+ writeLinkMark(mark2) {
20193
+ const href = mark2.attrs?.href || "";
19412
20194
  const linkText = (href ?? "").replace(LINK_BREAKSCAPE_REGEX, "^]");
19413
20195
  const s = `link:${linkText}`;
19414
20196
  this.write(s);
19415
20197
  }
19416
- writeRefMark(mark) {
19417
- const ref = mark.attrs?.reference ?? "";
20198
+ writeRefMark(mark2) {
20199
+ const ref = mark2.attrs?.reference ?? "";
19418
20200
  const s = `\u25BA${ref}`;
19419
20201
  this.write(s);
19420
20202
  }
19421
- writeXRefMark(mark) {
19422
- const xref = mark.attrs?.xref ?? "";
19423
- const ref = mark.attrs?.reference ?? "";
20203
+ writeXRefMark(mark2) {
20204
+ const xref = mark2.attrs?.xref ?? "";
20205
+ const ref = mark2.attrs?.reference ?? "";
19424
20206
  let s = `xref:${xref}`;
19425
20207
  if (ref) s += `|\u25BA${ref}`;
19426
20208
  this.write(s);
19427
20209
  }
19428
- writeExtRefMark(mark) {
19429
- const extref = mark.attrs?.extref ?? "";
19430
- const refs = mark.attrs?.references ?? [];
19431
- const provider = mark.attrs?.provider ?? "";
20210
+ writeExtRefMark(mark2) {
20211
+ const extref = mark2.attrs?.extref ?? "";
20212
+ const refs = mark2.attrs?.references ?? [];
20213
+ const provider = mark2.attrs?.provider ?? "";
19432
20214
  let s = `extref:${extref}`;
19433
20215
  for (const ref of refs) {
19434
20216
  s += `|\u25BA${ref ?? ""}`;
@@ -19436,39 +20218,39 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19436
20218
  s += `|provider:${provider}`;
19437
20219
  this.write(s);
19438
20220
  }
19439
- writeFootnoteMark(mark) {
20221
+ writeFootnoteMark(mark2) {
19440
20222
  const s = `footnote:`;
19441
20223
  this.write(s);
19442
20224
  const text = this.internalTextGenerator?.generateSync(
19443
- mark.attrs?.content,
20225
+ mark2.attrs?.content,
19444
20226
  this.textFormat,
19445
20227
  this.textLocation,
19446
20228
  {
19447
20229
  ...this.generateOptions,
19448
- forceInline: true
20230
+ forceInline: true,
20231
+ chainValueContext: true
19449
20232
  }
19450
20233
  ) ?? "";
19451
20234
  this.write(text);
19452
20235
  }
19453
- writeFootnoteStarMark(mark) {
20236
+ writeFootnoteStarMark(mark2) {
19454
20237
  const s = `footnote*:`;
19455
20238
  this.write(s);
19456
20239
  const text = this.internalTextGenerator?.generateSync(
19457
- mark.attrs?.content,
20240
+ mark2.attrs?.content,
19458
20241
  this.textFormat,
19459
20242
  this.textLocation,
19460
20243
  {
19461
20244
  ...this.generateOptions,
19462
- forceInline: true
20245
+ forceInline: true,
20246
+ chainValueContext: true
19463
20247
  }
19464
20248
  ) ?? "";
19465
20249
  this.write(text);
19466
20250
  }
19467
- writeSymbolMark(mark) {
19468
- if (mark.attrs == null) return;
19469
- const attrs = mark.attrs;
19470
- const mediaAttrs = this.getMediaAttrs("symbol", attrs);
19471
- const s = mediaAttrs ?? "";
20251
+ writeSymbolMark(mark2) {
20252
+ const attrs = mark2.attrs ?? {};
20253
+ const s = `symbol:${attrs.src ?? ""}${serializeMediaChain("symbol", attrs)}`;
19472
20254
  this.write(s);
19473
20255
  }
19474
20256
  writeInlineMarkStartEnd() {
@@ -19498,52 +20280,6 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19498
20280
  }
19499
20281
  this.writeString(tag);
19500
20282
  }
19501
- getMediaAttrs(mediaType, attrs, options) {
19502
- if (!mediaType) return void 0;
19503
- const opts = Object.assign({}, options);
19504
- const ignoreAttributes = opts.ignoreAttributes ?? /* @__PURE__ */ new Set();
19505
- let s = `${mediaType}:${attrs?.src ?? ""}`;
19506
- const entries = Object.entries(attrs).filter(([k, _v]) => k !== "src");
19507
- for (let i = 0; i < entries.length; i++) {
19508
- const [k, v] = entries[i];
19509
- if (ignoreAttributes.has(k)) continue;
19510
- switch (k) {
19511
- case "textAlign":
19512
- if (v !== "left") s += `|captionAlign:${v}`;
19513
- break;
19514
- case "alignment":
19515
- if (v !== "center") {
19516
- if (v) s += `|alignment:${v}`;
19517
- }
19518
- break;
19519
- case "title":
19520
- if (v) s += `|caption:${v}`;
19521
- break;
19522
- case "class":
19523
- if (v !== "center") {
19524
- if (v) s += `|align:${v}`;
19525
- }
19526
- break;
19527
- case "comment":
19528
- if (v) s += `|#${v}`;
19529
- break;
19530
- case "":
19531
- if (stringUtils.isString(v)) s += `|:${v}`;
19532
- else s += `|`;
19533
- break;
19534
- case "zoomDisabled":
19535
- if (!v) s += "|zoomDisabled:false";
19536
- break;
19537
- case "alt":
19538
- case "width":
19539
- case "height":
19540
- default:
19541
- if (k && v) s += `|${k}:${v}`;
19542
- break;
19543
- }
19544
- }
19545
- return s;
19546
- }
19547
20283
  //
19548
20284
  // Helper functions
19549
20285
  //
@@ -19569,6 +20305,7 @@ var TextGenerator = class _TextGenerator extends AstWalkerGenerator {
19569
20305
  */
19570
20306
  write(value) {
19571
20307
  value = this.getInterTextBreakscape(value) + value;
20308
+ this.chainJustClosed = false;
19572
20309
  if (this.options.writeCallback) {
19573
20310
  this.options.writeCallback(value);
19574
20311
  }
@@ -33754,8 +34491,8 @@ var Builder = class extends BaseBuilder {
33754
34491
  break;
33755
34492
  }
33756
34493
  case BodyBitType.mark: {
33757
- const mark = part;
33758
- instance7.fillBooleanExample([mark], __isDefaultExample, example, false);
34494
+ const mark2 = part;
34495
+ instance7.fillBooleanExample([mark2], __isDefaultExample, example, false);
33759
34496
  break;
33760
34497
  }
33761
34498
  case BodyBitType.select: {
@@ -34536,10 +35273,10 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
34536
35273
  const markConfig = node.value;
34537
35274
  const parent = this.getParentNode(route);
34538
35275
  if (parent?.key !== NodeType.markConfig) return true;
34539
- const { mark, color, emphasis } = markConfig;
34540
- if (mark) {
35276
+ const { mark: mark2, color, emphasis } = markConfig;
35277
+ if (mark2) {
34541
35278
  this.writeNL();
34542
- this.writeProperty("mark", mark, route, {
35279
+ this.writeProperty("mark", mark2, route, {
34543
35280
  format: TagFormat.plainText
34544
35281
  });
34545
35282
  if (color) {
@@ -34756,9 +35493,9 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
34756
35493
  }
34757
35494
  // bodyBit -> mark
34758
35495
  enter_mark(node, _route) {
34759
- const mark = node.value;
35496
+ const mark2 = node.value;
34760
35497
  this.writeOPE();
34761
- this.writeTextOrValue(mark.solution, TextFormat2.plainText, TextLocation2.tag);
35498
+ this.writeTextOrValue(mark2.solution, TextFormat2.plainText, TextLocation2.tag);
34762
35499
  this.writeCL();
34763
35500
  return true;
34764
35501
  }
@@ -34818,9 +35555,9 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
34818
35555
  leaf_mark(node, route) {
34819
35556
  const root = route[0];
34820
35557
  if (root?.key !== NodeType.mark) return;
34821
- const mark = node.value;
34822
- if (mark) {
34823
- this.writeProperty("mark", mark, route, {
35558
+ const mark2 = node.value;
35559
+ if (mark2) {
35560
+ this.writeProperty("mark", mark2, route, {
34824
35561
  format: TagFormat.plainText
34825
35562
  });
34826
35563
  }
@@ -35534,7 +36271,7 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
35534
36271
  leaf_level(node, route) {
35535
36272
  const parent = this.getParentNode(route);
35536
36273
  if (parent?.key !== NodeType.bitsValue) return true;
35537
- if (!instance2.isOfBitType(this.bitType, [BitType2.chapter])) return true;
36274
+ if (!instance2.isOfBitType(this.bitType, [BitType2.chapter, BitType2.h])) return true;
35538
36275
  const level = node.value;
35539
36276
  const bit = parent?.value;
35540
36277
  if (level > 0 && bit.title == null) {
@@ -36577,8 +37314,6 @@ var MARK_TO_TAG = {
36577
37314
  highlight: "mark",
36578
37315
  code: "code"
36579
37316
  };
36580
- var INLINE_IMAGE_RE = /==([^=]*(?:=(?!=)[^=]*)*)==\|imageInline:([^|\s]+)((?:\|(?:@?[A-Za-z][A-Za-z0-9_-]*:[^|\s]+|#[^|\s]*))*)\|?/g;
36581
- var MAX_IMAGE_DIMENSION = 9999;
36582
37317
  var HtmlTableGenerator = class {
36583
37318
  constructor() {
36584
37319
  __publicField(this, "indentUnit", " ");
@@ -36720,13 +37455,13 @@ var HtmlTableGenerator = class {
36720
37455
  if (!marks || marks.length === 0) return text;
36721
37456
  let open = "";
36722
37457
  let close = "";
36723
- for (const mark of marks) {
36724
- if (mark.type === "link") {
36725
- const href = mark.attrs?.href ?? "";
37458
+ for (const mark2 of marks) {
37459
+ if (mark2.type === "link") {
37460
+ const href = mark2.attrs?.href ?? "";
36726
37461
  open += `<a href="${this.escapeAttr(href)}">`;
36727
37462
  close = `</a>${close}`;
36728
37463
  } else {
36729
- const tag = MARK_TO_TAG[mark.type];
37464
+ const tag = MARK_TO_TAG[mark2.type];
36730
37465
  if (tag) {
36731
37466
  open += `<${tag}>`;
36732
37467
  close = `</${tag}>${close}`;
@@ -36790,37 +37525,7 @@ var HtmlTableGenerator = class {
36790
37525
  return `<img ${parts.join(" ")}>`;
36791
37526
  }
36792
37527
  textToHtml(text) {
36793
- let html = "";
36794
- let lastIndex = 0;
36795
- for (const match of text.matchAll(INLINE_IMAGE_RE)) {
36796
- const index = match.index ?? 0;
36797
- html += this.escapeText(text.slice(lastIndex, index));
36798
- html += this.inlineImageTokenToHtml(match);
36799
- lastIndex = index + match[0].length;
36800
- }
36801
- html += this.escapeText(text.slice(lastIndex));
36802
- return html;
36803
- }
36804
- inlineImageTokenToHtml(match) {
36805
- const attrs = {
36806
- alt: match[1],
36807
- src: match[2]
36808
- };
36809
- const rawAttrs = match[3] ?? "";
36810
- for (const attr of rawAttrs.split("|")) {
36811
- if (!attr || attr.startsWith("#")) continue;
36812
- const colon = attr.indexOf(":");
36813
- if (colon < 1) continue;
36814
- const key = attr.slice(0, colon).replace(/^@/, "");
36815
- const value = attr.slice(colon + 1);
36816
- if (key === "width" || key === "height") {
36817
- const n = Number.parseInt(value, 10);
36818
- if (!Number.isNaN(n) && n > 0 && n <= MAX_IMAGE_DIMENSION) attrs[key] = n;
36819
- } else if (key === "class" || key === "title") {
36820
- attrs[key] = value;
36821
- }
36822
- }
36823
- return this.imageToHtml({ type: "imageInline", attrs });
37528
+ return this.escapeText(text);
36824
37529
  }
36825
37530
  // --- formulas -------------------------------------------------------------
36826
37531
  latexToHtml(node) {
@@ -41304,13 +42009,13 @@ function markChainContentProcessor(context, contentDepth, tagsConfig, content, t
41304
42009
  if (contentDepth === ContentDepth.Chain) {
41305
42010
  markTagContentProcessor(context, ContentDepth.Chain, content, target);
41306
42011
  } else {
41307
- const mark = buildMark(
42012
+ const mark2 = buildMark(
41308
42013
  context,
41309
42014
  contentDepth,
41310
42015
  tagsConfig,
41311
42016
  content
41312
42017
  );
41313
- if (mark) bodyParts.push(mark);
42018
+ if (mark2) bodyParts.push(mark2);
41314
42019
  }
41315
42020
  }
41316
42021
  function buildMark(context, _contentDepth, tagsConfig, content) {
@@ -41325,13 +42030,13 @@ function buildMark(context, _contentDepth, tagsConfig, content) {
41325
42030
  if (context.DEBUG_CHAIN_TAGS) context.debugPrint("mark TAGS", chainTags);
41326
42031
  const { solution } = tags2;
41327
42032
  const { mark: markType, ...rest } = chainTags;
41328
- const mark = {
42033
+ const mark2 = {
41329
42034
  type: BodyBitType.mark,
41330
42035
  solution: solution ?? "",
41331
42036
  mark: instance4.asSingle(markType) ?? "",
41332
42037
  ...rest
41333
42038
  };
41334
- return mark;
42039
+ return mark2;
41335
42040
  }
41336
42041
 
41337
42042
  // src/parser/bitmark/peg/contentProcessors/PropertyContentProcessor.ts
@@ -41583,7 +42288,7 @@ function markConfigChainContentProcessor(context, _contentDepth, tagsConfig, con
41583
42288
  content.chain
41584
42289
  );
41585
42290
  if (context.DEBUG_CHAIN_TAGS) context.debugPrint("mark TAGS", tags2);
41586
- const mark = instance3.unbreakscape(
42291
+ const mark2 = instance3.unbreakscape(
41587
42292
  stringUtils.trimmedString(content.value) ?? "unknown",
41588
42293
  {
41589
42294
  format: TextFormat2.bitmarkText,
@@ -41591,7 +42296,7 @@ function markConfigChainContentProcessor(context, _contentDepth, tagsConfig, con
41591
42296
  }
41592
42297
  );
41593
42298
  const config = {
41594
- mark,
42299
+ mark: mark2,
41595
42300
  emphasis: "underline",
41596
42301
  ...tags2
41597
42302
  };
@@ -42059,15 +42764,23 @@ function titleTagContentProcessor(context, _contentDepth, _tagsConfig, content,
42059
42764
  titleString: titleText ?? ""
42060
42765
  };
42061
42766
  }
42062
- function buildTitles(_context, bitType, title) {
42767
+ var H_TITLE_LEVEL_MAX = 7;
42768
+ function buildTitles(context, bitType, title) {
42063
42769
  title = title ?? [];
42064
- if (instance2.isOfBitType(bitType, BitType2.chapter)) {
42770
+ if (instance2.isOfBitType(bitType, [BitType2.chapter, BitType2.h])) {
42065
42771
  let t;
42066
42772
  if (title.length > 0) t = title[title.length - 1];
42773
+ let level = title.length > 0 ? title.length - 1 : void 0;
42774
+ if (level != null && level > H_TITLE_LEVEL_MAX && instance2.isOfBitType(bitType, BitType2.h)) {
42775
+ context.addWarning(
42776
+ `Title level of ${level} too high, setting to max value of ${H_TITLE_LEVEL_MAX}`
42777
+ );
42778
+ level = H_TITLE_LEVEL_MAX;
42779
+ }
42067
42780
  return {
42068
42781
  title: t?.titleAst ?? [],
42069
42782
  titleString: t?.titleString ?? "",
42070
- level: title.length > 0 ? title.length - 1 : void 0
42783
+ level
42071
42784
  };
42072
42785
  } else {
42073
42786
  if (Array.isArray(title)) {