@gmb/bitmark-parser-generator 5.26.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/browser/bitmark-parser-generator.min.js +1 -1
- package/dist/browser/bundle-report.html +2 -2
- package/dist/browser/cjs/index.cjs +1124 -748
- package/dist/browser/cjs/index.cjs.map +1 -1
- package/dist/browser/cjs/index.d.cts +151 -63
- package/dist/browser/esm/index.d.ts +151 -63
- package/dist/browser/esm/index.js +1124 -748
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/cli/main.js +1153 -747
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +1152 -749
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +151 -63
- package/dist/index.d.ts +151 -63
- package/dist/index.js +1152 -749
- package/dist/index.js.map +1 -1
- package/package.json +19 -19
package/dist/cli/main.js
CHANGED
|
@@ -545,6 +545,14 @@ var BitType = {
|
|
|
545
545
|
smartStandardRemarkNonNormativeCollapsible: "smart-standard-remark-non-normative-collapsible",
|
|
546
546
|
smartStandardRemarkNormative: "smart-standard-remark-normative",
|
|
547
547
|
smartStandardRemarkNormativeCollapsible: "smart-standard-remark-normative-collapsible",
|
|
548
|
+
smartStandardRemarkTableExtendedImageNonNormative: "smart-standard-remark-table-extended-image-non-normative",
|
|
549
|
+
smartStandardRemarkTableExtendedImageNonNormativeCollapsible: "smart-standard-remark-table-extended-image-non-normative-collapsible",
|
|
550
|
+
smartStandardRemarkTableExtendedImageNormative: "smart-standard-remark-table-extended-image-normative",
|
|
551
|
+
smartStandardRemarkTableExtendedImageNormativeCollapsible: "smart-standard-remark-table-extended-image-normative-collapsible",
|
|
552
|
+
smartStandardRemarkTableExtendedNonNormative: "smart-standard-remark-table-extended-non-normative",
|
|
553
|
+
smartStandardRemarkTableExtendedNonNormativeCollapsible: "smart-standard-remark-table-extended-non-normative-collapsible",
|
|
554
|
+
smartStandardRemarkTableExtendedNormative: "smart-standard-remark-table-extended-normative",
|
|
555
|
+
smartStandardRemarkTableExtendedNormativeCollapsible: "smart-standard-remark-table-extended-normative-collapsible",
|
|
548
556
|
smartStandardRemarkTableImageNonNormative: "smart-standard-remark-table-image-non-normative",
|
|
549
557
|
smartStandardRemarkTableImageNonNormativeCollapsible: "smart-standard-remark-table-image-non-normative-collapsible",
|
|
550
558
|
smartStandardRemarkTableImageNormative: "smart-standard-remark-table-image-normative",
|
|
@@ -553,6 +561,14 @@ var BitType = {
|
|
|
553
561
|
smartStandardRemarkTableNonNormativeCollapsible: "smart-standard-remark-table-non-normative-collapsible",
|
|
554
562
|
smartStandardRemarkTableNormative: "smart-standard-remark-table-normative",
|
|
555
563
|
smartStandardRemarkTableNormativeCollapsible: "smart-standard-remark-table-normative-collapsible",
|
|
564
|
+
smartStandardTableExtendedImageNonNormative: "smart-standard-table-extended-image-non-normative",
|
|
565
|
+
smartStandardTableExtendedImageNonNormativeCollapsible: "smart-standard-table-extended-image-non-normative-collapsible",
|
|
566
|
+
smartStandardTableExtendedImageNormative: "smart-standard-table-extended-image-normative",
|
|
567
|
+
smartStandardTableExtendedImageNormativeCollapsible: "smart-standard-table-extended-image-normative-collapsible",
|
|
568
|
+
smartStandardTableExtendedNonNormative: "smart-standard-table-extended-non-normative",
|
|
569
|
+
smartStandardTableExtendedNonNormativeCollapsible: "smart-standard-table-extended-non-normative-collapsible",
|
|
570
|
+
smartStandardTableExtendedNormative: "smart-standard-table-extended-normative",
|
|
571
|
+
smartStandardTableExtendedNormativeCollapsible: "smart-standard-table-extended-normative-collapsible",
|
|
556
572
|
smartStandardTableImageNonNormative: "smart-standard-table-image-non-normative",
|
|
557
573
|
smartStandardTableImageNonNormativeCollapsible: "smart-standard-table-image-non-normative-collapsible",
|
|
558
574
|
smartStandardTableImageNormative: "smart-standard-table-image-normative",
|
|
@@ -575,10 +591,18 @@ var BitType = {
|
|
|
575
591
|
standardNoteNormative: "standard-note-normative",
|
|
576
592
|
standardRemarkNonNormative: "standard-remark-non-normative",
|
|
577
593
|
standardRemarkNormative: "standard-remark-normative",
|
|
594
|
+
standardRemarkTableExtendedImageNonNormative: "standard-remark-table-extended-image-non-normative",
|
|
595
|
+
standardRemarkTableExtendedImageNormative: "standard-remark-table-extended-image-normative",
|
|
596
|
+
standardRemarkTableExtendedNonNormative: "standard-remark-table-extended-non-normative",
|
|
597
|
+
standardRemarkTableExtendedNormative: "standard-remark-table-extended-normative",
|
|
578
598
|
standardRemarkTableImageNonNormative: "standard-remark-table-image-non-normative",
|
|
579
599
|
standardRemarkTableImageNormative: "standard-remark-table-image-normative",
|
|
580
600
|
standardRemarkTableNonNormative: "standard-remark-table-non-normative",
|
|
581
601
|
standardRemarkTableNormative: "standard-remark-table-normative",
|
|
602
|
+
standardTableExtendedImageNonNormative: "standard-table-extended-image-non-normative",
|
|
603
|
+
standardTableExtendedImageNormative: "standard-table-extended-image-normative",
|
|
604
|
+
standardTableExtendedNonNormative: "standard-table-extended-non-normative",
|
|
605
|
+
standardTableExtendedNormative: "standard-table-extended-normative",
|
|
582
606
|
standardTableImageNonNormative: "standard-table-image-non-normative",
|
|
583
607
|
standardTableImageNormative: "standard-table-image-normative",
|
|
584
608
|
standardTableNonNormative: "standard-table-non-normative",
|
|
@@ -777,6 +801,10 @@ var AbstractTagConfig = class {
|
|
|
777
801
|
// New JSON-pattern jsonKey (export-only)
|
|
778
802
|
hasExportJsonKey;
|
|
779
803
|
// True iff exportJsonKey was explicitly set
|
|
804
|
+
htmlKey;
|
|
805
|
+
// HTML key-pattern (export-only)
|
|
806
|
+
hasHtmlKey;
|
|
807
|
+
// True iff htmlKey was explicitly set
|
|
780
808
|
deprecated;
|
|
781
809
|
// Deprecated version
|
|
782
810
|
constructor(params) {
|
|
@@ -789,6 +817,8 @@ var AbstractTagConfig = class {
|
|
|
789
817
|
this.jsonKey = params.jsonKey;
|
|
790
818
|
this.exportJsonKey = params.exportJsonKey;
|
|
791
819
|
this.hasExportJsonKey = params.hasExportJsonKey;
|
|
820
|
+
this.htmlKey = params.htmlKey;
|
|
821
|
+
this.hasHtmlKey = params.hasHtmlKey;
|
|
792
822
|
this.deprecated = params.deprecated;
|
|
793
823
|
}
|
|
794
824
|
};
|
|
@@ -922,9 +952,12 @@ var CardVariantConfig = class {
|
|
|
922
952
|
exportJsonKey;
|
|
923
953
|
// New JSON-pattern jsonKey
|
|
924
954
|
hasExportJsonKey;
|
|
955
|
+
htmlKey;
|
|
956
|
+
// HTML key-pattern
|
|
957
|
+
hasHtmlKey;
|
|
925
958
|
format;
|
|
926
959
|
// Body text format. Default: bitmark++
|
|
927
|
-
constructor(tags2, bodyAllowed, bodyRequired, repeatCount, jsonKey, exportJsonKey, hasExportJsonKey = false, format) {
|
|
960
|
+
constructor(tags2, bodyAllowed, bodyRequired, repeatCount, jsonKey, exportJsonKey, hasExportJsonKey = false, format, htmlKey, hasHtmlKey = false) {
|
|
928
961
|
this.tags = tags2;
|
|
929
962
|
this.bodyAllowed = bodyAllowed == null ? true : bodyAllowed;
|
|
930
963
|
this.bodyRequired = bodyRequired;
|
|
@@ -932,6 +965,8 @@ var CardVariantConfig = class {
|
|
|
932
965
|
this.jsonKey = jsonKey;
|
|
933
966
|
this.exportJsonKey = exportJsonKey;
|
|
934
967
|
this.hasExportJsonKey = hasExportJsonKey;
|
|
968
|
+
this.htmlKey = htmlKey;
|
|
969
|
+
this.hasHtmlKey = hasHtmlKey;
|
|
935
970
|
this.format = format;
|
|
936
971
|
}
|
|
937
972
|
toString(options) {
|
|
@@ -961,13 +996,17 @@ var CardSideConfig = class {
|
|
|
961
996
|
jsonKey;
|
|
962
997
|
exportJsonKey;
|
|
963
998
|
hasExportJsonKey;
|
|
999
|
+
htmlKey;
|
|
1000
|
+
hasHtmlKey;
|
|
964
1001
|
variants;
|
|
965
|
-
constructor(name, repeat, variants, jsonKey, exportJsonKey, hasExportJsonKey = false) {
|
|
1002
|
+
constructor(name, repeat, variants, jsonKey, exportJsonKey, hasExportJsonKey = false, htmlKey, hasHtmlKey = false) {
|
|
966
1003
|
this.name = name;
|
|
967
1004
|
this.repeat = repeat;
|
|
968
1005
|
this.jsonKey = jsonKey;
|
|
969
1006
|
this.exportJsonKey = exportJsonKey;
|
|
970
1007
|
this.hasExportJsonKey = hasExportJsonKey;
|
|
1008
|
+
this.htmlKey = htmlKey;
|
|
1009
|
+
this.hasHtmlKey = hasHtmlKey;
|
|
971
1010
|
this.variants = variants;
|
|
972
1011
|
}
|
|
973
1012
|
toString(options) {
|
|
@@ -993,6 +1032,8 @@ var CardSetConfig = class {
|
|
|
993
1032
|
jsonKey;
|
|
994
1033
|
exportJsonKey;
|
|
995
1034
|
hasExportJsonKey;
|
|
1035
|
+
htmlKey;
|
|
1036
|
+
hasHtmlKey;
|
|
996
1037
|
sections;
|
|
997
1038
|
sides;
|
|
998
1039
|
// Legacy accessor — provides the same shape as the old `variants: CardVariantConfig[][]`
|
|
@@ -1000,11 +1041,13 @@ var CardSetConfig = class {
|
|
|
1000
1041
|
get variants() {
|
|
1001
1042
|
return this.sides.map((side) => side.variants);
|
|
1002
1043
|
}
|
|
1003
|
-
constructor(configKey, jsonKey, exportJsonKey, hasExportJsonKey, sections, sides) {
|
|
1044
|
+
constructor(configKey, jsonKey, exportJsonKey, hasExportJsonKey, sections, sides, htmlKey = void 0, hasHtmlKey = false) {
|
|
1004
1045
|
this.configKey = configKey;
|
|
1005
1046
|
this.jsonKey = jsonKey;
|
|
1006
1047
|
this.exportJsonKey = exportJsonKey;
|
|
1007
1048
|
this.hasExportJsonKey = hasExportJsonKey;
|
|
1049
|
+
this.htmlKey = htmlKey;
|
|
1050
|
+
this.hasHtmlKey = hasHtmlKey;
|
|
1008
1051
|
this.sections = sections;
|
|
1009
1052
|
this.sides = sides;
|
|
1010
1053
|
}
|
|
@@ -1287,6 +1330,8 @@ var propertyKeys = {
|
|
|
1287
1330
|
property_externalLinkText: "@externalLinkText",
|
|
1288
1331
|
property_feedbackEngine: "@feedbackEngine",
|
|
1289
1332
|
property_feedbackType: "@feedbackType",
|
|
1333
|
+
property_userFeedbackTranslationUrl: "@userFeedbackTranslationUrl",
|
|
1334
|
+
property_userFeedbackContentUrl: "@userFeedbackContentUrl",
|
|
1290
1335
|
property_flashcardSet: "@flashcardSet",
|
|
1291
1336
|
property_focusX: "@focusX",
|
|
1292
1337
|
property_focusY: "@focusY",
|
|
@@ -3661,6 +3706,16 @@ var CARDSETS = {
|
|
|
3661
3706
|
[CardSetConfigKey.table]: {
|
|
3662
3707
|
jsonKey: null,
|
|
3663
3708
|
exportJsonKey: null,
|
|
3709
|
+
// PLAN-109 / HTML.md §8 — idiomatic HTML mapping. The classic (non-extended)
|
|
3710
|
+
// table produces the same `<table>`/`<thead>`/`<tbody>`/`<tfoot>` structure as
|
|
3711
|
+
// table-extended, so the structural htmlKeys mirror that cardSet. NOTE: the
|
|
3712
|
+
// JSON side routes the FIRST header card → `columns` (header) and SUBSEQUENT
|
|
3713
|
+
// header cards → `data` (body); HTML uses a uniform `<thead>` for the whole
|
|
3714
|
+
// `table-header` section, so a multi-card header (e.g. a second header card
|
|
3715
|
+
// that JSON sends to `data`) renders as additional `<thead>` rows rather than
|
|
3716
|
+
// moving to `<tbody>`. Per-card header/body splitting needs engine-level
|
|
3717
|
+
// routing not yet expressible in the pattern vocabulary — see PLAN-109.
|
|
3718
|
+
htmlKey: { "@el": "table", "@children": "$" },
|
|
3664
3719
|
sections: {
|
|
3665
3720
|
"table-header": {
|
|
3666
3721
|
// First header card's row of cells → `columns`. Subsequent header
|
|
@@ -3679,25 +3734,36 @@ var CARDSETS = {
|
|
|
3679
3734
|
},
|
|
3680
3735
|
{ "@cardIndex=0": { "@bit": { table: { columns: "$" } } } },
|
|
3681
3736
|
{ "@bit": { table: { data: ["$"] } } }
|
|
3682
|
-
]
|
|
3737
|
+
],
|
|
3738
|
+
// Header section → `<thead>` rows of `<th>`; `@tableColWidth` bubbles a
|
|
3739
|
+
// `width` attr onto the enclosing `<th>` (HTML-C2).
|
|
3740
|
+
htmlKey: { "@el": "thead", "@children": { "@el": "tr", "@children": "$" } },
|
|
3741
|
+
sideHtmlKey: { "@el": "th", "@children": "$" }
|
|
3683
3742
|
},
|
|
3684
3743
|
"table-body": {
|
|
3685
3744
|
// Batched emission: `$` is the entire 2D array of body card rows.
|
|
3686
3745
|
// This is the default section (no qualifier → cards land here).
|
|
3687
3746
|
jsonKey: "table.data",
|
|
3688
3747
|
exportJsonKey: { "@bit": { table: { data: "$" } } },
|
|
3748
|
+
htmlKey: { "@el": "tbody", "@children": { "@el": "tr", "@children": "$" } },
|
|
3689
3749
|
isDefault: true
|
|
3690
3750
|
},
|
|
3691
3751
|
"table-footer": {
|
|
3692
3752
|
// Batched emission: `$` is the entire 2D array of footer rows.
|
|
3693
3753
|
jsonKey: "table.data",
|
|
3694
|
-
exportJsonKey: { "@bit": { table: { data: "$" } } }
|
|
3754
|
+
exportJsonKey: { "@bit": { table: { data: "$" } } },
|
|
3755
|
+
// Footer cells route to `data` (not `columns`), so they are `<td>` (no
|
|
3756
|
+
// sideHtmlKey override — the cell side default applies).
|
|
3757
|
+
htmlKey: { "@el": "tfoot", "@children": { "@el": "tr", "@children": "$" } }
|
|
3695
3758
|
}
|
|
3696
3759
|
},
|
|
3697
3760
|
sides: [
|
|
3698
3761
|
{
|
|
3699
3762
|
name: "cell",
|
|
3700
3763
|
repeat: true,
|
|
3764
|
+
// Default (body/footer) cell → `<td>`; the header section overrides to
|
|
3765
|
+
// `<th>` via its sideHtmlKey (HTML.md §8).
|
|
3766
|
+
htmlKey: { "@el": "td", "@children": "$" },
|
|
3701
3767
|
variants: [
|
|
3702
3768
|
{
|
|
3703
3769
|
jsonKey: null,
|
|
@@ -3714,21 +3780,32 @@ var CARDSETS = {
|
|
|
3714
3780
|
},
|
|
3715
3781
|
{
|
|
3716
3782
|
key: ConfigKey.property_tableCellType,
|
|
3783
|
+
// HTML.md §8: first-match predicate selecting `<th>` vs `<td>`.
|
|
3784
|
+
htmlKey: [{ "@value=th": { "@el": "th" } }, { "@absent": { "@el": "td" } }],
|
|
3717
3785
|
description: "Table cell type (th/td).",
|
|
3718
3786
|
format: TagFormat.plainText
|
|
3719
3787
|
},
|
|
3720
3788
|
{
|
|
3721
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: "$" } } },
|
|
3722
3793
|
description: "Number of rows the cell spans.",
|
|
3723
3794
|
format: TagFormat.number
|
|
3724
3795
|
},
|
|
3725
3796
|
{
|
|
3726
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: "$" } } },
|
|
3727
3801
|
description: "Number of columns the cell spans.",
|
|
3728
3802
|
format: TagFormat.number
|
|
3729
3803
|
},
|
|
3730
3804
|
{
|
|
3731
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: "$" } } },
|
|
3732
3809
|
description: "Scope attribute for header cells.",
|
|
3733
3810
|
format: TagFormat.plainText
|
|
3734
3811
|
},
|
|
@@ -3736,6 +3813,9 @@ var CARDSETS = {
|
|
|
3736
3813
|
key: ConfigKey.property_tableColWidth,
|
|
3737
3814
|
jsonKey: "^table.columnWidths[{s}]",
|
|
3738
3815
|
exportJsonKey: { "@bit": { table: { columnWidths: { $s: "$" } } } },
|
|
3816
|
+
// HTML.md §8 + HTML-C2: contribute a `width` attribute onto the
|
|
3817
|
+
// enclosing cell element (`<th>`/`<td>`).
|
|
3818
|
+
htmlKey: { "@el": { "@attr": { width: "$" } } },
|
|
3739
3819
|
description: "Width for the column.",
|
|
3740
3820
|
format: TagFormat.number
|
|
3741
3821
|
}
|
|
@@ -3751,6 +3831,12 @@ var CARDSETS = {
|
|
|
3751
3831
|
//
|
|
3752
3832
|
[CardSetConfigKey.tableExtended]: {
|
|
3753
3833
|
jsonKey: null,
|
|
3834
|
+
// PLAN-109 / HTML.md §8 — idiomatic HTML mapping for the extended table.
|
|
3835
|
+
// The card-set container is the `<table>` element; each section is a
|
|
3836
|
+
// table section element (`<thead>`/`<tbody>`/`<tfoot>`) whose children are
|
|
3837
|
+
// `<tr>` rows, and each cell side is a `<td>` (body) or `<th>` (header /
|
|
3838
|
+
// footer, via the section sideHtmlKey override).
|
|
3839
|
+
htmlKey: { "@el": "table", "@children": "$" },
|
|
3754
3840
|
sections: {
|
|
3755
3841
|
"table-header": {
|
|
3756
3842
|
jsonKey: "table.header.rows",
|
|
@@ -3770,19 +3856,29 @@ var CARDSETS = {
|
|
|
3770
3856
|
},
|
|
3771
3857
|
{ table: { header: { rows: ["$"] } } }
|
|
3772
3858
|
],
|
|
3859
|
+
htmlKey: { "@el": "thead", "@children": { "@el": "tr", "@children": "$" } },
|
|
3773
3860
|
sideJsonKey: "cells[{s}]|set(title=true)",
|
|
3774
|
-
sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } }
|
|
3861
|
+
sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } },
|
|
3862
|
+
// Header cells are `<th>`. The `width` attribute is contributed by the
|
|
3863
|
+
// `@tableColWidth` tag, which bubbles it onto the enclosing `<th>`
|
|
3864
|
+
// (HTML-C2) — so it is not repeated here.
|
|
3865
|
+
sideHtmlKey: { "@el": "th", "@children": "$" }
|
|
3775
3866
|
},
|
|
3776
3867
|
"table-body": {
|
|
3777
3868
|
jsonKey: "table.body.rows",
|
|
3778
3869
|
exportJsonKey: { table: { body: { rows: "$" } } },
|
|
3870
|
+
htmlKey: { "@el": "tbody", "@children": { "@el": "tr", "@children": "$" } },
|
|
3779
3871
|
isDefault: true
|
|
3780
3872
|
},
|
|
3781
3873
|
"table-footer": {
|
|
3782
3874
|
jsonKey: "table.footer.rows",
|
|
3783
3875
|
exportJsonKey: { table: { footer: { rows: "$" } } },
|
|
3876
|
+
htmlKey: { "@el": "tfoot", "@children": { "@el": "tr", "@children": "$" } },
|
|
3784
3877
|
sideJsonKey: "cells[{s}]|set(title=true)",
|
|
3785
|
-
sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } }
|
|
3878
|
+
sideExportJsonKey: { cells: { $s: { title: true, $: "$" } } },
|
|
3879
|
+
// Footer cells render as `<th>` (mirrors the header `title: true`
|
|
3880
|
+
// mapping); §8 lists only the header side, so this parallels it.
|
|
3881
|
+
sideHtmlKey: { "@el": "th", "@children": "$" }
|
|
3786
3882
|
}
|
|
3787
3883
|
},
|
|
3788
3884
|
sides: [
|
|
@@ -3791,6 +3887,9 @@ var CARDSETS = {
|
|
|
3791
3887
|
repeat: true,
|
|
3792
3888
|
jsonKey: "cells[{s}]",
|
|
3793
3889
|
exportJsonKey: { cells: { $s: "$" } },
|
|
3890
|
+
// Default (body) cell → `<td>`; the header/footer sections override the
|
|
3891
|
+
// side to `<th>` via their sideHtmlKey (HTML.md §8).
|
|
3892
|
+
htmlKey: { "@el": "td", "@children": "$" },
|
|
3794
3893
|
variants: [
|
|
3795
3894
|
{
|
|
3796
3895
|
jsonKey: "content",
|
|
@@ -3814,6 +3913,9 @@ var CARDSETS = {
|
|
|
3814
3913
|
key: ConfigKey.property_tableCellType,
|
|
3815
3914
|
jsonKey: "title|bool(th)",
|
|
3816
3915
|
exportJsonKey: [{ "@value=th": { title: true } }],
|
|
3916
|
+
// HTML.md §8: same first-match predicate machinery selecting
|
|
3917
|
+
// `<th>` vs `<td>` instead of `title:true` vs nothing.
|
|
3918
|
+
htmlKey: [{ "@value=th": { "@el": "th" } }, { "@absent": { "@el": "td" } }],
|
|
3817
3919
|
description: "Table cell type (th/td).",
|
|
3818
3920
|
format: TagFormat.plainText
|
|
3819
3921
|
},
|
|
@@ -3821,6 +3923,9 @@ var CARDSETS = {
|
|
|
3821
3923
|
key: ConfigKey.property_tableRowSpan,
|
|
3822
3924
|
jsonKey: "rowspan",
|
|
3823
3925
|
exportJsonKey: { rowspan: "$" },
|
|
3926
|
+
// HTML-C2: contribute a `rowspan` attribute onto the enclosing
|
|
3927
|
+
// cell element (`<th>`/`<td>`).
|
|
3928
|
+
htmlKey: { "@el": { "@attr": { rowspan: "$" } } },
|
|
3824
3929
|
description: "Number of rows the cell spans.",
|
|
3825
3930
|
format: TagFormat.number
|
|
3826
3931
|
},
|
|
@@ -3828,6 +3933,9 @@ var CARDSETS = {
|
|
|
3828
3933
|
key: ConfigKey.property_tableColSpan,
|
|
3829
3934
|
jsonKey: "colspan",
|
|
3830
3935
|
exportJsonKey: { colspan: "$" },
|
|
3936
|
+
// HTML-C2: contribute a `colspan` attribute onto the enclosing
|
|
3937
|
+
// cell element (`<th>`/`<td>`).
|
|
3938
|
+
htmlKey: { "@el": { "@attr": { colspan: "$" } } },
|
|
3831
3939
|
description: "Number of columns the cell spans.",
|
|
3832
3940
|
format: TagFormat.number
|
|
3833
3941
|
},
|
|
@@ -3835,6 +3943,9 @@ var CARDSETS = {
|
|
|
3835
3943
|
key: ConfigKey.property_tableScope,
|
|
3836
3944
|
jsonKey: "scope",
|
|
3837
3945
|
exportJsonKey: { scope: "$" },
|
|
3946
|
+
// HTML-C2: contribute a `scope` attribute onto the enclosing
|
|
3947
|
+
// cell element (`<th>`/`<td>`).
|
|
3948
|
+
htmlKey: { "@el": { "@attr": { scope: "$" } } },
|
|
3838
3949
|
description: "Scope attribute for header cells.",
|
|
3839
3950
|
format: TagFormat.plainText
|
|
3840
3951
|
},
|
|
@@ -3843,6 +3954,9 @@ var CARDSETS = {
|
|
|
3843
3954
|
// PLAN-080: write to the cell's `colwidth` field.
|
|
3844
3955
|
jsonKey: "colwidth",
|
|
3845
3956
|
exportJsonKey: { colwidth: "$" },
|
|
3957
|
+
// HTML.md §8 + HTML-C2: contribute a `width` attribute onto the
|
|
3958
|
+
// enclosing cell element (`<th>`/`<td>`).
|
|
3959
|
+
htmlKey: { "@el": { "@attr": { width: "$" } } },
|
|
3846
3960
|
description: "Width for the column.",
|
|
3847
3961
|
format: TagFormat.number
|
|
3848
3962
|
}
|
|
@@ -5642,6 +5756,16 @@ var GROUPS = {
|
|
|
5642
5756
|
description: "External Id of the translated book",
|
|
5643
5757
|
format: TagFormat.plainText
|
|
5644
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
|
+
},
|
|
5645
5769
|
{
|
|
5646
5770
|
key: ConfigKey.property_duration,
|
|
5647
5771
|
description: "The duration of the book",
|
|
@@ -6771,7 +6895,9 @@ var ConfigHydrator = class {
|
|
|
6771
6895
|
variantsOfSide,
|
|
6772
6896
|
_side.jsonKey,
|
|
6773
6897
|
_side.exportJsonKey,
|
|
6774
|
-
Object.prototype.hasOwnProperty.call(_side, "exportJsonKey")
|
|
6898
|
+
Object.prototype.hasOwnProperty.call(_side, "exportJsonKey"),
|
|
6899
|
+
_side.htmlKey,
|
|
6900
|
+
Object.prototype.hasOwnProperty.call(_side, "htmlKey")
|
|
6775
6901
|
);
|
|
6776
6902
|
sides.push(sideConfig);
|
|
6777
6903
|
}
|
|
@@ -6781,7 +6907,9 @@ var ConfigHydrator = class {
|
|
|
6781
6907
|
_cardSetConfig.exportJsonKey,
|
|
6782
6908
|
Object.prototype.hasOwnProperty.call(_cardSetConfig, "exportJsonKey"),
|
|
6783
6909
|
this.hydrateCardSections(_cardSetConfig.sections),
|
|
6784
|
-
sides
|
|
6910
|
+
sides,
|
|
6911
|
+
_cardSetConfig.htmlKey,
|
|
6912
|
+
Object.prototype.hasOwnProperty.call(_cardSetConfig, "htmlKey")
|
|
6785
6913
|
);
|
|
6786
6914
|
return cardSetConfig;
|
|
6787
6915
|
}
|
|
@@ -6793,10 +6921,14 @@ var ConfigHydrator = class {
|
|
|
6793
6921
|
jsonKey: v.jsonKey,
|
|
6794
6922
|
exportJsonKey: v.exportJsonKey,
|
|
6795
6923
|
hasExportJsonKey: Object.prototype.hasOwnProperty.call(v, "exportJsonKey"),
|
|
6924
|
+
htmlKey: v.htmlKey,
|
|
6925
|
+
hasHtmlKey: Object.prototype.hasOwnProperty.call(v, "htmlKey"),
|
|
6796
6926
|
isDefault: v.isDefault,
|
|
6797
6927
|
sideJsonKey: v.sideJsonKey,
|
|
6798
6928
|
sideExportJsonKey: v.sideExportJsonKey,
|
|
6799
6929
|
hasSideExportJsonKey: Object.prototype.hasOwnProperty.call(v, "sideExportJsonKey"),
|
|
6930
|
+
sideHtmlKey: v.sideHtmlKey,
|
|
6931
|
+
hasSideHtmlKey: Object.prototype.hasOwnProperty.call(v, "sideHtmlKey"),
|
|
6800
6932
|
// PLAN-085: cardinality fields pass through; defaults applied
|
|
6801
6933
|
// downstream by the config consumer (Rust treats `0` / undefined
|
|
6802
6934
|
// as unbounded).
|
|
@@ -6814,7 +6946,8 @@ var ConfigHydrator = class {
|
|
|
6814
6946
|
chain: _chain,
|
|
6815
6947
|
deprecated,
|
|
6816
6948
|
jsonKey,
|
|
6817
|
-
exportJsonKey
|
|
6949
|
+
exportJsonKey,
|
|
6950
|
+
htmlKey
|
|
6818
6951
|
} = _tag;
|
|
6819
6952
|
const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
|
|
6820
6953
|
if (!configKey) throw new Error(`No tag key found for config key '${configKey}'`);
|
|
@@ -6833,6 +6966,8 @@ var ConfigHydrator = class {
|
|
|
6833
6966
|
jsonKey,
|
|
6834
6967
|
exportJsonKey,
|
|
6835
6968
|
hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
|
|
6969
|
+
htmlKey,
|
|
6970
|
+
hasHtmlKey: Object.prototype.hasOwnProperty.call(_tag, "htmlKey"),
|
|
6836
6971
|
deprecated
|
|
6837
6972
|
});
|
|
6838
6973
|
return {
|
|
@@ -6852,7 +6987,8 @@ var ConfigHydrator = class {
|
|
|
6852
6987
|
values,
|
|
6853
6988
|
defaultValue,
|
|
6854
6989
|
jsonKey,
|
|
6855
|
-
exportJsonKey
|
|
6990
|
+
exportJsonKey,
|
|
6991
|
+
htmlKey
|
|
6856
6992
|
} = _tag;
|
|
6857
6993
|
const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
|
|
6858
6994
|
if (!configKey) throw new Error(`No property key found for config key '${configKey}'`);
|
|
@@ -6870,6 +7006,8 @@ var ConfigHydrator = class {
|
|
|
6870
7006
|
jsonKey,
|
|
6871
7007
|
exportJsonKey,
|
|
6872
7008
|
hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
|
|
7009
|
+
htmlKey,
|
|
7010
|
+
hasHtmlKey: Object.prototype.hasOwnProperty.call(_tag, "htmlKey"),
|
|
6873
7011
|
format,
|
|
6874
7012
|
values,
|
|
6875
7013
|
defaultValue,
|
|
@@ -6889,7 +7027,8 @@ var ConfigHydrator = class {
|
|
|
6889
7027
|
chain: _chain,
|
|
6890
7028
|
deprecated,
|
|
6891
7029
|
jsonKey,
|
|
6892
|
-
exportJsonKey
|
|
7030
|
+
exportJsonKey,
|
|
7031
|
+
htmlKey
|
|
6893
7032
|
} = _tag;
|
|
6894
7033
|
const configKey = Enum(ConfigKey).fromValue(_configKey) || ConfigKey._unknown;
|
|
6895
7034
|
if (!configKey) throw new Error(`No resource key found for config key '${configKey}'`);
|
|
@@ -6907,6 +7046,8 @@ var ConfigHydrator = class {
|
|
|
6907
7046
|
jsonKey,
|
|
6908
7047
|
exportJsonKey,
|
|
6909
7048
|
hasExportJsonKey: Object.prototype.hasOwnProperty.call(_tag, "exportJsonKey"),
|
|
7049
|
+
htmlKey,
|
|
7050
|
+
hasHtmlKey: Object.prototype.hasOwnProperty.call(_tag, "htmlKey"),
|
|
6910
7051
|
deprecated
|
|
6911
7052
|
});
|
|
6912
7053
|
return {
|
|
@@ -6945,6 +7086,7 @@ var ConfigHydrator = class {
|
|
|
6945
7086
|
repeatCount,
|
|
6946
7087
|
jsonKey,
|
|
6947
7088
|
exportJsonKey,
|
|
7089
|
+
htmlKey,
|
|
6948
7090
|
format
|
|
6949
7091
|
} = _variant;
|
|
6950
7092
|
const tags2 = this.hydrateTagsConfig(_tags);
|
|
@@ -6956,7 +7098,9 @@ var ConfigHydrator = class {
|
|
|
6956
7098
|
jsonKey,
|
|
6957
7099
|
exportJsonKey,
|
|
6958
7100
|
Object.prototype.hasOwnProperty.call(_variant, "exportJsonKey"),
|
|
6959
|
-
format
|
|
7101
|
+
format,
|
|
7102
|
+
htmlKey,
|
|
7103
|
+
Object.prototype.hasOwnProperty.call(_variant, "htmlKey")
|
|
6960
7104
|
);
|
|
6961
7105
|
return cardSetConfig;
|
|
6962
7106
|
}
|
|
@@ -10089,11 +10233,6 @@ var BITS = {
|
|
|
10089
10233
|
baseBitType: BitType._standard,
|
|
10090
10234
|
description: "Extractor rule bit, used to define extraction rules with reference images and instructions",
|
|
10091
10235
|
tags: [
|
|
10092
|
-
{
|
|
10093
|
-
exportJsonKey: { title: "$" },
|
|
10094
|
-
key: ConfigKey.tag_title,
|
|
10095
|
-
description: "The name of the extraction rule"
|
|
10096
|
-
},
|
|
10097
10236
|
{
|
|
10098
10237
|
key: ConfigKey.group_resourceBitTags,
|
|
10099
10238
|
description: "Resource bit tags for extraction rule images"
|
|
@@ -10729,7 +10868,9 @@ var BITS = {
|
|
|
10729
10868
|
{
|
|
10730
10869
|
key: ConfigKey.property_caption,
|
|
10731
10870
|
description: "Caption for the table image, used to provide a description for the image",
|
|
10732
|
-
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": "$" }
|
|
10733
10874
|
},
|
|
10734
10875
|
{
|
|
10735
10876
|
key: ConfigKey.group_backgroundWallpaper,
|
|
@@ -10772,6 +10913,26 @@ var BITS = {
|
|
|
10772
10913
|
baseBitType: BitType.tableImage,
|
|
10773
10914
|
description: "Standard non-normative remark table image bit, used to create non-normative remark images in tables in articles or books"
|
|
10774
10915
|
},
|
|
10916
|
+
[BitType.standardTableExtendedImageNormative]: {
|
|
10917
|
+
since: "1.16.0",
|
|
10918
|
+
baseBitType: BitType.tableExtendedImage,
|
|
10919
|
+
description: "Standard normative extended table image bit, used to create normative extended images in tables in articles or books"
|
|
10920
|
+
},
|
|
10921
|
+
[BitType.standardTableExtendedImageNonNormative]: {
|
|
10922
|
+
since: "1.16.0",
|
|
10923
|
+
baseBitType: BitType.tableExtendedImage,
|
|
10924
|
+
description: "Standard non-normative extended table image bit, used to create non-normative extended images in tables in articles or books"
|
|
10925
|
+
},
|
|
10926
|
+
[BitType.standardRemarkTableExtendedImageNormative]: {
|
|
10927
|
+
since: "1.17.0",
|
|
10928
|
+
baseBitType: BitType.tableExtendedImage,
|
|
10929
|
+
description: "Standard normative remark extended table image bit, used to create normative remark extended images in tables in articles or books"
|
|
10930
|
+
},
|
|
10931
|
+
[BitType.standardRemarkTableExtendedImageNonNormative]: {
|
|
10932
|
+
since: "1.17.0",
|
|
10933
|
+
baseBitType: BitType.tableExtendedImage,
|
|
10934
|
+
description: "Standard non-normative remark extended table image bit, used to create non-normative remark extended images in tables in articles or books"
|
|
10935
|
+
},
|
|
10775
10936
|
[BitType.smartStandardTableImageNormative]: {
|
|
10776
10937
|
since: "1.28.0",
|
|
10777
10938
|
baseBitType: BitType.standardTableImageNormative,
|
|
@@ -10792,6 +10953,26 @@ var BITS = {
|
|
|
10792
10953
|
baseBitType: BitType.standardRemarkTableImageNonNormative,
|
|
10793
10954
|
description: "Smart standard non-normative remark table image bit, used to create smart standard non-normative remark images in tables in articles or books"
|
|
10794
10955
|
},
|
|
10956
|
+
[BitType.smartStandardTableExtendedImageNormative]: {
|
|
10957
|
+
since: "1.28.0",
|
|
10958
|
+
baseBitType: BitType.standardTableExtendedImageNormative,
|
|
10959
|
+
description: "Smart standard normative extended table image bit, used to create smart standard normative extended images in tables in articles or books"
|
|
10960
|
+
},
|
|
10961
|
+
[BitType.smartStandardTableExtendedImageNonNormative]: {
|
|
10962
|
+
since: "1.28.0",
|
|
10963
|
+
baseBitType: BitType.standardTableExtendedImageNonNormative,
|
|
10964
|
+
description: "Smart standard non-normative extended table image bit, used to create smart standard non-normative extended images in tables in articles or books"
|
|
10965
|
+
},
|
|
10966
|
+
[BitType.smartStandardRemarkTableExtendedImageNormative]: {
|
|
10967
|
+
since: "1.28.0",
|
|
10968
|
+
baseBitType: BitType.standardRemarkTableExtendedImageNormative,
|
|
10969
|
+
description: "Smart standard normative remark extended table image bit, used to create smart standard normative remark extended images in tables in articles or books"
|
|
10970
|
+
},
|
|
10971
|
+
[BitType.smartStandardRemarkTableExtendedImageNonNormative]: {
|
|
10972
|
+
since: "1.28.0",
|
|
10973
|
+
baseBitType: BitType.standardRemarkTableExtendedImageNonNormative,
|
|
10974
|
+
description: "Smart standard non-normative remark extended table image bit, used to create smart standard non-normative remark extended images in tables in articles or books"
|
|
10975
|
+
},
|
|
10795
10976
|
[BitType.smartStandardTableImageNormativeCollapsible]: {
|
|
10796
10977
|
since: "1.28.0",
|
|
10797
10978
|
baseBitType: BitType.smartStandardTableImageNormative,
|
|
@@ -10812,6 +10993,26 @@ var BITS = {
|
|
|
10812
10993
|
baseBitType: BitType.smartStandardRemarkTableImageNonNormative,
|
|
10813
10994
|
description: "Collapsible smart standard non-normative remark table image bit, used to create collapsible smart standard non-normative remark images in tables in articles or books"
|
|
10814
10995
|
},
|
|
10996
|
+
[BitType.smartStandardTableExtendedImageNormativeCollapsible]: {
|
|
10997
|
+
since: "1.28.0",
|
|
10998
|
+
baseBitType: BitType.smartStandardTableExtendedImageNormative,
|
|
10999
|
+
description: "Collapsible smart standard normative extended table image bit, used to create collapsible smart standard normative extended images in tables in articles or books"
|
|
11000
|
+
},
|
|
11001
|
+
[BitType.smartStandardTableExtendedImageNonNormativeCollapsible]: {
|
|
11002
|
+
since: "1.28.0",
|
|
11003
|
+
baseBitType: BitType.smartStandardTableExtendedImageNonNormative,
|
|
11004
|
+
description: "Collapsible smart standard non-normative extended table image bit, used to create collapsible smart standard non-normative extended images in tables in articles or books"
|
|
11005
|
+
},
|
|
11006
|
+
[BitType.smartStandardRemarkTableExtendedImageNormativeCollapsible]: {
|
|
11007
|
+
since: "1.28.0",
|
|
11008
|
+
baseBitType: BitType.smartStandardRemarkTableExtendedImageNormative,
|
|
11009
|
+
description: "Collapsible smart standard normative remark extended table image bit, used to create collapsible smart standard normative remark extended images in tables in articles or books"
|
|
11010
|
+
},
|
|
11011
|
+
[BitType.smartStandardRemarkTableExtendedImageNonNormativeCollapsible]: {
|
|
11012
|
+
since: "1.28.0",
|
|
11013
|
+
baseBitType: BitType.smartStandardRemarkTableExtendedImageNonNormative,
|
|
11014
|
+
description: "Collapsible smart standard non-normative remark extended table image bit, used to create collapsible smart standard non-normative remark extended images in tables in articles or books"
|
|
11015
|
+
},
|
|
10815
11016
|
[BitType.imageLink]: {
|
|
10816
11017
|
since: "1.3.0",
|
|
10817
11018
|
baseBitType: BitType._standard,
|
|
@@ -12360,7 +12561,12 @@ var BITS = {
|
|
|
12360
12561
|
{
|
|
12361
12562
|
key: ConfigKey.property_caption,
|
|
12362
12563
|
description: "Caption for the table, used to define the title of the table",
|
|
12363
|
-
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": "$" }
|
|
12364
12570
|
},
|
|
12365
12571
|
{
|
|
12366
12572
|
key: ConfigKey.property_tableFixedHeader,
|
|
@@ -12445,7 +12651,9 @@ var BITS = {
|
|
|
12445
12651
|
{
|
|
12446
12652
|
key: ConfigKey.property_caption,
|
|
12447
12653
|
description: "Caption for the table image, used to provide a description for the image",
|
|
12448
|
-
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": "$" }
|
|
12449
12657
|
},
|
|
12450
12658
|
{
|
|
12451
12659
|
key: ConfigKey.group_backgroundWallpaper,
|
|
@@ -12488,6 +12696,26 @@ var BITS = {
|
|
|
12488
12696
|
baseBitType: BitType.table,
|
|
12489
12697
|
description: "Standard non-normative remark table bit, used to create standard non-normative remark tables in articles or books"
|
|
12490
12698
|
},
|
|
12699
|
+
[BitType.standardTableExtendedNormative]: {
|
|
12700
|
+
since: "1.16.0",
|
|
12701
|
+
baseBitType: BitType.tableExtended,
|
|
12702
|
+
description: "Standard normative extended table bit, used to create standard normative extended tables in articles or books"
|
|
12703
|
+
},
|
|
12704
|
+
[BitType.standardTableExtendedNonNormative]: {
|
|
12705
|
+
since: "1.16.0",
|
|
12706
|
+
baseBitType: BitType.tableExtended,
|
|
12707
|
+
description: "Standard non-normative extended table bit, used to create standard non-normative extended tables in articles or books"
|
|
12708
|
+
},
|
|
12709
|
+
[BitType.standardRemarkTableExtendedNormative]: {
|
|
12710
|
+
since: "1.17.0",
|
|
12711
|
+
baseBitType: BitType.tableExtended,
|
|
12712
|
+
description: "Standard normative remark extended table bit, used to create standard normative remark extended tables in articles or books"
|
|
12713
|
+
},
|
|
12714
|
+
[BitType.standardRemarkTableExtendedNonNormative]: {
|
|
12715
|
+
since: "1.17.0",
|
|
12716
|
+
baseBitType: BitType.tableExtended,
|
|
12717
|
+
description: "Standard non-normative remark extended table bit, used to create standard non-normative remark extended tables in articles or books"
|
|
12718
|
+
},
|
|
12491
12719
|
[BitType.smartStandardTableNormative]: {
|
|
12492
12720
|
since: "1.28.0",
|
|
12493
12721
|
baseBitType: BitType.standardTableNormative,
|
|
@@ -12508,6 +12736,26 @@ var BITS = {
|
|
|
12508
12736
|
baseBitType: BitType.standardRemarkTableNonNormative,
|
|
12509
12737
|
description: "Smart standard non-normative remark table bit, used to create smart standard non-normative remark tables in articles or books"
|
|
12510
12738
|
},
|
|
12739
|
+
[BitType.smartStandardTableExtendedNormative]: {
|
|
12740
|
+
since: "1.28.0",
|
|
12741
|
+
baseBitType: BitType.standardTableExtendedNormative,
|
|
12742
|
+
description: "Smart standard normative extended table bit, used to create smart standard normative extended tables in articles or books"
|
|
12743
|
+
},
|
|
12744
|
+
[BitType.smartStandardTableExtendedNonNormative]: {
|
|
12745
|
+
since: "1.28.0",
|
|
12746
|
+
baseBitType: BitType.standardTableExtendedNonNormative,
|
|
12747
|
+
description: "Smart standard non-normative extended table bit, used to create smart standard non-normative extended tables in articles or books"
|
|
12748
|
+
},
|
|
12749
|
+
[BitType.smartStandardRemarkTableExtendedNormative]: {
|
|
12750
|
+
since: "1.28.0",
|
|
12751
|
+
baseBitType: BitType.standardRemarkTableExtendedNormative,
|
|
12752
|
+
description: "Smart standard normative remark extended table bit, used to create smart standard normative remark extended tables in articles or books"
|
|
12753
|
+
},
|
|
12754
|
+
[BitType.smartStandardRemarkTableExtendedNonNormative]: {
|
|
12755
|
+
since: "1.28.0",
|
|
12756
|
+
baseBitType: BitType.standardRemarkTableExtendedNonNormative,
|
|
12757
|
+
description: "Smart standard non-normative remark extended table bit, used to create smart standard non-normative remark extended tables in articles or books"
|
|
12758
|
+
},
|
|
12511
12759
|
[BitType.smartStandardTableNormativeCollapsible]: {
|
|
12512
12760
|
since: "1.28.0",
|
|
12513
12761
|
baseBitType: BitType.smartStandardTableNormative,
|
|
@@ -12528,6 +12776,26 @@ var BITS = {
|
|
|
12528
12776
|
baseBitType: BitType.smartStandardRemarkTableNonNormative,
|
|
12529
12777
|
description: "Collapsible smart standard non-normative remark table bit, used to create collapsible smart standard non-normative remark tables in articles or books"
|
|
12530
12778
|
},
|
|
12779
|
+
[BitType.smartStandardTableExtendedNormativeCollapsible]: {
|
|
12780
|
+
since: "1.28.0",
|
|
12781
|
+
baseBitType: BitType.smartStandardTableExtendedNormative,
|
|
12782
|
+
description: "Collapsible smart standard normative extended table bit, used to create collapsible smart standard normative extended tables in articles or books"
|
|
12783
|
+
},
|
|
12784
|
+
[BitType.smartStandardTableExtendedNonNormativeCollapsible]: {
|
|
12785
|
+
since: "1.28.0",
|
|
12786
|
+
baseBitType: BitType.smartStandardTableExtendedNonNormative,
|
|
12787
|
+
description: "Collapsible smart standard non-normative extended table bit, used to create collapsible smart standard non-normative extended tables in articles or books"
|
|
12788
|
+
},
|
|
12789
|
+
[BitType.smartStandardRemarkTableExtendedNormativeCollapsible]: {
|
|
12790
|
+
since: "1.28.0",
|
|
12791
|
+
baseBitType: BitType.smartStandardRemarkTableExtendedNormative,
|
|
12792
|
+
description: "Collapsible smart standard normative remark extended table bit, used to create collapsible smart standard normative remark extended tables in articles or books"
|
|
12793
|
+
},
|
|
12794
|
+
[BitType.smartStandardRemarkTableExtendedNonNormativeCollapsible]: {
|
|
12795
|
+
since: "1.28.0",
|
|
12796
|
+
baseBitType: BitType.smartStandardRemarkTableExtendedNonNormative,
|
|
12797
|
+
description: "Collapsible smart standard non-normative remark extended table bit, used to create collapsible smart standard non-normative remark extended tables in articles or books"
|
|
12798
|
+
},
|
|
12531
12799
|
[BitType.parameters]: {
|
|
12532
12800
|
since: "1.18.0",
|
|
12533
12801
|
baseBitType: BitType.table,
|
|
@@ -13469,6 +13737,8 @@ var Config = class {
|
|
|
13469
13737
|
jsonKey: tag.jsonKey,
|
|
13470
13738
|
exportJsonKey: tag.exportJsonKey,
|
|
13471
13739
|
hasExportJsonKey: tag.hasExportJsonKey,
|
|
13740
|
+
htmlKey: tag.htmlKey,
|
|
13741
|
+
hasHtmlKey: tag.hasHtmlKey,
|
|
13472
13742
|
deprecated: tag.deprecated
|
|
13473
13743
|
});
|
|
13474
13744
|
finalResourceTags[k] = newTag;
|
|
@@ -13573,7 +13843,7 @@ var instance2 = new Config();
|
|
|
13573
13843
|
// src/generated/package_info.ts
|
|
13574
13844
|
var PACKAGE_INFO = {
|
|
13575
13845
|
"name": "@gmb/bitmark-parser-generator",
|
|
13576
|
-
"version": "5.
|
|
13846
|
+
"version": "5.28.0",
|
|
13577
13847
|
"license": "ISC"};
|
|
13578
13848
|
var Environment = {
|
|
13579
13849
|
unknown: "",
|
|
@@ -14431,6 +14701,10 @@ var NodeType = {
|
|
|
14431
14701
|
relatedBookValue: "relatedBookValue",
|
|
14432
14702
|
translationOfBook: "translationOfBook",
|
|
14433
14703
|
translationOfBookValue: "translationOfBookValue",
|
|
14704
|
+
userFeedbackTranslationUrl: "userFeedbackTranslationUrl",
|
|
14705
|
+
userFeedbackTranslationUrlValue: "userFeedbackTranslationUrlValue",
|
|
14706
|
+
userFeedbackContentUrl: "userFeedbackContentUrl",
|
|
14707
|
+
userFeedbackContentUrlValue: "userFeedbackContentUrlValue",
|
|
14434
14708
|
releaseDate: "releaseDate",
|
|
14435
14709
|
releaseDateValue: "releaseDateValue",
|
|
14436
14710
|
releaseKind: "releaseKind",
|
|
@@ -27456,6 +27730,18 @@ var Builder = class extends BaseBuilder {
|
|
|
27456
27730
|
data.translationOfBook,
|
|
27457
27731
|
options
|
|
27458
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
|
+
),
|
|
27459
27745
|
author: this.toAstProperty(bitType, ConfigKey.property_author, data.author, options),
|
|
27460
27746
|
subject: this.toAstProperty(bitType, ConfigKey.property_subject, data.subject, options),
|
|
27461
27747
|
date: this.toAstProperty(bitType, ConfigKey.property_date, data.date, options),
|
|
@@ -31231,7 +31517,8 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
|
|
|
31231
31517
|
this.writeNL();
|
|
31232
31518
|
}
|
|
31233
31519
|
const content = cell.content ?? instance3.EMPTY_STRING;
|
|
31234
|
-
|
|
31520
|
+
const options = this.options.noBreakscaping ? { noBreakscaping: true } : void 0;
|
|
31521
|
+
this.writeTextOrValue(content, this.textFormat, TextLocation.body, options);
|
|
31235
31522
|
}
|
|
31236
31523
|
writeTableCellProperty(name, value) {
|
|
31237
31524
|
this.writeOPA();
|
|
@@ -32692,6 +32979,276 @@ var BitmarkStringGenerator = class {
|
|
|
32692
32979
|
return this.writer.getString();
|
|
32693
32980
|
}
|
|
32694
32981
|
};
|
|
32982
|
+
|
|
32983
|
+
// src/generator/html/HtmlTableGenerator.ts
|
|
32984
|
+
var MARK_TO_TAG = {
|
|
32985
|
+
bold: "b",
|
|
32986
|
+
italic: "i",
|
|
32987
|
+
superscript: "sup",
|
|
32988
|
+
subscript: "sub",
|
|
32989
|
+
strike: "s",
|
|
32990
|
+
del: "del",
|
|
32991
|
+
ins: "ins",
|
|
32992
|
+
underline: "u",
|
|
32993
|
+
highlight: "mark",
|
|
32994
|
+
code: "code"
|
|
32995
|
+
};
|
|
32996
|
+
var INLINE_IMAGE_RE = /==([^=]*(?:=(?!=)[^=]*)*)==\|imageInline:([^|\s]+)((?:\|(?:@?[A-Za-z][A-Za-z0-9_-]*:[^|\s]+|#[^|\s]*))*)\|?/g;
|
|
32997
|
+
var MAX_IMAGE_DIMENSION = 9999;
|
|
32998
|
+
var HtmlTableGenerator = class {
|
|
32999
|
+
indentUnit = " ";
|
|
33000
|
+
/**
|
|
33001
|
+
* Generate HTML table fragments from a string or JSON value.
|
|
33002
|
+
* @returns the concatenated `<table>` fragments, blank-line separated (empty string if none).
|
|
33003
|
+
*/
|
|
33004
|
+
generate(input) {
|
|
33005
|
+
let data = input;
|
|
33006
|
+
if (typeof data === "string") {
|
|
33007
|
+
try {
|
|
33008
|
+
data = JSON.parse(data);
|
|
33009
|
+
} catch {
|
|
33010
|
+
return "";
|
|
33011
|
+
}
|
|
33012
|
+
}
|
|
33013
|
+
const bits = this.collectBits(data);
|
|
33014
|
+
const fragments = [];
|
|
33015
|
+
for (const bit of bits) {
|
|
33016
|
+
const html = this.renderTableBit(bit);
|
|
33017
|
+
if (html) fragments.push(html);
|
|
33018
|
+
}
|
|
33019
|
+
return fragments.join("\n\n");
|
|
33020
|
+
}
|
|
33021
|
+
// --- bit collection -------------------------------------------------------
|
|
33022
|
+
collectBits(data) {
|
|
33023
|
+
const out = [];
|
|
33024
|
+
const visit = (value) => {
|
|
33025
|
+
if (value == null || typeof value !== "object") return;
|
|
33026
|
+
if (Array.isArray(value)) {
|
|
33027
|
+
value.forEach(visit);
|
|
33028
|
+
return;
|
|
33029
|
+
}
|
|
33030
|
+
const obj = value;
|
|
33031
|
+
if ("bit" in obj && obj.bit && typeof obj.bit === "object") {
|
|
33032
|
+
out.push(obj.bit);
|
|
33033
|
+
} else if ("type" in obj) {
|
|
33034
|
+
out.push(obj);
|
|
33035
|
+
}
|
|
33036
|
+
};
|
|
33037
|
+
visit(data);
|
|
33038
|
+
return out;
|
|
33039
|
+
}
|
|
33040
|
+
// --- table rendering ------------------------------------------------------
|
|
33041
|
+
renderTableBit(bit) {
|
|
33042
|
+
const table = bit.table;
|
|
33043
|
+
if (!table) return "";
|
|
33044
|
+
if (bit.type !== "table" && bit.type !== "table-extended") return "";
|
|
33045
|
+
const extended = this.toExtended(table);
|
|
33046
|
+
const lines = [];
|
|
33047
|
+
lines.push("<table>");
|
|
33048
|
+
if (bit.caption != null) {
|
|
33049
|
+
const caption = this.cellContentToHtml(this.asTextAst(bit.caption));
|
|
33050
|
+
if (caption) lines.push(`${this.indentUnit}<caption>${caption}</caption>`);
|
|
33051
|
+
}
|
|
33052
|
+
this.renderSection(lines, "thead", extended.header, "header");
|
|
33053
|
+
this.renderSection(lines, "tbody", extended.body, "body");
|
|
33054
|
+
this.renderSection(lines, "tfoot", extended.footer, "footer");
|
|
33055
|
+
lines.push("</table>");
|
|
33056
|
+
return lines.join("\n");
|
|
33057
|
+
}
|
|
33058
|
+
toExtended(table) {
|
|
33059
|
+
const t = table;
|
|
33060
|
+
if (t.header || t.body || t.footer) return table;
|
|
33061
|
+
return convertBasicToExtendedTableFormat(table);
|
|
33062
|
+
}
|
|
33063
|
+
renderSection(lines, tag, section, key) {
|
|
33064
|
+
if (!section || !section.rows || section.rows.length === 0) return;
|
|
33065
|
+
lines.push(`${this.indentUnit}<${tag}>`);
|
|
33066
|
+
for (const row of section.rows) {
|
|
33067
|
+
lines.push(`${this.indentUnit.repeat(2)}<tr>`);
|
|
33068
|
+
for (const cell of row.cells ?? []) {
|
|
33069
|
+
lines.push(`${this.indentUnit.repeat(3)}${this.renderCell(cell, key)}`);
|
|
33070
|
+
}
|
|
33071
|
+
lines.push(`${this.indentUnit.repeat(2)}</tr>`);
|
|
33072
|
+
}
|
|
33073
|
+
lines.push(`${this.indentUnit}</${tag}>`);
|
|
33074
|
+
}
|
|
33075
|
+
renderCell(cell, _key) {
|
|
33076
|
+
const tag = cell.title === true ? "th" : "td";
|
|
33077
|
+
const attrs = [];
|
|
33078
|
+
if (cell.rowspan && cell.rowspan > 1) attrs.push(`rowspan="${cell.rowspan}"`);
|
|
33079
|
+
if (cell.colspan && cell.colspan > 1) attrs.push(`colspan="${cell.colspan}"`);
|
|
33080
|
+
if (cell.scope) attrs.push(`scope="${cell.scope}"`);
|
|
33081
|
+
if (cell.colwidth && cell.colwidth > 0) attrs.push(`width="${cell.colwidth}"`);
|
|
33082
|
+
const open = attrs.length > 0 ? `<${tag} ${attrs.join(" ")}>` : `<${tag}>`;
|
|
33083
|
+
return `${open}${this.cellContentToHtml(this.asTextAst(cell.content))}</${tag}>`;
|
|
33084
|
+
}
|
|
33085
|
+
// --- cell content (TextAst -> HTML) ---------------------------------------
|
|
33086
|
+
asTextAst(content) {
|
|
33087
|
+
if (content == null) return [];
|
|
33088
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
33089
|
+
return content;
|
|
33090
|
+
}
|
|
33091
|
+
cellContentToHtml(blocks) {
|
|
33092
|
+
if (blocks.length === 0) return "";
|
|
33093
|
+
if (blocks.length === 1 && blocks[0].type === "paragraph") {
|
|
33094
|
+
return this.inlineToHtml(blocks[0].content ?? []);
|
|
33095
|
+
}
|
|
33096
|
+
return blocks.map((b) => this.blockToHtml(b)).join("");
|
|
33097
|
+
}
|
|
33098
|
+
blockToHtml(node) {
|
|
33099
|
+
switch (node.type) {
|
|
33100
|
+
case "paragraph":
|
|
33101
|
+
return `<p>${this.inlineToHtml(node.content ?? [])}</p>`;
|
|
33102
|
+
case "bulletList":
|
|
33103
|
+
case "noBulletList":
|
|
33104
|
+
case "orderedList":
|
|
33105
|
+
case "orderedListRoman":
|
|
33106
|
+
case "orderedListRomanLower":
|
|
33107
|
+
case "letteredList":
|
|
33108
|
+
case "letteredListLower":
|
|
33109
|
+
case "taskList":
|
|
33110
|
+
return this.listToHtml(node);
|
|
33111
|
+
case "image":
|
|
33112
|
+
case "imageInline":
|
|
33113
|
+
return this.imageToHtml(node);
|
|
33114
|
+
case "latex":
|
|
33115
|
+
return this.latexToHtml(node);
|
|
33116
|
+
default:
|
|
33117
|
+
return this.inlineToHtml([node]);
|
|
33118
|
+
}
|
|
33119
|
+
}
|
|
33120
|
+
inlineToHtml(nodes) {
|
|
33121
|
+
return nodes.map((n) => this.inlineNodeToHtml(n)).join("");
|
|
33122
|
+
}
|
|
33123
|
+
inlineNodeToHtml(node) {
|
|
33124
|
+
if (node.type === "hardBreak") return "<br>";
|
|
33125
|
+
if (node.type === "image" || node.type === "imageInline") return this.imageToHtml(node);
|
|
33126
|
+
if (node.type === "latex") return this.latexToHtml(node);
|
|
33127
|
+
if (node.type === "text") {
|
|
33128
|
+
return this.wrapMarks(this.textToHtml(node.text ?? ""), node.marks);
|
|
33129
|
+
}
|
|
33130
|
+
if (node.content) return this.inlineToHtml(node.content);
|
|
33131
|
+
return this.escapeText(node.text ?? "");
|
|
33132
|
+
}
|
|
33133
|
+
wrapMarks(text, marks) {
|
|
33134
|
+
if (!marks || marks.length === 0) return text;
|
|
33135
|
+
let open = "";
|
|
33136
|
+
let close = "";
|
|
33137
|
+
for (const mark of marks) {
|
|
33138
|
+
if (mark.type === "link") {
|
|
33139
|
+
const href = mark.attrs?.href ?? "";
|
|
33140
|
+
open += `<a href="${this.escapeAttr(href)}">`;
|
|
33141
|
+
close = `</a>${close}`;
|
|
33142
|
+
} else {
|
|
33143
|
+
const tag = MARK_TO_TAG[mark.type];
|
|
33144
|
+
if (tag) {
|
|
33145
|
+
open += `<${tag}>`;
|
|
33146
|
+
close = `</${tag}>${close}`;
|
|
33147
|
+
}
|
|
33148
|
+
}
|
|
33149
|
+
}
|
|
33150
|
+
return `${open}${text}${close}`;
|
|
33151
|
+
}
|
|
33152
|
+
// --- lists ----------------------------------------------------------------
|
|
33153
|
+
listToHtml(node) {
|
|
33154
|
+
const { tag, attrs } = this.listTag(node);
|
|
33155
|
+
const items = (node.content ?? []).map((item) => this.listItemToHtml(item, node.type === "taskList")).join("");
|
|
33156
|
+
return `<${tag}${attrs}>${items}</${tag}>`;
|
|
33157
|
+
}
|
|
33158
|
+
listTag(node) {
|
|
33159
|
+
const start = node.attrs?.start;
|
|
33160
|
+
const startAttr = typeof start === "number" && start !== 1 ? ` start="${start}"` : "";
|
|
33161
|
+
switch (node.type) {
|
|
33162
|
+
case "orderedList":
|
|
33163
|
+
return { tag: "ol", attrs: startAttr };
|
|
33164
|
+
case "orderedListRoman":
|
|
33165
|
+
return { tag: "ol", attrs: ` type="I"${startAttr}` };
|
|
33166
|
+
case "orderedListRomanLower":
|
|
33167
|
+
return { tag: "ol", attrs: ` type="i"${startAttr}` };
|
|
33168
|
+
case "letteredList":
|
|
33169
|
+
return { tag: "ol", attrs: ` type="A"${startAttr}` };
|
|
33170
|
+
case "letteredListLower":
|
|
33171
|
+
return { tag: "ol", attrs: ` type="a"${startAttr}` };
|
|
33172
|
+
case "noBulletList":
|
|
33173
|
+
return { tag: "ul", attrs: ' style="list-style:none"' };
|
|
33174
|
+
case "taskList":
|
|
33175
|
+
case "bulletList":
|
|
33176
|
+
default:
|
|
33177
|
+
return { tag: "ul", attrs: "" };
|
|
33178
|
+
}
|
|
33179
|
+
}
|
|
33180
|
+
listItemToHtml(item, task) {
|
|
33181
|
+
const inner = (item.content ?? []).map((b) => {
|
|
33182
|
+
if (b.type === "paragraph") return this.inlineToHtml(b.content ?? []);
|
|
33183
|
+
return this.blockToHtml(b);
|
|
33184
|
+
}).join("");
|
|
33185
|
+
if (task) {
|
|
33186
|
+
const checked = item.attrs?.checked ? " checked" : "";
|
|
33187
|
+
return `<li><input type="checkbox"${checked}>${inner}</li>`;
|
|
33188
|
+
}
|
|
33189
|
+
return `<li>${inner}</li>`;
|
|
33190
|
+
}
|
|
33191
|
+
// --- images ---------------------------------------------------------------
|
|
33192
|
+
imageToHtml(node) {
|
|
33193
|
+
const attrs = node.attrs ?? {};
|
|
33194
|
+
const parts = [];
|
|
33195
|
+
const src = attrs.src;
|
|
33196
|
+
parts.push(`src="${this.escapeAttr(typeof src === "string" ? src : "")}"`);
|
|
33197
|
+
if (typeof attrs.alt === "string") parts.push(`alt="${this.escapeAttr(attrs.alt)}"`);
|
|
33198
|
+
if (typeof attrs.title === "string") parts.push(`title="${this.escapeAttr(attrs.title)}"`);
|
|
33199
|
+
if (attrs.width != null) parts.push(`width="${attrs.width}"`);
|
|
33200
|
+
if (attrs.height != null) parts.push(`height="${attrs.height}"`);
|
|
33201
|
+
if (typeof attrs.class === "string" && attrs.class) {
|
|
33202
|
+
parts.push(`class="${this.escapeAttr(attrs.class)}"`);
|
|
33203
|
+
}
|
|
33204
|
+
return `<img ${parts.join(" ")}>`;
|
|
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
|
+
}
|
|
33244
|
+
// --- escaping -------------------------------------------------------------
|
|
33245
|
+
escapeText(text) {
|
|
33246
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
33247
|
+
}
|
|
33248
|
+
escapeAttr(text) {
|
|
33249
|
+
return this.escapeText(text).replace(/"/g, """);
|
|
33250
|
+
}
|
|
33251
|
+
};
|
|
32695
33252
|
var MOVE_BODY_RECURSION_LIMIT = 5e3;
|
|
32696
33253
|
var DEFAULT_OPTIONS3 = {
|
|
32697
33254
|
// debugGenerationInline: true,
|
|
@@ -32992,6 +33549,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
|
|
|
32992
33549
|
this.addProperty(this.bitJson, k, values, { array: true });
|
|
32993
33550
|
}
|
|
32994
33551
|
}
|
|
33552
|
+
return false;
|
|
32995
33553
|
}
|
|
32996
33554
|
// bitmarkAst -> bits -> bitsValue -> cardNode -> cardBits -> cardBitsValue
|
|
32997
33555
|
enter_cardBitsValue(node, route) {
|
|
@@ -37538,6 +38096,8 @@ function propertyContentProcessor(context, contentDepth, tagsConfig, content, ta
|
|
|
37538
38096
|
jsonKey: void 0,
|
|
37539
38097
|
exportJsonKey: void 0,
|
|
37540
38098
|
hasExportJsonKey: false,
|
|
38099
|
+
htmlKey: void 0,
|
|
38100
|
+
hasHtmlKey: false,
|
|
37541
38101
|
format: TagFormat.bitmarkText,
|
|
37542
38102
|
values: void 0,
|
|
37543
38103
|
defaultValue: void 0,
|
|
@@ -41892,6 +42452,537 @@ var BitmarkParser = class {
|
|
|
41892
42452
|
return parse2(bitmark);
|
|
41893
42453
|
}
|
|
41894
42454
|
};
|
|
42455
|
+
|
|
42456
|
+
// src/parser/html/HtmlDom.ts
|
|
42457
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
42458
|
+
"area",
|
|
42459
|
+
"base",
|
|
42460
|
+
"br",
|
|
42461
|
+
"col",
|
|
42462
|
+
"embed",
|
|
42463
|
+
"hr",
|
|
42464
|
+
"img",
|
|
42465
|
+
"input",
|
|
42466
|
+
"link",
|
|
42467
|
+
"meta",
|
|
42468
|
+
"param",
|
|
42469
|
+
"source",
|
|
42470
|
+
"track",
|
|
42471
|
+
"wbr"
|
|
42472
|
+
]);
|
|
42473
|
+
var IMPLIED_CLOSE = {
|
|
42474
|
+
li: /* @__PURE__ */ new Set(["li"]),
|
|
42475
|
+
td: /* @__PURE__ */ new Set(["td", "th"]),
|
|
42476
|
+
th: /* @__PURE__ */ new Set(["td", "th"]),
|
|
42477
|
+
tr: /* @__PURE__ */ new Set(["td", "th", "tr"]),
|
|
42478
|
+
thead: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
42479
|
+
tbody: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
42480
|
+
tfoot: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
42481
|
+
p: /* @__PURE__ */ new Set(["p"]),
|
|
42482
|
+
option: /* @__PURE__ */ new Set(["option"])
|
|
42483
|
+
};
|
|
42484
|
+
var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9:-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
|
|
42485
|
+
var ATTR_RE = /([a-zA-Z_:][a-zA-Z0-9:._-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
|
|
42486
|
+
function parseAttrs(raw) {
|
|
42487
|
+
const attrs = {};
|
|
42488
|
+
if (!raw) return attrs;
|
|
42489
|
+
ATTR_RE.lastIndex = 0;
|
|
42490
|
+
let m;
|
|
42491
|
+
while ((m = ATTR_RE.exec(raw)) !== null) {
|
|
42492
|
+
const name = m[1].toLowerCase();
|
|
42493
|
+
let value = m[2] ?? "";
|
|
42494
|
+
if (value.length >= 2 && (value[0] === '"' || value[0] === "'")) {
|
|
42495
|
+
value = value.slice(1, -1);
|
|
42496
|
+
}
|
|
42497
|
+
attrs[name] = value;
|
|
42498
|
+
}
|
|
42499
|
+
return attrs;
|
|
42500
|
+
}
|
|
42501
|
+
function stripNonContent(html) {
|
|
42502
|
+
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, "").replace(/<!doctype[^>]*>/gi, "").replace(/<script\b[\s\S]*?<\/script>/gi, "").replace(/<style\b[\s\S]*?<\/style>/gi, "");
|
|
42503
|
+
}
|
|
42504
|
+
function tokenize(html) {
|
|
42505
|
+
const tokens = [];
|
|
42506
|
+
const clean = stripNonContent(html);
|
|
42507
|
+
TAG_RE.lastIndex = 0;
|
|
42508
|
+
let lastIndex = 0;
|
|
42509
|
+
let m;
|
|
42510
|
+
while ((m = TAG_RE.exec(clean)) !== null) {
|
|
42511
|
+
if (m.index > lastIndex) {
|
|
42512
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex, m.index) });
|
|
42513
|
+
}
|
|
42514
|
+
lastIndex = TAG_RE.lastIndex;
|
|
42515
|
+
const isClose = m[1] === "/";
|
|
42516
|
+
const name = m[2].toLowerCase();
|
|
42517
|
+
if (isClose) {
|
|
42518
|
+
tokens.push({ kind: "close", name });
|
|
42519
|
+
} else {
|
|
42520
|
+
tokens.push({
|
|
42521
|
+
kind: "open",
|
|
42522
|
+
name,
|
|
42523
|
+
attrs: parseAttrs(m[3]),
|
|
42524
|
+
selfClose: m[4] === "/"
|
|
42525
|
+
});
|
|
42526
|
+
}
|
|
42527
|
+
}
|
|
42528
|
+
if (lastIndex < clean.length) {
|
|
42529
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex) });
|
|
42530
|
+
}
|
|
42531
|
+
return tokens;
|
|
42532
|
+
}
|
|
42533
|
+
function parseHtml(html) {
|
|
42534
|
+
const root = { type: "element", name: "#root", attrs: {}, children: [] };
|
|
42535
|
+
const stack = [root];
|
|
42536
|
+
const top = () => stack[stack.length - 1];
|
|
42537
|
+
for (const token of tokenize(html)) {
|
|
42538
|
+
if (token.kind === "text") {
|
|
42539
|
+
if (token.text) top().children.push({ type: "text", value: token.text });
|
|
42540
|
+
continue;
|
|
42541
|
+
}
|
|
42542
|
+
if (token.kind === "open") {
|
|
42543
|
+
const name = token.name;
|
|
42544
|
+
const closes = IMPLIED_CLOSE[name];
|
|
42545
|
+
if (closes) {
|
|
42546
|
+
while (stack.length > 1 && closes.has(top().name)) stack.pop();
|
|
42547
|
+
}
|
|
42548
|
+
const el = {
|
|
42549
|
+
type: "element",
|
|
42550
|
+
name,
|
|
42551
|
+
attrs: token.attrs ?? {},
|
|
42552
|
+
children: []
|
|
42553
|
+
};
|
|
42554
|
+
top().children.push(el);
|
|
42555
|
+
if (!token.selfClose && !VOID_ELEMENTS.has(name)) {
|
|
42556
|
+
stack.push(el);
|
|
42557
|
+
}
|
|
42558
|
+
continue;
|
|
42559
|
+
}
|
|
42560
|
+
for (let i = stack.length - 1; i > 0; i--) {
|
|
42561
|
+
if (stack[i].name === token.name) {
|
|
42562
|
+
stack.length = i;
|
|
42563
|
+
break;
|
|
42564
|
+
}
|
|
42565
|
+
}
|
|
42566
|
+
}
|
|
42567
|
+
return root.children;
|
|
42568
|
+
}
|
|
42569
|
+
function childElements(el, names) {
|
|
42570
|
+
return el.children.filter((c) => c.type === "element" && names.has(c.name));
|
|
42571
|
+
}
|
|
42572
|
+
|
|
42573
|
+
// src/parser/html/HtmlTableParser.ts
|
|
42574
|
+
var MARK_TAGS = {
|
|
42575
|
+
b: "bold",
|
|
42576
|
+
strong: "bold",
|
|
42577
|
+
i: "italic",
|
|
42578
|
+
em: "italic",
|
|
42579
|
+
sup: "superscript",
|
|
42580
|
+
sub: "subscript",
|
|
42581
|
+
s: "strike",
|
|
42582
|
+
strike: "strike",
|
|
42583
|
+
del: "del",
|
|
42584
|
+
ins: "ins",
|
|
42585
|
+
u: "underline",
|
|
42586
|
+
mark: "highlight",
|
|
42587
|
+
code: "code"
|
|
42588
|
+
};
|
|
42589
|
+
var SECTION_TAGS = /* @__PURE__ */ new Set(["thead", "tbody", "tfoot"]);
|
|
42590
|
+
var ROW_TAGS = /* @__PURE__ */ new Set(["tr"]);
|
|
42591
|
+
var CELL_TAGS = /* @__PURE__ */ new Set(["td", "th"]);
|
|
42592
|
+
var LI_TAGS = /* @__PURE__ */ new Set(["li"]);
|
|
42593
|
+
var VALID_SCOPES = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
42594
|
+
var NAMED_ENTITIES = {
|
|
42595
|
+
amp: "&",
|
|
42596
|
+
lt: "<",
|
|
42597
|
+
gt: ">",
|
|
42598
|
+
quot: '"',
|
|
42599
|
+
apos: "'",
|
|
42600
|
+
nbsp: "\xA0"
|
|
42601
|
+
};
|
|
42602
|
+
function decodeEntities(text) {
|
|
42603
|
+
return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, (whole, body) => {
|
|
42604
|
+
if (body[0] === "#") {
|
|
42605
|
+
const code = body[1] === "x" || body[1] === "X" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);
|
|
42606
|
+
if (Number.isFinite(code) && code >= 0 && code <= 1114111) {
|
|
42607
|
+
try {
|
|
42608
|
+
return String.fromCodePoint(code);
|
|
42609
|
+
} catch {
|
|
42610
|
+
return whole;
|
|
42611
|
+
}
|
|
42612
|
+
}
|
|
42613
|
+
return whole;
|
|
42614
|
+
}
|
|
42615
|
+
return NAMED_ENTITIES[body] ?? whole;
|
|
42616
|
+
});
|
|
42617
|
+
}
|
|
42618
|
+
function intAttr(value) {
|
|
42619
|
+
if (value == null) return void 0;
|
|
42620
|
+
const n = Number.parseInt(value, 10);
|
|
42621
|
+
return Number.isInteger(n) ? n : void 0;
|
|
42622
|
+
}
|
|
42623
|
+
function isElement(node) {
|
|
42624
|
+
return node.type === "element";
|
|
42625
|
+
}
|
|
42626
|
+
var HtmlTableParser = class {
|
|
42627
|
+
keepUnknownTags = false;
|
|
42628
|
+
/**
|
|
42629
|
+
* Parse an HTML string and return one table bit per top-level `<table>`.
|
|
42630
|
+
*/
|
|
42631
|
+
parse(html, options) {
|
|
42632
|
+
this.keepUnknownTags = options?.keepUnknownTags ?? false;
|
|
42633
|
+
const tableFormat = options?.tableFormat ?? "table-extended";
|
|
42634
|
+
const onWarning = options?.onWarning;
|
|
42635
|
+
const tables = this.collectTopLevelTables(parseHtml(html));
|
|
42636
|
+
const bits = [];
|
|
42637
|
+
for (const table of tables) {
|
|
42638
|
+
const bit = this.tableToBit(table, tableFormat, onWarning);
|
|
42639
|
+
if (bit) bits.push(bit);
|
|
42640
|
+
}
|
|
42641
|
+
return bits;
|
|
42642
|
+
}
|
|
42643
|
+
// --- table extraction -----------------------------------------------------
|
|
42644
|
+
/** Collect every `<table>` element, NOT descending into nested tables. */
|
|
42645
|
+
collectTopLevelTables(nodes) {
|
|
42646
|
+
const tables = [];
|
|
42647
|
+
const visit = (node) => {
|
|
42648
|
+
if (!isElement(node)) return;
|
|
42649
|
+
if (node.name === "table") {
|
|
42650
|
+
tables.push(node);
|
|
42651
|
+
return;
|
|
42652
|
+
}
|
|
42653
|
+
node.children.forEach(visit);
|
|
42654
|
+
};
|
|
42655
|
+
nodes.forEach(visit);
|
|
42656
|
+
return tables;
|
|
42657
|
+
}
|
|
42658
|
+
tableToBit(table, tableFormat, onWarning) {
|
|
42659
|
+
const header = [];
|
|
42660
|
+
const body = [];
|
|
42661
|
+
const footer = [];
|
|
42662
|
+
let caption;
|
|
42663
|
+
for (const child of table.children) {
|
|
42664
|
+
if (!isElement(child)) continue;
|
|
42665
|
+
if (child.name === "caption") {
|
|
42666
|
+
const capContent = this.inlineNodes(child.children, []);
|
|
42667
|
+
const trimmed = this.trimInline(capContent);
|
|
42668
|
+
if (trimmed.length > 0) caption = trimmed;
|
|
42669
|
+
} else if (SECTION_TAGS.has(child.name)) {
|
|
42670
|
+
const target = child.name === "thead" ? header : child.name === "tfoot" ? footer : body;
|
|
42671
|
+
for (const tr of childElements(child, ROW_TAGS)) {
|
|
42672
|
+
target.push(this.rowToCells(tr));
|
|
42673
|
+
}
|
|
42674
|
+
} else if (ROW_TAGS.has(child.name)) {
|
|
42675
|
+
body.push(this.rowToCells(child));
|
|
42676
|
+
}
|
|
42677
|
+
}
|
|
42678
|
+
if (header.length === 0 && body.length === 0 && footer.length === 0) {
|
|
42679
|
+
return void 0;
|
|
42680
|
+
}
|
|
42681
|
+
const tableExtended = {};
|
|
42682
|
+
if (header.length > 0) tableExtended.header = { rows: header };
|
|
42683
|
+
if (body.length > 0) tableExtended.body = { rows: body };
|
|
42684
|
+
if (footer.length > 0) tableExtended.footer = { rows: footer };
|
|
42685
|
+
let tableData = tableExtended;
|
|
42686
|
+
if (tableFormat === "table") {
|
|
42687
|
+
if (this.isLossyAsBasic(tableExtended)) {
|
|
42688
|
+
onWarning?.(
|
|
42689
|
+
"Converting an HTML table to [.table] loses rowspan/colspan/scope and multi-section structure; use --tableFormat table-extended to preserve them."
|
|
42690
|
+
);
|
|
42691
|
+
}
|
|
42692
|
+
tableData = convertExtendedToBasicTableFormat(tableExtended);
|
|
42693
|
+
}
|
|
42694
|
+
const bit = {
|
|
42695
|
+
type: tableFormat,
|
|
42696
|
+
format: "bitmark++",
|
|
42697
|
+
table: tableData
|
|
42698
|
+
};
|
|
42699
|
+
if (caption) bit.caption = caption;
|
|
42700
|
+
return bit;
|
|
42701
|
+
}
|
|
42702
|
+
rowToCells(tr) {
|
|
42703
|
+
const cells = [];
|
|
42704
|
+
for (const cell of childElements(tr, CELL_TAGS)) {
|
|
42705
|
+
cells.push(this.cellToJson(cell));
|
|
42706
|
+
}
|
|
42707
|
+
return { cells };
|
|
42708
|
+
}
|
|
42709
|
+
cellToJson(cell) {
|
|
42710
|
+
const json = {
|
|
42711
|
+
content: this.blockNodes(cell.children)
|
|
42712
|
+
};
|
|
42713
|
+
if (cell.name === "th") json.title = true;
|
|
42714
|
+
const rowspan = intAttr(cell.attrs.rowspan);
|
|
42715
|
+
if (rowspan != null && rowspan >= 2) json.rowspan = rowspan;
|
|
42716
|
+
const colspan = intAttr(cell.attrs.colspan);
|
|
42717
|
+
if (colspan != null && colspan >= 2) json.colspan = colspan;
|
|
42718
|
+
const scope = cell.attrs.scope?.toLowerCase();
|
|
42719
|
+
if (scope && VALID_SCOPES.has(scope)) {
|
|
42720
|
+
json.scope = scope;
|
|
42721
|
+
}
|
|
42722
|
+
const width = this.widthFromCell(cell);
|
|
42723
|
+
if (width != null) json.colwidth = width;
|
|
42724
|
+
return json;
|
|
42725
|
+
}
|
|
42726
|
+
widthFromCell(cell) {
|
|
42727
|
+
const attrWidth = intAttr(cell.attrs.width);
|
|
42728
|
+
if (attrWidth != null && attrWidth > 0) return attrWidth;
|
|
42729
|
+
const style = cell.attrs.style;
|
|
42730
|
+
if (style) {
|
|
42731
|
+
const m = style.match(/width\s*:\s*(\d+)\s*px/i);
|
|
42732
|
+
if (m) {
|
|
42733
|
+
const n = Number.parseInt(m[1], 10);
|
|
42734
|
+
if (Number.isInteger(n) && n > 0) return n;
|
|
42735
|
+
}
|
|
42736
|
+
}
|
|
42737
|
+
return void 0;
|
|
42738
|
+
}
|
|
42739
|
+
isLossyAsBasic(table) {
|
|
42740
|
+
if (table.footer) return true;
|
|
42741
|
+
if (table.header && table.header.rows.length > 1) return true;
|
|
42742
|
+
const sections = [table.header, table.body, table.footer];
|
|
42743
|
+
for (const section of sections) {
|
|
42744
|
+
if (!section) continue;
|
|
42745
|
+
for (const row of section.rows) {
|
|
42746
|
+
for (const cell of row.cells) {
|
|
42747
|
+
if (cell.rowspan || cell.colspan || cell.scope) return true;
|
|
42748
|
+
}
|
|
42749
|
+
}
|
|
42750
|
+
}
|
|
42751
|
+
return false;
|
|
42752
|
+
}
|
|
42753
|
+
// --- content conversion (HTML -> TextAst) ---------------------------------
|
|
42754
|
+
/**
|
|
42755
|
+
* Convert a cell/li's child nodes into block-level TextAst nodes (paragraphs, lists, images).
|
|
42756
|
+
*/
|
|
42757
|
+
blockNodes(nodes) {
|
|
42758
|
+
const blocks = [];
|
|
42759
|
+
let inline = [];
|
|
42760
|
+
const flush = () => {
|
|
42761
|
+
const trimmed = this.trimInline(inline);
|
|
42762
|
+
inline = [];
|
|
42763
|
+
if (trimmed.length === 0) return;
|
|
42764
|
+
if (trimmed.length === 1 && trimmed[0].type === "imageInline") {
|
|
42765
|
+
blocks.push({ ...trimmed[0], type: "image" });
|
|
42766
|
+
} else {
|
|
42767
|
+
blocks.push({ type: "paragraph", content: trimmed, attrs: {} });
|
|
42768
|
+
}
|
|
42769
|
+
};
|
|
42770
|
+
for (const node of nodes) {
|
|
42771
|
+
if (!isElement(node)) {
|
|
42772
|
+
inline.push(...this.inlineText(node.value, []));
|
|
42773
|
+
continue;
|
|
42774
|
+
}
|
|
42775
|
+
const name = node.name;
|
|
42776
|
+
if (name === "p") {
|
|
42777
|
+
flush();
|
|
42778
|
+
const content = this.trimInline(this.inlineNodes(node.children, []));
|
|
42779
|
+
if (content.length > 0) {
|
|
42780
|
+
blocks.push({ type: "paragraph", content, attrs: {} });
|
|
42781
|
+
}
|
|
42782
|
+
} else if (this.isListTag(name)) {
|
|
42783
|
+
flush();
|
|
42784
|
+
const list = this.listNode(node);
|
|
42785
|
+
if (list) blocks.push(list);
|
|
42786
|
+
} else {
|
|
42787
|
+
inline.push(...this.inlineFromElement(node, []));
|
|
42788
|
+
}
|
|
42789
|
+
}
|
|
42790
|
+
flush();
|
|
42791
|
+
return blocks;
|
|
42792
|
+
}
|
|
42793
|
+
/** Convert child nodes to a flat list of inline TextNodes, applying the given marks. */
|
|
42794
|
+
inlineNodes(nodes, marks) {
|
|
42795
|
+
const out = [];
|
|
42796
|
+
for (const node of nodes) {
|
|
42797
|
+
if (!isElement(node)) {
|
|
42798
|
+
out.push(...this.inlineText(node.value, marks));
|
|
42799
|
+
} else {
|
|
42800
|
+
out.push(...this.inlineFromElement(node, marks));
|
|
42801
|
+
}
|
|
42802
|
+
}
|
|
42803
|
+
return out;
|
|
42804
|
+
}
|
|
42805
|
+
inlineFromElement(el, marks) {
|
|
42806
|
+
const name = el.name;
|
|
42807
|
+
if (name === "br") {
|
|
42808
|
+
return [{ type: "hardBreak" }];
|
|
42809
|
+
}
|
|
42810
|
+
if (name === "img") {
|
|
42811
|
+
return [this.imageNode(el, true)];
|
|
42812
|
+
}
|
|
42813
|
+
if (this.isMathTag(name)) {
|
|
42814
|
+
return [this.latexNode(el)];
|
|
42815
|
+
}
|
|
42816
|
+
const markType = MARK_TAGS[name];
|
|
42817
|
+
if (markType) {
|
|
42818
|
+
return this.inlineNodes(el.children, [...marks, { type: markType }]);
|
|
42819
|
+
}
|
|
42820
|
+
if (name === "a") {
|
|
42821
|
+
const linkMark = {
|
|
42822
|
+
type: "link",
|
|
42823
|
+
attrs: {
|
|
42824
|
+
href: el.attrs.href ?? "",
|
|
42825
|
+
...el.attrs.target ? { target: el.attrs.target } : {}
|
|
42826
|
+
}
|
|
42827
|
+
};
|
|
42828
|
+
return this.inlineNodes(el.children, [...marks, linkMark]);
|
|
42829
|
+
}
|
|
42830
|
+
if (this.keepUnknownTags) {
|
|
42831
|
+
const open = this.serializeOpenTag(el);
|
|
42832
|
+
const close = `</${name}>`;
|
|
42833
|
+
return [
|
|
42834
|
+
...this.inlineText(open, marks),
|
|
42835
|
+
...this.inlineNodes(el.children, marks),
|
|
42836
|
+
...this.inlineText(close, marks)
|
|
42837
|
+
];
|
|
42838
|
+
}
|
|
42839
|
+
return this.inlineNodes(el.children, marks);
|
|
42840
|
+
}
|
|
42841
|
+
inlineText(raw, marks) {
|
|
42842
|
+
const text = decodeEntities(raw).replace(/\s+/g, " ");
|
|
42843
|
+
if (text === "") return [];
|
|
42844
|
+
const node = { text, type: "text" };
|
|
42845
|
+
if (marks.length > 0) node.marks = marks.map((m) => ({ ...m }));
|
|
42846
|
+
return [node];
|
|
42847
|
+
}
|
|
42848
|
+
serializeOpenTag(el) {
|
|
42849
|
+
const attrs = Object.entries(el.attrs).map(([k, v]) => v === "" ? ` ${k}` : ` ${k}="${v}"`).join("");
|
|
42850
|
+
return `<${el.name}${attrs}>`;
|
|
42851
|
+
}
|
|
42852
|
+
// --- lists ----------------------------------------------------------------
|
|
42853
|
+
isListTag(name) {
|
|
42854
|
+
return name === "ul" || name === "ol";
|
|
42855
|
+
}
|
|
42856
|
+
listNode(el) {
|
|
42857
|
+
const items = childElements(el, LI_TAGS);
|
|
42858
|
+
if (items.length === 0) return void 0;
|
|
42859
|
+
const isTask = el.name === "ul" && items.some((li) => {
|
|
42860
|
+
const firstEl = li.children.find(isElement);
|
|
42861
|
+
return firstEl?.name === "input" && firstEl.attrs.type?.toLowerCase() === "checkbox";
|
|
42862
|
+
});
|
|
42863
|
+
if (isTask) {
|
|
42864
|
+
return {
|
|
42865
|
+
type: "taskList",
|
|
42866
|
+
content: items.map((li) => this.taskItemNode(li))
|
|
42867
|
+
};
|
|
42868
|
+
}
|
|
42869
|
+
const type = this.listType(el);
|
|
42870
|
+
const node = {
|
|
42871
|
+
type,
|
|
42872
|
+
content: items.map((li) => this.listItemNode(li))
|
|
42873
|
+
};
|
|
42874
|
+
if (el.name === "ol") {
|
|
42875
|
+
const start = intAttr(el.attrs.start);
|
|
42876
|
+
if (start != null) {
|
|
42877
|
+
node.attrs = { start };
|
|
42878
|
+
}
|
|
42879
|
+
}
|
|
42880
|
+
return node;
|
|
42881
|
+
}
|
|
42882
|
+
listType(el) {
|
|
42883
|
+
if (el.name === "ol") {
|
|
42884
|
+
switch (el.attrs.type) {
|
|
42885
|
+
case "i":
|
|
42886
|
+
return "orderedListRomanLower";
|
|
42887
|
+
case "I":
|
|
42888
|
+
return "orderedListRoman";
|
|
42889
|
+
case "a":
|
|
42890
|
+
return "letteredListLower";
|
|
42891
|
+
case "A":
|
|
42892
|
+
return "letteredList";
|
|
42893
|
+
default:
|
|
42894
|
+
return "orderedList";
|
|
42895
|
+
}
|
|
42896
|
+
}
|
|
42897
|
+
const style = el.attrs.style ?? "";
|
|
42898
|
+
if (/list-style(-type)?\s*:\s*none/i.test(style)) return "noBulletList";
|
|
42899
|
+
return "bulletList";
|
|
42900
|
+
}
|
|
42901
|
+
listItemNode(li) {
|
|
42902
|
+
let content = this.blockNodes(li.children);
|
|
42903
|
+
if (content.length === 0) {
|
|
42904
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
42905
|
+
}
|
|
42906
|
+
return { type: "listItem", content };
|
|
42907
|
+
}
|
|
42908
|
+
taskItemNode(li) {
|
|
42909
|
+
const checkbox = li.children.find(
|
|
42910
|
+
(c) => isElement(c) && c.name === "input" && c.attrs.type?.toLowerCase() === "checkbox"
|
|
42911
|
+
);
|
|
42912
|
+
const checked = checkbox ? "checked" in checkbox.attrs : false;
|
|
42913
|
+
const rest = li.children.filter((c) => c !== checkbox);
|
|
42914
|
+
let content = this.blockNodes(rest);
|
|
42915
|
+
if (content.length === 0) {
|
|
42916
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
42917
|
+
}
|
|
42918
|
+
return { type: "taskItem", attrs: { checked }, content };
|
|
42919
|
+
}
|
|
42920
|
+
// --- images ---------------------------------------------------------------
|
|
42921
|
+
imageNode(el, inline) {
|
|
42922
|
+
const attrs = { src: el.attrs.src ?? "" };
|
|
42923
|
+
attrs.alt = el.attrs.alt ?? null;
|
|
42924
|
+
attrs.title = el.attrs.title ?? null;
|
|
42925
|
+
const width = intAttr(el.attrs.width);
|
|
42926
|
+
if (width != null) attrs.width = width;
|
|
42927
|
+
const height = intAttr(el.attrs.height);
|
|
42928
|
+
if (height != null) attrs.height = height;
|
|
42929
|
+
if (el.attrs.class) attrs.class = el.attrs.class;
|
|
42930
|
+
return { type: inline ? "imageInline" : "image", attrs };
|
|
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
|
+
}
|
|
42969
|
+
// --- whitespace -----------------------------------------------------------
|
|
42970
|
+
/** Trim leading/trailing whitespace from inline content (edges only). */
|
|
42971
|
+
trimInline(nodes) {
|
|
42972
|
+
const out = nodes.slice();
|
|
42973
|
+
const isWs = (n) => n.type === "text" && /^\s*$/.test(n.text ?? "");
|
|
42974
|
+
while (out.length > 0 && isWs(out[0])) out.shift();
|
|
42975
|
+
if (out.length > 0 && out[0].type === "text") {
|
|
42976
|
+
out[0] = { ...out[0], text: (out[0].text ?? "").replace(/^\s+/, "") };
|
|
42977
|
+
}
|
|
42978
|
+
while (out.length > 0 && isWs(out[out.length - 1])) out.pop();
|
|
42979
|
+
if (out.length > 0 && out[out.length - 1].type === "text") {
|
|
42980
|
+
const last = out.length - 1;
|
|
42981
|
+
out[last] = { ...out[last], text: (out[last].text ?? "").replace(/\s+$/, "") };
|
|
42982
|
+
}
|
|
42983
|
+
return out.filter((n) => !(n.type === "text" && n.text === ""));
|
|
42984
|
+
}
|
|
42985
|
+
};
|
|
41895
42986
|
var StreamWriter = class {
|
|
41896
42987
|
_stream;
|
|
41897
42988
|
endOfLineString = os.EOL;
|
|
@@ -42162,233 +43253,6 @@ var BitmarkFileGenerator = class {
|
|
|
42162
43253
|
this.generator.generateSync(_ast);
|
|
42163
43254
|
}
|
|
42164
43255
|
};
|
|
42165
|
-
|
|
42166
|
-
// src/generator/html/HtmlTableGenerator.ts
|
|
42167
|
-
var MARK_TO_TAG = {
|
|
42168
|
-
bold: "b",
|
|
42169
|
-
italic: "i",
|
|
42170
|
-
superscript: "sup",
|
|
42171
|
-
subscript: "sub",
|
|
42172
|
-
strike: "s",
|
|
42173
|
-
del: "del",
|
|
42174
|
-
ins: "ins",
|
|
42175
|
-
underline: "u",
|
|
42176
|
-
highlight: "mark",
|
|
42177
|
-
code: "code"
|
|
42178
|
-
};
|
|
42179
|
-
var HtmlTableGenerator = class {
|
|
42180
|
-
indentUnit = " ";
|
|
42181
|
-
/**
|
|
42182
|
-
* Generate HTML table fragments from a string or JSON value.
|
|
42183
|
-
* @returns the concatenated `<table>` fragments, blank-line separated (empty string if none).
|
|
42184
|
-
*/
|
|
42185
|
-
generate(input) {
|
|
42186
|
-
let data = input;
|
|
42187
|
-
if (typeof data === "string") {
|
|
42188
|
-
try {
|
|
42189
|
-
data = JSON.parse(data);
|
|
42190
|
-
} catch {
|
|
42191
|
-
return "";
|
|
42192
|
-
}
|
|
42193
|
-
}
|
|
42194
|
-
const bits = this.collectBits(data);
|
|
42195
|
-
const fragments = [];
|
|
42196
|
-
for (const bit of bits) {
|
|
42197
|
-
const html = this.renderTableBit(bit);
|
|
42198
|
-
if (html) fragments.push(html);
|
|
42199
|
-
}
|
|
42200
|
-
return fragments.join("\n\n");
|
|
42201
|
-
}
|
|
42202
|
-
// --- bit collection -------------------------------------------------------
|
|
42203
|
-
collectBits(data) {
|
|
42204
|
-
const out = [];
|
|
42205
|
-
const visit = (value) => {
|
|
42206
|
-
if (value == null || typeof value !== "object") return;
|
|
42207
|
-
if (Array.isArray(value)) {
|
|
42208
|
-
value.forEach(visit);
|
|
42209
|
-
return;
|
|
42210
|
-
}
|
|
42211
|
-
const obj = value;
|
|
42212
|
-
if ("bit" in obj && obj.bit && typeof obj.bit === "object") {
|
|
42213
|
-
out.push(obj.bit);
|
|
42214
|
-
} else if ("type" in obj) {
|
|
42215
|
-
out.push(obj);
|
|
42216
|
-
}
|
|
42217
|
-
};
|
|
42218
|
-
visit(data);
|
|
42219
|
-
return out;
|
|
42220
|
-
}
|
|
42221
|
-
// --- table rendering ------------------------------------------------------
|
|
42222
|
-
renderTableBit(bit) {
|
|
42223
|
-
const table = bit.table;
|
|
42224
|
-
if (!table) return "";
|
|
42225
|
-
if (bit.type !== "table" && bit.type !== "table-extended") return "";
|
|
42226
|
-
const extended = this.toExtended(table);
|
|
42227
|
-
const lines = [];
|
|
42228
|
-
lines.push("<table>");
|
|
42229
|
-
if (bit.caption != null) {
|
|
42230
|
-
const caption = this.cellContentToHtml(this.asTextAst(bit.caption));
|
|
42231
|
-
if (caption) lines.push(`${this.indentUnit}<caption>${caption}</caption>`);
|
|
42232
|
-
}
|
|
42233
|
-
this.renderSection(lines, "thead", extended.header, "header");
|
|
42234
|
-
this.renderSection(lines, "tbody", extended.body, "body");
|
|
42235
|
-
this.renderSection(lines, "tfoot", extended.footer, "footer");
|
|
42236
|
-
lines.push("</table>");
|
|
42237
|
-
return lines.join("\n");
|
|
42238
|
-
}
|
|
42239
|
-
toExtended(table) {
|
|
42240
|
-
const t = table;
|
|
42241
|
-
if (t.header || t.body || t.footer) return table;
|
|
42242
|
-
return convertBasicToExtendedTableFormat(table);
|
|
42243
|
-
}
|
|
42244
|
-
renderSection(lines, tag, section, key) {
|
|
42245
|
-
if (!section || !section.rows || section.rows.length === 0) return;
|
|
42246
|
-
lines.push(`${this.indentUnit}<${tag}>`);
|
|
42247
|
-
for (const row of section.rows) {
|
|
42248
|
-
lines.push(`${this.indentUnit.repeat(2)}<tr>`);
|
|
42249
|
-
for (const cell of row.cells ?? []) {
|
|
42250
|
-
lines.push(`${this.indentUnit.repeat(3)}${this.renderCell(cell, key)}`);
|
|
42251
|
-
}
|
|
42252
|
-
lines.push(`${this.indentUnit.repeat(2)}</tr>`);
|
|
42253
|
-
}
|
|
42254
|
-
lines.push(`${this.indentUnit}</${tag}>`);
|
|
42255
|
-
}
|
|
42256
|
-
renderCell(cell, _key) {
|
|
42257
|
-
const tag = cell.title === true ? "th" : "td";
|
|
42258
|
-
const attrs = [];
|
|
42259
|
-
if (cell.rowspan && cell.rowspan > 1) attrs.push(`rowspan="${cell.rowspan}"`);
|
|
42260
|
-
if (cell.colspan && cell.colspan > 1) attrs.push(`colspan="${cell.colspan}"`);
|
|
42261
|
-
if (cell.scope) attrs.push(`scope="${cell.scope}"`);
|
|
42262
|
-
if (cell.colwidth && cell.colwidth > 0) attrs.push(`width="${cell.colwidth}"`);
|
|
42263
|
-
const open = attrs.length > 0 ? `<${tag} ${attrs.join(" ")}>` : `<${tag}>`;
|
|
42264
|
-
return `${open}${this.cellContentToHtml(this.asTextAst(cell.content))}</${tag}>`;
|
|
42265
|
-
}
|
|
42266
|
-
// --- cell content (TextAst -> HTML) ---------------------------------------
|
|
42267
|
-
asTextAst(content) {
|
|
42268
|
-
if (content == null) return [];
|
|
42269
|
-
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
42270
|
-
return content;
|
|
42271
|
-
}
|
|
42272
|
-
cellContentToHtml(blocks) {
|
|
42273
|
-
if (blocks.length === 0) return "";
|
|
42274
|
-
if (blocks.length === 1 && blocks[0].type === "paragraph") {
|
|
42275
|
-
return this.inlineToHtml(blocks[0].content ?? []);
|
|
42276
|
-
}
|
|
42277
|
-
return blocks.map((b) => this.blockToHtml(b)).join("");
|
|
42278
|
-
}
|
|
42279
|
-
blockToHtml(node) {
|
|
42280
|
-
switch (node.type) {
|
|
42281
|
-
case "paragraph":
|
|
42282
|
-
return `<p>${this.inlineToHtml(node.content ?? [])}</p>`;
|
|
42283
|
-
case "bulletList":
|
|
42284
|
-
case "noBulletList":
|
|
42285
|
-
case "orderedList":
|
|
42286
|
-
case "orderedListRoman":
|
|
42287
|
-
case "orderedListRomanLower":
|
|
42288
|
-
case "letteredList":
|
|
42289
|
-
case "letteredListLower":
|
|
42290
|
-
case "taskList":
|
|
42291
|
-
return this.listToHtml(node);
|
|
42292
|
-
case "image":
|
|
42293
|
-
case "imageInline":
|
|
42294
|
-
return this.imageToHtml(node);
|
|
42295
|
-
default:
|
|
42296
|
-
return this.inlineToHtml([node]);
|
|
42297
|
-
}
|
|
42298
|
-
}
|
|
42299
|
-
inlineToHtml(nodes) {
|
|
42300
|
-
return nodes.map((n) => this.inlineNodeToHtml(n)).join("");
|
|
42301
|
-
}
|
|
42302
|
-
inlineNodeToHtml(node) {
|
|
42303
|
-
if (node.type === "hardBreak") return "<br>";
|
|
42304
|
-
if (node.type === "image" || node.type === "imageInline") return this.imageToHtml(node);
|
|
42305
|
-
if (node.type === "text") {
|
|
42306
|
-
return this.wrapMarks(this.escapeText(node.text ?? ""), node.marks);
|
|
42307
|
-
}
|
|
42308
|
-
if (node.content) return this.inlineToHtml(node.content);
|
|
42309
|
-
return this.escapeText(node.text ?? "");
|
|
42310
|
-
}
|
|
42311
|
-
wrapMarks(text, marks) {
|
|
42312
|
-
if (!marks || marks.length === 0) return text;
|
|
42313
|
-
let open = "";
|
|
42314
|
-
let close = "";
|
|
42315
|
-
for (const mark of marks) {
|
|
42316
|
-
if (mark.type === "link") {
|
|
42317
|
-
const href = mark.attrs?.href ?? "";
|
|
42318
|
-
open += `<a href="${this.escapeAttr(href)}">`;
|
|
42319
|
-
close = `</a>${close}`;
|
|
42320
|
-
} else {
|
|
42321
|
-
const tag = MARK_TO_TAG[mark.type];
|
|
42322
|
-
if (tag) {
|
|
42323
|
-
open += `<${tag}>`;
|
|
42324
|
-
close = `</${tag}>${close}`;
|
|
42325
|
-
}
|
|
42326
|
-
}
|
|
42327
|
-
}
|
|
42328
|
-
return `${open}${text}${close}`;
|
|
42329
|
-
}
|
|
42330
|
-
// --- lists ----------------------------------------------------------------
|
|
42331
|
-
listToHtml(node) {
|
|
42332
|
-
const { tag, attrs } = this.listTag(node);
|
|
42333
|
-
const items = (node.content ?? []).map((item) => this.listItemToHtml(item, node.type === "taskList")).join("");
|
|
42334
|
-
return `<${tag}${attrs}>${items}</${tag}>`;
|
|
42335
|
-
}
|
|
42336
|
-
listTag(node) {
|
|
42337
|
-
const start = node.attrs?.start;
|
|
42338
|
-
const startAttr = typeof start === "number" && start !== 1 ? ` start="${start}"` : "";
|
|
42339
|
-
switch (node.type) {
|
|
42340
|
-
case "orderedList":
|
|
42341
|
-
return { tag: "ol", attrs: startAttr };
|
|
42342
|
-
case "orderedListRoman":
|
|
42343
|
-
return { tag: "ol", attrs: ` type="I"${startAttr}` };
|
|
42344
|
-
case "orderedListRomanLower":
|
|
42345
|
-
return { tag: "ol", attrs: ` type="i"${startAttr}` };
|
|
42346
|
-
case "letteredList":
|
|
42347
|
-
return { tag: "ol", attrs: ` type="A"${startAttr}` };
|
|
42348
|
-
case "letteredListLower":
|
|
42349
|
-
return { tag: "ol", attrs: ` type="a"${startAttr}` };
|
|
42350
|
-
case "noBulletList":
|
|
42351
|
-
return { tag: "ul", attrs: ' style="list-style:none"' };
|
|
42352
|
-
case "taskList":
|
|
42353
|
-
case "bulletList":
|
|
42354
|
-
default:
|
|
42355
|
-
return { tag: "ul", attrs: "" };
|
|
42356
|
-
}
|
|
42357
|
-
}
|
|
42358
|
-
listItemToHtml(item, task) {
|
|
42359
|
-
const inner = (item.content ?? []).map((b) => {
|
|
42360
|
-
if (b.type === "paragraph") return this.inlineToHtml(b.content ?? []);
|
|
42361
|
-
return this.blockToHtml(b);
|
|
42362
|
-
}).join("");
|
|
42363
|
-
if (task) {
|
|
42364
|
-
const checked = item.attrs?.checked ? " checked" : "";
|
|
42365
|
-
return `<li><input type="checkbox"${checked}>${inner}</li>`;
|
|
42366
|
-
}
|
|
42367
|
-
return `<li>${inner}</li>`;
|
|
42368
|
-
}
|
|
42369
|
-
// --- images ---------------------------------------------------------------
|
|
42370
|
-
imageToHtml(node) {
|
|
42371
|
-
const attrs = node.attrs ?? {};
|
|
42372
|
-
const parts = [];
|
|
42373
|
-
const src = attrs.src;
|
|
42374
|
-
parts.push(`src="${this.escapeAttr(typeof src === "string" ? src : "")}"`);
|
|
42375
|
-
if (typeof attrs.alt === "string") parts.push(`alt="${this.escapeAttr(attrs.alt)}"`);
|
|
42376
|
-
if (typeof attrs.title === "string") parts.push(`title="${this.escapeAttr(attrs.title)}"`);
|
|
42377
|
-
if (attrs.width != null) parts.push(`width="${attrs.width}"`);
|
|
42378
|
-
if (attrs.height != null) parts.push(`height="${attrs.height}"`);
|
|
42379
|
-
if (typeof attrs.class === "string" && attrs.class) {
|
|
42380
|
-
parts.push(`class="${this.escapeAttr(attrs.class)}"`);
|
|
42381
|
-
}
|
|
42382
|
-
return `<img ${parts.join(" ")}>`;
|
|
42383
|
-
}
|
|
42384
|
-
// --- escaping -------------------------------------------------------------
|
|
42385
|
-
escapeText(text) {
|
|
42386
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
42387
|
-
}
|
|
42388
|
-
escapeAttr(text) {
|
|
42389
|
-
return this.escapeText(text).replace(/"/g, """);
|
|
42390
|
-
}
|
|
42391
|
-
};
|
|
42392
43256
|
var JsonFileGenerator = class {
|
|
42393
43257
|
generator;
|
|
42394
43258
|
async;
|
|
@@ -42805,6 +43669,7 @@ var ConfigBuilder = class {
|
|
|
42805
43669
|
k = stringUtils.camelToKebab(k);
|
|
42806
43670
|
const resolvedGroups = resolveGroupReferences(k);
|
|
42807
43671
|
const hasOuterExport = Object.prototype.hasOwnProperty.call(tag, "exportJsonKey");
|
|
43672
|
+
const hasOuterHtml = Object.prototype.hasOwnProperty.call(tag, "htmlKey");
|
|
42808
43673
|
if (!hasOuterExport && tag.jsonKey != null) {
|
|
42809
43674
|
const headingPath = [...pathStack, `tags.${tag.key}`].join(" / ");
|
|
42810
43675
|
exportJsonKeyErrors.push(
|
|
@@ -42814,6 +43679,8 @@ var ConfigBuilder = class {
|
|
|
42814
43679
|
for (const ref of resolvedGroups) {
|
|
42815
43680
|
const exportJsonKeyChosen = hasOuterExport ? tag.exportJsonKey : ref.exportJsonKey;
|
|
42816
43681
|
const hasExportChosen = hasOuterExport || !!ref.hasExportJsonKey;
|
|
43682
|
+
const htmlKeyChosen = hasOuterHtml ? tag.htmlKey : ref.htmlKey;
|
|
43683
|
+
const hasHtmlChosen = hasOuterHtml || !!ref.hasHtmlKey;
|
|
42817
43684
|
const min = tag.minCount != null ? tag.minCount : ref.min;
|
|
42818
43685
|
const max = tag.maxCount != null ? tag.maxCount : ref.max;
|
|
42819
43686
|
const description = tag.description ? tag.description : ref.description;
|
|
@@ -42821,6 +43688,7 @@ var ConfigBuilder = class {
|
|
|
42821
43688
|
type: "group",
|
|
42822
43689
|
key: ref.key,
|
|
42823
43690
|
...hasExportChosen ? { jsonKey: exportJsonKeyChosen } : {},
|
|
43691
|
+
...hasHtmlChosen ? { htmlKey: htmlKeyChosen } : {},
|
|
42824
43692
|
...min != null ? { min } : {},
|
|
42825
43693
|
...max != null ? { max } : {},
|
|
42826
43694
|
...description ? { description } : {}
|
|
@@ -42849,10 +43717,13 @@ var ConfigBuilder = class {
|
|
|
42849
43717
|
);
|
|
42850
43718
|
exportJsonKeyField = {};
|
|
42851
43719
|
}
|
|
43720
|
+
const hasHtml = Object.prototype.hasOwnProperty.call(tag, "htmlKey");
|
|
43721
|
+
const htmlKeyField = hasHtml ? { htmlKey: tag.htmlKey } : {};
|
|
42852
43722
|
const t = {
|
|
42853
43723
|
type: "tag",
|
|
42854
43724
|
key: tagName,
|
|
42855
43725
|
...exportJsonKeyField,
|
|
43726
|
+
...htmlKeyField,
|
|
42856
43727
|
format,
|
|
42857
43728
|
default: tag.defaultValue ?? null,
|
|
42858
43729
|
...tag.nullable ? { nullable: true } : {},
|
|
@@ -42875,6 +43746,13 @@ var ConfigBuilder = class {
|
|
|
42875
43746
|
);
|
|
42876
43747
|
return {};
|
|
42877
43748
|
};
|
|
43749
|
+
const cardHtmlKeyField = (container, htmlExportKey) => {
|
|
43750
|
+
const c = container;
|
|
43751
|
+
if (Object.prototype.hasOwnProperty.call(c, htmlExportKey)) {
|
|
43752
|
+
return { htmlKey: c[htmlExportKey] };
|
|
43753
|
+
}
|
|
43754
|
+
return {};
|
|
43755
|
+
};
|
|
42878
43756
|
const serializeCardSet = (cardSetKey) => {
|
|
42879
43757
|
const variantBodyFormat = (variant) => variant.format ?? TextFormat.bitmarkText;
|
|
42880
43758
|
const cardSetConfig = CARDSETS[cardSetKey];
|
|
@@ -42905,6 +43783,7 @@ var ConfigBuilder = class {
|
|
|
42905
43783
|
}
|
|
42906
43784
|
return {
|
|
42907
43785
|
...cardJsonKeyField(variant, "jsonKey", "exportJsonKey", variantPath),
|
|
43786
|
+
...cardHtmlKeyField(variant, "htmlKey"),
|
|
42908
43787
|
format: variantBodyFormat(variant),
|
|
42909
43788
|
tags: variantTags,
|
|
42910
43789
|
repeatCount: variant.repeatCount ?? 1,
|
|
@@ -42916,6 +43795,7 @@ var ConfigBuilder = class {
|
|
|
42916
43795
|
name: side.name,
|
|
42917
43796
|
...side.repeat ? { repeat: side.repeat } : {},
|
|
42918
43797
|
...cardJsonKeyField(side, "jsonKey", "exportJsonKey", sidePath),
|
|
43798
|
+
...cardHtmlKeyField(side, "htmlKey"),
|
|
42919
43799
|
variants
|
|
42920
43800
|
};
|
|
42921
43801
|
});
|
|
@@ -42923,20 +43803,23 @@ var ConfigBuilder = class {
|
|
|
42923
43803
|
const cards = Object.entries(cardSetConfig.sections).map(([sectionName, section]) => {
|
|
42924
43804
|
const sectionPath = `cardSets.${normalizedKey} / cards.${sectionName}`;
|
|
42925
43805
|
const hasSideExport = Object.prototype.hasOwnProperty.call(section, "sideExportJsonKey");
|
|
43806
|
+
const hasSideHtml = Object.prototype.hasOwnProperty.call(section, "sideHtmlKey");
|
|
42926
43807
|
let cardSides = sides;
|
|
42927
|
-
if (hasSideExport || section.sideJsonKey != null) {
|
|
43808
|
+
if (hasSideExport || section.sideJsonKey != null || hasSideHtml) {
|
|
42928
43809
|
const sideOverride = cardJsonKeyField(
|
|
42929
43810
|
section,
|
|
42930
43811
|
"sideJsonKey",
|
|
42931
43812
|
"sideExportJsonKey",
|
|
42932
43813
|
`${sectionPath} / sides.*`
|
|
42933
43814
|
);
|
|
42934
|
-
|
|
43815
|
+
const sideHtmlOverride = cardHtmlKeyField(section, "sideHtmlKey");
|
|
43816
|
+
cardSides = sides.map((s) => ({ ...s, ...sideOverride, ...sideHtmlOverride }));
|
|
42935
43817
|
}
|
|
42936
43818
|
return {
|
|
42937
43819
|
name: sectionName,
|
|
42938
43820
|
...section.isDefault ? { isDefault: true } : {},
|
|
42939
43821
|
...cardJsonKeyField(section, "jsonKey", "exportJsonKey", sectionPath),
|
|
43822
|
+
...cardHtmlKeyField(section, "htmlKey"),
|
|
42940
43823
|
// PLAN-085: per-section cardinality. Emit only when non-default
|
|
42941
43824
|
// (treat `0` / undefined as "unbounded — omit").
|
|
42942
43825
|
...section.minCount != null && section.minCount !== 0 ? { min: section.minCount } : {},
|
|
@@ -42944,7 +43827,7 @@ var ConfigBuilder = class {
|
|
|
42944
43827
|
sides: cardSides
|
|
42945
43828
|
};
|
|
42946
43829
|
});
|
|
42947
|
-
return { name: normalizedKey, cards };
|
|
43830
|
+
return { name: normalizedKey, ...cardHtmlKeyField(cardSetConfig, "htmlKey"), cards };
|
|
42948
43831
|
}
|
|
42949
43832
|
const cardSetPath = `cardSets.${normalizedKey} / cards.default`;
|
|
42950
43833
|
return {
|
|
@@ -42954,6 +43837,7 @@ var ConfigBuilder = class {
|
|
|
42954
43837
|
name: "default",
|
|
42955
43838
|
isDefault: true,
|
|
42956
43839
|
...cardJsonKeyField(cardSetConfig, "jsonKey", "exportJsonKey", cardSetPath),
|
|
43840
|
+
...cardHtmlKeyField(cardSetConfig, "htmlKey"),
|
|
42957
43841
|
sides
|
|
42958
43842
|
}
|
|
42959
43843
|
]
|
|
@@ -42993,6 +43877,10 @@ var ConfigBuilder = class {
|
|
|
42993
43877
|
ref.exportJsonKey = t.jsonKey;
|
|
42994
43878
|
ref.hasExportJsonKey = true;
|
|
42995
43879
|
}
|
|
43880
|
+
if (Object.prototype.hasOwnProperty.call(t, "htmlKey")) {
|
|
43881
|
+
ref.htmlKey = t.htmlKey;
|
|
43882
|
+
ref.hasHtmlKey = true;
|
|
43883
|
+
}
|
|
42996
43884
|
replacements.push(ref);
|
|
42997
43885
|
}
|
|
42998
43886
|
squashedGroups.set(groupKey, replacements);
|
|
@@ -43027,6 +43915,7 @@ var ConfigBuilder = class {
|
|
|
43027
43915
|
type: "group",
|
|
43028
43916
|
key: ref.key,
|
|
43029
43917
|
...ref.hasExportJsonKey ? { jsonKey: ref.exportJsonKey } : {},
|
|
43918
|
+
...ref.hasHtmlKey ? { htmlKey: ref.htmlKey } : {},
|
|
43030
43919
|
...ref.min != null ? { min: ref.min } : {},
|
|
43031
43920
|
...ref.max != null ? { max: ref.max } : {},
|
|
43032
43921
|
...ref.description ? { description: ref.description } : {}
|
|
@@ -43040,6 +43929,7 @@ var ConfigBuilder = class {
|
|
|
43040
43929
|
type: "group",
|
|
43041
43930
|
key: ref.key,
|
|
43042
43931
|
...ref.hasExportJsonKey ? { jsonKey: ref.exportJsonKey } : {},
|
|
43932
|
+
...ref.hasHtmlKey ? { htmlKey: ref.htmlKey } : {},
|
|
43043
43933
|
...ref.min != null ? { min: ref.min } : {},
|
|
43044
43934
|
...ref.max != null ? { max: ref.max } : {},
|
|
43045
43935
|
...ref.description ? { description: ref.description } : {}
|
|
@@ -43169,6 +44059,7 @@ var ConfigBuilder = class {
|
|
|
43169
44059
|
type: "group",
|
|
43170
44060
|
key: ref.key,
|
|
43171
44061
|
...ref.hasExportJsonKey ? { jsonKey: ref.exportJsonKey } : {},
|
|
44062
|
+
...ref.hasHtmlKey ? { htmlKey: ref.htmlKey } : {},
|
|
43172
44063
|
...ref.min != null ? { min: ref.min } : {},
|
|
43173
44064
|
...ref.max != null ? { max: ref.max } : {},
|
|
43174
44065
|
...ref.description ? { description: ref.description } : {}
|
|
@@ -43358,497 +44249,6 @@ var ConfigBuilder = class {
|
|
|
43358
44249
|
}
|
|
43359
44250
|
};
|
|
43360
44251
|
|
|
43361
|
-
// src/parser/html/HtmlDom.ts
|
|
43362
|
-
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
43363
|
-
"area",
|
|
43364
|
-
"base",
|
|
43365
|
-
"br",
|
|
43366
|
-
"col",
|
|
43367
|
-
"embed",
|
|
43368
|
-
"hr",
|
|
43369
|
-
"img",
|
|
43370
|
-
"input",
|
|
43371
|
-
"link",
|
|
43372
|
-
"meta",
|
|
43373
|
-
"param",
|
|
43374
|
-
"source",
|
|
43375
|
-
"track",
|
|
43376
|
-
"wbr"
|
|
43377
|
-
]);
|
|
43378
|
-
var IMPLIED_CLOSE = {
|
|
43379
|
-
li: /* @__PURE__ */ new Set(["li"]),
|
|
43380
|
-
td: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43381
|
-
th: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43382
|
-
tr: /* @__PURE__ */ new Set(["td", "th", "tr"]),
|
|
43383
|
-
thead: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43384
|
-
tbody: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43385
|
-
tfoot: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43386
|
-
p: /* @__PURE__ */ new Set(["p"]),
|
|
43387
|
-
option: /* @__PURE__ */ new Set(["option"])
|
|
43388
|
-
};
|
|
43389
|
-
var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
|
|
43390
|
-
var ATTR_RE = /([a-zA-Z_:][a-zA-Z0-9:._-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
|
|
43391
|
-
function parseAttrs(raw) {
|
|
43392
|
-
const attrs = {};
|
|
43393
|
-
if (!raw) return attrs;
|
|
43394
|
-
ATTR_RE.lastIndex = 0;
|
|
43395
|
-
let m;
|
|
43396
|
-
while ((m = ATTR_RE.exec(raw)) !== null) {
|
|
43397
|
-
const name = m[1].toLowerCase();
|
|
43398
|
-
let value = m[2] ?? "";
|
|
43399
|
-
if (value.length >= 2 && (value[0] === '"' || value[0] === "'")) {
|
|
43400
|
-
value = value.slice(1, -1);
|
|
43401
|
-
}
|
|
43402
|
-
attrs[name] = value;
|
|
43403
|
-
}
|
|
43404
|
-
return attrs;
|
|
43405
|
-
}
|
|
43406
|
-
function stripNonContent(html) {
|
|
43407
|
-
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, "").replace(/<!doctype[^>]*>/gi, "").replace(/<script\b[\s\S]*?<\/script>/gi, "").replace(/<style\b[\s\S]*?<\/style>/gi, "");
|
|
43408
|
-
}
|
|
43409
|
-
function tokenize(html) {
|
|
43410
|
-
const tokens = [];
|
|
43411
|
-
const clean = stripNonContent(html);
|
|
43412
|
-
TAG_RE.lastIndex = 0;
|
|
43413
|
-
let lastIndex = 0;
|
|
43414
|
-
let m;
|
|
43415
|
-
while ((m = TAG_RE.exec(clean)) !== null) {
|
|
43416
|
-
if (m.index > lastIndex) {
|
|
43417
|
-
tokens.push({ kind: "text", text: clean.slice(lastIndex, m.index) });
|
|
43418
|
-
}
|
|
43419
|
-
lastIndex = TAG_RE.lastIndex;
|
|
43420
|
-
const isClose = m[1] === "/";
|
|
43421
|
-
const name = m[2].toLowerCase();
|
|
43422
|
-
if (isClose) {
|
|
43423
|
-
tokens.push({ kind: "close", name });
|
|
43424
|
-
} else {
|
|
43425
|
-
tokens.push({
|
|
43426
|
-
kind: "open",
|
|
43427
|
-
name,
|
|
43428
|
-
attrs: parseAttrs(m[3]),
|
|
43429
|
-
selfClose: m[4] === "/"
|
|
43430
|
-
});
|
|
43431
|
-
}
|
|
43432
|
-
}
|
|
43433
|
-
if (lastIndex < clean.length) {
|
|
43434
|
-
tokens.push({ kind: "text", text: clean.slice(lastIndex) });
|
|
43435
|
-
}
|
|
43436
|
-
return tokens;
|
|
43437
|
-
}
|
|
43438
|
-
function parseHtml(html) {
|
|
43439
|
-
const root = { type: "element", name: "#root", attrs: {}, children: [] };
|
|
43440
|
-
const stack = [root];
|
|
43441
|
-
const top = () => stack[stack.length - 1];
|
|
43442
|
-
for (const token of tokenize(html)) {
|
|
43443
|
-
if (token.kind === "text") {
|
|
43444
|
-
if (token.text) top().children.push({ type: "text", value: token.text });
|
|
43445
|
-
continue;
|
|
43446
|
-
}
|
|
43447
|
-
if (token.kind === "open") {
|
|
43448
|
-
const name = token.name;
|
|
43449
|
-
const closes = IMPLIED_CLOSE[name];
|
|
43450
|
-
if (closes) {
|
|
43451
|
-
while (stack.length > 1 && closes.has(top().name)) stack.pop();
|
|
43452
|
-
}
|
|
43453
|
-
const el = {
|
|
43454
|
-
type: "element",
|
|
43455
|
-
name,
|
|
43456
|
-
attrs: token.attrs ?? {},
|
|
43457
|
-
children: []
|
|
43458
|
-
};
|
|
43459
|
-
top().children.push(el);
|
|
43460
|
-
if (!token.selfClose && !VOID_ELEMENTS.has(name)) {
|
|
43461
|
-
stack.push(el);
|
|
43462
|
-
}
|
|
43463
|
-
continue;
|
|
43464
|
-
}
|
|
43465
|
-
for (let i = stack.length - 1; i > 0; i--) {
|
|
43466
|
-
if (stack[i].name === token.name) {
|
|
43467
|
-
stack.length = i;
|
|
43468
|
-
break;
|
|
43469
|
-
}
|
|
43470
|
-
}
|
|
43471
|
-
}
|
|
43472
|
-
return root.children;
|
|
43473
|
-
}
|
|
43474
|
-
function childElements(el, names) {
|
|
43475
|
-
return el.children.filter((c) => c.type === "element" && names.has(c.name));
|
|
43476
|
-
}
|
|
43477
|
-
|
|
43478
|
-
// src/parser/html/HtmlTableParser.ts
|
|
43479
|
-
var MARK_TAGS = {
|
|
43480
|
-
b: "bold",
|
|
43481
|
-
strong: "bold",
|
|
43482
|
-
i: "italic",
|
|
43483
|
-
em: "italic",
|
|
43484
|
-
sup: "superscript",
|
|
43485
|
-
sub: "subscript",
|
|
43486
|
-
s: "strike",
|
|
43487
|
-
strike: "strike",
|
|
43488
|
-
del: "del",
|
|
43489
|
-
ins: "ins",
|
|
43490
|
-
u: "underline",
|
|
43491
|
-
mark: "highlight",
|
|
43492
|
-
code: "code"
|
|
43493
|
-
};
|
|
43494
|
-
var SECTION_TAGS = /* @__PURE__ */ new Set(["thead", "tbody", "tfoot"]);
|
|
43495
|
-
var ROW_TAGS = /* @__PURE__ */ new Set(["tr"]);
|
|
43496
|
-
var CELL_TAGS = /* @__PURE__ */ new Set(["td", "th"]);
|
|
43497
|
-
var LI_TAGS = /* @__PURE__ */ new Set(["li"]);
|
|
43498
|
-
var VALID_SCOPES = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
43499
|
-
var NAMED_ENTITIES = {
|
|
43500
|
-
amp: "&",
|
|
43501
|
-
lt: "<",
|
|
43502
|
-
gt: ">",
|
|
43503
|
-
quot: '"',
|
|
43504
|
-
apos: "'",
|
|
43505
|
-
nbsp: "\xA0"
|
|
43506
|
-
};
|
|
43507
|
-
function decodeEntities(text) {
|
|
43508
|
-
return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, (whole, body) => {
|
|
43509
|
-
if (body[0] === "#") {
|
|
43510
|
-
const code = body[1] === "x" || body[1] === "X" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);
|
|
43511
|
-
if (Number.isFinite(code) && code >= 0 && code <= 1114111) {
|
|
43512
|
-
try {
|
|
43513
|
-
return String.fromCodePoint(code);
|
|
43514
|
-
} catch {
|
|
43515
|
-
return whole;
|
|
43516
|
-
}
|
|
43517
|
-
}
|
|
43518
|
-
return whole;
|
|
43519
|
-
}
|
|
43520
|
-
return NAMED_ENTITIES[body] ?? whole;
|
|
43521
|
-
});
|
|
43522
|
-
}
|
|
43523
|
-
function intAttr(value) {
|
|
43524
|
-
if (value == null) return void 0;
|
|
43525
|
-
const n = Number.parseInt(value, 10);
|
|
43526
|
-
return Number.isInteger(n) ? n : void 0;
|
|
43527
|
-
}
|
|
43528
|
-
function isElement(node) {
|
|
43529
|
-
return node.type === "element";
|
|
43530
|
-
}
|
|
43531
|
-
var HtmlTableParser = class {
|
|
43532
|
-
keepUnknownTags = false;
|
|
43533
|
-
/**
|
|
43534
|
-
* Parse an HTML string and return one table bit per top-level `<table>`.
|
|
43535
|
-
*/
|
|
43536
|
-
parse(html, options) {
|
|
43537
|
-
this.keepUnknownTags = options?.keepUnknownTags ?? false;
|
|
43538
|
-
const tableFormat = options?.tableFormat ?? "table-extended";
|
|
43539
|
-
const onWarning = options?.onWarning;
|
|
43540
|
-
const tables = this.collectTopLevelTables(parseHtml(html));
|
|
43541
|
-
const bits = [];
|
|
43542
|
-
for (const table of tables) {
|
|
43543
|
-
const bit = this.tableToBit(table, tableFormat, onWarning);
|
|
43544
|
-
if (bit) bits.push(bit);
|
|
43545
|
-
}
|
|
43546
|
-
return bits;
|
|
43547
|
-
}
|
|
43548
|
-
// --- table extraction -----------------------------------------------------
|
|
43549
|
-
/** Collect every `<table>` element, NOT descending into nested tables. */
|
|
43550
|
-
collectTopLevelTables(nodes) {
|
|
43551
|
-
const tables = [];
|
|
43552
|
-
const visit = (node) => {
|
|
43553
|
-
if (!isElement(node)) return;
|
|
43554
|
-
if (node.name === "table") {
|
|
43555
|
-
tables.push(node);
|
|
43556
|
-
return;
|
|
43557
|
-
}
|
|
43558
|
-
node.children.forEach(visit);
|
|
43559
|
-
};
|
|
43560
|
-
nodes.forEach(visit);
|
|
43561
|
-
return tables;
|
|
43562
|
-
}
|
|
43563
|
-
tableToBit(table, tableFormat, onWarning) {
|
|
43564
|
-
const header = [];
|
|
43565
|
-
const body = [];
|
|
43566
|
-
const footer = [];
|
|
43567
|
-
let caption;
|
|
43568
|
-
for (const child of table.children) {
|
|
43569
|
-
if (!isElement(child)) continue;
|
|
43570
|
-
if (child.name === "caption") {
|
|
43571
|
-
const capContent = this.inlineNodes(child.children, []);
|
|
43572
|
-
const trimmed = this.trimInline(capContent);
|
|
43573
|
-
if (trimmed.length > 0) caption = trimmed;
|
|
43574
|
-
} else if (SECTION_TAGS.has(child.name)) {
|
|
43575
|
-
const target = child.name === "thead" ? header : child.name === "tfoot" ? footer : body;
|
|
43576
|
-
for (const tr of childElements(child, ROW_TAGS)) {
|
|
43577
|
-
target.push(this.rowToCells(tr));
|
|
43578
|
-
}
|
|
43579
|
-
} else if (ROW_TAGS.has(child.name)) {
|
|
43580
|
-
body.push(this.rowToCells(child));
|
|
43581
|
-
}
|
|
43582
|
-
}
|
|
43583
|
-
if (header.length === 0 && body.length === 0 && footer.length === 0) {
|
|
43584
|
-
return void 0;
|
|
43585
|
-
}
|
|
43586
|
-
const tableExtended = {};
|
|
43587
|
-
if (header.length > 0) tableExtended.header = { rows: header };
|
|
43588
|
-
if (body.length > 0) tableExtended.body = { rows: body };
|
|
43589
|
-
if (footer.length > 0) tableExtended.footer = { rows: footer };
|
|
43590
|
-
let tableData = tableExtended;
|
|
43591
|
-
if (tableFormat === "table") {
|
|
43592
|
-
if (this.isLossyAsBasic(tableExtended)) {
|
|
43593
|
-
onWarning?.(
|
|
43594
|
-
"Converting an HTML table to [.table] loses rowspan/colspan/scope and multi-section structure; use --tableFormat table-extended to preserve them."
|
|
43595
|
-
);
|
|
43596
|
-
}
|
|
43597
|
-
tableData = convertExtendedToBasicTableFormat(tableExtended);
|
|
43598
|
-
}
|
|
43599
|
-
const bit = {
|
|
43600
|
-
type: tableFormat,
|
|
43601
|
-
format: "bitmark++",
|
|
43602
|
-
table: tableData
|
|
43603
|
-
};
|
|
43604
|
-
if (caption) bit.caption = caption;
|
|
43605
|
-
return bit;
|
|
43606
|
-
}
|
|
43607
|
-
rowToCells(tr) {
|
|
43608
|
-
const cells = [];
|
|
43609
|
-
for (const cell of childElements(tr, CELL_TAGS)) {
|
|
43610
|
-
cells.push(this.cellToJson(cell));
|
|
43611
|
-
}
|
|
43612
|
-
return { cells };
|
|
43613
|
-
}
|
|
43614
|
-
cellToJson(cell) {
|
|
43615
|
-
const json = {
|
|
43616
|
-
content: this.blockNodes(cell.children)
|
|
43617
|
-
};
|
|
43618
|
-
if (cell.name === "th") json.title = true;
|
|
43619
|
-
const rowspan = intAttr(cell.attrs.rowspan);
|
|
43620
|
-
if (rowspan != null && rowspan >= 2) json.rowspan = rowspan;
|
|
43621
|
-
const colspan = intAttr(cell.attrs.colspan);
|
|
43622
|
-
if (colspan != null && colspan >= 2) json.colspan = colspan;
|
|
43623
|
-
const scope = cell.attrs.scope?.toLowerCase();
|
|
43624
|
-
if (scope && VALID_SCOPES.has(scope)) {
|
|
43625
|
-
json.scope = scope;
|
|
43626
|
-
}
|
|
43627
|
-
const width = this.widthFromCell(cell);
|
|
43628
|
-
if (width != null) json.colwidth = width;
|
|
43629
|
-
return json;
|
|
43630
|
-
}
|
|
43631
|
-
widthFromCell(cell) {
|
|
43632
|
-
const attrWidth = intAttr(cell.attrs.width);
|
|
43633
|
-
if (attrWidth != null && attrWidth > 0) return attrWidth;
|
|
43634
|
-
const style = cell.attrs.style;
|
|
43635
|
-
if (style) {
|
|
43636
|
-
const m = style.match(/width\s*:\s*(\d+)\s*px/i);
|
|
43637
|
-
if (m) {
|
|
43638
|
-
const n = Number.parseInt(m[1], 10);
|
|
43639
|
-
if (Number.isInteger(n) && n > 0) return n;
|
|
43640
|
-
}
|
|
43641
|
-
}
|
|
43642
|
-
return void 0;
|
|
43643
|
-
}
|
|
43644
|
-
isLossyAsBasic(table) {
|
|
43645
|
-
if (table.footer) return true;
|
|
43646
|
-
if (table.header && table.header.rows.length > 1) return true;
|
|
43647
|
-
const sections = [table.header, table.body, table.footer];
|
|
43648
|
-
for (const section of sections) {
|
|
43649
|
-
if (!section) continue;
|
|
43650
|
-
for (const row of section.rows) {
|
|
43651
|
-
for (const cell of row.cells) {
|
|
43652
|
-
if (cell.rowspan || cell.colspan || cell.scope) return true;
|
|
43653
|
-
}
|
|
43654
|
-
}
|
|
43655
|
-
}
|
|
43656
|
-
return false;
|
|
43657
|
-
}
|
|
43658
|
-
// --- content conversion (HTML -> TextAst) ---------------------------------
|
|
43659
|
-
/**
|
|
43660
|
-
* Convert a cell/li's child nodes into block-level TextAst nodes (paragraphs, lists, images).
|
|
43661
|
-
*/
|
|
43662
|
-
blockNodes(nodes) {
|
|
43663
|
-
const blocks = [];
|
|
43664
|
-
let inline = [];
|
|
43665
|
-
const flush = () => {
|
|
43666
|
-
const trimmed = this.trimInline(inline);
|
|
43667
|
-
inline = [];
|
|
43668
|
-
if (trimmed.length === 0) return;
|
|
43669
|
-
if (trimmed.length === 1 && trimmed[0].type === "imageInline") {
|
|
43670
|
-
blocks.push({ ...trimmed[0], type: "image" });
|
|
43671
|
-
} else {
|
|
43672
|
-
blocks.push({ type: "paragraph", content: trimmed, attrs: {} });
|
|
43673
|
-
}
|
|
43674
|
-
};
|
|
43675
|
-
for (const node of nodes) {
|
|
43676
|
-
if (!isElement(node)) {
|
|
43677
|
-
inline.push(...this.inlineText(node.value, []));
|
|
43678
|
-
continue;
|
|
43679
|
-
}
|
|
43680
|
-
const name = node.name;
|
|
43681
|
-
if (name === "p") {
|
|
43682
|
-
flush();
|
|
43683
|
-
const content = this.trimInline(this.inlineNodes(node.children, []));
|
|
43684
|
-
if (content.length > 0) {
|
|
43685
|
-
blocks.push({ type: "paragraph", content, attrs: {} });
|
|
43686
|
-
}
|
|
43687
|
-
} else if (this.isListTag(name)) {
|
|
43688
|
-
flush();
|
|
43689
|
-
const list = this.listNode(node);
|
|
43690
|
-
if (list) blocks.push(list);
|
|
43691
|
-
} else {
|
|
43692
|
-
inline.push(...this.inlineFromElement(node, []));
|
|
43693
|
-
}
|
|
43694
|
-
}
|
|
43695
|
-
flush();
|
|
43696
|
-
return blocks;
|
|
43697
|
-
}
|
|
43698
|
-
/** Convert child nodes to a flat list of inline TextNodes, applying the given marks. */
|
|
43699
|
-
inlineNodes(nodes, marks) {
|
|
43700
|
-
const out = [];
|
|
43701
|
-
for (const node of nodes) {
|
|
43702
|
-
if (!isElement(node)) {
|
|
43703
|
-
out.push(...this.inlineText(node.value, marks));
|
|
43704
|
-
} else {
|
|
43705
|
-
out.push(...this.inlineFromElement(node, marks));
|
|
43706
|
-
}
|
|
43707
|
-
}
|
|
43708
|
-
return out;
|
|
43709
|
-
}
|
|
43710
|
-
inlineFromElement(el, marks) {
|
|
43711
|
-
const name = el.name;
|
|
43712
|
-
if (name === "br") {
|
|
43713
|
-
return [{ type: "hardBreak" }];
|
|
43714
|
-
}
|
|
43715
|
-
if (name === "img") {
|
|
43716
|
-
return [this.imageNode(el, true)];
|
|
43717
|
-
}
|
|
43718
|
-
const markType = MARK_TAGS[name];
|
|
43719
|
-
if (markType) {
|
|
43720
|
-
return this.inlineNodes(el.children, [...marks, { type: markType }]);
|
|
43721
|
-
}
|
|
43722
|
-
if (name === "a") {
|
|
43723
|
-
const linkMark = {
|
|
43724
|
-
type: "link",
|
|
43725
|
-
attrs: {
|
|
43726
|
-
href: el.attrs.href ?? "",
|
|
43727
|
-
...el.attrs.target ? { target: el.attrs.target } : {}
|
|
43728
|
-
}
|
|
43729
|
-
};
|
|
43730
|
-
return this.inlineNodes(el.children, [...marks, linkMark]);
|
|
43731
|
-
}
|
|
43732
|
-
if (this.keepUnknownTags) {
|
|
43733
|
-
const open = this.serializeOpenTag(el);
|
|
43734
|
-
const close = `</${name}>`;
|
|
43735
|
-
return [
|
|
43736
|
-
...this.inlineText(open, marks),
|
|
43737
|
-
...this.inlineNodes(el.children, marks),
|
|
43738
|
-
...this.inlineText(close, marks)
|
|
43739
|
-
];
|
|
43740
|
-
}
|
|
43741
|
-
return this.inlineNodes(el.children, marks);
|
|
43742
|
-
}
|
|
43743
|
-
inlineText(raw, marks) {
|
|
43744
|
-
const text = decodeEntities(raw).replace(/\s+/g, " ");
|
|
43745
|
-
if (text === "") return [];
|
|
43746
|
-
const node = { text, type: "text" };
|
|
43747
|
-
if (marks.length > 0) node.marks = marks.map((m) => ({ ...m }));
|
|
43748
|
-
return [node];
|
|
43749
|
-
}
|
|
43750
|
-
serializeOpenTag(el) {
|
|
43751
|
-
const attrs = Object.entries(el.attrs).map(([k, v]) => v === "" ? ` ${k}` : ` ${k}="${v}"`).join("");
|
|
43752
|
-
return `<${el.name}${attrs}>`;
|
|
43753
|
-
}
|
|
43754
|
-
// --- lists ----------------------------------------------------------------
|
|
43755
|
-
isListTag(name) {
|
|
43756
|
-
return name === "ul" || name === "ol";
|
|
43757
|
-
}
|
|
43758
|
-
listNode(el) {
|
|
43759
|
-
const items = childElements(el, LI_TAGS);
|
|
43760
|
-
if (items.length === 0) return void 0;
|
|
43761
|
-
const isTask = el.name === "ul" && items.some((li) => {
|
|
43762
|
-
const firstEl = li.children.find(isElement);
|
|
43763
|
-
return firstEl?.name === "input" && firstEl.attrs.type?.toLowerCase() === "checkbox";
|
|
43764
|
-
});
|
|
43765
|
-
if (isTask) {
|
|
43766
|
-
return {
|
|
43767
|
-
type: "taskList",
|
|
43768
|
-
content: items.map((li) => this.taskItemNode(li))
|
|
43769
|
-
};
|
|
43770
|
-
}
|
|
43771
|
-
const type = this.listType(el);
|
|
43772
|
-
const node = {
|
|
43773
|
-
type,
|
|
43774
|
-
content: items.map((li) => this.listItemNode(li))
|
|
43775
|
-
};
|
|
43776
|
-
if (el.name === "ol") {
|
|
43777
|
-
const start = intAttr(el.attrs.start);
|
|
43778
|
-
if (start != null) {
|
|
43779
|
-
node.attrs = { start };
|
|
43780
|
-
}
|
|
43781
|
-
}
|
|
43782
|
-
return node;
|
|
43783
|
-
}
|
|
43784
|
-
listType(el) {
|
|
43785
|
-
if (el.name === "ol") {
|
|
43786
|
-
switch (el.attrs.type) {
|
|
43787
|
-
case "i":
|
|
43788
|
-
return "orderedListRomanLower";
|
|
43789
|
-
case "I":
|
|
43790
|
-
return "orderedListRoman";
|
|
43791
|
-
case "a":
|
|
43792
|
-
return "letteredListLower";
|
|
43793
|
-
case "A":
|
|
43794
|
-
return "letteredList";
|
|
43795
|
-
default:
|
|
43796
|
-
return "orderedList";
|
|
43797
|
-
}
|
|
43798
|
-
}
|
|
43799
|
-
const style = el.attrs.style ?? "";
|
|
43800
|
-
if (/list-style(-type)?\s*:\s*none/i.test(style)) return "noBulletList";
|
|
43801
|
-
return "bulletList";
|
|
43802
|
-
}
|
|
43803
|
-
listItemNode(li) {
|
|
43804
|
-
let content = this.blockNodes(li.children);
|
|
43805
|
-
if (content.length === 0) {
|
|
43806
|
-
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
43807
|
-
}
|
|
43808
|
-
return { type: "listItem", content };
|
|
43809
|
-
}
|
|
43810
|
-
taskItemNode(li) {
|
|
43811
|
-
const checkbox = li.children.find(
|
|
43812
|
-
(c) => isElement(c) && c.name === "input" && c.attrs.type?.toLowerCase() === "checkbox"
|
|
43813
|
-
);
|
|
43814
|
-
const checked = checkbox ? "checked" in checkbox.attrs : false;
|
|
43815
|
-
const rest = li.children.filter((c) => c !== checkbox);
|
|
43816
|
-
let content = this.blockNodes(rest);
|
|
43817
|
-
if (content.length === 0) {
|
|
43818
|
-
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
43819
|
-
}
|
|
43820
|
-
return { type: "taskItem", attrs: { checked }, content };
|
|
43821
|
-
}
|
|
43822
|
-
// --- images ---------------------------------------------------------------
|
|
43823
|
-
imageNode(el, inline) {
|
|
43824
|
-
const attrs = { src: el.attrs.src ?? "" };
|
|
43825
|
-
attrs.alt = el.attrs.alt ?? null;
|
|
43826
|
-
attrs.title = el.attrs.title ?? null;
|
|
43827
|
-
const width = intAttr(el.attrs.width);
|
|
43828
|
-
if (width != null) attrs.width = width;
|
|
43829
|
-
const height = intAttr(el.attrs.height);
|
|
43830
|
-
if (height != null) attrs.height = height;
|
|
43831
|
-
if (el.attrs.class) attrs.class = el.attrs.class;
|
|
43832
|
-
return { type: inline ? "imageInline" : "image", attrs };
|
|
43833
|
-
}
|
|
43834
|
-
// --- whitespace -----------------------------------------------------------
|
|
43835
|
-
/** Trim leading/trailing whitespace from inline content (edges only). */
|
|
43836
|
-
trimInline(nodes) {
|
|
43837
|
-
const out = nodes.slice();
|
|
43838
|
-
const isWs = (n) => n.type === "text" && /^\s*$/.test(n.text ?? "");
|
|
43839
|
-
while (out.length > 0 && isWs(out[0])) out.shift();
|
|
43840
|
-
if (out.length > 0 && out[0].type === "text") {
|
|
43841
|
-
out[0] = { ...out[0], text: (out[0].text ?? "").replace(/^\s+/, "") };
|
|
43842
|
-
}
|
|
43843
|
-
while (out.length > 0 && isWs(out[out.length - 1])) out.pop();
|
|
43844
|
-
if (out.length > 0 && out[out.length - 1].type === "text") {
|
|
43845
|
-
const last = out.length - 1;
|
|
43846
|
-
out[last] = { ...out[last], text: (out[last].text ?? "").replace(/\s+$/, "") };
|
|
43847
|
-
}
|
|
43848
|
-
return out.filter((n) => !(n.type === "text" && n.text === ""));
|
|
43849
|
-
}
|
|
43850
|
-
};
|
|
43851
|
-
|
|
43852
44252
|
// src/BitmarkParserGenerator.ts
|
|
43853
44253
|
var Input = {
|
|
43854
44254
|
/**
|
|
@@ -44463,7 +44863,10 @@ var BitmarkParserGenerator = class {
|
|
|
44463
44863
|
outputFile: opts.outputFile,
|
|
44464
44864
|
fileOptions: opts.fileOptions,
|
|
44465
44865
|
jsonOptions: opts.jsonOptions,
|
|
44466
|
-
bitmarkOptions:
|
|
44866
|
+
bitmarkOptions: {
|
|
44867
|
+
...opts.bitmarkOptions,
|
|
44868
|
+
...opts.noBreakscaping ? { noBreakscaping: true } : {}
|
|
44869
|
+
}
|
|
44467
44870
|
});
|
|
44468
44871
|
}
|
|
44469
44872
|
const outputFormat = opts.outputFormat ?? "html";
|
|
@@ -44825,7 +45228,7 @@ function createConvertHtmlTableCommand() {
|
|
|
44825
45228
|
)
|
|
44826
45229
|
).addOption(
|
|
44827
45230
|
new Option("--tableFormat <format>", "bit type to emit for HTML input").choices(TABLE_FORMAT_CHOICES).default("table-extended")
|
|
44828
|
-
).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(
|
|
44829
45232
|
"--indent <indent>",
|
|
44830
45233
|
"prettify indent (default: 2 when --pretty is set)",
|
|
44831
45234
|
(v) => Number.parseInt(v, 10)
|
|
@@ -44841,6 +45244,7 @@ function createConvertHtmlTableCommand() {
|
|
|
44841
45244
|
options.tableFormat
|
|
44842
45245
|
),
|
|
44843
45246
|
keepUnknownTags: options.keepUnknownTags,
|
|
45247
|
+
noBreakscaping: options.noBreakscaping,
|
|
44844
45248
|
jsonOptions: {
|
|
44845
45249
|
prettify
|
|
44846
45250
|
}
|
|
@@ -44866,7 +45270,9 @@ Examples:
|
|
|
44866
45270
|
|
|
44867
45271
|
$ bitmark-parser convertHtmlTable input.bitmark -o output.html
|
|
44868
45272
|
|
|
44869
|
-
$ bitmark-parser convertHtmlTable --tableFormat table input.html
|
|
45273
|
+
$ bitmark-parser convertHtmlTable --tableFormat table input.html
|
|
45274
|
+
|
|
45275
|
+
$ bitmark-parser convertHtmlTable --noBreakscaping input.html`
|
|
44870
45276
|
);
|
|
44871
45277
|
return cmd;
|
|
44872
45278
|
}
|