@gmb/bitmark-parser-generator 5.24.0 → 5.26.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 +1040 -17
- package/dist/browser/cjs/index.cjs.map +1 -1
- package/dist/browser/cjs/index.d.cts +175 -1
- package/dist/browser/esm/index.d.ts +175 -1
- package/dist/browser/esm/index.js +1038 -17
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/cli/main.js +1155 -75
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +1040 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +175 -1
- package/dist/index.d.ts +175 -1
- package/dist/index.js +1038 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,8 @@ __export(index_exports, {
|
|
|
46
46
|
Builder: () => Builder,
|
|
47
47
|
CardSetVersion: () => CardSetVersion,
|
|
48
48
|
FileWriter: () => FileWriter,
|
|
49
|
+
HtmlTableGenerator: () => HtmlTableGenerator,
|
|
50
|
+
HtmlTableParser: () => HtmlTableParser,
|
|
49
51
|
InfoFormat: () => InfoFormat,
|
|
50
52
|
InfoType: () => InfoType,
|
|
51
53
|
Input: () => Input,
|
|
@@ -293,6 +295,7 @@ var BitType = {
|
|
|
293
295
|
dangerAlt: "danger-alt",
|
|
294
296
|
dangerCollapsible: "danger-collapsible",
|
|
295
297
|
definitionList: "definition-list",
|
|
298
|
+
definitionListCollapsible: "definition-list-collapsible",
|
|
296
299
|
definitionTerm: "definition-term",
|
|
297
300
|
deleted: "deleted",
|
|
298
301
|
details: "details",
|
|
@@ -573,6 +576,8 @@ var BitType = {
|
|
|
573
576
|
smartStandardArticleNonNormativeCollapsible: "smart-standard-article-non-normative-collapsible",
|
|
574
577
|
smartStandardArticleNormative: "smart-standard-article-normative",
|
|
575
578
|
smartStandardArticleNormativeCollapsible: "smart-standard-article-normative-collapsible",
|
|
579
|
+
smartStandardDefinitionListNonNormative: "smart-standard-definition-list-non-normative",
|
|
580
|
+
smartStandardDefinitionListNormative: "smart-standard-definition-list-normative",
|
|
576
581
|
smartStandardExampleNonNormative: "smart-standard-example-non-normative",
|
|
577
582
|
smartStandardExampleNonNormativeCollapsible: "smart-standard-example-non-normative-collapsible",
|
|
578
583
|
smartStandardExampleNormative: "smart-standard-example-normative",
|
|
@@ -623,6 +628,8 @@ var BitType = {
|
|
|
623
628
|
smartStandardTableNormativeCollapsible: "smart-standard-table-normative-collapsible",
|
|
624
629
|
standardArticleNonNormative: "standard-article-non-normative",
|
|
625
630
|
standardArticleNormative: "standard-article-normative",
|
|
631
|
+
standardDefinitionListNonNormative: "standard-definition-list-non-normative",
|
|
632
|
+
standardDefinitionListNormative: "standard-definition-list-normative",
|
|
626
633
|
standardExampleNonNormative: "standard-example-non-normative",
|
|
627
634
|
standardExampleNormative: "standard-example-normative",
|
|
628
635
|
standardImageFigureNonNormative: "standard-image-figure-non-normative",
|
|
@@ -794,6 +801,7 @@ var CardSetConfigKey = {
|
|
|
794
801
|
flashcard: "flashcard",
|
|
795
802
|
flashcard1: "flashcard1",
|
|
796
803
|
definitionList: "definitionList",
|
|
804
|
+
definitionListPlain: "definitionListPlain",
|
|
797
805
|
elements: "elements",
|
|
798
806
|
statements: "statements",
|
|
799
807
|
quiz: "quiz",
|
|
@@ -1407,6 +1415,7 @@ var propertyKeys = {
|
|
|
1407
1415
|
property_enforceUpdateOverUserInput: "@enforceUpdateOverUserInput",
|
|
1408
1416
|
property_extractorExtractionTimestamp: "@extractorExtractionTimestamp",
|
|
1409
1417
|
property_isCaseSensitive: "@isCaseSensitive",
|
|
1418
|
+
property_isCollapsible: "@isCollapsible",
|
|
1410
1419
|
property_isInfoOnly: "@isInfoOnly",
|
|
1411
1420
|
property_isPublic: "@isPublic",
|
|
1412
1421
|
property_isTemplate: "@isTemplate",
|
|
@@ -2611,6 +2620,126 @@ var CARDSETS = {
|
|
|
2611
2620
|
]
|
|
2612
2621
|
},
|
|
2613
2622
|
//
|
|
2623
|
+
// definition-list-plain
|
|
2624
|
+
//
|
|
2625
|
+
// Same shape as `definitionList`, but every variant body is rendered as
|
|
2626
|
+
// plain text (string), not bitmark+ AST. Used by
|
|
2627
|
+
// `meta-search-default-terms` / `meta-search-default-topics`, which need
|
|
2628
|
+
// term/definition text emitted verbatim instead of as a ProseMirror tree.
|
|
2629
|
+
//
|
|
2630
|
+
[CardSetConfigKey.definitionListPlain]: {
|
|
2631
|
+
jsonKey: "definitions",
|
|
2632
|
+
exportJsonKey: { definitions: "$" },
|
|
2633
|
+
sides: [
|
|
2634
|
+
{
|
|
2635
|
+
name: "term",
|
|
2636
|
+
variants: [
|
|
2637
|
+
{
|
|
2638
|
+
jsonKey: "term.text",
|
|
2639
|
+
exportJsonKey: [{ "@absent": { term: {} } }, { term: { text: "$" } }],
|
|
2640
|
+
format: TextFormat.plainText,
|
|
2641
|
+
tags: [
|
|
2642
|
+
{
|
|
2643
|
+
key: ConfigKey.group_standardTags,
|
|
2644
|
+
description: "Standard tags for the definition."
|
|
2645
|
+
},
|
|
2646
|
+
{
|
|
2647
|
+
key: ConfigKey.tag_title,
|
|
2648
|
+
description: "Title of the definition.",
|
|
2649
|
+
format: TagFormat.plainText,
|
|
2650
|
+
jsonKey: "^heading.forKeys",
|
|
2651
|
+
exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
|
|
2652
|
+
},
|
|
2653
|
+
{
|
|
2654
|
+
key: ConfigKey.group_resourceIcon,
|
|
2655
|
+
description: "Icon resource for the definition.",
|
|
2656
|
+
format: TagFormat.plainText,
|
|
2657
|
+
jsonKey: "term.icon|resource(type=image, key=image)",
|
|
2658
|
+
exportJsonKey: { term: { icon: { type: "image", image: { src: "$" } } } }
|
|
2659
|
+
},
|
|
2660
|
+
{
|
|
2661
|
+
key: ConfigKey.property_example,
|
|
2662
|
+
exportJsonKey: [
|
|
2663
|
+
{ "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2664
|
+
{ "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2665
|
+
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
2666
|
+
],
|
|
2667
|
+
description: "Example marker for the definition term.",
|
|
2668
|
+
format: TagFormat.bitmarkText,
|
|
2669
|
+
nullable: true
|
|
2670
|
+
}
|
|
2671
|
+
]
|
|
2672
|
+
}
|
|
2673
|
+
]
|
|
2674
|
+
},
|
|
2675
|
+
{
|
|
2676
|
+
name: "definition",
|
|
2677
|
+
variants: [
|
|
2678
|
+
{
|
|
2679
|
+
jsonKey: "definition.text",
|
|
2680
|
+
exportJsonKey: [{ "@absent": { definition: {} } }, { definition: { text: "$" } }],
|
|
2681
|
+
format: TextFormat.plainText,
|
|
2682
|
+
tags: [
|
|
2683
|
+
{
|
|
2684
|
+
key: ConfigKey.group_standardTags,
|
|
2685
|
+
description: "Standard tags for the definition."
|
|
2686
|
+
},
|
|
2687
|
+
{
|
|
2688
|
+
key: ConfigKey.tag_title,
|
|
2689
|
+
description: "Title of the definition.",
|
|
2690
|
+
format: TagFormat.plainText,
|
|
2691
|
+
jsonKey: "^heading.forValues",
|
|
2692
|
+
exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
|
|
2693
|
+
},
|
|
2694
|
+
{
|
|
2695
|
+
key: ConfigKey.group_resourceIcon,
|
|
2696
|
+
description: "Icon resource for the definition.",
|
|
2697
|
+
jsonKey: "definition.icon|resource(type=image, key=image)",
|
|
2698
|
+
exportJsonKey: { definition: { icon: { type: "image", image: { src: "$" } } } }
|
|
2699
|
+
},
|
|
2700
|
+
{
|
|
2701
|
+
key: ConfigKey.property_example,
|
|
2702
|
+
exportJsonKey: [
|
|
2703
|
+
{ "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2704
|
+
{ "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2705
|
+
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
2706
|
+
],
|
|
2707
|
+
description: "Example marker for the definition.",
|
|
2708
|
+
format: TagFormat.bitmarkText,
|
|
2709
|
+
nullable: true
|
|
2710
|
+
}
|
|
2711
|
+
]
|
|
2712
|
+
},
|
|
2713
|
+
{
|
|
2714
|
+
jsonKey: "alternativeDefinitions[].text",
|
|
2715
|
+
exportJsonKey: { alternativeDefinitions: [{ text: "$" }] },
|
|
2716
|
+
format: TextFormat.plainText,
|
|
2717
|
+
tags: [
|
|
2718
|
+
{
|
|
2719
|
+
key: ConfigKey.group_standardTags,
|
|
2720
|
+
description: "Standard tags for the definition."
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
exportJsonKey: { title: "$" },
|
|
2724
|
+
key: ConfigKey.tag_title,
|
|
2725
|
+
description: "Title of the definition."
|
|
2726
|
+
},
|
|
2727
|
+
{
|
|
2728
|
+
key: ConfigKey.group_resourceIcon,
|
|
2729
|
+
description: "Icon resource for the definition.",
|
|
2730
|
+
jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)",
|
|
2731
|
+
exportJsonKey: {
|
|
2732
|
+
alternativeDefinitions: [{ icon: { type: "image", image: { src: "$" } } }]
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
],
|
|
2736
|
+
repeatCount: Count.infinity
|
|
2737
|
+
}
|
|
2738
|
+
]
|
|
2739
|
+
}
|
|
2740
|
+
]
|
|
2741
|
+
},
|
|
2742
|
+
//
|
|
2614
2743
|
// match-pairs
|
|
2615
2744
|
//
|
|
2616
2745
|
[CardSetConfigKey.matchPairs]: {
|
|
@@ -3548,12 +3677,29 @@ var CARDSETS = {
|
|
|
3548
3677
|
// ALIGN-EXAMPLE-CASCADE §3.10: `questions` is NOT in BPG's
|
|
3549
3678
|
// `pushExampleDownTree` dispatch — bit-header `[@example]`
|
|
3550
3679
|
// does not propagate `example`/`isExample` onto question
|
|
3551
|
-
// entries. Only entry-local `[@example]` fires
|
|
3552
|
-
//
|
|
3553
|
-
//
|
|
3680
|
+
// entries. Only entry-local `[@example]` fires.
|
|
3681
|
+
//
|
|
3682
|
+
// BPG's `BaseBuilder.toExample` for interview questions
|
|
3683
|
+
// (Builder.ts:2575,2588) uses `data.__sampleSolutionAst`
|
|
3684
|
+
// as `defaultExample` — bare `[@example]` (which sets
|
|
3685
|
+
// `__isDefaultExample=true, example=undefined`) emits the
|
|
3686
|
+
// parsed sample-solution AST in the `example` slot. The
|
|
3687
|
+
// `@keyonly` rule mirrors that runtime behaviour via
|
|
3688
|
+
// `$parent.sampleSolution` — the chain-walker's post-walk
|
|
3689
|
+
// retry resolves this once the sibling `[@sampleSolution]`
|
|
3690
|
+
// chain has merged into the shared scope (interview's
|
|
3691
|
+
// `[@example]` typically precedes `[@sampleSolution]` in
|
|
3692
|
+
// source). Format coercion turns the resolved string
|
|
3693
|
+
// value into a PM tree.
|
|
3554
3694
|
key: ConfigKey.property_example,
|
|
3555
3695
|
exportJsonKey: [
|
|
3556
|
-
{
|
|
3696
|
+
{
|
|
3697
|
+
"@keyonly": {
|
|
3698
|
+
isExample: true,
|
|
3699
|
+
example: "$parent.sampleSolution",
|
|
3700
|
+
"@bit": { isExample: true }
|
|
3701
|
+
}
|
|
3702
|
+
},
|
|
3557
3703
|
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
3558
3704
|
],
|
|
3559
3705
|
description: "Example marker for the question (entry-local only; no bit-header cascade).",
|
|
@@ -5376,7 +5522,11 @@ var GROUPS = {
|
|
|
5376
5522
|
{
|
|
5377
5523
|
key: ConfigKey.property_mark,
|
|
5378
5524
|
jsonKey: "marks.mark",
|
|
5379
|
-
|
|
5525
|
+
// `emphasis: 'underline'` is the per-entry default for mark
|
|
5526
|
+
// configs — mirrors the hardcoded default in BPG
|
|
5527
|
+
// `MarkConfigChainContentProcessor.ts:55-58`. Chained
|
|
5528
|
+
// `[@emphasis:…]` overrides via deep-merge into `marks[-1]`.
|
|
5529
|
+
exportJsonKey: { marks: [{ mark: "$", emphasis: "underline" }] },
|
|
5380
5530
|
description: "The mark configuration",
|
|
5381
5531
|
format: TagFormat.plainText,
|
|
5382
5532
|
maxCount: Count.infinity,
|
|
@@ -5418,13 +5568,22 @@ var GROUPS = {
|
|
|
5418
5568
|
{
|
|
5419
5569
|
key: ConfigKey.property_example,
|
|
5420
5570
|
jsonKey: "example",
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5571
|
+
// Per-mark `@example` is a boolean toggle. BPG's runtime
|
|
5572
|
+
// `ExampleTagContentProcessor.handleDefaultOnlyExample`
|
|
5573
|
+
// (lines 147-161) normalises ANY `[@example]` or
|
|
5574
|
+
// `[@example:V]` on a mark body-bit to
|
|
5575
|
+
// `__isDefaultExample=true, example=undefined`; the
|
|
5576
|
+
// downstream `toExample(_, _, defaultExample=true)` in
|
|
5577
|
+
// `BaseBuilder.ts:80-87` then emits `example: true`
|
|
5578
|
+
// regardless of source. Declare a single unconditional
|
|
5579
|
+
// boolean-shape rule so the exported schema matches that
|
|
5580
|
+
// runtime semantic instead of the misleading `example: $`
|
|
5581
|
+
// shape (which would only fire if `handleDefaultOnlyExample`
|
|
5582
|
+
// were removed). `@bit: {isExample: true}` cascades the
|
|
5583
|
+
// marker — but NOT the `example` value — to bit root.
|
|
5584
|
+
exportJsonKey: { isExample: true, example: true, "@bit": { isExample: true } },
|
|
5426
5585
|
description: "An example for the marked content",
|
|
5427
|
-
format: TagFormat.
|
|
5586
|
+
format: TagFormat.boolean,
|
|
5428
5587
|
nullable: true
|
|
5429
5588
|
}
|
|
5430
5589
|
]
|
|
@@ -8200,6 +8359,12 @@ var BITS = {
|
|
|
8200
8359
|
description: "The progress of the chapter, used for tracking reading progress",
|
|
8201
8360
|
format: TagFormat.boolean,
|
|
8202
8361
|
defaultValue: "true"
|
|
8362
|
+
},
|
|
8363
|
+
{
|
|
8364
|
+
key: ConfigKey.property_isCollapsible,
|
|
8365
|
+
description: "If true, the chapter is collapsible",
|
|
8366
|
+
format: TagFormat.boolean,
|
|
8367
|
+
defaultValue: "false"
|
|
8203
8368
|
}
|
|
8204
8369
|
]
|
|
8205
8370
|
},
|
|
@@ -8974,7 +9139,12 @@ var BITS = {
|
|
|
8974
9139
|
maxCount: Count.infinity
|
|
8975
9140
|
},
|
|
8976
9141
|
{
|
|
8977
|
-
// Override inherited @example from group_standardTags:
|
|
9142
|
+
// Override inherited @example from group_standardTags: emits both
|
|
9143
|
+
// `isExample` (bool) AND `example` (paragraph array). Declared as
|
|
9144
|
+
// bitmarkText because BPG `JsonGenerator.toExample` renders the
|
|
9145
|
+
// root-example value through the bit's textFormat (not this tag's
|
|
9146
|
+
// declared format) — `TagFormat.plainText` here would be ignored
|
|
9147
|
+
// at runtime and is misleading.
|
|
8978
9148
|
key: ConfigKey.property_example,
|
|
8979
9149
|
exportJsonKey: [
|
|
8980
9150
|
{ "@keyonly": { isExample: true, example: "true" } },
|
|
@@ -8982,7 +9152,7 @@ var BITS = {
|
|
|
8982
9152
|
{ isExample: true, example: "$" }
|
|
8983
9153
|
],
|
|
8984
9154
|
description: "The example text for the essay bit",
|
|
8985
|
-
format: TagFormat.
|
|
9155
|
+
format: TagFormat.bitmarkText,
|
|
8986
9156
|
nullable: true
|
|
8987
9157
|
}
|
|
8988
9158
|
],
|
|
@@ -10028,6 +10198,11 @@ var BITS = {
|
|
|
10028
10198
|
baseBitType: BitType._standard,
|
|
10029
10199
|
description: "Extractor rule bit, used to define extraction rules with reference images and instructions",
|
|
10030
10200
|
tags: [
|
|
10201
|
+
{
|
|
10202
|
+
exportJsonKey: { title: "$" },
|
|
10203
|
+
key: ConfigKey.tag_title,
|
|
10204
|
+
description: "The name of the extraction rule"
|
|
10205
|
+
},
|
|
10031
10206
|
{
|
|
10032
10207
|
key: ConfigKey.group_resourceBitTags,
|
|
10033
10208
|
description: "Resource bit tags for extraction rule images"
|
|
@@ -10344,11 +10519,36 @@ var BITS = {
|
|
|
10344
10519
|
],
|
|
10345
10520
|
cardSet: CardSetConfigKey.definitionList
|
|
10346
10521
|
},
|
|
10522
|
+
[BitType.definitionListCollapsible]: {
|
|
10523
|
+
since: "5.25.0",
|
|
10524
|
+
baseBitType: BitType.definitionList,
|
|
10525
|
+
description: "Collapsible definition list bit, used to create collapsible lists of definitions in articles or books"
|
|
10526
|
+
},
|
|
10527
|
+
[BitType.standardDefinitionListNormative]: {
|
|
10528
|
+
since: "5.24.0",
|
|
10529
|
+
baseBitType: BitType.definitionList,
|
|
10530
|
+
description: "Standard normative definition list bit, used to create normative standard definition lists in articles or books"
|
|
10531
|
+
},
|
|
10532
|
+
[BitType.standardDefinitionListNonNormative]: {
|
|
10533
|
+
since: "5.24.0",
|
|
10534
|
+
baseBitType: BitType.definitionList,
|
|
10535
|
+
description: "Standard non-normative definition list bit, used to create non-normative standard definition lists in articles or books"
|
|
10536
|
+
},
|
|
10537
|
+
[BitType.smartStandardDefinitionListNormative]: {
|
|
10538
|
+
since: "5.24.0",
|
|
10539
|
+
baseBitType: BitType.standardDefinitionListNormative,
|
|
10540
|
+
description: "Smart standard normative definition list bit, used to create normative smart standard definition lists in articles or books"
|
|
10541
|
+
},
|
|
10542
|
+
[BitType.smartStandardDefinitionListNonNormative]: {
|
|
10543
|
+
since: "5.24.0",
|
|
10544
|
+
baseBitType: BitType.standardDefinitionListNonNormative,
|
|
10545
|
+
description: "Smart standard non-normative definition list bit, used to create non-normative smart standard definition lists in articles or books"
|
|
10546
|
+
},
|
|
10347
10547
|
[BitType.metaSearchDefaultTerms]: {
|
|
10348
10548
|
since: "3.12.0",
|
|
10349
10549
|
baseBitType: BitType._standard,
|
|
10350
10550
|
description: "Meta search default terms bit, used to define default search terms in articles",
|
|
10351
|
-
cardSet: CardSetConfigKey.
|
|
10551
|
+
cardSet: CardSetConfigKey.definitionListPlain
|
|
10352
10552
|
},
|
|
10353
10553
|
[BitType.metaSearchDefaultTopics]: {
|
|
10354
10554
|
since: "3.12.0",
|
|
@@ -10392,7 +10592,11 @@ var BITS = {
|
|
|
10392
10592
|
[BitType.qAndACard]: {
|
|
10393
10593
|
since: "3.25.0",
|
|
10394
10594
|
baseBitType: BitType.flashcard1,
|
|
10395
|
-
description: "Q&A card bit, used to create question and answer cards in articles or books"
|
|
10595
|
+
description: "Q&A card bit, used to create question and answer cards in articles or books",
|
|
10596
|
+
// PLAN-085: q-and-a-card permits multiple cards (some fixtures carry
|
|
10597
|
+
// two). Override the inherited `flashcard1` (max=1) cardset back to
|
|
10598
|
+
// the unbounded `flashcard` cardset.
|
|
10599
|
+
cardSet: CardSetConfigKey.flashcard
|
|
10396
10600
|
},
|
|
10397
10601
|
[BitType.focusImage]: {
|
|
10398
10602
|
since: "1.3.0",
|
|
@@ -13478,7 +13682,7 @@ var instance2 = new Config();
|
|
|
13478
13682
|
// src/generated/package_info.ts
|
|
13479
13683
|
var PACKAGE_INFO = {
|
|
13480
13684
|
"name": "@gmb/bitmark-parser-generator",
|
|
13481
|
-
"version": "5.
|
|
13685
|
+
"version": "5.26.0",
|
|
13482
13686
|
"author": "Get More Brain Ltd",
|
|
13483
13687
|
"license": "ISC",
|
|
13484
13688
|
"description": "A bitmark parser and generator using Peggy.js"
|
|
@@ -14124,6 +14328,8 @@ var NodeType = {
|
|
|
14124
14328
|
internalPrintPdf: "internalPrintPdf",
|
|
14125
14329
|
internalPrintPdfValue: "internalPrintPdfValue",
|
|
14126
14330
|
isCaseSensitive: "isCaseSensitive",
|
|
14331
|
+
isCollapsible: "isCollapsible",
|
|
14332
|
+
isCollapsibleValue: "isCollapsibleValue",
|
|
14127
14333
|
isCommented: "isCommented",
|
|
14128
14334
|
isCorrect: "isCorrect",
|
|
14129
14335
|
isEditable: "isEditable",
|
|
@@ -28362,6 +28568,12 @@ var Builder = class extends BaseBuilder {
|
|
|
28362
28568
|
level: instance6.asNumber(data.level),
|
|
28363
28569
|
toc: this.toAstProperty(bitType, ConfigKey.property_toc, data.toc, options),
|
|
28364
28570
|
progress: this.toAstProperty(bitType, ConfigKey.property_progress, data.progress, options),
|
|
28571
|
+
isCollapsible: this.toAstProperty(
|
|
28572
|
+
bitType,
|
|
28573
|
+
ConfigKey.property_isCollapsible,
|
|
28574
|
+
data.isCollapsible,
|
|
28575
|
+
options
|
|
28576
|
+
),
|
|
28365
28577
|
anchor: data.anchor,
|
|
28366
28578
|
reference: data.reference,
|
|
28367
28579
|
referenceEnd: data.referenceEnd,
|
|
@@ -33908,6 +34120,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
|
|
|
33908
34120
|
if (instance2.isOfBitType(bitType, BitType.chapter)) {
|
|
33909
34121
|
if (bitJson.toc == null) bitJson.toc = true;
|
|
33910
34122
|
if (bitJson.progress == null) bitJson.progress = true;
|
|
34123
|
+
if (bitJson.isCollapsible == null) bitJson.isCollapsible = false;
|
|
33911
34124
|
if (bitJson.level == null) bitJson.level = 1;
|
|
33912
34125
|
if (bitJson.body == null) bitJson.body = this.bodyDefault;
|
|
33913
34126
|
}
|
|
@@ -36123,6 +36336,7 @@ function buildCards(context, bitType, textFormat, parsedCardSet, statementV1, st
|
|
|
36123
36336
|
case CardSetConfigKey.flashcard:
|
|
36124
36337
|
case CardSetConfigKey.flashcard1:
|
|
36125
36338
|
case CardSetConfigKey.definitionList:
|
|
36339
|
+
case CardSetConfigKey.definitionListPlain:
|
|
36126
36340
|
result = parseFlashcardOrDefinitionList(context, bitType, processedCardSet);
|
|
36127
36341
|
break;
|
|
36128
36342
|
case CardSetConfigKey.elements:
|
|
@@ -42459,6 +42673,235 @@ var BitmarkFileGenerator = class {
|
|
|
42459
42673
|
}
|
|
42460
42674
|
};
|
|
42461
42675
|
|
|
42676
|
+
// src/generator/html/HtmlTableGenerator.ts
|
|
42677
|
+
var MARK_TO_TAG = {
|
|
42678
|
+
bold: "b",
|
|
42679
|
+
italic: "i",
|
|
42680
|
+
superscript: "sup",
|
|
42681
|
+
subscript: "sub",
|
|
42682
|
+
strike: "s",
|
|
42683
|
+
del: "del",
|
|
42684
|
+
ins: "ins",
|
|
42685
|
+
underline: "u",
|
|
42686
|
+
highlight: "mark",
|
|
42687
|
+
code: "code"
|
|
42688
|
+
};
|
|
42689
|
+
var HtmlTableGenerator = class {
|
|
42690
|
+
constructor() {
|
|
42691
|
+
__publicField(this, "indentUnit", " ");
|
|
42692
|
+
}
|
|
42693
|
+
/**
|
|
42694
|
+
* Generate HTML table fragments from a string or JSON value.
|
|
42695
|
+
* @returns the concatenated `<table>` fragments, blank-line separated (empty string if none).
|
|
42696
|
+
*/
|
|
42697
|
+
generate(input) {
|
|
42698
|
+
let data = input;
|
|
42699
|
+
if (typeof data === "string") {
|
|
42700
|
+
try {
|
|
42701
|
+
data = JSON.parse(data);
|
|
42702
|
+
} catch {
|
|
42703
|
+
return "";
|
|
42704
|
+
}
|
|
42705
|
+
}
|
|
42706
|
+
const bits = this.collectBits(data);
|
|
42707
|
+
const fragments = [];
|
|
42708
|
+
for (const bit of bits) {
|
|
42709
|
+
const html = this.renderTableBit(bit);
|
|
42710
|
+
if (html) fragments.push(html);
|
|
42711
|
+
}
|
|
42712
|
+
return fragments.join("\n\n");
|
|
42713
|
+
}
|
|
42714
|
+
// --- bit collection -------------------------------------------------------
|
|
42715
|
+
collectBits(data) {
|
|
42716
|
+
const out = [];
|
|
42717
|
+
const visit = (value) => {
|
|
42718
|
+
if (value == null || typeof value !== "object") return;
|
|
42719
|
+
if (Array.isArray(value)) {
|
|
42720
|
+
value.forEach(visit);
|
|
42721
|
+
return;
|
|
42722
|
+
}
|
|
42723
|
+
const obj = value;
|
|
42724
|
+
if ("bit" in obj && obj.bit && typeof obj.bit === "object") {
|
|
42725
|
+
out.push(obj.bit);
|
|
42726
|
+
} else if ("type" in obj) {
|
|
42727
|
+
out.push(obj);
|
|
42728
|
+
}
|
|
42729
|
+
};
|
|
42730
|
+
visit(data);
|
|
42731
|
+
return out;
|
|
42732
|
+
}
|
|
42733
|
+
// --- table rendering ------------------------------------------------------
|
|
42734
|
+
renderTableBit(bit) {
|
|
42735
|
+
const table = bit.table;
|
|
42736
|
+
if (!table) return "";
|
|
42737
|
+
if (bit.type !== "table" && bit.type !== "table-extended") return "";
|
|
42738
|
+
const extended = this.toExtended(table);
|
|
42739
|
+
const lines = [];
|
|
42740
|
+
lines.push("<table>");
|
|
42741
|
+
if (bit.caption != null) {
|
|
42742
|
+
const caption = this.cellContentToHtml(this.asTextAst(bit.caption));
|
|
42743
|
+
if (caption) lines.push(`${this.indentUnit}<caption>${caption}</caption>`);
|
|
42744
|
+
}
|
|
42745
|
+
this.renderSection(lines, "thead", extended.header, "header");
|
|
42746
|
+
this.renderSection(lines, "tbody", extended.body, "body");
|
|
42747
|
+
this.renderSection(lines, "tfoot", extended.footer, "footer");
|
|
42748
|
+
lines.push("</table>");
|
|
42749
|
+
return lines.join("\n");
|
|
42750
|
+
}
|
|
42751
|
+
toExtended(table) {
|
|
42752
|
+
const t = table;
|
|
42753
|
+
if (t.header || t.body || t.footer) return table;
|
|
42754
|
+
return convertBasicToExtendedTableFormat(table);
|
|
42755
|
+
}
|
|
42756
|
+
renderSection(lines, tag, section, key) {
|
|
42757
|
+
if (!section || !section.rows || section.rows.length === 0) return;
|
|
42758
|
+
lines.push(`${this.indentUnit}<${tag}>`);
|
|
42759
|
+
for (const row of section.rows) {
|
|
42760
|
+
lines.push(`${this.indentUnit.repeat(2)}<tr>`);
|
|
42761
|
+
for (const cell of row.cells ?? []) {
|
|
42762
|
+
lines.push(`${this.indentUnit.repeat(3)}${this.renderCell(cell, key)}`);
|
|
42763
|
+
}
|
|
42764
|
+
lines.push(`${this.indentUnit.repeat(2)}</tr>`);
|
|
42765
|
+
}
|
|
42766
|
+
lines.push(`${this.indentUnit}</${tag}>`);
|
|
42767
|
+
}
|
|
42768
|
+
renderCell(cell, _key) {
|
|
42769
|
+
const tag = cell.title === true ? "th" : "td";
|
|
42770
|
+
const attrs = [];
|
|
42771
|
+
if (cell.rowspan && cell.rowspan > 1) attrs.push(`rowspan="${cell.rowspan}"`);
|
|
42772
|
+
if (cell.colspan && cell.colspan > 1) attrs.push(`colspan="${cell.colspan}"`);
|
|
42773
|
+
if (cell.scope) attrs.push(`scope="${cell.scope}"`);
|
|
42774
|
+
if (cell.colwidth && cell.colwidth > 0) attrs.push(`width="${cell.colwidth}"`);
|
|
42775
|
+
const open = attrs.length > 0 ? `<${tag} ${attrs.join(" ")}>` : `<${tag}>`;
|
|
42776
|
+
return `${open}${this.cellContentToHtml(this.asTextAst(cell.content))}</${tag}>`;
|
|
42777
|
+
}
|
|
42778
|
+
// --- cell content (TextAst -> HTML) ---------------------------------------
|
|
42779
|
+
asTextAst(content) {
|
|
42780
|
+
if (content == null) return [];
|
|
42781
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
42782
|
+
return content;
|
|
42783
|
+
}
|
|
42784
|
+
cellContentToHtml(blocks) {
|
|
42785
|
+
if (blocks.length === 0) return "";
|
|
42786
|
+
if (blocks.length === 1 && blocks[0].type === "paragraph") {
|
|
42787
|
+
return this.inlineToHtml(blocks[0].content ?? []);
|
|
42788
|
+
}
|
|
42789
|
+
return blocks.map((b) => this.blockToHtml(b)).join("");
|
|
42790
|
+
}
|
|
42791
|
+
blockToHtml(node) {
|
|
42792
|
+
switch (node.type) {
|
|
42793
|
+
case "paragraph":
|
|
42794
|
+
return `<p>${this.inlineToHtml(node.content ?? [])}</p>`;
|
|
42795
|
+
case "bulletList":
|
|
42796
|
+
case "noBulletList":
|
|
42797
|
+
case "orderedList":
|
|
42798
|
+
case "orderedListRoman":
|
|
42799
|
+
case "orderedListRomanLower":
|
|
42800
|
+
case "letteredList":
|
|
42801
|
+
case "letteredListLower":
|
|
42802
|
+
case "taskList":
|
|
42803
|
+
return this.listToHtml(node);
|
|
42804
|
+
case "image":
|
|
42805
|
+
case "imageInline":
|
|
42806
|
+
return this.imageToHtml(node);
|
|
42807
|
+
default:
|
|
42808
|
+
return this.inlineToHtml([node]);
|
|
42809
|
+
}
|
|
42810
|
+
}
|
|
42811
|
+
inlineToHtml(nodes) {
|
|
42812
|
+
return nodes.map((n) => this.inlineNodeToHtml(n)).join("");
|
|
42813
|
+
}
|
|
42814
|
+
inlineNodeToHtml(node) {
|
|
42815
|
+
if (node.type === "hardBreak") return "<br>";
|
|
42816
|
+
if (node.type === "image" || node.type === "imageInline") return this.imageToHtml(node);
|
|
42817
|
+
if (node.type === "text") {
|
|
42818
|
+
return this.wrapMarks(this.escapeText(node.text ?? ""), node.marks);
|
|
42819
|
+
}
|
|
42820
|
+
if (node.content) return this.inlineToHtml(node.content);
|
|
42821
|
+
return this.escapeText(node.text ?? "");
|
|
42822
|
+
}
|
|
42823
|
+
wrapMarks(text, marks) {
|
|
42824
|
+
if (!marks || marks.length === 0) return text;
|
|
42825
|
+
let open = "";
|
|
42826
|
+
let close = "";
|
|
42827
|
+
for (const mark of marks) {
|
|
42828
|
+
if (mark.type === "link") {
|
|
42829
|
+
const href = mark.attrs?.href ?? "";
|
|
42830
|
+
open += `<a href="${this.escapeAttr(href)}">`;
|
|
42831
|
+
close = `</a>${close}`;
|
|
42832
|
+
} else {
|
|
42833
|
+
const tag = MARK_TO_TAG[mark.type];
|
|
42834
|
+
if (tag) {
|
|
42835
|
+
open += `<${tag}>`;
|
|
42836
|
+
close = `</${tag}>${close}`;
|
|
42837
|
+
}
|
|
42838
|
+
}
|
|
42839
|
+
}
|
|
42840
|
+
return `${open}${text}${close}`;
|
|
42841
|
+
}
|
|
42842
|
+
// --- lists ----------------------------------------------------------------
|
|
42843
|
+
listToHtml(node) {
|
|
42844
|
+
const { tag, attrs } = this.listTag(node);
|
|
42845
|
+
const items = (node.content ?? []).map((item) => this.listItemToHtml(item, node.type === "taskList")).join("");
|
|
42846
|
+
return `<${tag}${attrs}>${items}</${tag}>`;
|
|
42847
|
+
}
|
|
42848
|
+
listTag(node) {
|
|
42849
|
+
const start = node.attrs?.start;
|
|
42850
|
+
const startAttr = typeof start === "number" && start !== 1 ? ` start="${start}"` : "";
|
|
42851
|
+
switch (node.type) {
|
|
42852
|
+
case "orderedList":
|
|
42853
|
+
return { tag: "ol", attrs: startAttr };
|
|
42854
|
+
case "orderedListRoman":
|
|
42855
|
+
return { tag: "ol", attrs: ` type="I"${startAttr}` };
|
|
42856
|
+
case "orderedListRomanLower":
|
|
42857
|
+
return { tag: "ol", attrs: ` type="i"${startAttr}` };
|
|
42858
|
+
case "letteredList":
|
|
42859
|
+
return { tag: "ol", attrs: ` type="A"${startAttr}` };
|
|
42860
|
+
case "letteredListLower":
|
|
42861
|
+
return { tag: "ol", attrs: ` type="a"${startAttr}` };
|
|
42862
|
+
case "noBulletList":
|
|
42863
|
+
return { tag: "ul", attrs: ' style="list-style:none"' };
|
|
42864
|
+
case "taskList":
|
|
42865
|
+
case "bulletList":
|
|
42866
|
+
default:
|
|
42867
|
+
return { tag: "ul", attrs: "" };
|
|
42868
|
+
}
|
|
42869
|
+
}
|
|
42870
|
+
listItemToHtml(item, task) {
|
|
42871
|
+
const inner = (item.content ?? []).map((b) => {
|
|
42872
|
+
if (b.type === "paragraph") return this.inlineToHtml(b.content ?? []);
|
|
42873
|
+
return this.blockToHtml(b);
|
|
42874
|
+
}).join("");
|
|
42875
|
+
if (task) {
|
|
42876
|
+
const checked = item.attrs?.checked ? " checked" : "";
|
|
42877
|
+
return `<li><input type="checkbox"${checked}>${inner}</li>`;
|
|
42878
|
+
}
|
|
42879
|
+
return `<li>${inner}</li>`;
|
|
42880
|
+
}
|
|
42881
|
+
// --- images ---------------------------------------------------------------
|
|
42882
|
+
imageToHtml(node) {
|
|
42883
|
+
const attrs = node.attrs ?? {};
|
|
42884
|
+
const parts = [];
|
|
42885
|
+
const src = attrs.src;
|
|
42886
|
+
parts.push(`src="${this.escapeAttr(typeof src === "string" ? src : "")}"`);
|
|
42887
|
+
if (typeof attrs.alt === "string") parts.push(`alt="${this.escapeAttr(attrs.alt)}"`);
|
|
42888
|
+
if (typeof attrs.title === "string") parts.push(`title="${this.escapeAttr(attrs.title)}"`);
|
|
42889
|
+
if (attrs.width != null) parts.push(`width="${attrs.width}"`);
|
|
42890
|
+
if (attrs.height != null) parts.push(`height="${attrs.height}"`);
|
|
42891
|
+
if (typeof attrs.class === "string" && attrs.class) {
|
|
42892
|
+
parts.push(`class="${this.escapeAttr(attrs.class)}"`);
|
|
42893
|
+
}
|
|
42894
|
+
return `<img ${parts.join(" ")}>`;
|
|
42895
|
+
}
|
|
42896
|
+
// --- escaping -------------------------------------------------------------
|
|
42897
|
+
escapeText(text) {
|
|
42898
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
42899
|
+
}
|
|
42900
|
+
escapeAttr(text) {
|
|
42901
|
+
return this.escapeText(text).replace(/"/g, """);
|
|
42902
|
+
}
|
|
42903
|
+
};
|
|
42904
|
+
|
|
42462
42905
|
// src/generator/json/JsonFileGenerator.ts
|
|
42463
42906
|
var import_node_fs4 = require("fs");
|
|
42464
42907
|
var JsonFileGenerator = class {
|
|
@@ -43435,6 +43878,499 @@ var ConfigBuilder = class {
|
|
|
43435
43878
|
}
|
|
43436
43879
|
};
|
|
43437
43880
|
|
|
43881
|
+
// src/parser/html/HtmlDom.ts
|
|
43882
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
43883
|
+
"area",
|
|
43884
|
+
"base",
|
|
43885
|
+
"br",
|
|
43886
|
+
"col",
|
|
43887
|
+
"embed",
|
|
43888
|
+
"hr",
|
|
43889
|
+
"img",
|
|
43890
|
+
"input",
|
|
43891
|
+
"link",
|
|
43892
|
+
"meta",
|
|
43893
|
+
"param",
|
|
43894
|
+
"source",
|
|
43895
|
+
"track",
|
|
43896
|
+
"wbr"
|
|
43897
|
+
]);
|
|
43898
|
+
var IMPLIED_CLOSE = {
|
|
43899
|
+
li: /* @__PURE__ */ new Set(["li"]),
|
|
43900
|
+
td: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43901
|
+
th: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43902
|
+
tr: /* @__PURE__ */ new Set(["td", "th", "tr"]),
|
|
43903
|
+
thead: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43904
|
+
tbody: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43905
|
+
tfoot: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43906
|
+
p: /* @__PURE__ */ new Set(["p"]),
|
|
43907
|
+
option: /* @__PURE__ */ new Set(["option"])
|
|
43908
|
+
};
|
|
43909
|
+
var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
|
|
43910
|
+
var ATTR_RE = /([a-zA-Z_:][a-zA-Z0-9:._-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
|
|
43911
|
+
function parseAttrs(raw) {
|
|
43912
|
+
const attrs = {};
|
|
43913
|
+
if (!raw) return attrs;
|
|
43914
|
+
ATTR_RE.lastIndex = 0;
|
|
43915
|
+
let m;
|
|
43916
|
+
while ((m = ATTR_RE.exec(raw)) !== null) {
|
|
43917
|
+
const name = m[1].toLowerCase();
|
|
43918
|
+
let value = m[2] ?? "";
|
|
43919
|
+
if (value.length >= 2 && (value[0] === '"' || value[0] === "'")) {
|
|
43920
|
+
value = value.slice(1, -1);
|
|
43921
|
+
}
|
|
43922
|
+
attrs[name] = value;
|
|
43923
|
+
}
|
|
43924
|
+
return attrs;
|
|
43925
|
+
}
|
|
43926
|
+
function stripNonContent(html) {
|
|
43927
|
+
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, "");
|
|
43928
|
+
}
|
|
43929
|
+
function tokenize(html) {
|
|
43930
|
+
const tokens = [];
|
|
43931
|
+
const clean = stripNonContent(html);
|
|
43932
|
+
TAG_RE.lastIndex = 0;
|
|
43933
|
+
let lastIndex = 0;
|
|
43934
|
+
let m;
|
|
43935
|
+
while ((m = TAG_RE.exec(clean)) !== null) {
|
|
43936
|
+
if (m.index > lastIndex) {
|
|
43937
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex, m.index) });
|
|
43938
|
+
}
|
|
43939
|
+
lastIndex = TAG_RE.lastIndex;
|
|
43940
|
+
const isClose = m[1] === "/";
|
|
43941
|
+
const name = m[2].toLowerCase();
|
|
43942
|
+
if (isClose) {
|
|
43943
|
+
tokens.push({ kind: "close", name });
|
|
43944
|
+
} else {
|
|
43945
|
+
tokens.push({
|
|
43946
|
+
kind: "open",
|
|
43947
|
+
name,
|
|
43948
|
+
attrs: parseAttrs(m[3]),
|
|
43949
|
+
selfClose: m[4] === "/"
|
|
43950
|
+
});
|
|
43951
|
+
}
|
|
43952
|
+
}
|
|
43953
|
+
if (lastIndex < clean.length) {
|
|
43954
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex) });
|
|
43955
|
+
}
|
|
43956
|
+
return tokens;
|
|
43957
|
+
}
|
|
43958
|
+
function parseHtml(html) {
|
|
43959
|
+
const root = { type: "element", name: "#root", attrs: {}, children: [] };
|
|
43960
|
+
const stack = [root];
|
|
43961
|
+
const top = () => stack[stack.length - 1];
|
|
43962
|
+
for (const token of tokenize(html)) {
|
|
43963
|
+
if (token.kind === "text") {
|
|
43964
|
+
if (token.text) top().children.push({ type: "text", value: token.text });
|
|
43965
|
+
continue;
|
|
43966
|
+
}
|
|
43967
|
+
if (token.kind === "open") {
|
|
43968
|
+
const name = token.name;
|
|
43969
|
+
const closes = IMPLIED_CLOSE[name];
|
|
43970
|
+
if (closes) {
|
|
43971
|
+
while (stack.length > 1 && closes.has(top().name)) stack.pop();
|
|
43972
|
+
}
|
|
43973
|
+
const el = {
|
|
43974
|
+
type: "element",
|
|
43975
|
+
name,
|
|
43976
|
+
attrs: token.attrs ?? {},
|
|
43977
|
+
children: []
|
|
43978
|
+
};
|
|
43979
|
+
top().children.push(el);
|
|
43980
|
+
if (!token.selfClose && !VOID_ELEMENTS.has(name)) {
|
|
43981
|
+
stack.push(el);
|
|
43982
|
+
}
|
|
43983
|
+
continue;
|
|
43984
|
+
}
|
|
43985
|
+
for (let i = stack.length - 1; i > 0; i--) {
|
|
43986
|
+
if (stack[i].name === token.name) {
|
|
43987
|
+
stack.length = i;
|
|
43988
|
+
break;
|
|
43989
|
+
}
|
|
43990
|
+
}
|
|
43991
|
+
}
|
|
43992
|
+
return root.children;
|
|
43993
|
+
}
|
|
43994
|
+
function childElements(el, names) {
|
|
43995
|
+
return el.children.filter((c) => c.type === "element" && names.has(c.name));
|
|
43996
|
+
}
|
|
43997
|
+
|
|
43998
|
+
// src/parser/html/HtmlTableParser.ts
|
|
43999
|
+
var MARK_TAGS = {
|
|
44000
|
+
b: "bold",
|
|
44001
|
+
strong: "bold",
|
|
44002
|
+
i: "italic",
|
|
44003
|
+
em: "italic",
|
|
44004
|
+
sup: "superscript",
|
|
44005
|
+
sub: "subscript",
|
|
44006
|
+
s: "strike",
|
|
44007
|
+
strike: "strike",
|
|
44008
|
+
del: "del",
|
|
44009
|
+
ins: "ins",
|
|
44010
|
+
u: "underline",
|
|
44011
|
+
mark: "highlight",
|
|
44012
|
+
code: "code"
|
|
44013
|
+
};
|
|
44014
|
+
var SECTION_TAGS = /* @__PURE__ */ new Set(["thead", "tbody", "tfoot"]);
|
|
44015
|
+
var ROW_TAGS = /* @__PURE__ */ new Set(["tr"]);
|
|
44016
|
+
var CELL_TAGS = /* @__PURE__ */ new Set(["td", "th"]);
|
|
44017
|
+
var LI_TAGS = /* @__PURE__ */ new Set(["li"]);
|
|
44018
|
+
var VALID_SCOPES = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
44019
|
+
var NAMED_ENTITIES = {
|
|
44020
|
+
amp: "&",
|
|
44021
|
+
lt: "<",
|
|
44022
|
+
gt: ">",
|
|
44023
|
+
quot: '"',
|
|
44024
|
+
apos: "'",
|
|
44025
|
+
nbsp: "\xA0"
|
|
44026
|
+
};
|
|
44027
|
+
function decodeEntities(text) {
|
|
44028
|
+
return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, (whole, body) => {
|
|
44029
|
+
if (body[0] === "#") {
|
|
44030
|
+
const code = body[1] === "x" || body[1] === "X" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);
|
|
44031
|
+
if (Number.isFinite(code) && code >= 0 && code <= 1114111) {
|
|
44032
|
+
try {
|
|
44033
|
+
return String.fromCodePoint(code);
|
|
44034
|
+
} catch {
|
|
44035
|
+
return whole;
|
|
44036
|
+
}
|
|
44037
|
+
}
|
|
44038
|
+
return whole;
|
|
44039
|
+
}
|
|
44040
|
+
return NAMED_ENTITIES[body] ?? whole;
|
|
44041
|
+
});
|
|
44042
|
+
}
|
|
44043
|
+
function intAttr(value) {
|
|
44044
|
+
if (value == null) return void 0;
|
|
44045
|
+
const n = Number.parseInt(value, 10);
|
|
44046
|
+
return Number.isInteger(n) ? n : void 0;
|
|
44047
|
+
}
|
|
44048
|
+
function isElement(node) {
|
|
44049
|
+
return node.type === "element";
|
|
44050
|
+
}
|
|
44051
|
+
var HtmlTableParser = class {
|
|
44052
|
+
constructor() {
|
|
44053
|
+
__publicField(this, "keepUnknownTags", false);
|
|
44054
|
+
}
|
|
44055
|
+
/**
|
|
44056
|
+
* Parse an HTML string and return one table bit per top-level `<table>`.
|
|
44057
|
+
*/
|
|
44058
|
+
parse(html, options) {
|
|
44059
|
+
this.keepUnknownTags = options?.keepUnknownTags ?? false;
|
|
44060
|
+
const tableFormat = options?.tableFormat ?? "table-extended";
|
|
44061
|
+
const onWarning = options?.onWarning;
|
|
44062
|
+
const tables = this.collectTopLevelTables(parseHtml(html));
|
|
44063
|
+
const bits = [];
|
|
44064
|
+
for (const table of tables) {
|
|
44065
|
+
const bit = this.tableToBit(table, tableFormat, onWarning);
|
|
44066
|
+
if (bit) bits.push(bit);
|
|
44067
|
+
}
|
|
44068
|
+
return bits;
|
|
44069
|
+
}
|
|
44070
|
+
// --- table extraction -----------------------------------------------------
|
|
44071
|
+
/** Collect every `<table>` element, NOT descending into nested tables. */
|
|
44072
|
+
collectTopLevelTables(nodes) {
|
|
44073
|
+
const tables = [];
|
|
44074
|
+
const visit = (node) => {
|
|
44075
|
+
if (!isElement(node)) return;
|
|
44076
|
+
if (node.name === "table") {
|
|
44077
|
+
tables.push(node);
|
|
44078
|
+
return;
|
|
44079
|
+
}
|
|
44080
|
+
node.children.forEach(visit);
|
|
44081
|
+
};
|
|
44082
|
+
nodes.forEach(visit);
|
|
44083
|
+
return tables;
|
|
44084
|
+
}
|
|
44085
|
+
tableToBit(table, tableFormat, onWarning) {
|
|
44086
|
+
const header = [];
|
|
44087
|
+
const body = [];
|
|
44088
|
+
const footer = [];
|
|
44089
|
+
let caption;
|
|
44090
|
+
for (const child of table.children) {
|
|
44091
|
+
if (!isElement(child)) continue;
|
|
44092
|
+
if (child.name === "caption") {
|
|
44093
|
+
const capContent = this.inlineNodes(child.children, []);
|
|
44094
|
+
const trimmed = this.trimInline(capContent);
|
|
44095
|
+
if (trimmed.length > 0) caption = trimmed;
|
|
44096
|
+
} else if (SECTION_TAGS.has(child.name)) {
|
|
44097
|
+
const target = child.name === "thead" ? header : child.name === "tfoot" ? footer : body;
|
|
44098
|
+
for (const tr of childElements(child, ROW_TAGS)) {
|
|
44099
|
+
target.push(this.rowToCells(tr));
|
|
44100
|
+
}
|
|
44101
|
+
} else if (ROW_TAGS.has(child.name)) {
|
|
44102
|
+
body.push(this.rowToCells(child));
|
|
44103
|
+
}
|
|
44104
|
+
}
|
|
44105
|
+
if (header.length === 0 && body.length === 0 && footer.length === 0) {
|
|
44106
|
+
return void 0;
|
|
44107
|
+
}
|
|
44108
|
+
const tableExtended = {};
|
|
44109
|
+
if (header.length > 0) tableExtended.header = { rows: header };
|
|
44110
|
+
if (body.length > 0) tableExtended.body = { rows: body };
|
|
44111
|
+
if (footer.length > 0) tableExtended.footer = { rows: footer };
|
|
44112
|
+
let tableData = tableExtended;
|
|
44113
|
+
if (tableFormat === "table") {
|
|
44114
|
+
if (this.isLossyAsBasic(tableExtended)) {
|
|
44115
|
+
onWarning?.(
|
|
44116
|
+
"Converting an HTML table to [.table] loses rowspan/colspan/scope and multi-section structure; use --tableFormat table-extended to preserve them."
|
|
44117
|
+
);
|
|
44118
|
+
}
|
|
44119
|
+
tableData = convertExtendedToBasicTableFormat(tableExtended);
|
|
44120
|
+
}
|
|
44121
|
+
const bit = {
|
|
44122
|
+
type: tableFormat,
|
|
44123
|
+
format: "bitmark++",
|
|
44124
|
+
table: tableData
|
|
44125
|
+
};
|
|
44126
|
+
if (caption) bit.caption = caption;
|
|
44127
|
+
return bit;
|
|
44128
|
+
}
|
|
44129
|
+
rowToCells(tr) {
|
|
44130
|
+
const cells = [];
|
|
44131
|
+
for (const cell of childElements(tr, CELL_TAGS)) {
|
|
44132
|
+
cells.push(this.cellToJson(cell));
|
|
44133
|
+
}
|
|
44134
|
+
return { cells };
|
|
44135
|
+
}
|
|
44136
|
+
cellToJson(cell) {
|
|
44137
|
+
const json = {
|
|
44138
|
+
content: this.blockNodes(cell.children)
|
|
44139
|
+
};
|
|
44140
|
+
if (cell.name === "th") json.title = true;
|
|
44141
|
+
const rowspan = intAttr(cell.attrs.rowspan);
|
|
44142
|
+
if (rowspan != null && rowspan >= 2) json.rowspan = rowspan;
|
|
44143
|
+
const colspan = intAttr(cell.attrs.colspan);
|
|
44144
|
+
if (colspan != null && colspan >= 2) json.colspan = colspan;
|
|
44145
|
+
const scope = cell.attrs.scope?.toLowerCase();
|
|
44146
|
+
if (scope && VALID_SCOPES.has(scope)) {
|
|
44147
|
+
json.scope = scope;
|
|
44148
|
+
}
|
|
44149
|
+
const width = this.widthFromCell(cell);
|
|
44150
|
+
if (width != null) json.colwidth = width;
|
|
44151
|
+
return json;
|
|
44152
|
+
}
|
|
44153
|
+
widthFromCell(cell) {
|
|
44154
|
+
const attrWidth = intAttr(cell.attrs.width);
|
|
44155
|
+
if (attrWidth != null && attrWidth > 0) return attrWidth;
|
|
44156
|
+
const style = cell.attrs.style;
|
|
44157
|
+
if (style) {
|
|
44158
|
+
const m = style.match(/width\s*:\s*(\d+)\s*px/i);
|
|
44159
|
+
if (m) {
|
|
44160
|
+
const n = Number.parseInt(m[1], 10);
|
|
44161
|
+
if (Number.isInteger(n) && n > 0) return n;
|
|
44162
|
+
}
|
|
44163
|
+
}
|
|
44164
|
+
return void 0;
|
|
44165
|
+
}
|
|
44166
|
+
isLossyAsBasic(table) {
|
|
44167
|
+
if (table.footer) return true;
|
|
44168
|
+
if (table.header && table.header.rows.length > 1) return true;
|
|
44169
|
+
const sections = [table.header, table.body, table.footer];
|
|
44170
|
+
for (const section of sections) {
|
|
44171
|
+
if (!section) continue;
|
|
44172
|
+
for (const row of section.rows) {
|
|
44173
|
+
for (const cell of row.cells) {
|
|
44174
|
+
if (cell.rowspan || cell.colspan || cell.scope) return true;
|
|
44175
|
+
}
|
|
44176
|
+
}
|
|
44177
|
+
}
|
|
44178
|
+
return false;
|
|
44179
|
+
}
|
|
44180
|
+
// --- content conversion (HTML -> TextAst) ---------------------------------
|
|
44181
|
+
/**
|
|
44182
|
+
* Convert a cell/li's child nodes into block-level TextAst nodes (paragraphs, lists, images).
|
|
44183
|
+
*/
|
|
44184
|
+
blockNodes(nodes) {
|
|
44185
|
+
const blocks = [];
|
|
44186
|
+
let inline = [];
|
|
44187
|
+
const flush = () => {
|
|
44188
|
+
const trimmed = this.trimInline(inline);
|
|
44189
|
+
inline = [];
|
|
44190
|
+
if (trimmed.length === 0) return;
|
|
44191
|
+
if (trimmed.length === 1 && trimmed[0].type === "imageInline") {
|
|
44192
|
+
blocks.push({ ...trimmed[0], type: "image" });
|
|
44193
|
+
} else {
|
|
44194
|
+
blocks.push({ type: "paragraph", content: trimmed, attrs: {} });
|
|
44195
|
+
}
|
|
44196
|
+
};
|
|
44197
|
+
for (const node of nodes) {
|
|
44198
|
+
if (!isElement(node)) {
|
|
44199
|
+
inline.push(...this.inlineText(node.value, []));
|
|
44200
|
+
continue;
|
|
44201
|
+
}
|
|
44202
|
+
const name = node.name;
|
|
44203
|
+
if (name === "p") {
|
|
44204
|
+
flush();
|
|
44205
|
+
const content = this.trimInline(this.inlineNodes(node.children, []));
|
|
44206
|
+
if (content.length > 0) {
|
|
44207
|
+
blocks.push({ type: "paragraph", content, attrs: {} });
|
|
44208
|
+
}
|
|
44209
|
+
} else if (this.isListTag(name)) {
|
|
44210
|
+
flush();
|
|
44211
|
+
const list = this.listNode(node);
|
|
44212
|
+
if (list) blocks.push(list);
|
|
44213
|
+
} else {
|
|
44214
|
+
inline.push(...this.inlineFromElement(node, []));
|
|
44215
|
+
}
|
|
44216
|
+
}
|
|
44217
|
+
flush();
|
|
44218
|
+
return blocks;
|
|
44219
|
+
}
|
|
44220
|
+
/** Convert child nodes to a flat list of inline TextNodes, applying the given marks. */
|
|
44221
|
+
inlineNodes(nodes, marks) {
|
|
44222
|
+
const out = [];
|
|
44223
|
+
for (const node of nodes) {
|
|
44224
|
+
if (!isElement(node)) {
|
|
44225
|
+
out.push(...this.inlineText(node.value, marks));
|
|
44226
|
+
} else {
|
|
44227
|
+
out.push(...this.inlineFromElement(node, marks));
|
|
44228
|
+
}
|
|
44229
|
+
}
|
|
44230
|
+
return out;
|
|
44231
|
+
}
|
|
44232
|
+
inlineFromElement(el, marks) {
|
|
44233
|
+
const name = el.name;
|
|
44234
|
+
if (name === "br") {
|
|
44235
|
+
return [{ type: "hardBreak" }];
|
|
44236
|
+
}
|
|
44237
|
+
if (name === "img") {
|
|
44238
|
+
return [this.imageNode(el, true)];
|
|
44239
|
+
}
|
|
44240
|
+
const markType = MARK_TAGS[name];
|
|
44241
|
+
if (markType) {
|
|
44242
|
+
return this.inlineNodes(el.children, [...marks, { type: markType }]);
|
|
44243
|
+
}
|
|
44244
|
+
if (name === "a") {
|
|
44245
|
+
const linkMark = {
|
|
44246
|
+
type: "link",
|
|
44247
|
+
attrs: {
|
|
44248
|
+
href: el.attrs.href ?? "",
|
|
44249
|
+
...el.attrs.target ? { target: el.attrs.target } : {}
|
|
44250
|
+
}
|
|
44251
|
+
};
|
|
44252
|
+
return this.inlineNodes(el.children, [...marks, linkMark]);
|
|
44253
|
+
}
|
|
44254
|
+
if (this.keepUnknownTags) {
|
|
44255
|
+
const open = this.serializeOpenTag(el);
|
|
44256
|
+
const close = `</${name}>`;
|
|
44257
|
+
return [
|
|
44258
|
+
...this.inlineText(open, marks),
|
|
44259
|
+
...this.inlineNodes(el.children, marks),
|
|
44260
|
+
...this.inlineText(close, marks)
|
|
44261
|
+
];
|
|
44262
|
+
}
|
|
44263
|
+
return this.inlineNodes(el.children, marks);
|
|
44264
|
+
}
|
|
44265
|
+
inlineText(raw, marks) {
|
|
44266
|
+
const text = decodeEntities(raw).replace(/\s+/g, " ");
|
|
44267
|
+
if (text === "") return [];
|
|
44268
|
+
const node = { text, type: "text" };
|
|
44269
|
+
if (marks.length > 0) node.marks = marks.map((m) => ({ ...m }));
|
|
44270
|
+
return [node];
|
|
44271
|
+
}
|
|
44272
|
+
serializeOpenTag(el) {
|
|
44273
|
+
const attrs = Object.entries(el.attrs).map(([k, v]) => v === "" ? ` ${k}` : ` ${k}="${v}"`).join("");
|
|
44274
|
+
return `<${el.name}${attrs}>`;
|
|
44275
|
+
}
|
|
44276
|
+
// --- lists ----------------------------------------------------------------
|
|
44277
|
+
isListTag(name) {
|
|
44278
|
+
return name === "ul" || name === "ol";
|
|
44279
|
+
}
|
|
44280
|
+
listNode(el) {
|
|
44281
|
+
const items = childElements(el, LI_TAGS);
|
|
44282
|
+
if (items.length === 0) return void 0;
|
|
44283
|
+
const isTask = el.name === "ul" && items.some((li) => {
|
|
44284
|
+
const firstEl = li.children.find(isElement);
|
|
44285
|
+
return firstEl?.name === "input" && firstEl.attrs.type?.toLowerCase() === "checkbox";
|
|
44286
|
+
});
|
|
44287
|
+
if (isTask) {
|
|
44288
|
+
return {
|
|
44289
|
+
type: "taskList",
|
|
44290
|
+
content: items.map((li) => this.taskItemNode(li))
|
|
44291
|
+
};
|
|
44292
|
+
}
|
|
44293
|
+
const type = this.listType(el);
|
|
44294
|
+
const node = {
|
|
44295
|
+
type,
|
|
44296
|
+
content: items.map((li) => this.listItemNode(li))
|
|
44297
|
+
};
|
|
44298
|
+
if (el.name === "ol") {
|
|
44299
|
+
const start = intAttr(el.attrs.start);
|
|
44300
|
+
if (start != null) {
|
|
44301
|
+
node.attrs = { start };
|
|
44302
|
+
}
|
|
44303
|
+
}
|
|
44304
|
+
return node;
|
|
44305
|
+
}
|
|
44306
|
+
listType(el) {
|
|
44307
|
+
if (el.name === "ol") {
|
|
44308
|
+
switch (el.attrs.type) {
|
|
44309
|
+
case "i":
|
|
44310
|
+
return "orderedListRomanLower";
|
|
44311
|
+
case "I":
|
|
44312
|
+
return "orderedListRoman";
|
|
44313
|
+
case "a":
|
|
44314
|
+
return "letteredListLower";
|
|
44315
|
+
case "A":
|
|
44316
|
+
return "letteredList";
|
|
44317
|
+
default:
|
|
44318
|
+
return "orderedList";
|
|
44319
|
+
}
|
|
44320
|
+
}
|
|
44321
|
+
const style = el.attrs.style ?? "";
|
|
44322
|
+
if (/list-style(-type)?\s*:\s*none/i.test(style)) return "noBulletList";
|
|
44323
|
+
return "bulletList";
|
|
44324
|
+
}
|
|
44325
|
+
listItemNode(li) {
|
|
44326
|
+
let content = this.blockNodes(li.children);
|
|
44327
|
+
if (content.length === 0) {
|
|
44328
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
44329
|
+
}
|
|
44330
|
+
return { type: "listItem", content };
|
|
44331
|
+
}
|
|
44332
|
+
taskItemNode(li) {
|
|
44333
|
+
const checkbox = li.children.find(
|
|
44334
|
+
(c) => isElement(c) && c.name === "input" && c.attrs.type?.toLowerCase() === "checkbox"
|
|
44335
|
+
);
|
|
44336
|
+
const checked = checkbox ? "checked" in checkbox.attrs : false;
|
|
44337
|
+
const rest = li.children.filter((c) => c !== checkbox);
|
|
44338
|
+
let content = this.blockNodes(rest);
|
|
44339
|
+
if (content.length === 0) {
|
|
44340
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
44341
|
+
}
|
|
44342
|
+
return { type: "taskItem", attrs: { checked }, content };
|
|
44343
|
+
}
|
|
44344
|
+
// --- images ---------------------------------------------------------------
|
|
44345
|
+
imageNode(el, inline) {
|
|
44346
|
+
const attrs = { src: el.attrs.src ?? "" };
|
|
44347
|
+
attrs.alt = el.attrs.alt ?? null;
|
|
44348
|
+
attrs.title = el.attrs.title ?? null;
|
|
44349
|
+
const width = intAttr(el.attrs.width);
|
|
44350
|
+
if (width != null) attrs.width = width;
|
|
44351
|
+
const height = intAttr(el.attrs.height);
|
|
44352
|
+
if (height != null) attrs.height = height;
|
|
44353
|
+
if (el.attrs.class) attrs.class = el.attrs.class;
|
|
44354
|
+
return { type: inline ? "imageInline" : "image", attrs };
|
|
44355
|
+
}
|
|
44356
|
+
// --- whitespace -----------------------------------------------------------
|
|
44357
|
+
/** Trim leading/trailing whitespace from inline content (edges only). */
|
|
44358
|
+
trimInline(nodes) {
|
|
44359
|
+
const out = nodes.slice();
|
|
44360
|
+
const isWs = (n) => n.type === "text" && /^\s*$/.test(n.text ?? "");
|
|
44361
|
+
while (out.length > 0 && isWs(out[0])) out.shift();
|
|
44362
|
+
if (out.length > 0 && out[0].type === "text") {
|
|
44363
|
+
out[0] = { ...out[0], text: (out[0].text ?? "").replace(/^\s+/, "") };
|
|
44364
|
+
}
|
|
44365
|
+
while (out.length > 0 && isWs(out[out.length - 1])) out.pop();
|
|
44366
|
+
if (out.length > 0 && out[out.length - 1].type === "text") {
|
|
44367
|
+
const last = out.length - 1;
|
|
44368
|
+
out[last] = { ...out[last], text: (out[last].text ?? "").replace(/\s+$/, "") };
|
|
44369
|
+
}
|
|
44370
|
+
return out.filter((n) => !(n.type === "text" && n.text === ""));
|
|
44371
|
+
}
|
|
44372
|
+
};
|
|
44373
|
+
|
|
43438
44374
|
// src/BitmarkParserGenerator.ts
|
|
43439
44375
|
var Input = {
|
|
43440
44376
|
/**
|
|
@@ -43476,7 +44412,11 @@ var InputFormat = {
|
|
|
43476
44412
|
/**
|
|
43477
44413
|
* Input is plain text
|
|
43478
44414
|
*/
|
|
43479
|
-
plainText: "plainText"
|
|
44415
|
+
plainText: "plainText",
|
|
44416
|
+
/**
|
|
44417
|
+
* Input is HTML (used by convertHtmlTable)
|
|
44418
|
+
*/
|
|
44419
|
+
html: "html"
|
|
43480
44420
|
};
|
|
43481
44421
|
var BitmarkParserGenerator = class {
|
|
43482
44422
|
constructor() {
|
|
@@ -44011,6 +44951,87 @@ var BitmarkParserGenerator = class {
|
|
|
44011
44951
|
const res = generator.generate(data);
|
|
44012
44952
|
return res;
|
|
44013
44953
|
}
|
|
44954
|
+
/**
|
|
44955
|
+
* Convert between HTML tables and bitmark tables.
|
|
44956
|
+
*
|
|
44957
|
+
* Direction is auto-detected (override with `options.inputFormat`):
|
|
44958
|
+
* - HTML input: every `<table>` is extracted and emitted as a `[.table-extended]` (or `[.table]`)
|
|
44959
|
+
* bit; output as bitmark (default), JSON, AST, or HTML (re-emit).
|
|
44960
|
+
* - bitmark / JSON / AST input: each `table` / `table-extended` bit is rendered as an HTML
|
|
44961
|
+
* `<table>` fragment.
|
|
44962
|
+
*
|
|
44963
|
+
* Cell content is reproduced verbatim except inline conversion to bitmark marks (bold, italic,
|
|
44964
|
+
* superscript, etc.), with lists and images mapped to their bitmark equivalents.
|
|
44965
|
+
*
|
|
44966
|
+
* @param input - HTML, bitmark, JSON or AST string; or a parsed JSON/AST value; or a file path.
|
|
44967
|
+
* @param options - the conversion options
|
|
44968
|
+
* @returns the converted output as a string (or object for JSON/AST), or void when writing a file
|
|
44969
|
+
* @throws Error if any error occurs
|
|
44970
|
+
*/
|
|
44971
|
+
convertHtmlTable(input, options) {
|
|
44972
|
+
const opts = Object.assign({}, options);
|
|
44973
|
+
if (env.isBrowser && opts.outputFile) {
|
|
44974
|
+
throw new Error("Cannot write to file in browser environment");
|
|
44975
|
+
}
|
|
44976
|
+
let inStr = input;
|
|
44977
|
+
const inputIsString = typeof input === "string";
|
|
44978
|
+
if (env.isNode && inputIsString && import_fs_extra4.default.existsSync(inStr)) {
|
|
44979
|
+
inStr = import_fs_extra4.default.readFileSync(inStr, { encoding: "utf8" });
|
|
44980
|
+
}
|
|
44981
|
+
const isHtmlString = (s) => {
|
|
44982
|
+
const t = s.replace(/^\s+/, "");
|
|
44983
|
+
return t.startsWith("<") && /<table/i.test(t);
|
|
44984
|
+
};
|
|
44985
|
+
let htmlInput;
|
|
44986
|
+
if (opts.inputFormat === InputFormat.html) {
|
|
44987
|
+
htmlInput = true;
|
|
44988
|
+
} else if (opts.inputFormat != null) {
|
|
44989
|
+
htmlInput = false;
|
|
44990
|
+
} else {
|
|
44991
|
+
htmlInput = inputIsString && isHtmlString(inStr);
|
|
44992
|
+
}
|
|
44993
|
+
if (htmlInput) {
|
|
44994
|
+
const parser2 = new HtmlTableParser();
|
|
44995
|
+
const bits = parser2.parse(inStr, {
|
|
44996
|
+
tableFormat: opts.tableFormat ?? "table-extended",
|
|
44997
|
+
keepUnknownTags: opts.keepUnknownTags,
|
|
44998
|
+
onWarning: (m) => console.warn(m)
|
|
44999
|
+
});
|
|
45000
|
+
const outputFormat2 = opts.outputFormat ?? Output.bitmark;
|
|
45001
|
+
if (outputFormat2 === "html") {
|
|
45002
|
+
const json2 = this.convert(bits, { outputFormat: Output.json });
|
|
45003
|
+
return this.outputHtml(new HtmlTableGenerator().generate(json2), opts);
|
|
45004
|
+
}
|
|
45005
|
+
return this.convert(bits, {
|
|
45006
|
+
outputFormat: (0, import_superenum51.Enum)(Output).fromValue(outputFormat2),
|
|
45007
|
+
outputFile: opts.outputFile,
|
|
45008
|
+
fileOptions: opts.fileOptions,
|
|
45009
|
+
jsonOptions: opts.jsonOptions,
|
|
45010
|
+
bitmarkOptions: opts.bitmarkOptions
|
|
45011
|
+
});
|
|
45012
|
+
}
|
|
45013
|
+
const outputFormat = opts.outputFormat ?? "html";
|
|
45014
|
+
if (outputFormat !== "html") {
|
|
45015
|
+
throw new Error(
|
|
45016
|
+
"convertHtmlTable: non-HTML input can only be converted to HTML. Use convert() for bitmark/JSON/AST conversions."
|
|
45017
|
+
);
|
|
45018
|
+
}
|
|
45019
|
+
const json = this.convert(inputIsString ? inStr : input, { outputFormat: Output.json });
|
|
45020
|
+
return this.outputHtml(new HtmlTableGenerator().generate(json), opts);
|
|
45021
|
+
}
|
|
45022
|
+
/**
|
|
45023
|
+
* Write an HTML string to the configured output file, or return it.
|
|
45024
|
+
*/
|
|
45025
|
+
outputHtml(html, opts) {
|
|
45026
|
+
if (opts.outputFile) {
|
|
45027
|
+
const output = opts.outputFile.toString();
|
|
45028
|
+
const flag = opts.fileOptions?.append ? "a" : "w";
|
|
45029
|
+
import_fs_extra4.default.ensureDirSync(import_node_path4.default.dirname(output));
|
|
45030
|
+
import_fs_extra4.default.writeFileSync(output, html, { flag });
|
|
45031
|
+
return;
|
|
45032
|
+
}
|
|
45033
|
+
return html;
|
|
45034
|
+
}
|
|
44014
45035
|
/**
|
|
44015
45036
|
* Breakscape bitmark text.
|
|
44016
45037
|
*
|
|
@@ -44307,6 +45328,8 @@ init();
|
|
|
44307
45328
|
Builder,
|
|
44308
45329
|
CardSetVersion,
|
|
44309
45330
|
FileWriter,
|
|
45331
|
+
HtmlTableGenerator,
|
|
45332
|
+
HtmlTableParser,
|
|
44310
45333
|
InfoFormat,
|
|
44311
45334
|
InfoType,
|
|
44312
45335
|
Input,
|