@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
|
@@ -34,6 +34,8 @@ __export(index_exports, {
|
|
|
34
34
|
BoundingBoxIndex: () => BoundingBoxIndex,
|
|
35
35
|
Builder: () => Builder,
|
|
36
36
|
CardSetVersion: () => CardSetVersion,
|
|
37
|
+
HtmlTableGenerator: () => HtmlTableGenerator2,
|
|
38
|
+
HtmlTableParser: () => HtmlTableParser2,
|
|
37
39
|
InfoFormat: () => InfoFormat,
|
|
38
40
|
InfoType: () => InfoType,
|
|
39
41
|
Input: () => Input,
|
|
@@ -279,6 +281,7 @@ var BitType2 = {
|
|
|
279
281
|
dangerAlt: "danger-alt",
|
|
280
282
|
dangerCollapsible: "danger-collapsible",
|
|
281
283
|
definitionList: "definition-list",
|
|
284
|
+
definitionListCollapsible: "definition-list-collapsible",
|
|
282
285
|
definitionTerm: "definition-term",
|
|
283
286
|
deleted: "deleted",
|
|
284
287
|
details: "details",
|
|
@@ -559,6 +562,8 @@ var BitType2 = {
|
|
|
559
562
|
smartStandardArticleNonNormativeCollapsible: "smart-standard-article-non-normative-collapsible",
|
|
560
563
|
smartStandardArticleNormative: "smart-standard-article-normative",
|
|
561
564
|
smartStandardArticleNormativeCollapsible: "smart-standard-article-normative-collapsible",
|
|
565
|
+
smartStandardDefinitionListNonNormative: "smart-standard-definition-list-non-normative",
|
|
566
|
+
smartStandardDefinitionListNormative: "smart-standard-definition-list-normative",
|
|
562
567
|
smartStandardExampleNonNormative: "smart-standard-example-non-normative",
|
|
563
568
|
smartStandardExampleNonNormativeCollapsible: "smart-standard-example-non-normative-collapsible",
|
|
564
569
|
smartStandardExampleNormative: "smart-standard-example-normative",
|
|
@@ -609,6 +614,8 @@ var BitType2 = {
|
|
|
609
614
|
smartStandardTableNormativeCollapsible: "smart-standard-table-normative-collapsible",
|
|
610
615
|
standardArticleNonNormative: "standard-article-non-normative",
|
|
611
616
|
standardArticleNormative: "standard-article-normative",
|
|
617
|
+
standardDefinitionListNonNormative: "standard-definition-list-non-normative",
|
|
618
|
+
standardDefinitionListNormative: "standard-definition-list-normative",
|
|
612
619
|
standardExampleNonNormative: "standard-example-non-normative",
|
|
613
620
|
standardExampleNormative: "standard-example-normative",
|
|
614
621
|
standardImageFigureNonNormative: "standard-image-figure-non-normative",
|
|
@@ -780,6 +787,7 @@ var CardSetConfigKey = {
|
|
|
780
787
|
flashcard: "flashcard",
|
|
781
788
|
flashcard1: "flashcard1",
|
|
782
789
|
definitionList: "definitionList",
|
|
790
|
+
definitionListPlain: "definitionListPlain",
|
|
783
791
|
elements: "elements",
|
|
784
792
|
statements: "statements",
|
|
785
793
|
quiz: "quiz",
|
|
@@ -1393,6 +1401,7 @@ var propertyKeys = {
|
|
|
1393
1401
|
property_enforceUpdateOverUserInput: "@enforceUpdateOverUserInput",
|
|
1394
1402
|
property_extractorExtractionTimestamp: "@extractorExtractionTimestamp",
|
|
1395
1403
|
property_isCaseSensitive: "@isCaseSensitive",
|
|
1404
|
+
property_isCollapsible: "@isCollapsible",
|
|
1396
1405
|
property_isInfoOnly: "@isInfoOnly",
|
|
1397
1406
|
property_isPublic: "@isPublic",
|
|
1398
1407
|
property_isTemplate: "@isTemplate",
|
|
@@ -2597,6 +2606,126 @@ var CARDSETS = {
|
|
|
2597
2606
|
]
|
|
2598
2607
|
},
|
|
2599
2608
|
//
|
|
2609
|
+
// definition-list-plain
|
|
2610
|
+
//
|
|
2611
|
+
// Same shape as `definitionList`, but every variant body is rendered as
|
|
2612
|
+
// plain text (string), not bitmark+ AST. Used by
|
|
2613
|
+
// `meta-search-default-terms` / `meta-search-default-topics`, which need
|
|
2614
|
+
// term/definition text emitted verbatim instead of as a ProseMirror tree.
|
|
2615
|
+
//
|
|
2616
|
+
[CardSetConfigKey.definitionListPlain]: {
|
|
2617
|
+
jsonKey: "definitions",
|
|
2618
|
+
exportJsonKey: { definitions: "$" },
|
|
2619
|
+
sides: [
|
|
2620
|
+
{
|
|
2621
|
+
name: "term",
|
|
2622
|
+
variants: [
|
|
2623
|
+
{
|
|
2624
|
+
jsonKey: "term.text",
|
|
2625
|
+
exportJsonKey: [{ "@absent": { term: {} } }, { term: { text: "$" } }],
|
|
2626
|
+
format: TextFormat2.plainText,
|
|
2627
|
+
tags: [
|
|
2628
|
+
{
|
|
2629
|
+
key: ConfigKey.group_standardTags,
|
|
2630
|
+
description: "Standard tags for the definition."
|
|
2631
|
+
},
|
|
2632
|
+
{
|
|
2633
|
+
key: ConfigKey.tag_title,
|
|
2634
|
+
description: "Title of the definition.",
|
|
2635
|
+
format: TagFormat.plainText,
|
|
2636
|
+
jsonKey: "^heading.forKeys",
|
|
2637
|
+
exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
|
|
2638
|
+
},
|
|
2639
|
+
{
|
|
2640
|
+
key: ConfigKey.group_resourceIcon,
|
|
2641
|
+
description: "Icon resource for the definition.",
|
|
2642
|
+
format: TagFormat.plainText,
|
|
2643
|
+
jsonKey: "term.icon|resource(type=image, key=image)",
|
|
2644
|
+
exportJsonKey: { term: { icon: { type: "image", image: { src: "$" } } } }
|
|
2645
|
+
},
|
|
2646
|
+
{
|
|
2647
|
+
key: ConfigKey.property_example,
|
|
2648
|
+
exportJsonKey: [
|
|
2649
|
+
{ "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2650
|
+
{ "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2651
|
+
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
2652
|
+
],
|
|
2653
|
+
description: "Example marker for the definition term.",
|
|
2654
|
+
format: TagFormat.bitmarkText,
|
|
2655
|
+
nullable: true
|
|
2656
|
+
}
|
|
2657
|
+
]
|
|
2658
|
+
}
|
|
2659
|
+
]
|
|
2660
|
+
},
|
|
2661
|
+
{
|
|
2662
|
+
name: "definition",
|
|
2663
|
+
variants: [
|
|
2664
|
+
{
|
|
2665
|
+
jsonKey: "definition.text",
|
|
2666
|
+
exportJsonKey: [{ "@absent": { definition: {} } }, { definition: { text: "$" } }],
|
|
2667
|
+
format: TextFormat2.plainText,
|
|
2668
|
+
tags: [
|
|
2669
|
+
{
|
|
2670
|
+
key: ConfigKey.group_standardTags,
|
|
2671
|
+
description: "Standard tags for the definition."
|
|
2672
|
+
},
|
|
2673
|
+
{
|
|
2674
|
+
key: ConfigKey.tag_title,
|
|
2675
|
+
description: "Title of the definition.",
|
|
2676
|
+
format: TagFormat.plainText,
|
|
2677
|
+
jsonKey: "^heading.forValues",
|
|
2678
|
+
exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
|
|
2679
|
+
},
|
|
2680
|
+
{
|
|
2681
|
+
key: ConfigKey.group_resourceIcon,
|
|
2682
|
+
description: "Icon resource for the definition.",
|
|
2683
|
+
jsonKey: "definition.icon|resource(type=image, key=image)",
|
|
2684
|
+
exportJsonKey: { definition: { icon: { type: "image", image: { src: "$" } } } }
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
key: ConfigKey.property_example,
|
|
2688
|
+
exportJsonKey: [
|
|
2689
|
+
{ "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2690
|
+
{ "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2691
|
+
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
2692
|
+
],
|
|
2693
|
+
description: "Example marker for the definition.",
|
|
2694
|
+
format: TagFormat.bitmarkText,
|
|
2695
|
+
nullable: true
|
|
2696
|
+
}
|
|
2697
|
+
]
|
|
2698
|
+
},
|
|
2699
|
+
{
|
|
2700
|
+
jsonKey: "alternativeDefinitions[].text",
|
|
2701
|
+
exportJsonKey: { alternativeDefinitions: [{ text: "$" }] },
|
|
2702
|
+
format: TextFormat2.plainText,
|
|
2703
|
+
tags: [
|
|
2704
|
+
{
|
|
2705
|
+
key: ConfigKey.group_standardTags,
|
|
2706
|
+
description: "Standard tags for the definition."
|
|
2707
|
+
},
|
|
2708
|
+
{
|
|
2709
|
+
exportJsonKey: { title: "$" },
|
|
2710
|
+
key: ConfigKey.tag_title,
|
|
2711
|
+
description: "Title of the definition."
|
|
2712
|
+
},
|
|
2713
|
+
{
|
|
2714
|
+
key: ConfigKey.group_resourceIcon,
|
|
2715
|
+
description: "Icon resource for the definition.",
|
|
2716
|
+
jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)",
|
|
2717
|
+
exportJsonKey: {
|
|
2718
|
+
alternativeDefinitions: [{ icon: { type: "image", image: { src: "$" } } }]
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
],
|
|
2722
|
+
repeatCount: Count.infinity
|
|
2723
|
+
}
|
|
2724
|
+
]
|
|
2725
|
+
}
|
|
2726
|
+
]
|
|
2727
|
+
},
|
|
2728
|
+
//
|
|
2600
2729
|
// match-pairs
|
|
2601
2730
|
//
|
|
2602
2731
|
[CardSetConfigKey.matchPairs]: {
|
|
@@ -3534,12 +3663,29 @@ var CARDSETS = {
|
|
|
3534
3663
|
// ALIGN-EXAMPLE-CASCADE §3.10: `questions` is NOT in BPG's
|
|
3535
3664
|
// `pushExampleDownTree` dispatch — bit-header `[@example]`
|
|
3536
3665
|
// does not propagate `example`/`isExample` onto question
|
|
3537
|
-
// entries. Only entry-local `[@example]` fires
|
|
3538
|
-
//
|
|
3539
|
-
//
|
|
3666
|
+
// entries. Only entry-local `[@example]` fires.
|
|
3667
|
+
//
|
|
3668
|
+
// BPG's `BaseBuilder.toExample` for interview questions
|
|
3669
|
+
// (Builder.ts:2575,2588) uses `data.__sampleSolutionAst`
|
|
3670
|
+
// as `defaultExample` — bare `[@example]` (which sets
|
|
3671
|
+
// `__isDefaultExample=true, example=undefined`) emits the
|
|
3672
|
+
// parsed sample-solution AST in the `example` slot. The
|
|
3673
|
+
// `@keyonly` rule mirrors that runtime behaviour via
|
|
3674
|
+
// `$parent.sampleSolution` — the chain-walker's post-walk
|
|
3675
|
+
// retry resolves this once the sibling `[@sampleSolution]`
|
|
3676
|
+
// chain has merged into the shared scope (interview's
|
|
3677
|
+
// `[@example]` typically precedes `[@sampleSolution]` in
|
|
3678
|
+
// source). Format coercion turns the resolved string
|
|
3679
|
+
// value into a PM tree.
|
|
3540
3680
|
key: ConfigKey.property_example,
|
|
3541
3681
|
exportJsonKey: [
|
|
3542
|
-
{
|
|
3682
|
+
{
|
|
3683
|
+
"@keyonly": {
|
|
3684
|
+
isExample: true,
|
|
3685
|
+
example: "$parent.sampleSolution",
|
|
3686
|
+
"@bit": { isExample: true }
|
|
3687
|
+
}
|
|
3688
|
+
},
|
|
3543
3689
|
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
3544
3690
|
],
|
|
3545
3691
|
description: "Example marker for the question (entry-local only; no bit-header cascade).",
|
|
@@ -5362,7 +5508,11 @@ var GROUPS = {
|
|
|
5362
5508
|
{
|
|
5363
5509
|
key: ConfigKey.property_mark,
|
|
5364
5510
|
jsonKey: "marks.mark",
|
|
5365
|
-
|
|
5511
|
+
// `emphasis: 'underline'` is the per-entry default for mark
|
|
5512
|
+
// configs — mirrors the hardcoded default in BPG
|
|
5513
|
+
// `MarkConfigChainContentProcessor.ts:55-58`. Chained
|
|
5514
|
+
// `[@emphasis:…]` overrides via deep-merge into `marks[-1]`.
|
|
5515
|
+
exportJsonKey: { marks: [{ mark: "$", emphasis: "underline" }] },
|
|
5366
5516
|
description: "The mark configuration",
|
|
5367
5517
|
format: TagFormat.plainText,
|
|
5368
5518
|
maxCount: Count.infinity,
|
|
@@ -5404,13 +5554,22 @@ var GROUPS = {
|
|
|
5404
5554
|
{
|
|
5405
5555
|
key: ConfigKey.property_example,
|
|
5406
5556
|
jsonKey: "example",
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5557
|
+
// Per-mark `@example` is a boolean toggle. BPG's runtime
|
|
5558
|
+
// `ExampleTagContentProcessor.handleDefaultOnlyExample`
|
|
5559
|
+
// (lines 147-161) normalises ANY `[@example]` or
|
|
5560
|
+
// `[@example:V]` on a mark body-bit to
|
|
5561
|
+
// `__isDefaultExample=true, example=undefined`; the
|
|
5562
|
+
// downstream `toExample(_, _, defaultExample=true)` in
|
|
5563
|
+
// `BaseBuilder.ts:80-87` then emits `example: true`
|
|
5564
|
+
// regardless of source. Declare a single unconditional
|
|
5565
|
+
// boolean-shape rule so the exported schema matches that
|
|
5566
|
+
// runtime semantic instead of the misleading `example: $`
|
|
5567
|
+
// shape (which would only fire if `handleDefaultOnlyExample`
|
|
5568
|
+
// were removed). `@bit: {isExample: true}` cascades the
|
|
5569
|
+
// marker — but NOT the `example` value — to bit root.
|
|
5570
|
+
exportJsonKey: { isExample: true, example: true, "@bit": { isExample: true } },
|
|
5412
5571
|
description: "An example for the marked content",
|
|
5413
|
-
format: TagFormat.
|
|
5572
|
+
format: TagFormat.boolean,
|
|
5414
5573
|
nullable: true
|
|
5415
5574
|
}
|
|
5416
5575
|
]
|
|
@@ -8186,6 +8345,12 @@ var BITS = {
|
|
|
8186
8345
|
description: "The progress of the chapter, used for tracking reading progress",
|
|
8187
8346
|
format: TagFormat.boolean,
|
|
8188
8347
|
defaultValue: "true"
|
|
8348
|
+
},
|
|
8349
|
+
{
|
|
8350
|
+
key: ConfigKey.property_isCollapsible,
|
|
8351
|
+
description: "If true, the chapter is collapsible",
|
|
8352
|
+
format: TagFormat.boolean,
|
|
8353
|
+
defaultValue: "false"
|
|
8189
8354
|
}
|
|
8190
8355
|
]
|
|
8191
8356
|
},
|
|
@@ -8960,7 +9125,12 @@ var BITS = {
|
|
|
8960
9125
|
maxCount: Count.infinity
|
|
8961
9126
|
},
|
|
8962
9127
|
{
|
|
8963
|
-
// Override inherited @example from group_standardTags:
|
|
9128
|
+
// Override inherited @example from group_standardTags: emits both
|
|
9129
|
+
// `isExample` (bool) AND `example` (paragraph array). Declared as
|
|
9130
|
+
// bitmarkText because BPG `JsonGenerator.toExample` renders the
|
|
9131
|
+
// root-example value through the bit's textFormat (not this tag's
|
|
9132
|
+
// declared format) — `TagFormat.plainText` here would be ignored
|
|
9133
|
+
// at runtime and is misleading.
|
|
8964
9134
|
key: ConfigKey.property_example,
|
|
8965
9135
|
exportJsonKey: [
|
|
8966
9136
|
{ "@keyonly": { isExample: true, example: "true" } },
|
|
@@ -8968,7 +9138,7 @@ var BITS = {
|
|
|
8968
9138
|
{ isExample: true, example: "$" }
|
|
8969
9139
|
],
|
|
8970
9140
|
description: "The example text for the essay bit",
|
|
8971
|
-
format: TagFormat.
|
|
9141
|
+
format: TagFormat.bitmarkText,
|
|
8972
9142
|
nullable: true
|
|
8973
9143
|
}
|
|
8974
9144
|
],
|
|
@@ -10014,6 +10184,11 @@ var BITS = {
|
|
|
10014
10184
|
baseBitType: BitType2._standard,
|
|
10015
10185
|
description: "Extractor rule bit, used to define extraction rules with reference images and instructions",
|
|
10016
10186
|
tags: [
|
|
10187
|
+
{
|
|
10188
|
+
exportJsonKey: { title: "$" },
|
|
10189
|
+
key: ConfigKey.tag_title,
|
|
10190
|
+
description: "The name of the extraction rule"
|
|
10191
|
+
},
|
|
10017
10192
|
{
|
|
10018
10193
|
key: ConfigKey.group_resourceBitTags,
|
|
10019
10194
|
description: "Resource bit tags for extraction rule images"
|
|
@@ -10330,11 +10505,36 @@ var BITS = {
|
|
|
10330
10505
|
],
|
|
10331
10506
|
cardSet: CardSetConfigKey.definitionList
|
|
10332
10507
|
},
|
|
10508
|
+
[BitType2.definitionListCollapsible]: {
|
|
10509
|
+
since: "5.25.0",
|
|
10510
|
+
baseBitType: BitType2.definitionList,
|
|
10511
|
+
description: "Collapsible definition list bit, used to create collapsible lists of definitions in articles or books"
|
|
10512
|
+
},
|
|
10513
|
+
[BitType2.standardDefinitionListNormative]: {
|
|
10514
|
+
since: "5.24.0",
|
|
10515
|
+
baseBitType: BitType2.definitionList,
|
|
10516
|
+
description: "Standard normative definition list bit, used to create normative standard definition lists in articles or books"
|
|
10517
|
+
},
|
|
10518
|
+
[BitType2.standardDefinitionListNonNormative]: {
|
|
10519
|
+
since: "5.24.0",
|
|
10520
|
+
baseBitType: BitType2.definitionList,
|
|
10521
|
+
description: "Standard non-normative definition list bit, used to create non-normative standard definition lists in articles or books"
|
|
10522
|
+
},
|
|
10523
|
+
[BitType2.smartStandardDefinitionListNormative]: {
|
|
10524
|
+
since: "5.24.0",
|
|
10525
|
+
baseBitType: BitType2.standardDefinitionListNormative,
|
|
10526
|
+
description: "Smart standard normative definition list bit, used to create normative smart standard definition lists in articles or books"
|
|
10527
|
+
},
|
|
10528
|
+
[BitType2.smartStandardDefinitionListNonNormative]: {
|
|
10529
|
+
since: "5.24.0",
|
|
10530
|
+
baseBitType: BitType2.standardDefinitionListNonNormative,
|
|
10531
|
+
description: "Smart standard non-normative definition list bit, used to create non-normative smart standard definition lists in articles or books"
|
|
10532
|
+
},
|
|
10333
10533
|
[BitType2.metaSearchDefaultTerms]: {
|
|
10334
10534
|
since: "3.12.0",
|
|
10335
10535
|
baseBitType: BitType2._standard,
|
|
10336
10536
|
description: "Meta search default terms bit, used to define default search terms in articles",
|
|
10337
|
-
cardSet: CardSetConfigKey.
|
|
10537
|
+
cardSet: CardSetConfigKey.definitionListPlain
|
|
10338
10538
|
},
|
|
10339
10539
|
[BitType2.metaSearchDefaultTopics]: {
|
|
10340
10540
|
since: "3.12.0",
|
|
@@ -10378,7 +10578,11 @@ var BITS = {
|
|
|
10378
10578
|
[BitType2.qAndACard]: {
|
|
10379
10579
|
since: "3.25.0",
|
|
10380
10580
|
baseBitType: BitType2.flashcard1,
|
|
10381
|
-
description: "Q&A card bit, used to create question and answer cards in articles or books"
|
|
10581
|
+
description: "Q&A card bit, used to create question and answer cards in articles or books",
|
|
10582
|
+
// PLAN-085: q-and-a-card permits multiple cards (some fixtures carry
|
|
10583
|
+
// two). Override the inherited `flashcard1` (max=1) cardset back to
|
|
10584
|
+
// the unbounded `flashcard` cardset.
|
|
10585
|
+
cardSet: CardSetConfigKey.flashcard
|
|
10382
10586
|
},
|
|
10383
10587
|
[BitType2.focusImage]: {
|
|
10384
10588
|
since: "1.3.0",
|
|
@@ -13464,7 +13668,7 @@ var instance2 = new Config();
|
|
|
13464
13668
|
// src/generated/package_info.ts
|
|
13465
13669
|
var PACKAGE_INFO = {
|
|
13466
13670
|
"name": "@gmb/bitmark-parser-generator",
|
|
13467
|
-
"version": "5.
|
|
13671
|
+
"version": "5.26.0",
|
|
13468
13672
|
"author": "Get More Brain Ltd",
|
|
13469
13673
|
"license": "ISC",
|
|
13470
13674
|
"description": "A bitmark parser and generator using Peggy.js"
|
|
@@ -14110,6 +14314,8 @@ var NodeType = {
|
|
|
14110
14314
|
internalPrintPdf: "internalPrintPdf",
|
|
14111
14315
|
internalPrintPdfValue: "internalPrintPdfValue",
|
|
14112
14316
|
isCaseSensitive: "isCaseSensitive",
|
|
14317
|
+
isCollapsible: "isCollapsible",
|
|
14318
|
+
isCollapsibleValue: "isCollapsibleValue",
|
|
14113
14319
|
isCommented: "isCommented",
|
|
14114
14320
|
isCorrect: "isCorrect",
|
|
14115
14321
|
isEditable: "isEditable",
|
|
@@ -28348,6 +28554,12 @@ var Builder = class extends BaseBuilder {
|
|
|
28348
28554
|
level: instance6.asNumber(data.level),
|
|
28349
28555
|
toc: this.toAstProperty(bitType, ConfigKey.property_toc, data.toc, options),
|
|
28350
28556
|
progress: this.toAstProperty(bitType, ConfigKey.property_progress, data.progress, options),
|
|
28557
|
+
isCollapsible: this.toAstProperty(
|
|
28558
|
+
bitType,
|
|
28559
|
+
ConfigKey.property_isCollapsible,
|
|
28560
|
+
data.isCollapsible,
|
|
28561
|
+
options
|
|
28562
|
+
),
|
|
28351
28563
|
anchor: data.anchor,
|
|
28352
28564
|
reference: data.reference,
|
|
28353
28565
|
referenceEnd: data.referenceEnd,
|
|
@@ -33894,6 +34106,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
|
|
|
33894
34106
|
if (instance2.isOfBitType(bitType, BitType2.chapter)) {
|
|
33895
34107
|
if (bitJson.toc == null) bitJson.toc = true;
|
|
33896
34108
|
if (bitJson.progress == null) bitJson.progress = true;
|
|
34109
|
+
if (bitJson.isCollapsible == null) bitJson.isCollapsible = false;
|
|
33897
34110
|
if (bitJson.level == null) bitJson.level = 1;
|
|
33898
34111
|
if (bitJson.body == null) bitJson.body = this.bodyDefault;
|
|
33899
34112
|
}
|
|
@@ -36091,6 +36304,7 @@ function buildCards(context, bitType, textFormat, parsedCardSet, statementV1, st
|
|
|
36091
36304
|
case CardSetConfigKey.flashcard:
|
|
36092
36305
|
case CardSetConfigKey.flashcard1:
|
|
36093
36306
|
case CardSetConfigKey.definitionList:
|
|
36307
|
+
case CardSetConfigKey.definitionListPlain:
|
|
36094
36308
|
result = parseFlashcardOrDefinitionList(context, bitType, processedCardSet);
|
|
36095
36309
|
break;
|
|
36096
36310
|
case CardSetConfigKey.elements:
|
|
@@ -42157,7 +42371,11 @@ var InputFormat = {
|
|
|
42157
42371
|
/**
|
|
42158
42372
|
* Input is plain text
|
|
42159
42373
|
*/
|
|
42160
|
-
plainText: "plainText"
|
|
42374
|
+
plainText: "plainText",
|
|
42375
|
+
/**
|
|
42376
|
+
* Input is HTML (used by convertHtmlTable)
|
|
42377
|
+
*/
|
|
42378
|
+
html: "html"
|
|
42161
42379
|
};
|
|
42162
42380
|
var BitmarkParserGenerator = class {
|
|
42163
42381
|
constructor() {
|
|
@@ -42692,6 +42910,87 @@ var BitmarkParserGenerator = class {
|
|
|
42692
42910
|
const res = generator.generate(data);
|
|
42693
42911
|
return res;
|
|
42694
42912
|
}
|
|
42913
|
+
/**
|
|
42914
|
+
* Convert between HTML tables and bitmark tables.
|
|
42915
|
+
*
|
|
42916
|
+
* Direction is auto-detected (override with `options.inputFormat`):
|
|
42917
|
+
* - HTML input: every `<table>` is extracted and emitted as a `[.table-extended]` (or `[.table]`)
|
|
42918
|
+
* bit; output as bitmark (default), JSON, AST, or HTML (re-emit).
|
|
42919
|
+
* - bitmark / JSON / AST input: each `table` / `table-extended` bit is rendered as an HTML
|
|
42920
|
+
* `<table>` fragment.
|
|
42921
|
+
*
|
|
42922
|
+
* Cell content is reproduced verbatim except inline conversion to bitmark marks (bold, italic,
|
|
42923
|
+
* superscript, etc.), with lists and images mapped to their bitmark equivalents.
|
|
42924
|
+
*
|
|
42925
|
+
* @param input - HTML, bitmark, JSON or AST string; or a parsed JSON/AST value; or a file path.
|
|
42926
|
+
* @param options - the conversion options
|
|
42927
|
+
* @returns the converted output as a string (or object for JSON/AST), or void when writing a file
|
|
42928
|
+
* @throws Error if any error occurs
|
|
42929
|
+
*/
|
|
42930
|
+
convertHtmlTable(input, options) {
|
|
42931
|
+
const opts = Object.assign({}, options);
|
|
42932
|
+
if (env.isBrowser && opts.outputFile) {
|
|
42933
|
+
throw new Error("Cannot write to file in browser environment");
|
|
42934
|
+
}
|
|
42935
|
+
let inStr = input;
|
|
42936
|
+
const inputIsString = typeof input === "string";
|
|
42937
|
+
if (env.isNode && inputIsString && fs.existsSync(inStr)) {
|
|
42938
|
+
inStr = fs.readFileSync(inStr, { encoding: "utf8" });
|
|
42939
|
+
}
|
|
42940
|
+
const isHtmlString = (s) => {
|
|
42941
|
+
const t = s.replace(/^\s+/, "");
|
|
42942
|
+
return t.startsWith("<") && /<table/i.test(t);
|
|
42943
|
+
};
|
|
42944
|
+
let htmlInput;
|
|
42945
|
+
if (opts.inputFormat === InputFormat.html) {
|
|
42946
|
+
htmlInput = true;
|
|
42947
|
+
} else if (opts.inputFormat != null) {
|
|
42948
|
+
htmlInput = false;
|
|
42949
|
+
} else {
|
|
42950
|
+
htmlInput = inputIsString && isHtmlString(inStr);
|
|
42951
|
+
}
|
|
42952
|
+
if (htmlInput) {
|
|
42953
|
+
const parser2 = new HtmlTableParser();
|
|
42954
|
+
const bits = parser2.parse(inStr, {
|
|
42955
|
+
tableFormat: opts.tableFormat ?? "table-extended",
|
|
42956
|
+
keepUnknownTags: opts.keepUnknownTags,
|
|
42957
|
+
onWarning: (m) => console.warn(m)
|
|
42958
|
+
});
|
|
42959
|
+
const outputFormat2 = opts.outputFormat ?? Output.bitmark;
|
|
42960
|
+
if (outputFormat2 === "html") {
|
|
42961
|
+
const json2 = this.convert(bits, { outputFormat: Output.json });
|
|
42962
|
+
return this.outputHtml(new HtmlTableGenerator().generate(json2), opts);
|
|
42963
|
+
}
|
|
42964
|
+
return this.convert(bits, {
|
|
42965
|
+
outputFormat: (0, import_superenum50.Enum)(Output).fromValue(outputFormat2),
|
|
42966
|
+
outputFile: opts.outputFile,
|
|
42967
|
+
fileOptions: opts.fileOptions,
|
|
42968
|
+
jsonOptions: opts.jsonOptions,
|
|
42969
|
+
bitmarkOptions: opts.bitmarkOptions
|
|
42970
|
+
});
|
|
42971
|
+
}
|
|
42972
|
+
const outputFormat = opts.outputFormat ?? "html";
|
|
42973
|
+
if (outputFormat !== "html") {
|
|
42974
|
+
throw new Error(
|
|
42975
|
+
"convertHtmlTable: non-HTML input can only be converted to HTML. Use convert() for bitmark/JSON/AST conversions."
|
|
42976
|
+
);
|
|
42977
|
+
}
|
|
42978
|
+
const json = this.convert(inputIsString ? inStr : input, { outputFormat: Output.json });
|
|
42979
|
+
return this.outputHtml(new HtmlTableGenerator().generate(json), opts);
|
|
42980
|
+
}
|
|
42981
|
+
/**
|
|
42982
|
+
* Write an HTML string to the configured output file, or return it.
|
|
42983
|
+
*/
|
|
42984
|
+
outputHtml(html, opts) {
|
|
42985
|
+
if (opts.outputFile) {
|
|
42986
|
+
const output = opts.outputFile.toString();
|
|
42987
|
+
const flag = opts.fileOptions?.append ? "a" : "w";
|
|
42988
|
+
fs.ensureDirSync(path.dirname(output));
|
|
42989
|
+
fs.writeFileSync(output, html, { flag });
|
|
42990
|
+
return;
|
|
42991
|
+
}
|
|
42992
|
+
return html;
|
|
42993
|
+
}
|
|
42695
42994
|
/**
|
|
42696
42995
|
* Breakscape bitmark text.
|
|
42697
42996
|
*
|
|
@@ -42970,6 +43269,728 @@ var BoundingBoxIndex = class _BoundingBoxIndex {
|
|
|
42970
43269
|
}
|
|
42971
43270
|
};
|
|
42972
43271
|
|
|
43272
|
+
// src/generator/html/HtmlTableGenerator.ts
|
|
43273
|
+
var MARK_TO_TAG = {
|
|
43274
|
+
bold: "b",
|
|
43275
|
+
italic: "i",
|
|
43276
|
+
superscript: "sup",
|
|
43277
|
+
subscript: "sub",
|
|
43278
|
+
strike: "s",
|
|
43279
|
+
del: "del",
|
|
43280
|
+
ins: "ins",
|
|
43281
|
+
underline: "u",
|
|
43282
|
+
highlight: "mark",
|
|
43283
|
+
code: "code"
|
|
43284
|
+
};
|
|
43285
|
+
var HtmlTableGenerator2 = class {
|
|
43286
|
+
constructor() {
|
|
43287
|
+
__publicField(this, "indentUnit", " ");
|
|
43288
|
+
}
|
|
43289
|
+
/**
|
|
43290
|
+
* Generate HTML table fragments from a string or JSON value.
|
|
43291
|
+
* @returns the concatenated `<table>` fragments, blank-line separated (empty string if none).
|
|
43292
|
+
*/
|
|
43293
|
+
generate(input) {
|
|
43294
|
+
let data = input;
|
|
43295
|
+
if (typeof data === "string") {
|
|
43296
|
+
try {
|
|
43297
|
+
data = JSON.parse(data);
|
|
43298
|
+
} catch {
|
|
43299
|
+
return "";
|
|
43300
|
+
}
|
|
43301
|
+
}
|
|
43302
|
+
const bits = this.collectBits(data);
|
|
43303
|
+
const fragments = [];
|
|
43304
|
+
for (const bit of bits) {
|
|
43305
|
+
const html = this.renderTableBit(bit);
|
|
43306
|
+
if (html) fragments.push(html);
|
|
43307
|
+
}
|
|
43308
|
+
return fragments.join("\n\n");
|
|
43309
|
+
}
|
|
43310
|
+
// --- bit collection -------------------------------------------------------
|
|
43311
|
+
collectBits(data) {
|
|
43312
|
+
const out = [];
|
|
43313
|
+
const visit = (value) => {
|
|
43314
|
+
if (value == null || typeof value !== "object") return;
|
|
43315
|
+
if (Array.isArray(value)) {
|
|
43316
|
+
value.forEach(visit);
|
|
43317
|
+
return;
|
|
43318
|
+
}
|
|
43319
|
+
const obj = value;
|
|
43320
|
+
if ("bit" in obj && obj.bit && typeof obj.bit === "object") {
|
|
43321
|
+
out.push(obj.bit);
|
|
43322
|
+
} else if ("type" in obj) {
|
|
43323
|
+
out.push(obj);
|
|
43324
|
+
}
|
|
43325
|
+
};
|
|
43326
|
+
visit(data);
|
|
43327
|
+
return out;
|
|
43328
|
+
}
|
|
43329
|
+
// --- table rendering ------------------------------------------------------
|
|
43330
|
+
renderTableBit(bit) {
|
|
43331
|
+
const table = bit.table;
|
|
43332
|
+
if (!table) return "";
|
|
43333
|
+
if (bit.type !== "table" && bit.type !== "table-extended") return "";
|
|
43334
|
+
const extended = this.toExtended(table);
|
|
43335
|
+
const lines = [];
|
|
43336
|
+
lines.push("<table>");
|
|
43337
|
+
if (bit.caption != null) {
|
|
43338
|
+
const caption = this.cellContentToHtml(this.asTextAst(bit.caption));
|
|
43339
|
+
if (caption) lines.push(`${this.indentUnit}<caption>${caption}</caption>`);
|
|
43340
|
+
}
|
|
43341
|
+
this.renderSection(lines, "thead", extended.header, "header");
|
|
43342
|
+
this.renderSection(lines, "tbody", extended.body, "body");
|
|
43343
|
+
this.renderSection(lines, "tfoot", extended.footer, "footer");
|
|
43344
|
+
lines.push("</table>");
|
|
43345
|
+
return lines.join("\n");
|
|
43346
|
+
}
|
|
43347
|
+
toExtended(table) {
|
|
43348
|
+
const t = table;
|
|
43349
|
+
if (t.header || t.body || t.footer) return table;
|
|
43350
|
+
return convertBasicToExtendedTableFormat(table);
|
|
43351
|
+
}
|
|
43352
|
+
renderSection(lines, tag, section, key) {
|
|
43353
|
+
if (!section || !section.rows || section.rows.length === 0) return;
|
|
43354
|
+
lines.push(`${this.indentUnit}<${tag}>`);
|
|
43355
|
+
for (const row of section.rows) {
|
|
43356
|
+
lines.push(`${this.indentUnit.repeat(2)}<tr>`);
|
|
43357
|
+
for (const cell of row.cells ?? []) {
|
|
43358
|
+
lines.push(`${this.indentUnit.repeat(3)}${this.renderCell(cell, key)}`);
|
|
43359
|
+
}
|
|
43360
|
+
lines.push(`${this.indentUnit.repeat(2)}</tr>`);
|
|
43361
|
+
}
|
|
43362
|
+
lines.push(`${this.indentUnit}</${tag}>`);
|
|
43363
|
+
}
|
|
43364
|
+
renderCell(cell, _key) {
|
|
43365
|
+
const tag = cell.title === true ? "th" : "td";
|
|
43366
|
+
const attrs = [];
|
|
43367
|
+
if (cell.rowspan && cell.rowspan > 1) attrs.push(`rowspan="${cell.rowspan}"`);
|
|
43368
|
+
if (cell.colspan && cell.colspan > 1) attrs.push(`colspan="${cell.colspan}"`);
|
|
43369
|
+
if (cell.scope) attrs.push(`scope="${cell.scope}"`);
|
|
43370
|
+
if (cell.colwidth && cell.colwidth > 0) attrs.push(`width="${cell.colwidth}"`);
|
|
43371
|
+
const open = attrs.length > 0 ? `<${tag} ${attrs.join(" ")}>` : `<${tag}>`;
|
|
43372
|
+
return `${open}${this.cellContentToHtml(this.asTextAst(cell.content))}</${tag}>`;
|
|
43373
|
+
}
|
|
43374
|
+
// --- cell content (TextAst -> HTML) ---------------------------------------
|
|
43375
|
+
asTextAst(content) {
|
|
43376
|
+
if (content == null) return [];
|
|
43377
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
43378
|
+
return content;
|
|
43379
|
+
}
|
|
43380
|
+
cellContentToHtml(blocks) {
|
|
43381
|
+
if (blocks.length === 0) return "";
|
|
43382
|
+
if (blocks.length === 1 && blocks[0].type === "paragraph") {
|
|
43383
|
+
return this.inlineToHtml(blocks[0].content ?? []);
|
|
43384
|
+
}
|
|
43385
|
+
return blocks.map((b) => this.blockToHtml(b)).join("");
|
|
43386
|
+
}
|
|
43387
|
+
blockToHtml(node) {
|
|
43388
|
+
switch (node.type) {
|
|
43389
|
+
case "paragraph":
|
|
43390
|
+
return `<p>${this.inlineToHtml(node.content ?? [])}</p>`;
|
|
43391
|
+
case "bulletList":
|
|
43392
|
+
case "noBulletList":
|
|
43393
|
+
case "orderedList":
|
|
43394
|
+
case "orderedListRoman":
|
|
43395
|
+
case "orderedListRomanLower":
|
|
43396
|
+
case "letteredList":
|
|
43397
|
+
case "letteredListLower":
|
|
43398
|
+
case "taskList":
|
|
43399
|
+
return this.listToHtml(node);
|
|
43400
|
+
case "image":
|
|
43401
|
+
case "imageInline":
|
|
43402
|
+
return this.imageToHtml(node);
|
|
43403
|
+
default:
|
|
43404
|
+
return this.inlineToHtml([node]);
|
|
43405
|
+
}
|
|
43406
|
+
}
|
|
43407
|
+
inlineToHtml(nodes) {
|
|
43408
|
+
return nodes.map((n) => this.inlineNodeToHtml(n)).join("");
|
|
43409
|
+
}
|
|
43410
|
+
inlineNodeToHtml(node) {
|
|
43411
|
+
if (node.type === "hardBreak") return "<br>";
|
|
43412
|
+
if (node.type === "image" || node.type === "imageInline") return this.imageToHtml(node);
|
|
43413
|
+
if (node.type === "text") {
|
|
43414
|
+
return this.wrapMarks(this.escapeText(node.text ?? ""), node.marks);
|
|
43415
|
+
}
|
|
43416
|
+
if (node.content) return this.inlineToHtml(node.content);
|
|
43417
|
+
return this.escapeText(node.text ?? "");
|
|
43418
|
+
}
|
|
43419
|
+
wrapMarks(text, marks) {
|
|
43420
|
+
if (!marks || marks.length === 0) return text;
|
|
43421
|
+
let open = "";
|
|
43422
|
+
let close = "";
|
|
43423
|
+
for (const mark of marks) {
|
|
43424
|
+
if (mark.type === "link") {
|
|
43425
|
+
const href = mark.attrs?.href ?? "";
|
|
43426
|
+
open += `<a href="${this.escapeAttr(href)}">`;
|
|
43427
|
+
close = `</a>${close}`;
|
|
43428
|
+
} else {
|
|
43429
|
+
const tag = MARK_TO_TAG[mark.type];
|
|
43430
|
+
if (tag) {
|
|
43431
|
+
open += `<${tag}>`;
|
|
43432
|
+
close = `</${tag}>${close}`;
|
|
43433
|
+
}
|
|
43434
|
+
}
|
|
43435
|
+
}
|
|
43436
|
+
return `${open}${text}${close}`;
|
|
43437
|
+
}
|
|
43438
|
+
// --- lists ----------------------------------------------------------------
|
|
43439
|
+
listToHtml(node) {
|
|
43440
|
+
const { tag, attrs } = this.listTag(node);
|
|
43441
|
+
const items = (node.content ?? []).map((item) => this.listItemToHtml(item, node.type === "taskList")).join("");
|
|
43442
|
+
return `<${tag}${attrs}>${items}</${tag}>`;
|
|
43443
|
+
}
|
|
43444
|
+
listTag(node) {
|
|
43445
|
+
const start = node.attrs?.start;
|
|
43446
|
+
const startAttr = typeof start === "number" && start !== 1 ? ` start="${start}"` : "";
|
|
43447
|
+
switch (node.type) {
|
|
43448
|
+
case "orderedList":
|
|
43449
|
+
return { tag: "ol", attrs: startAttr };
|
|
43450
|
+
case "orderedListRoman":
|
|
43451
|
+
return { tag: "ol", attrs: ` type="I"${startAttr}` };
|
|
43452
|
+
case "orderedListRomanLower":
|
|
43453
|
+
return { tag: "ol", attrs: ` type="i"${startAttr}` };
|
|
43454
|
+
case "letteredList":
|
|
43455
|
+
return { tag: "ol", attrs: ` type="A"${startAttr}` };
|
|
43456
|
+
case "letteredListLower":
|
|
43457
|
+
return { tag: "ol", attrs: ` type="a"${startAttr}` };
|
|
43458
|
+
case "noBulletList":
|
|
43459
|
+
return { tag: "ul", attrs: ' style="list-style:none"' };
|
|
43460
|
+
case "taskList":
|
|
43461
|
+
case "bulletList":
|
|
43462
|
+
default:
|
|
43463
|
+
return { tag: "ul", attrs: "" };
|
|
43464
|
+
}
|
|
43465
|
+
}
|
|
43466
|
+
listItemToHtml(item, task) {
|
|
43467
|
+
const inner = (item.content ?? []).map((b) => {
|
|
43468
|
+
if (b.type === "paragraph") return this.inlineToHtml(b.content ?? []);
|
|
43469
|
+
return this.blockToHtml(b);
|
|
43470
|
+
}).join("");
|
|
43471
|
+
if (task) {
|
|
43472
|
+
const checked = item.attrs?.checked ? " checked" : "";
|
|
43473
|
+
return `<li><input type="checkbox"${checked}>${inner}</li>`;
|
|
43474
|
+
}
|
|
43475
|
+
return `<li>${inner}</li>`;
|
|
43476
|
+
}
|
|
43477
|
+
// --- images ---------------------------------------------------------------
|
|
43478
|
+
imageToHtml(node) {
|
|
43479
|
+
const attrs = node.attrs ?? {};
|
|
43480
|
+
const parts = [];
|
|
43481
|
+
const src = attrs.src;
|
|
43482
|
+
parts.push(`src="${this.escapeAttr(typeof src === "string" ? src : "")}"`);
|
|
43483
|
+
if (typeof attrs.alt === "string") parts.push(`alt="${this.escapeAttr(attrs.alt)}"`);
|
|
43484
|
+
if (typeof attrs.title === "string") parts.push(`title="${this.escapeAttr(attrs.title)}"`);
|
|
43485
|
+
if (attrs.width != null) parts.push(`width="${attrs.width}"`);
|
|
43486
|
+
if (attrs.height != null) parts.push(`height="${attrs.height}"`);
|
|
43487
|
+
if (typeof attrs.class === "string" && attrs.class) {
|
|
43488
|
+
parts.push(`class="${this.escapeAttr(attrs.class)}"`);
|
|
43489
|
+
}
|
|
43490
|
+
return `<img ${parts.join(" ")}>`;
|
|
43491
|
+
}
|
|
43492
|
+
// --- escaping -------------------------------------------------------------
|
|
43493
|
+
escapeText(text) {
|
|
43494
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
43495
|
+
}
|
|
43496
|
+
escapeAttr(text) {
|
|
43497
|
+
return this.escapeText(text).replace(/"/g, """);
|
|
43498
|
+
}
|
|
43499
|
+
};
|
|
43500
|
+
|
|
43501
|
+
// src/parser/html/HtmlDom.ts
|
|
43502
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
43503
|
+
"area",
|
|
43504
|
+
"base",
|
|
43505
|
+
"br",
|
|
43506
|
+
"col",
|
|
43507
|
+
"embed",
|
|
43508
|
+
"hr",
|
|
43509
|
+
"img",
|
|
43510
|
+
"input",
|
|
43511
|
+
"link",
|
|
43512
|
+
"meta",
|
|
43513
|
+
"param",
|
|
43514
|
+
"source",
|
|
43515
|
+
"track",
|
|
43516
|
+
"wbr"
|
|
43517
|
+
]);
|
|
43518
|
+
var IMPLIED_CLOSE = {
|
|
43519
|
+
li: /* @__PURE__ */ new Set(["li"]),
|
|
43520
|
+
td: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43521
|
+
th: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43522
|
+
tr: /* @__PURE__ */ new Set(["td", "th", "tr"]),
|
|
43523
|
+
thead: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43524
|
+
tbody: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43525
|
+
tfoot: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43526
|
+
p: /* @__PURE__ */ new Set(["p"]),
|
|
43527
|
+
option: /* @__PURE__ */ new Set(["option"])
|
|
43528
|
+
};
|
|
43529
|
+
var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
|
|
43530
|
+
var ATTR_RE = /([a-zA-Z_:][a-zA-Z0-9:._-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
|
|
43531
|
+
function parseAttrs(raw) {
|
|
43532
|
+
const attrs = {};
|
|
43533
|
+
if (!raw) return attrs;
|
|
43534
|
+
ATTR_RE.lastIndex = 0;
|
|
43535
|
+
let m;
|
|
43536
|
+
while ((m = ATTR_RE.exec(raw)) !== null) {
|
|
43537
|
+
const name = m[1].toLowerCase();
|
|
43538
|
+
let value = m[2] ?? "";
|
|
43539
|
+
if (value.length >= 2 && (value[0] === '"' || value[0] === "'")) {
|
|
43540
|
+
value = value.slice(1, -1);
|
|
43541
|
+
}
|
|
43542
|
+
attrs[name] = value;
|
|
43543
|
+
}
|
|
43544
|
+
return attrs;
|
|
43545
|
+
}
|
|
43546
|
+
function stripNonContent(html) {
|
|
43547
|
+
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, "");
|
|
43548
|
+
}
|
|
43549
|
+
function tokenize(html) {
|
|
43550
|
+
const tokens = [];
|
|
43551
|
+
const clean = stripNonContent(html);
|
|
43552
|
+
TAG_RE.lastIndex = 0;
|
|
43553
|
+
let lastIndex = 0;
|
|
43554
|
+
let m;
|
|
43555
|
+
while ((m = TAG_RE.exec(clean)) !== null) {
|
|
43556
|
+
if (m.index > lastIndex) {
|
|
43557
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex, m.index) });
|
|
43558
|
+
}
|
|
43559
|
+
lastIndex = TAG_RE.lastIndex;
|
|
43560
|
+
const isClose = m[1] === "/";
|
|
43561
|
+
const name = m[2].toLowerCase();
|
|
43562
|
+
if (isClose) {
|
|
43563
|
+
tokens.push({ kind: "close", name });
|
|
43564
|
+
} else {
|
|
43565
|
+
tokens.push({
|
|
43566
|
+
kind: "open",
|
|
43567
|
+
name,
|
|
43568
|
+
attrs: parseAttrs(m[3]),
|
|
43569
|
+
selfClose: m[4] === "/"
|
|
43570
|
+
});
|
|
43571
|
+
}
|
|
43572
|
+
}
|
|
43573
|
+
if (lastIndex < clean.length) {
|
|
43574
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex) });
|
|
43575
|
+
}
|
|
43576
|
+
return tokens;
|
|
43577
|
+
}
|
|
43578
|
+
function parseHtml(html) {
|
|
43579
|
+
const root = { type: "element", name: "#root", attrs: {}, children: [] };
|
|
43580
|
+
const stack = [root];
|
|
43581
|
+
const top = () => stack[stack.length - 1];
|
|
43582
|
+
for (const token of tokenize(html)) {
|
|
43583
|
+
if (token.kind === "text") {
|
|
43584
|
+
if (token.text) top().children.push({ type: "text", value: token.text });
|
|
43585
|
+
continue;
|
|
43586
|
+
}
|
|
43587
|
+
if (token.kind === "open") {
|
|
43588
|
+
const name = token.name;
|
|
43589
|
+
const closes = IMPLIED_CLOSE[name];
|
|
43590
|
+
if (closes) {
|
|
43591
|
+
while (stack.length > 1 && closes.has(top().name)) stack.pop();
|
|
43592
|
+
}
|
|
43593
|
+
const el = {
|
|
43594
|
+
type: "element",
|
|
43595
|
+
name,
|
|
43596
|
+
attrs: token.attrs ?? {},
|
|
43597
|
+
children: []
|
|
43598
|
+
};
|
|
43599
|
+
top().children.push(el);
|
|
43600
|
+
if (!token.selfClose && !VOID_ELEMENTS.has(name)) {
|
|
43601
|
+
stack.push(el);
|
|
43602
|
+
}
|
|
43603
|
+
continue;
|
|
43604
|
+
}
|
|
43605
|
+
for (let i = stack.length - 1; i > 0; i--) {
|
|
43606
|
+
if (stack[i].name === token.name) {
|
|
43607
|
+
stack.length = i;
|
|
43608
|
+
break;
|
|
43609
|
+
}
|
|
43610
|
+
}
|
|
43611
|
+
}
|
|
43612
|
+
return root.children;
|
|
43613
|
+
}
|
|
43614
|
+
function childElements(el, names) {
|
|
43615
|
+
return el.children.filter((c) => c.type === "element" && names.has(c.name));
|
|
43616
|
+
}
|
|
43617
|
+
|
|
43618
|
+
// src/parser/html/HtmlTableParser.ts
|
|
43619
|
+
var MARK_TAGS = {
|
|
43620
|
+
b: "bold",
|
|
43621
|
+
strong: "bold",
|
|
43622
|
+
i: "italic",
|
|
43623
|
+
em: "italic",
|
|
43624
|
+
sup: "superscript",
|
|
43625
|
+
sub: "subscript",
|
|
43626
|
+
s: "strike",
|
|
43627
|
+
strike: "strike",
|
|
43628
|
+
del: "del",
|
|
43629
|
+
ins: "ins",
|
|
43630
|
+
u: "underline",
|
|
43631
|
+
mark: "highlight",
|
|
43632
|
+
code: "code"
|
|
43633
|
+
};
|
|
43634
|
+
var SECTION_TAGS = /* @__PURE__ */ new Set(["thead", "tbody", "tfoot"]);
|
|
43635
|
+
var ROW_TAGS = /* @__PURE__ */ new Set(["tr"]);
|
|
43636
|
+
var CELL_TAGS = /* @__PURE__ */ new Set(["td", "th"]);
|
|
43637
|
+
var LI_TAGS = /* @__PURE__ */ new Set(["li"]);
|
|
43638
|
+
var VALID_SCOPES = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
43639
|
+
var NAMED_ENTITIES = {
|
|
43640
|
+
amp: "&",
|
|
43641
|
+
lt: "<",
|
|
43642
|
+
gt: ">",
|
|
43643
|
+
quot: '"',
|
|
43644
|
+
apos: "'",
|
|
43645
|
+
nbsp: "\xA0"
|
|
43646
|
+
};
|
|
43647
|
+
function decodeEntities(text) {
|
|
43648
|
+
return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, (whole, body) => {
|
|
43649
|
+
if (body[0] === "#") {
|
|
43650
|
+
const code = body[1] === "x" || body[1] === "X" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);
|
|
43651
|
+
if (Number.isFinite(code) && code >= 0 && code <= 1114111) {
|
|
43652
|
+
try {
|
|
43653
|
+
return String.fromCodePoint(code);
|
|
43654
|
+
} catch {
|
|
43655
|
+
return whole;
|
|
43656
|
+
}
|
|
43657
|
+
}
|
|
43658
|
+
return whole;
|
|
43659
|
+
}
|
|
43660
|
+
return NAMED_ENTITIES[body] ?? whole;
|
|
43661
|
+
});
|
|
43662
|
+
}
|
|
43663
|
+
function intAttr(value) {
|
|
43664
|
+
if (value == null) return void 0;
|
|
43665
|
+
const n = Number.parseInt(value, 10);
|
|
43666
|
+
return Number.isInteger(n) ? n : void 0;
|
|
43667
|
+
}
|
|
43668
|
+
function isElement(node) {
|
|
43669
|
+
return node.type === "element";
|
|
43670
|
+
}
|
|
43671
|
+
var HtmlTableParser2 = class {
|
|
43672
|
+
constructor() {
|
|
43673
|
+
__publicField(this, "keepUnknownTags", false);
|
|
43674
|
+
}
|
|
43675
|
+
/**
|
|
43676
|
+
* Parse an HTML string and return one table bit per top-level `<table>`.
|
|
43677
|
+
*/
|
|
43678
|
+
parse(html, options) {
|
|
43679
|
+
this.keepUnknownTags = options?.keepUnknownTags ?? false;
|
|
43680
|
+
const tableFormat = options?.tableFormat ?? "table-extended";
|
|
43681
|
+
const onWarning = options?.onWarning;
|
|
43682
|
+
const tables = this.collectTopLevelTables(parseHtml(html));
|
|
43683
|
+
const bits = [];
|
|
43684
|
+
for (const table of tables) {
|
|
43685
|
+
const bit = this.tableToBit(table, tableFormat, onWarning);
|
|
43686
|
+
if (bit) bits.push(bit);
|
|
43687
|
+
}
|
|
43688
|
+
return bits;
|
|
43689
|
+
}
|
|
43690
|
+
// --- table extraction -----------------------------------------------------
|
|
43691
|
+
/** Collect every `<table>` element, NOT descending into nested tables. */
|
|
43692
|
+
collectTopLevelTables(nodes) {
|
|
43693
|
+
const tables = [];
|
|
43694
|
+
const visit = (node) => {
|
|
43695
|
+
if (!isElement(node)) return;
|
|
43696
|
+
if (node.name === "table") {
|
|
43697
|
+
tables.push(node);
|
|
43698
|
+
return;
|
|
43699
|
+
}
|
|
43700
|
+
node.children.forEach(visit);
|
|
43701
|
+
};
|
|
43702
|
+
nodes.forEach(visit);
|
|
43703
|
+
return tables;
|
|
43704
|
+
}
|
|
43705
|
+
tableToBit(table, tableFormat, onWarning) {
|
|
43706
|
+
const header = [];
|
|
43707
|
+
const body = [];
|
|
43708
|
+
const footer = [];
|
|
43709
|
+
let caption;
|
|
43710
|
+
for (const child of table.children) {
|
|
43711
|
+
if (!isElement(child)) continue;
|
|
43712
|
+
if (child.name === "caption") {
|
|
43713
|
+
const capContent = this.inlineNodes(child.children, []);
|
|
43714
|
+
const trimmed = this.trimInline(capContent);
|
|
43715
|
+
if (trimmed.length > 0) caption = trimmed;
|
|
43716
|
+
} else if (SECTION_TAGS.has(child.name)) {
|
|
43717
|
+
const target = child.name === "thead" ? header : child.name === "tfoot" ? footer : body;
|
|
43718
|
+
for (const tr of childElements(child, ROW_TAGS)) {
|
|
43719
|
+
target.push(this.rowToCells(tr));
|
|
43720
|
+
}
|
|
43721
|
+
} else if (ROW_TAGS.has(child.name)) {
|
|
43722
|
+
body.push(this.rowToCells(child));
|
|
43723
|
+
}
|
|
43724
|
+
}
|
|
43725
|
+
if (header.length === 0 && body.length === 0 && footer.length === 0) {
|
|
43726
|
+
return void 0;
|
|
43727
|
+
}
|
|
43728
|
+
const tableExtended = {};
|
|
43729
|
+
if (header.length > 0) tableExtended.header = { rows: header };
|
|
43730
|
+
if (body.length > 0) tableExtended.body = { rows: body };
|
|
43731
|
+
if (footer.length > 0) tableExtended.footer = { rows: footer };
|
|
43732
|
+
let tableData = tableExtended;
|
|
43733
|
+
if (tableFormat === "table") {
|
|
43734
|
+
if (this.isLossyAsBasic(tableExtended)) {
|
|
43735
|
+
onWarning?.(
|
|
43736
|
+
"Converting an HTML table to [.table] loses rowspan/colspan/scope and multi-section structure; use --tableFormat table-extended to preserve them."
|
|
43737
|
+
);
|
|
43738
|
+
}
|
|
43739
|
+
tableData = convertExtendedToBasicTableFormat(tableExtended);
|
|
43740
|
+
}
|
|
43741
|
+
const bit = {
|
|
43742
|
+
type: tableFormat,
|
|
43743
|
+
format: "bitmark++",
|
|
43744
|
+
table: tableData
|
|
43745
|
+
};
|
|
43746
|
+
if (caption) bit.caption = caption;
|
|
43747
|
+
return bit;
|
|
43748
|
+
}
|
|
43749
|
+
rowToCells(tr) {
|
|
43750
|
+
const cells = [];
|
|
43751
|
+
for (const cell of childElements(tr, CELL_TAGS)) {
|
|
43752
|
+
cells.push(this.cellToJson(cell));
|
|
43753
|
+
}
|
|
43754
|
+
return { cells };
|
|
43755
|
+
}
|
|
43756
|
+
cellToJson(cell) {
|
|
43757
|
+
const json = {
|
|
43758
|
+
content: this.blockNodes(cell.children)
|
|
43759
|
+
};
|
|
43760
|
+
if (cell.name === "th") json.title = true;
|
|
43761
|
+
const rowspan = intAttr(cell.attrs.rowspan);
|
|
43762
|
+
if (rowspan != null && rowspan >= 2) json.rowspan = rowspan;
|
|
43763
|
+
const colspan = intAttr(cell.attrs.colspan);
|
|
43764
|
+
if (colspan != null && colspan >= 2) json.colspan = colspan;
|
|
43765
|
+
const scope = cell.attrs.scope?.toLowerCase();
|
|
43766
|
+
if (scope && VALID_SCOPES.has(scope)) {
|
|
43767
|
+
json.scope = scope;
|
|
43768
|
+
}
|
|
43769
|
+
const width = this.widthFromCell(cell);
|
|
43770
|
+
if (width != null) json.colwidth = width;
|
|
43771
|
+
return json;
|
|
43772
|
+
}
|
|
43773
|
+
widthFromCell(cell) {
|
|
43774
|
+
const attrWidth = intAttr(cell.attrs.width);
|
|
43775
|
+
if (attrWidth != null && attrWidth > 0) return attrWidth;
|
|
43776
|
+
const style = cell.attrs.style;
|
|
43777
|
+
if (style) {
|
|
43778
|
+
const m = style.match(/width\s*:\s*(\d+)\s*px/i);
|
|
43779
|
+
if (m) {
|
|
43780
|
+
const n = Number.parseInt(m[1], 10);
|
|
43781
|
+
if (Number.isInteger(n) && n > 0) return n;
|
|
43782
|
+
}
|
|
43783
|
+
}
|
|
43784
|
+
return void 0;
|
|
43785
|
+
}
|
|
43786
|
+
isLossyAsBasic(table) {
|
|
43787
|
+
if (table.footer) return true;
|
|
43788
|
+
if (table.header && table.header.rows.length > 1) return true;
|
|
43789
|
+
const sections = [table.header, table.body, table.footer];
|
|
43790
|
+
for (const section of sections) {
|
|
43791
|
+
if (!section) continue;
|
|
43792
|
+
for (const row of section.rows) {
|
|
43793
|
+
for (const cell of row.cells) {
|
|
43794
|
+
if (cell.rowspan || cell.colspan || cell.scope) return true;
|
|
43795
|
+
}
|
|
43796
|
+
}
|
|
43797
|
+
}
|
|
43798
|
+
return false;
|
|
43799
|
+
}
|
|
43800
|
+
// --- content conversion (HTML -> TextAst) ---------------------------------
|
|
43801
|
+
/**
|
|
43802
|
+
* Convert a cell/li's child nodes into block-level TextAst nodes (paragraphs, lists, images).
|
|
43803
|
+
*/
|
|
43804
|
+
blockNodes(nodes) {
|
|
43805
|
+
const blocks = [];
|
|
43806
|
+
let inline = [];
|
|
43807
|
+
const flush = () => {
|
|
43808
|
+
const trimmed = this.trimInline(inline);
|
|
43809
|
+
inline = [];
|
|
43810
|
+
if (trimmed.length === 0) return;
|
|
43811
|
+
if (trimmed.length === 1 && trimmed[0].type === "imageInline") {
|
|
43812
|
+
blocks.push({ ...trimmed[0], type: "image" });
|
|
43813
|
+
} else {
|
|
43814
|
+
blocks.push({ type: "paragraph", content: trimmed, attrs: {} });
|
|
43815
|
+
}
|
|
43816
|
+
};
|
|
43817
|
+
for (const node of nodes) {
|
|
43818
|
+
if (!isElement(node)) {
|
|
43819
|
+
inline.push(...this.inlineText(node.value, []));
|
|
43820
|
+
continue;
|
|
43821
|
+
}
|
|
43822
|
+
const name = node.name;
|
|
43823
|
+
if (name === "p") {
|
|
43824
|
+
flush();
|
|
43825
|
+
const content = this.trimInline(this.inlineNodes(node.children, []));
|
|
43826
|
+
if (content.length > 0) {
|
|
43827
|
+
blocks.push({ type: "paragraph", content, attrs: {} });
|
|
43828
|
+
}
|
|
43829
|
+
} else if (this.isListTag(name)) {
|
|
43830
|
+
flush();
|
|
43831
|
+
const list = this.listNode(node);
|
|
43832
|
+
if (list) blocks.push(list);
|
|
43833
|
+
} else {
|
|
43834
|
+
inline.push(...this.inlineFromElement(node, []));
|
|
43835
|
+
}
|
|
43836
|
+
}
|
|
43837
|
+
flush();
|
|
43838
|
+
return blocks;
|
|
43839
|
+
}
|
|
43840
|
+
/** Convert child nodes to a flat list of inline TextNodes, applying the given marks. */
|
|
43841
|
+
inlineNodes(nodes, marks) {
|
|
43842
|
+
const out = [];
|
|
43843
|
+
for (const node of nodes) {
|
|
43844
|
+
if (!isElement(node)) {
|
|
43845
|
+
out.push(...this.inlineText(node.value, marks));
|
|
43846
|
+
} else {
|
|
43847
|
+
out.push(...this.inlineFromElement(node, marks));
|
|
43848
|
+
}
|
|
43849
|
+
}
|
|
43850
|
+
return out;
|
|
43851
|
+
}
|
|
43852
|
+
inlineFromElement(el, marks) {
|
|
43853
|
+
const name = el.name;
|
|
43854
|
+
if (name === "br") {
|
|
43855
|
+
return [{ type: "hardBreak" }];
|
|
43856
|
+
}
|
|
43857
|
+
if (name === "img") {
|
|
43858
|
+
return [this.imageNode(el, true)];
|
|
43859
|
+
}
|
|
43860
|
+
const markType = MARK_TAGS[name];
|
|
43861
|
+
if (markType) {
|
|
43862
|
+
return this.inlineNodes(el.children, [...marks, { type: markType }]);
|
|
43863
|
+
}
|
|
43864
|
+
if (name === "a") {
|
|
43865
|
+
const linkMark = {
|
|
43866
|
+
type: "link",
|
|
43867
|
+
attrs: {
|
|
43868
|
+
href: el.attrs.href ?? "",
|
|
43869
|
+
...el.attrs.target ? { target: el.attrs.target } : {}
|
|
43870
|
+
}
|
|
43871
|
+
};
|
|
43872
|
+
return this.inlineNodes(el.children, [...marks, linkMark]);
|
|
43873
|
+
}
|
|
43874
|
+
if (this.keepUnknownTags) {
|
|
43875
|
+
const open = this.serializeOpenTag(el);
|
|
43876
|
+
const close = `</${name}>`;
|
|
43877
|
+
return [
|
|
43878
|
+
...this.inlineText(open, marks),
|
|
43879
|
+
...this.inlineNodes(el.children, marks),
|
|
43880
|
+
...this.inlineText(close, marks)
|
|
43881
|
+
];
|
|
43882
|
+
}
|
|
43883
|
+
return this.inlineNodes(el.children, marks);
|
|
43884
|
+
}
|
|
43885
|
+
inlineText(raw, marks) {
|
|
43886
|
+
const text = decodeEntities(raw).replace(/\s+/g, " ");
|
|
43887
|
+
if (text === "") return [];
|
|
43888
|
+
const node = { text, type: "text" };
|
|
43889
|
+
if (marks.length > 0) node.marks = marks.map((m) => ({ ...m }));
|
|
43890
|
+
return [node];
|
|
43891
|
+
}
|
|
43892
|
+
serializeOpenTag(el) {
|
|
43893
|
+
const attrs = Object.entries(el.attrs).map(([k, v]) => v === "" ? ` ${k}` : ` ${k}="${v}"`).join("");
|
|
43894
|
+
return `<${el.name}${attrs}>`;
|
|
43895
|
+
}
|
|
43896
|
+
// --- lists ----------------------------------------------------------------
|
|
43897
|
+
isListTag(name) {
|
|
43898
|
+
return name === "ul" || name === "ol";
|
|
43899
|
+
}
|
|
43900
|
+
listNode(el) {
|
|
43901
|
+
const items = childElements(el, LI_TAGS);
|
|
43902
|
+
if (items.length === 0) return void 0;
|
|
43903
|
+
const isTask = el.name === "ul" && items.some((li) => {
|
|
43904
|
+
const firstEl = li.children.find(isElement);
|
|
43905
|
+
return firstEl?.name === "input" && firstEl.attrs.type?.toLowerCase() === "checkbox";
|
|
43906
|
+
});
|
|
43907
|
+
if (isTask) {
|
|
43908
|
+
return {
|
|
43909
|
+
type: "taskList",
|
|
43910
|
+
content: items.map((li) => this.taskItemNode(li))
|
|
43911
|
+
};
|
|
43912
|
+
}
|
|
43913
|
+
const type = this.listType(el);
|
|
43914
|
+
const node = {
|
|
43915
|
+
type,
|
|
43916
|
+
content: items.map((li) => this.listItemNode(li))
|
|
43917
|
+
};
|
|
43918
|
+
if (el.name === "ol") {
|
|
43919
|
+
const start = intAttr(el.attrs.start);
|
|
43920
|
+
if (start != null) {
|
|
43921
|
+
node.attrs = { start };
|
|
43922
|
+
}
|
|
43923
|
+
}
|
|
43924
|
+
return node;
|
|
43925
|
+
}
|
|
43926
|
+
listType(el) {
|
|
43927
|
+
if (el.name === "ol") {
|
|
43928
|
+
switch (el.attrs.type) {
|
|
43929
|
+
case "i":
|
|
43930
|
+
return "orderedListRomanLower";
|
|
43931
|
+
case "I":
|
|
43932
|
+
return "orderedListRoman";
|
|
43933
|
+
case "a":
|
|
43934
|
+
return "letteredListLower";
|
|
43935
|
+
case "A":
|
|
43936
|
+
return "letteredList";
|
|
43937
|
+
default:
|
|
43938
|
+
return "orderedList";
|
|
43939
|
+
}
|
|
43940
|
+
}
|
|
43941
|
+
const style = el.attrs.style ?? "";
|
|
43942
|
+
if (/list-style(-type)?\s*:\s*none/i.test(style)) return "noBulletList";
|
|
43943
|
+
return "bulletList";
|
|
43944
|
+
}
|
|
43945
|
+
listItemNode(li) {
|
|
43946
|
+
let content = this.blockNodes(li.children);
|
|
43947
|
+
if (content.length === 0) {
|
|
43948
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
43949
|
+
}
|
|
43950
|
+
return { type: "listItem", content };
|
|
43951
|
+
}
|
|
43952
|
+
taskItemNode(li) {
|
|
43953
|
+
const checkbox = li.children.find(
|
|
43954
|
+
(c) => isElement(c) && c.name === "input" && c.attrs.type?.toLowerCase() === "checkbox"
|
|
43955
|
+
);
|
|
43956
|
+
const checked = checkbox ? "checked" in checkbox.attrs : false;
|
|
43957
|
+
const rest = li.children.filter((c) => c !== checkbox);
|
|
43958
|
+
let content = this.blockNodes(rest);
|
|
43959
|
+
if (content.length === 0) {
|
|
43960
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
43961
|
+
}
|
|
43962
|
+
return { type: "taskItem", attrs: { checked }, content };
|
|
43963
|
+
}
|
|
43964
|
+
// --- images ---------------------------------------------------------------
|
|
43965
|
+
imageNode(el, inline) {
|
|
43966
|
+
const attrs = { src: el.attrs.src ?? "" };
|
|
43967
|
+
attrs.alt = el.attrs.alt ?? null;
|
|
43968
|
+
attrs.title = el.attrs.title ?? null;
|
|
43969
|
+
const width = intAttr(el.attrs.width);
|
|
43970
|
+
if (width != null) attrs.width = width;
|
|
43971
|
+
const height = intAttr(el.attrs.height);
|
|
43972
|
+
if (height != null) attrs.height = height;
|
|
43973
|
+
if (el.attrs.class) attrs.class = el.attrs.class;
|
|
43974
|
+
return { type: inline ? "imageInline" : "image", attrs };
|
|
43975
|
+
}
|
|
43976
|
+
// --- whitespace -----------------------------------------------------------
|
|
43977
|
+
/** Trim leading/trailing whitespace from inline content (edges only). */
|
|
43978
|
+
trimInline(nodes) {
|
|
43979
|
+
const out = nodes.slice();
|
|
43980
|
+
const isWs = (n) => n.type === "text" && /^\s*$/.test(n.text ?? "");
|
|
43981
|
+
while (out.length > 0 && isWs(out[0])) out.shift();
|
|
43982
|
+
if (out.length > 0 && out[0].type === "text") {
|
|
43983
|
+
out[0] = { ...out[0], text: (out[0].text ?? "").replace(/^\s+/, "") };
|
|
43984
|
+
}
|
|
43985
|
+
while (out.length > 0 && isWs(out[out.length - 1])) out.pop();
|
|
43986
|
+
if (out.length > 0 && out[out.length - 1].type === "text") {
|
|
43987
|
+
const last = out.length - 1;
|
|
43988
|
+
out[last] = { ...out[last], text: (out[last].text ?? "").replace(/\s+$/, "") };
|
|
43989
|
+
}
|
|
43990
|
+
return out.filter((n) => !(n.type === "text" && n.text === ""));
|
|
43991
|
+
}
|
|
43992
|
+
};
|
|
43993
|
+
|
|
42973
43994
|
// src/index.ts
|
|
42974
43995
|
init();
|
|
42975
43996
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -42986,6 +44007,8 @@ init();
|
|
|
42986
44007
|
BoundingBoxIndex,
|
|
42987
44008
|
Builder,
|
|
42988
44009
|
CardSetVersion,
|
|
44010
|
+
HtmlTableGenerator,
|
|
44011
|
+
HtmlTableParser,
|
|
42989
44012
|
InfoFormat,
|
|
42990
44013
|
InfoType,
|
|
42991
44014
|
Input,
|