@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.js
CHANGED
|
@@ -230,6 +230,7 @@ var BitType = {
|
|
|
230
230
|
dangerAlt: "danger-alt",
|
|
231
231
|
dangerCollapsible: "danger-collapsible",
|
|
232
232
|
definitionList: "definition-list",
|
|
233
|
+
definitionListCollapsible: "definition-list-collapsible",
|
|
233
234
|
definitionTerm: "definition-term",
|
|
234
235
|
deleted: "deleted",
|
|
235
236
|
details: "details",
|
|
@@ -510,6 +511,8 @@ var BitType = {
|
|
|
510
511
|
smartStandardArticleNonNormativeCollapsible: "smart-standard-article-non-normative-collapsible",
|
|
511
512
|
smartStandardArticleNormative: "smart-standard-article-normative",
|
|
512
513
|
smartStandardArticleNormativeCollapsible: "smart-standard-article-normative-collapsible",
|
|
514
|
+
smartStandardDefinitionListNonNormative: "smart-standard-definition-list-non-normative",
|
|
515
|
+
smartStandardDefinitionListNormative: "smart-standard-definition-list-normative",
|
|
513
516
|
smartStandardExampleNonNormative: "smart-standard-example-non-normative",
|
|
514
517
|
smartStandardExampleNonNormativeCollapsible: "smart-standard-example-non-normative-collapsible",
|
|
515
518
|
smartStandardExampleNormative: "smart-standard-example-normative",
|
|
@@ -560,6 +563,8 @@ var BitType = {
|
|
|
560
563
|
smartStandardTableNormativeCollapsible: "smart-standard-table-normative-collapsible",
|
|
561
564
|
standardArticleNonNormative: "standard-article-non-normative",
|
|
562
565
|
standardArticleNormative: "standard-article-normative",
|
|
566
|
+
standardDefinitionListNonNormative: "standard-definition-list-non-normative",
|
|
567
|
+
standardDefinitionListNormative: "standard-definition-list-normative",
|
|
563
568
|
standardExampleNonNormative: "standard-example-non-normative",
|
|
564
569
|
standardExampleNormative: "standard-example-normative",
|
|
565
570
|
standardImageFigureNonNormative: "standard-image-figure-non-normative",
|
|
@@ -731,6 +736,7 @@ var CardSetConfigKey = {
|
|
|
731
736
|
flashcard: "flashcard",
|
|
732
737
|
flashcard1: "flashcard1",
|
|
733
738
|
definitionList: "definitionList",
|
|
739
|
+
definitionListPlain: "definitionListPlain",
|
|
734
740
|
elements: "elements",
|
|
735
741
|
statements: "statements",
|
|
736
742
|
quiz: "quiz",
|
|
@@ -1344,6 +1350,7 @@ var propertyKeys = {
|
|
|
1344
1350
|
property_enforceUpdateOverUserInput: "@enforceUpdateOverUserInput",
|
|
1345
1351
|
property_extractorExtractionTimestamp: "@extractorExtractionTimestamp",
|
|
1346
1352
|
property_isCaseSensitive: "@isCaseSensitive",
|
|
1353
|
+
property_isCollapsible: "@isCollapsible",
|
|
1347
1354
|
property_isInfoOnly: "@isInfoOnly",
|
|
1348
1355
|
property_isPublic: "@isPublic",
|
|
1349
1356
|
property_isTemplate: "@isTemplate",
|
|
@@ -2548,6 +2555,126 @@ var CARDSETS = {
|
|
|
2548
2555
|
]
|
|
2549
2556
|
},
|
|
2550
2557
|
//
|
|
2558
|
+
// definition-list-plain
|
|
2559
|
+
//
|
|
2560
|
+
// Same shape as `definitionList`, but every variant body is rendered as
|
|
2561
|
+
// plain text (string), not bitmark+ AST. Used by
|
|
2562
|
+
// `meta-search-default-terms` / `meta-search-default-topics`, which need
|
|
2563
|
+
// term/definition text emitted verbatim instead of as a ProseMirror tree.
|
|
2564
|
+
//
|
|
2565
|
+
[CardSetConfigKey.definitionListPlain]: {
|
|
2566
|
+
jsonKey: "definitions",
|
|
2567
|
+
exportJsonKey: { definitions: "$" },
|
|
2568
|
+
sides: [
|
|
2569
|
+
{
|
|
2570
|
+
name: "term",
|
|
2571
|
+
variants: [
|
|
2572
|
+
{
|
|
2573
|
+
jsonKey: "term.text",
|
|
2574
|
+
exportJsonKey: [{ "@absent": { term: {} } }, { term: { text: "$" } }],
|
|
2575
|
+
format: TextFormat.plainText,
|
|
2576
|
+
tags: [
|
|
2577
|
+
{
|
|
2578
|
+
key: ConfigKey.group_standardTags,
|
|
2579
|
+
description: "Standard tags for the definition."
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
key: ConfigKey.tag_title,
|
|
2583
|
+
description: "Title of the definition.",
|
|
2584
|
+
format: TagFormat.plainText,
|
|
2585
|
+
jsonKey: "^heading.forKeys",
|
|
2586
|
+
exportJsonKey: { "@bit": { heading: { forKeys: "$" } } }
|
|
2587
|
+
},
|
|
2588
|
+
{
|
|
2589
|
+
key: ConfigKey.group_resourceIcon,
|
|
2590
|
+
description: "Icon resource for the definition.",
|
|
2591
|
+
format: TagFormat.plainText,
|
|
2592
|
+
jsonKey: "term.icon|resource(type=image, key=image)",
|
|
2593
|
+
exportJsonKey: { term: { icon: { type: "image", image: { src: "$" } } } }
|
|
2594
|
+
},
|
|
2595
|
+
{
|
|
2596
|
+
key: ConfigKey.property_example,
|
|
2597
|
+
exportJsonKey: [
|
|
2598
|
+
{ "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2599
|
+
{ "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2600
|
+
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
2601
|
+
],
|
|
2602
|
+
description: "Example marker for the definition term.",
|
|
2603
|
+
format: TagFormat.bitmarkText,
|
|
2604
|
+
nullable: true
|
|
2605
|
+
}
|
|
2606
|
+
]
|
|
2607
|
+
}
|
|
2608
|
+
]
|
|
2609
|
+
},
|
|
2610
|
+
{
|
|
2611
|
+
name: "definition",
|
|
2612
|
+
variants: [
|
|
2613
|
+
{
|
|
2614
|
+
jsonKey: "definition.text",
|
|
2615
|
+
exportJsonKey: [{ "@absent": { definition: {} } }, { definition: { text: "$" } }],
|
|
2616
|
+
format: TextFormat.plainText,
|
|
2617
|
+
tags: [
|
|
2618
|
+
{
|
|
2619
|
+
key: ConfigKey.group_standardTags,
|
|
2620
|
+
description: "Standard tags for the definition."
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
key: ConfigKey.tag_title,
|
|
2624
|
+
description: "Title of the definition.",
|
|
2625
|
+
format: TagFormat.plainText,
|
|
2626
|
+
jsonKey: "^heading.forValues",
|
|
2627
|
+
exportJsonKey: { "@bit": { heading: { forValues: "$" } } }
|
|
2628
|
+
},
|
|
2629
|
+
{
|
|
2630
|
+
key: ConfigKey.group_resourceIcon,
|
|
2631
|
+
description: "Icon resource for the definition.",
|
|
2632
|
+
jsonKey: "definition.icon|resource(type=image, key=image)",
|
|
2633
|
+
exportJsonKey: { definition: { icon: { type: "image", image: { src: "$" } } } }
|
|
2634
|
+
},
|
|
2635
|
+
{
|
|
2636
|
+
key: ConfigKey.property_example,
|
|
2637
|
+
exportJsonKey: [
|
|
2638
|
+
{ "@keyonly": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2639
|
+
{ "@absent": { isExample: true, example: true, "@bit": { isExample: true } } },
|
|
2640
|
+
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
2641
|
+
],
|
|
2642
|
+
description: "Example marker for the definition.",
|
|
2643
|
+
format: TagFormat.bitmarkText,
|
|
2644
|
+
nullable: true
|
|
2645
|
+
}
|
|
2646
|
+
]
|
|
2647
|
+
},
|
|
2648
|
+
{
|
|
2649
|
+
jsonKey: "alternativeDefinitions[].text",
|
|
2650
|
+
exportJsonKey: { alternativeDefinitions: [{ text: "$" }] },
|
|
2651
|
+
format: TextFormat.plainText,
|
|
2652
|
+
tags: [
|
|
2653
|
+
{
|
|
2654
|
+
key: ConfigKey.group_standardTags,
|
|
2655
|
+
description: "Standard tags for the definition."
|
|
2656
|
+
},
|
|
2657
|
+
{
|
|
2658
|
+
exportJsonKey: { title: "$" },
|
|
2659
|
+
key: ConfigKey.tag_title,
|
|
2660
|
+
description: "Title of the definition."
|
|
2661
|
+
},
|
|
2662
|
+
{
|
|
2663
|
+
key: ConfigKey.group_resourceIcon,
|
|
2664
|
+
description: "Icon resource for the definition.",
|
|
2665
|
+
jsonKey: "alternativeDefinitions[].icon|resource(type=image, key=image)",
|
|
2666
|
+
exportJsonKey: {
|
|
2667
|
+
alternativeDefinitions: [{ icon: { type: "image", image: { src: "$" } } }]
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
],
|
|
2671
|
+
repeatCount: Count.infinity
|
|
2672
|
+
}
|
|
2673
|
+
]
|
|
2674
|
+
}
|
|
2675
|
+
]
|
|
2676
|
+
},
|
|
2677
|
+
//
|
|
2551
2678
|
// match-pairs
|
|
2552
2679
|
//
|
|
2553
2680
|
[CardSetConfigKey.matchPairs]: {
|
|
@@ -3485,12 +3612,29 @@ var CARDSETS = {
|
|
|
3485
3612
|
// ALIGN-EXAMPLE-CASCADE §3.10: `questions` is NOT in BPG's
|
|
3486
3613
|
// `pushExampleDownTree` dispatch — bit-header `[@example]`
|
|
3487
3614
|
// does not propagate `example`/`isExample` onto question
|
|
3488
|
-
// entries. Only entry-local `[@example]` fires
|
|
3489
|
-
//
|
|
3490
|
-
//
|
|
3615
|
+
// entries. Only entry-local `[@example]` fires.
|
|
3616
|
+
//
|
|
3617
|
+
// BPG's `BaseBuilder.toExample` for interview questions
|
|
3618
|
+
// (Builder.ts:2575,2588) uses `data.__sampleSolutionAst`
|
|
3619
|
+
// as `defaultExample` — bare `[@example]` (which sets
|
|
3620
|
+
// `__isDefaultExample=true, example=undefined`) emits the
|
|
3621
|
+
// parsed sample-solution AST in the `example` slot. The
|
|
3622
|
+
// `@keyonly` rule mirrors that runtime behaviour via
|
|
3623
|
+
// `$parent.sampleSolution` — the chain-walker's post-walk
|
|
3624
|
+
// retry resolves this once the sibling `[@sampleSolution]`
|
|
3625
|
+
// chain has merged into the shared scope (interview's
|
|
3626
|
+
// `[@example]` typically precedes `[@sampleSolution]` in
|
|
3627
|
+
// source). Format coercion turns the resolved string
|
|
3628
|
+
// value into a PM tree.
|
|
3491
3629
|
key: ConfigKey.property_example,
|
|
3492
3630
|
exportJsonKey: [
|
|
3493
|
-
{
|
|
3631
|
+
{
|
|
3632
|
+
"@keyonly": {
|
|
3633
|
+
isExample: true,
|
|
3634
|
+
example: "$parent.sampleSolution",
|
|
3635
|
+
"@bit": { isExample: true }
|
|
3636
|
+
}
|
|
3637
|
+
},
|
|
3494
3638
|
{ isExample: true, example: "$", "@bit": { isExample: true } }
|
|
3495
3639
|
],
|
|
3496
3640
|
description: "Example marker for the question (entry-local only; no bit-header cascade).",
|
|
@@ -5313,7 +5457,11 @@ var GROUPS = {
|
|
|
5313
5457
|
{
|
|
5314
5458
|
key: ConfigKey.property_mark,
|
|
5315
5459
|
jsonKey: "marks.mark",
|
|
5316
|
-
|
|
5460
|
+
// `emphasis: 'underline'` is the per-entry default for mark
|
|
5461
|
+
// configs — mirrors the hardcoded default in BPG
|
|
5462
|
+
// `MarkConfigChainContentProcessor.ts:55-58`. Chained
|
|
5463
|
+
// `[@emphasis:…]` overrides via deep-merge into `marks[-1]`.
|
|
5464
|
+
exportJsonKey: { marks: [{ mark: "$", emphasis: "underline" }] },
|
|
5317
5465
|
description: "The mark configuration",
|
|
5318
5466
|
format: TagFormat.plainText,
|
|
5319
5467
|
maxCount: Count.infinity,
|
|
@@ -5355,13 +5503,22 @@ var GROUPS = {
|
|
|
5355
5503
|
{
|
|
5356
5504
|
key: ConfigKey.property_example,
|
|
5357
5505
|
jsonKey: "example",
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5506
|
+
// Per-mark `@example` is a boolean toggle. BPG's runtime
|
|
5507
|
+
// `ExampleTagContentProcessor.handleDefaultOnlyExample`
|
|
5508
|
+
// (lines 147-161) normalises ANY `[@example]` or
|
|
5509
|
+
// `[@example:V]` on a mark body-bit to
|
|
5510
|
+
// `__isDefaultExample=true, example=undefined`; the
|
|
5511
|
+
// downstream `toExample(_, _, defaultExample=true)` in
|
|
5512
|
+
// `BaseBuilder.ts:80-87` then emits `example: true`
|
|
5513
|
+
// regardless of source. Declare a single unconditional
|
|
5514
|
+
// boolean-shape rule so the exported schema matches that
|
|
5515
|
+
// runtime semantic instead of the misleading `example: $`
|
|
5516
|
+
// shape (which would only fire if `handleDefaultOnlyExample`
|
|
5517
|
+
// were removed). `@bit: {isExample: true}` cascades the
|
|
5518
|
+
// marker — but NOT the `example` value — to bit root.
|
|
5519
|
+
exportJsonKey: { isExample: true, example: true, "@bit": { isExample: true } },
|
|
5363
5520
|
description: "An example for the marked content",
|
|
5364
|
-
format: TagFormat.
|
|
5521
|
+
format: TagFormat.boolean,
|
|
5365
5522
|
nullable: true
|
|
5366
5523
|
}
|
|
5367
5524
|
]
|
|
@@ -8137,6 +8294,12 @@ var BITS = {
|
|
|
8137
8294
|
description: "The progress of the chapter, used for tracking reading progress",
|
|
8138
8295
|
format: TagFormat.boolean,
|
|
8139
8296
|
defaultValue: "true"
|
|
8297
|
+
},
|
|
8298
|
+
{
|
|
8299
|
+
key: ConfigKey.property_isCollapsible,
|
|
8300
|
+
description: "If true, the chapter is collapsible",
|
|
8301
|
+
format: TagFormat.boolean,
|
|
8302
|
+
defaultValue: "false"
|
|
8140
8303
|
}
|
|
8141
8304
|
]
|
|
8142
8305
|
},
|
|
@@ -8911,7 +9074,12 @@ var BITS = {
|
|
|
8911
9074
|
maxCount: Count.infinity
|
|
8912
9075
|
},
|
|
8913
9076
|
{
|
|
8914
|
-
// Override inherited @example from group_standardTags:
|
|
9077
|
+
// Override inherited @example from group_standardTags: emits both
|
|
9078
|
+
// `isExample` (bool) AND `example` (paragraph array). Declared as
|
|
9079
|
+
// bitmarkText because BPG `JsonGenerator.toExample` renders the
|
|
9080
|
+
// root-example value through the bit's textFormat (not this tag's
|
|
9081
|
+
// declared format) — `TagFormat.plainText` here would be ignored
|
|
9082
|
+
// at runtime and is misleading.
|
|
8915
9083
|
key: ConfigKey.property_example,
|
|
8916
9084
|
exportJsonKey: [
|
|
8917
9085
|
{ "@keyonly": { isExample: true, example: "true" } },
|
|
@@ -8919,7 +9087,7 @@ var BITS = {
|
|
|
8919
9087
|
{ isExample: true, example: "$" }
|
|
8920
9088
|
],
|
|
8921
9089
|
description: "The example text for the essay bit",
|
|
8922
|
-
format: TagFormat.
|
|
9090
|
+
format: TagFormat.bitmarkText,
|
|
8923
9091
|
nullable: true
|
|
8924
9092
|
}
|
|
8925
9093
|
],
|
|
@@ -9965,6 +10133,11 @@ var BITS = {
|
|
|
9965
10133
|
baseBitType: BitType._standard,
|
|
9966
10134
|
description: "Extractor rule bit, used to define extraction rules with reference images and instructions",
|
|
9967
10135
|
tags: [
|
|
10136
|
+
{
|
|
10137
|
+
exportJsonKey: { title: "$" },
|
|
10138
|
+
key: ConfigKey.tag_title,
|
|
10139
|
+
description: "The name of the extraction rule"
|
|
10140
|
+
},
|
|
9968
10141
|
{
|
|
9969
10142
|
key: ConfigKey.group_resourceBitTags,
|
|
9970
10143
|
description: "Resource bit tags for extraction rule images"
|
|
@@ -10281,11 +10454,36 @@ var BITS = {
|
|
|
10281
10454
|
],
|
|
10282
10455
|
cardSet: CardSetConfigKey.definitionList
|
|
10283
10456
|
},
|
|
10457
|
+
[BitType.definitionListCollapsible]: {
|
|
10458
|
+
since: "5.25.0",
|
|
10459
|
+
baseBitType: BitType.definitionList,
|
|
10460
|
+
description: "Collapsible definition list bit, used to create collapsible lists of definitions in articles or books"
|
|
10461
|
+
},
|
|
10462
|
+
[BitType.standardDefinitionListNormative]: {
|
|
10463
|
+
since: "5.24.0",
|
|
10464
|
+
baseBitType: BitType.definitionList,
|
|
10465
|
+
description: "Standard normative definition list bit, used to create normative standard definition lists in articles or books"
|
|
10466
|
+
},
|
|
10467
|
+
[BitType.standardDefinitionListNonNormative]: {
|
|
10468
|
+
since: "5.24.0",
|
|
10469
|
+
baseBitType: BitType.definitionList,
|
|
10470
|
+
description: "Standard non-normative definition list bit, used to create non-normative standard definition lists in articles or books"
|
|
10471
|
+
},
|
|
10472
|
+
[BitType.smartStandardDefinitionListNormative]: {
|
|
10473
|
+
since: "5.24.0",
|
|
10474
|
+
baseBitType: BitType.standardDefinitionListNormative,
|
|
10475
|
+
description: "Smart standard normative definition list bit, used to create normative smart standard definition lists in articles or books"
|
|
10476
|
+
},
|
|
10477
|
+
[BitType.smartStandardDefinitionListNonNormative]: {
|
|
10478
|
+
since: "5.24.0",
|
|
10479
|
+
baseBitType: BitType.standardDefinitionListNonNormative,
|
|
10480
|
+
description: "Smart standard non-normative definition list bit, used to create non-normative smart standard definition lists in articles or books"
|
|
10481
|
+
},
|
|
10284
10482
|
[BitType.metaSearchDefaultTerms]: {
|
|
10285
10483
|
since: "3.12.0",
|
|
10286
10484
|
baseBitType: BitType._standard,
|
|
10287
10485
|
description: "Meta search default terms bit, used to define default search terms in articles",
|
|
10288
|
-
cardSet: CardSetConfigKey.
|
|
10486
|
+
cardSet: CardSetConfigKey.definitionListPlain
|
|
10289
10487
|
},
|
|
10290
10488
|
[BitType.metaSearchDefaultTopics]: {
|
|
10291
10489
|
since: "3.12.0",
|
|
@@ -10329,7 +10527,11 @@ var BITS = {
|
|
|
10329
10527
|
[BitType.qAndACard]: {
|
|
10330
10528
|
since: "3.25.0",
|
|
10331
10529
|
baseBitType: BitType.flashcard1,
|
|
10332
|
-
description: "Q&A card bit, used to create question and answer cards in articles or books"
|
|
10530
|
+
description: "Q&A card bit, used to create question and answer cards in articles or books",
|
|
10531
|
+
// PLAN-085: q-and-a-card permits multiple cards (some fixtures carry
|
|
10532
|
+
// two). Override the inherited `flashcard1` (max=1) cardset back to
|
|
10533
|
+
// the unbounded `flashcard` cardset.
|
|
10534
|
+
cardSet: CardSetConfigKey.flashcard
|
|
10333
10535
|
},
|
|
10334
10536
|
[BitType.focusImage]: {
|
|
10335
10537
|
since: "1.3.0",
|
|
@@ -13415,7 +13617,7 @@ var instance2 = new Config();
|
|
|
13415
13617
|
// src/generated/package_info.ts
|
|
13416
13618
|
var PACKAGE_INFO = {
|
|
13417
13619
|
"name": "@gmb/bitmark-parser-generator",
|
|
13418
|
-
"version": "5.
|
|
13620
|
+
"version": "5.26.0",
|
|
13419
13621
|
"author": "Get More Brain Ltd",
|
|
13420
13622
|
"license": "ISC",
|
|
13421
13623
|
"description": "A bitmark parser and generator using Peggy.js"
|
|
@@ -14061,6 +14263,8 @@ var NodeType = {
|
|
|
14061
14263
|
internalPrintPdf: "internalPrintPdf",
|
|
14062
14264
|
internalPrintPdfValue: "internalPrintPdfValue",
|
|
14063
14265
|
isCaseSensitive: "isCaseSensitive",
|
|
14266
|
+
isCollapsible: "isCollapsible",
|
|
14267
|
+
isCollapsibleValue: "isCollapsibleValue",
|
|
14064
14268
|
isCommented: "isCommented",
|
|
14065
14269
|
isCorrect: "isCorrect",
|
|
14066
14270
|
isEditable: "isEditable",
|
|
@@ -28299,6 +28503,12 @@ var Builder = class extends BaseBuilder {
|
|
|
28299
28503
|
level: instance6.asNumber(data.level),
|
|
28300
28504
|
toc: this.toAstProperty(bitType, ConfigKey.property_toc, data.toc, options),
|
|
28301
28505
|
progress: this.toAstProperty(bitType, ConfigKey.property_progress, data.progress, options),
|
|
28506
|
+
isCollapsible: this.toAstProperty(
|
|
28507
|
+
bitType,
|
|
28508
|
+
ConfigKey.property_isCollapsible,
|
|
28509
|
+
data.isCollapsible,
|
|
28510
|
+
options
|
|
28511
|
+
),
|
|
28302
28512
|
anchor: data.anchor,
|
|
28303
28513
|
reference: data.reference,
|
|
28304
28514
|
referenceEnd: data.referenceEnd,
|
|
@@ -33845,6 +34055,7 @@ var JsonGenerator = class extends AstWalkerGenerator {
|
|
|
33845
34055
|
if (instance2.isOfBitType(bitType, BitType.chapter)) {
|
|
33846
34056
|
if (bitJson.toc == null) bitJson.toc = true;
|
|
33847
34057
|
if (bitJson.progress == null) bitJson.progress = true;
|
|
34058
|
+
if (bitJson.isCollapsible == null) bitJson.isCollapsible = false;
|
|
33848
34059
|
if (bitJson.level == null) bitJson.level = 1;
|
|
33849
34060
|
if (bitJson.body == null) bitJson.body = this.bodyDefault;
|
|
33850
34061
|
}
|
|
@@ -36060,6 +36271,7 @@ function buildCards(context, bitType, textFormat, parsedCardSet, statementV1, st
|
|
|
36060
36271
|
case CardSetConfigKey.flashcard:
|
|
36061
36272
|
case CardSetConfigKey.flashcard1:
|
|
36062
36273
|
case CardSetConfigKey.definitionList:
|
|
36274
|
+
case CardSetConfigKey.definitionListPlain:
|
|
36063
36275
|
result = parseFlashcardOrDefinitionList(context, bitType, processedCardSet);
|
|
36064
36276
|
break;
|
|
36065
36277
|
case CardSetConfigKey.elements:
|
|
@@ -42396,6 +42608,235 @@ var BitmarkFileGenerator = class {
|
|
|
42396
42608
|
}
|
|
42397
42609
|
};
|
|
42398
42610
|
|
|
42611
|
+
// src/generator/html/HtmlTableGenerator.ts
|
|
42612
|
+
var MARK_TO_TAG = {
|
|
42613
|
+
bold: "b",
|
|
42614
|
+
italic: "i",
|
|
42615
|
+
superscript: "sup",
|
|
42616
|
+
subscript: "sub",
|
|
42617
|
+
strike: "s",
|
|
42618
|
+
del: "del",
|
|
42619
|
+
ins: "ins",
|
|
42620
|
+
underline: "u",
|
|
42621
|
+
highlight: "mark",
|
|
42622
|
+
code: "code"
|
|
42623
|
+
};
|
|
42624
|
+
var HtmlTableGenerator = class {
|
|
42625
|
+
constructor() {
|
|
42626
|
+
__publicField(this, "indentUnit", " ");
|
|
42627
|
+
}
|
|
42628
|
+
/**
|
|
42629
|
+
* Generate HTML table fragments from a string or JSON value.
|
|
42630
|
+
* @returns the concatenated `<table>` fragments, blank-line separated (empty string if none).
|
|
42631
|
+
*/
|
|
42632
|
+
generate(input) {
|
|
42633
|
+
let data = input;
|
|
42634
|
+
if (typeof data === "string") {
|
|
42635
|
+
try {
|
|
42636
|
+
data = JSON.parse(data);
|
|
42637
|
+
} catch {
|
|
42638
|
+
return "";
|
|
42639
|
+
}
|
|
42640
|
+
}
|
|
42641
|
+
const bits = this.collectBits(data);
|
|
42642
|
+
const fragments = [];
|
|
42643
|
+
for (const bit of bits) {
|
|
42644
|
+
const html = this.renderTableBit(bit);
|
|
42645
|
+
if (html) fragments.push(html);
|
|
42646
|
+
}
|
|
42647
|
+
return fragments.join("\n\n");
|
|
42648
|
+
}
|
|
42649
|
+
// --- bit collection -------------------------------------------------------
|
|
42650
|
+
collectBits(data) {
|
|
42651
|
+
const out = [];
|
|
42652
|
+
const visit = (value) => {
|
|
42653
|
+
if (value == null || typeof value !== "object") return;
|
|
42654
|
+
if (Array.isArray(value)) {
|
|
42655
|
+
value.forEach(visit);
|
|
42656
|
+
return;
|
|
42657
|
+
}
|
|
42658
|
+
const obj = value;
|
|
42659
|
+
if ("bit" in obj && obj.bit && typeof obj.bit === "object") {
|
|
42660
|
+
out.push(obj.bit);
|
|
42661
|
+
} else if ("type" in obj) {
|
|
42662
|
+
out.push(obj);
|
|
42663
|
+
}
|
|
42664
|
+
};
|
|
42665
|
+
visit(data);
|
|
42666
|
+
return out;
|
|
42667
|
+
}
|
|
42668
|
+
// --- table rendering ------------------------------------------------------
|
|
42669
|
+
renderTableBit(bit) {
|
|
42670
|
+
const table = bit.table;
|
|
42671
|
+
if (!table) return "";
|
|
42672
|
+
if (bit.type !== "table" && bit.type !== "table-extended") return "";
|
|
42673
|
+
const extended = this.toExtended(table);
|
|
42674
|
+
const lines = [];
|
|
42675
|
+
lines.push("<table>");
|
|
42676
|
+
if (bit.caption != null) {
|
|
42677
|
+
const caption = this.cellContentToHtml(this.asTextAst(bit.caption));
|
|
42678
|
+
if (caption) lines.push(`${this.indentUnit}<caption>${caption}</caption>`);
|
|
42679
|
+
}
|
|
42680
|
+
this.renderSection(lines, "thead", extended.header, "header");
|
|
42681
|
+
this.renderSection(lines, "tbody", extended.body, "body");
|
|
42682
|
+
this.renderSection(lines, "tfoot", extended.footer, "footer");
|
|
42683
|
+
lines.push("</table>");
|
|
42684
|
+
return lines.join("\n");
|
|
42685
|
+
}
|
|
42686
|
+
toExtended(table) {
|
|
42687
|
+
const t = table;
|
|
42688
|
+
if (t.header || t.body || t.footer) return table;
|
|
42689
|
+
return convertBasicToExtendedTableFormat(table);
|
|
42690
|
+
}
|
|
42691
|
+
renderSection(lines, tag, section, key) {
|
|
42692
|
+
if (!section || !section.rows || section.rows.length === 0) return;
|
|
42693
|
+
lines.push(`${this.indentUnit}<${tag}>`);
|
|
42694
|
+
for (const row of section.rows) {
|
|
42695
|
+
lines.push(`${this.indentUnit.repeat(2)}<tr>`);
|
|
42696
|
+
for (const cell of row.cells ?? []) {
|
|
42697
|
+
lines.push(`${this.indentUnit.repeat(3)}${this.renderCell(cell, key)}`);
|
|
42698
|
+
}
|
|
42699
|
+
lines.push(`${this.indentUnit.repeat(2)}</tr>`);
|
|
42700
|
+
}
|
|
42701
|
+
lines.push(`${this.indentUnit}</${tag}>`);
|
|
42702
|
+
}
|
|
42703
|
+
renderCell(cell, _key) {
|
|
42704
|
+
const tag = cell.title === true ? "th" : "td";
|
|
42705
|
+
const attrs = [];
|
|
42706
|
+
if (cell.rowspan && cell.rowspan > 1) attrs.push(`rowspan="${cell.rowspan}"`);
|
|
42707
|
+
if (cell.colspan && cell.colspan > 1) attrs.push(`colspan="${cell.colspan}"`);
|
|
42708
|
+
if (cell.scope) attrs.push(`scope="${cell.scope}"`);
|
|
42709
|
+
if (cell.colwidth && cell.colwidth > 0) attrs.push(`width="${cell.colwidth}"`);
|
|
42710
|
+
const open = attrs.length > 0 ? `<${tag} ${attrs.join(" ")}>` : `<${tag}>`;
|
|
42711
|
+
return `${open}${this.cellContentToHtml(this.asTextAst(cell.content))}</${tag}>`;
|
|
42712
|
+
}
|
|
42713
|
+
// --- cell content (TextAst -> HTML) ---------------------------------------
|
|
42714
|
+
asTextAst(content) {
|
|
42715
|
+
if (content == null) return [];
|
|
42716
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
42717
|
+
return content;
|
|
42718
|
+
}
|
|
42719
|
+
cellContentToHtml(blocks) {
|
|
42720
|
+
if (blocks.length === 0) return "";
|
|
42721
|
+
if (blocks.length === 1 && blocks[0].type === "paragraph") {
|
|
42722
|
+
return this.inlineToHtml(blocks[0].content ?? []);
|
|
42723
|
+
}
|
|
42724
|
+
return blocks.map((b) => this.blockToHtml(b)).join("");
|
|
42725
|
+
}
|
|
42726
|
+
blockToHtml(node) {
|
|
42727
|
+
switch (node.type) {
|
|
42728
|
+
case "paragraph":
|
|
42729
|
+
return `<p>${this.inlineToHtml(node.content ?? [])}</p>`;
|
|
42730
|
+
case "bulletList":
|
|
42731
|
+
case "noBulletList":
|
|
42732
|
+
case "orderedList":
|
|
42733
|
+
case "orderedListRoman":
|
|
42734
|
+
case "orderedListRomanLower":
|
|
42735
|
+
case "letteredList":
|
|
42736
|
+
case "letteredListLower":
|
|
42737
|
+
case "taskList":
|
|
42738
|
+
return this.listToHtml(node);
|
|
42739
|
+
case "image":
|
|
42740
|
+
case "imageInline":
|
|
42741
|
+
return this.imageToHtml(node);
|
|
42742
|
+
default:
|
|
42743
|
+
return this.inlineToHtml([node]);
|
|
42744
|
+
}
|
|
42745
|
+
}
|
|
42746
|
+
inlineToHtml(nodes) {
|
|
42747
|
+
return nodes.map((n) => this.inlineNodeToHtml(n)).join("");
|
|
42748
|
+
}
|
|
42749
|
+
inlineNodeToHtml(node) {
|
|
42750
|
+
if (node.type === "hardBreak") return "<br>";
|
|
42751
|
+
if (node.type === "image" || node.type === "imageInline") return this.imageToHtml(node);
|
|
42752
|
+
if (node.type === "text") {
|
|
42753
|
+
return this.wrapMarks(this.escapeText(node.text ?? ""), node.marks);
|
|
42754
|
+
}
|
|
42755
|
+
if (node.content) return this.inlineToHtml(node.content);
|
|
42756
|
+
return this.escapeText(node.text ?? "");
|
|
42757
|
+
}
|
|
42758
|
+
wrapMarks(text, marks) {
|
|
42759
|
+
if (!marks || marks.length === 0) return text;
|
|
42760
|
+
let open = "";
|
|
42761
|
+
let close = "";
|
|
42762
|
+
for (const mark of marks) {
|
|
42763
|
+
if (mark.type === "link") {
|
|
42764
|
+
const href = mark.attrs?.href ?? "";
|
|
42765
|
+
open += `<a href="${this.escapeAttr(href)}">`;
|
|
42766
|
+
close = `</a>${close}`;
|
|
42767
|
+
} else {
|
|
42768
|
+
const tag = MARK_TO_TAG[mark.type];
|
|
42769
|
+
if (tag) {
|
|
42770
|
+
open += `<${tag}>`;
|
|
42771
|
+
close = `</${tag}>${close}`;
|
|
42772
|
+
}
|
|
42773
|
+
}
|
|
42774
|
+
}
|
|
42775
|
+
return `${open}${text}${close}`;
|
|
42776
|
+
}
|
|
42777
|
+
// --- lists ----------------------------------------------------------------
|
|
42778
|
+
listToHtml(node) {
|
|
42779
|
+
const { tag, attrs } = this.listTag(node);
|
|
42780
|
+
const items = (node.content ?? []).map((item) => this.listItemToHtml(item, node.type === "taskList")).join("");
|
|
42781
|
+
return `<${tag}${attrs}>${items}</${tag}>`;
|
|
42782
|
+
}
|
|
42783
|
+
listTag(node) {
|
|
42784
|
+
const start = node.attrs?.start;
|
|
42785
|
+
const startAttr = typeof start === "number" && start !== 1 ? ` start="${start}"` : "";
|
|
42786
|
+
switch (node.type) {
|
|
42787
|
+
case "orderedList":
|
|
42788
|
+
return { tag: "ol", attrs: startAttr };
|
|
42789
|
+
case "orderedListRoman":
|
|
42790
|
+
return { tag: "ol", attrs: ` type="I"${startAttr}` };
|
|
42791
|
+
case "orderedListRomanLower":
|
|
42792
|
+
return { tag: "ol", attrs: ` type="i"${startAttr}` };
|
|
42793
|
+
case "letteredList":
|
|
42794
|
+
return { tag: "ol", attrs: ` type="A"${startAttr}` };
|
|
42795
|
+
case "letteredListLower":
|
|
42796
|
+
return { tag: "ol", attrs: ` type="a"${startAttr}` };
|
|
42797
|
+
case "noBulletList":
|
|
42798
|
+
return { tag: "ul", attrs: ' style="list-style:none"' };
|
|
42799
|
+
case "taskList":
|
|
42800
|
+
case "bulletList":
|
|
42801
|
+
default:
|
|
42802
|
+
return { tag: "ul", attrs: "" };
|
|
42803
|
+
}
|
|
42804
|
+
}
|
|
42805
|
+
listItemToHtml(item, task) {
|
|
42806
|
+
const inner = (item.content ?? []).map((b) => {
|
|
42807
|
+
if (b.type === "paragraph") return this.inlineToHtml(b.content ?? []);
|
|
42808
|
+
return this.blockToHtml(b);
|
|
42809
|
+
}).join("");
|
|
42810
|
+
if (task) {
|
|
42811
|
+
const checked = item.attrs?.checked ? " checked" : "";
|
|
42812
|
+
return `<li><input type="checkbox"${checked}>${inner}</li>`;
|
|
42813
|
+
}
|
|
42814
|
+
return `<li>${inner}</li>`;
|
|
42815
|
+
}
|
|
42816
|
+
// --- images ---------------------------------------------------------------
|
|
42817
|
+
imageToHtml(node) {
|
|
42818
|
+
const attrs = node.attrs ?? {};
|
|
42819
|
+
const parts = [];
|
|
42820
|
+
const src = attrs.src;
|
|
42821
|
+
parts.push(`src="${this.escapeAttr(typeof src === "string" ? src : "")}"`);
|
|
42822
|
+
if (typeof attrs.alt === "string") parts.push(`alt="${this.escapeAttr(attrs.alt)}"`);
|
|
42823
|
+
if (typeof attrs.title === "string") parts.push(`title="${this.escapeAttr(attrs.title)}"`);
|
|
42824
|
+
if (attrs.width != null) parts.push(`width="${attrs.width}"`);
|
|
42825
|
+
if (attrs.height != null) parts.push(`height="${attrs.height}"`);
|
|
42826
|
+
if (typeof attrs.class === "string" && attrs.class) {
|
|
42827
|
+
parts.push(`class="${this.escapeAttr(attrs.class)}"`);
|
|
42828
|
+
}
|
|
42829
|
+
return `<img ${parts.join(" ")}>`;
|
|
42830
|
+
}
|
|
42831
|
+
// --- escaping -------------------------------------------------------------
|
|
42832
|
+
escapeText(text) {
|
|
42833
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
42834
|
+
}
|
|
42835
|
+
escapeAttr(text) {
|
|
42836
|
+
return this.escapeText(text).replace(/"/g, """);
|
|
42837
|
+
}
|
|
42838
|
+
};
|
|
42839
|
+
|
|
42399
42840
|
// src/generator/json/JsonFileGenerator.ts
|
|
42400
42841
|
import "fs";
|
|
42401
42842
|
var JsonFileGenerator = class {
|
|
@@ -43372,6 +43813,499 @@ var ConfigBuilder = class {
|
|
|
43372
43813
|
}
|
|
43373
43814
|
};
|
|
43374
43815
|
|
|
43816
|
+
// src/parser/html/HtmlDom.ts
|
|
43817
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
43818
|
+
"area",
|
|
43819
|
+
"base",
|
|
43820
|
+
"br",
|
|
43821
|
+
"col",
|
|
43822
|
+
"embed",
|
|
43823
|
+
"hr",
|
|
43824
|
+
"img",
|
|
43825
|
+
"input",
|
|
43826
|
+
"link",
|
|
43827
|
+
"meta",
|
|
43828
|
+
"param",
|
|
43829
|
+
"source",
|
|
43830
|
+
"track",
|
|
43831
|
+
"wbr"
|
|
43832
|
+
]);
|
|
43833
|
+
var IMPLIED_CLOSE = {
|
|
43834
|
+
li: /* @__PURE__ */ new Set(["li"]),
|
|
43835
|
+
td: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43836
|
+
th: /* @__PURE__ */ new Set(["td", "th"]),
|
|
43837
|
+
tr: /* @__PURE__ */ new Set(["td", "th", "tr"]),
|
|
43838
|
+
thead: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43839
|
+
tbody: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43840
|
+
tfoot: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot"]),
|
|
43841
|
+
p: /* @__PURE__ */ new Set(["p"]),
|
|
43842
|
+
option: /* @__PURE__ */ new Set(["option"])
|
|
43843
|
+
};
|
|
43844
|
+
var TAG_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)((?:\s+(?:"[^"]*"|'[^']*'|[^<>"'])*)?)(\/)?>/g;
|
|
43845
|
+
var ATTR_RE = /([a-zA-Z_:][a-zA-Z0-9:._-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
|
|
43846
|
+
function parseAttrs(raw) {
|
|
43847
|
+
const attrs = {};
|
|
43848
|
+
if (!raw) return attrs;
|
|
43849
|
+
ATTR_RE.lastIndex = 0;
|
|
43850
|
+
let m;
|
|
43851
|
+
while ((m = ATTR_RE.exec(raw)) !== null) {
|
|
43852
|
+
const name = m[1].toLowerCase();
|
|
43853
|
+
let value = m[2] ?? "";
|
|
43854
|
+
if (value.length >= 2 && (value[0] === '"' || value[0] === "'")) {
|
|
43855
|
+
value = value.slice(1, -1);
|
|
43856
|
+
}
|
|
43857
|
+
attrs[name] = value;
|
|
43858
|
+
}
|
|
43859
|
+
return attrs;
|
|
43860
|
+
}
|
|
43861
|
+
function stripNonContent(html) {
|
|
43862
|
+
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, "");
|
|
43863
|
+
}
|
|
43864
|
+
function tokenize(html) {
|
|
43865
|
+
const tokens = [];
|
|
43866
|
+
const clean = stripNonContent(html);
|
|
43867
|
+
TAG_RE.lastIndex = 0;
|
|
43868
|
+
let lastIndex = 0;
|
|
43869
|
+
let m;
|
|
43870
|
+
while ((m = TAG_RE.exec(clean)) !== null) {
|
|
43871
|
+
if (m.index > lastIndex) {
|
|
43872
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex, m.index) });
|
|
43873
|
+
}
|
|
43874
|
+
lastIndex = TAG_RE.lastIndex;
|
|
43875
|
+
const isClose = m[1] === "/";
|
|
43876
|
+
const name = m[2].toLowerCase();
|
|
43877
|
+
if (isClose) {
|
|
43878
|
+
tokens.push({ kind: "close", name });
|
|
43879
|
+
} else {
|
|
43880
|
+
tokens.push({
|
|
43881
|
+
kind: "open",
|
|
43882
|
+
name,
|
|
43883
|
+
attrs: parseAttrs(m[3]),
|
|
43884
|
+
selfClose: m[4] === "/"
|
|
43885
|
+
});
|
|
43886
|
+
}
|
|
43887
|
+
}
|
|
43888
|
+
if (lastIndex < clean.length) {
|
|
43889
|
+
tokens.push({ kind: "text", text: clean.slice(lastIndex) });
|
|
43890
|
+
}
|
|
43891
|
+
return tokens;
|
|
43892
|
+
}
|
|
43893
|
+
function parseHtml(html) {
|
|
43894
|
+
const root = { type: "element", name: "#root", attrs: {}, children: [] };
|
|
43895
|
+
const stack = [root];
|
|
43896
|
+
const top = () => stack[stack.length - 1];
|
|
43897
|
+
for (const token of tokenize(html)) {
|
|
43898
|
+
if (token.kind === "text") {
|
|
43899
|
+
if (token.text) top().children.push({ type: "text", value: token.text });
|
|
43900
|
+
continue;
|
|
43901
|
+
}
|
|
43902
|
+
if (token.kind === "open") {
|
|
43903
|
+
const name = token.name;
|
|
43904
|
+
const closes = IMPLIED_CLOSE[name];
|
|
43905
|
+
if (closes) {
|
|
43906
|
+
while (stack.length > 1 && closes.has(top().name)) stack.pop();
|
|
43907
|
+
}
|
|
43908
|
+
const el = {
|
|
43909
|
+
type: "element",
|
|
43910
|
+
name,
|
|
43911
|
+
attrs: token.attrs ?? {},
|
|
43912
|
+
children: []
|
|
43913
|
+
};
|
|
43914
|
+
top().children.push(el);
|
|
43915
|
+
if (!token.selfClose && !VOID_ELEMENTS.has(name)) {
|
|
43916
|
+
stack.push(el);
|
|
43917
|
+
}
|
|
43918
|
+
continue;
|
|
43919
|
+
}
|
|
43920
|
+
for (let i = stack.length - 1; i > 0; i--) {
|
|
43921
|
+
if (stack[i].name === token.name) {
|
|
43922
|
+
stack.length = i;
|
|
43923
|
+
break;
|
|
43924
|
+
}
|
|
43925
|
+
}
|
|
43926
|
+
}
|
|
43927
|
+
return root.children;
|
|
43928
|
+
}
|
|
43929
|
+
function childElements(el, names) {
|
|
43930
|
+
return el.children.filter((c) => c.type === "element" && names.has(c.name));
|
|
43931
|
+
}
|
|
43932
|
+
|
|
43933
|
+
// src/parser/html/HtmlTableParser.ts
|
|
43934
|
+
var MARK_TAGS = {
|
|
43935
|
+
b: "bold",
|
|
43936
|
+
strong: "bold",
|
|
43937
|
+
i: "italic",
|
|
43938
|
+
em: "italic",
|
|
43939
|
+
sup: "superscript",
|
|
43940
|
+
sub: "subscript",
|
|
43941
|
+
s: "strike",
|
|
43942
|
+
strike: "strike",
|
|
43943
|
+
del: "del",
|
|
43944
|
+
ins: "ins",
|
|
43945
|
+
u: "underline",
|
|
43946
|
+
mark: "highlight",
|
|
43947
|
+
code: "code"
|
|
43948
|
+
};
|
|
43949
|
+
var SECTION_TAGS = /* @__PURE__ */ new Set(["thead", "tbody", "tfoot"]);
|
|
43950
|
+
var ROW_TAGS = /* @__PURE__ */ new Set(["tr"]);
|
|
43951
|
+
var CELL_TAGS = /* @__PURE__ */ new Set(["td", "th"]);
|
|
43952
|
+
var LI_TAGS = /* @__PURE__ */ new Set(["li"]);
|
|
43953
|
+
var VALID_SCOPES = /* @__PURE__ */ new Set(["row", "col", "rowgroup", "colgroup"]);
|
|
43954
|
+
var NAMED_ENTITIES = {
|
|
43955
|
+
amp: "&",
|
|
43956
|
+
lt: "<",
|
|
43957
|
+
gt: ">",
|
|
43958
|
+
quot: '"',
|
|
43959
|
+
apos: "'",
|
|
43960
|
+
nbsp: "\xA0"
|
|
43961
|
+
};
|
|
43962
|
+
function decodeEntities(text) {
|
|
43963
|
+
return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, (whole, body) => {
|
|
43964
|
+
if (body[0] === "#") {
|
|
43965
|
+
const code = body[1] === "x" || body[1] === "X" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);
|
|
43966
|
+
if (Number.isFinite(code) && code >= 0 && code <= 1114111) {
|
|
43967
|
+
try {
|
|
43968
|
+
return String.fromCodePoint(code);
|
|
43969
|
+
} catch {
|
|
43970
|
+
return whole;
|
|
43971
|
+
}
|
|
43972
|
+
}
|
|
43973
|
+
return whole;
|
|
43974
|
+
}
|
|
43975
|
+
return NAMED_ENTITIES[body] ?? whole;
|
|
43976
|
+
});
|
|
43977
|
+
}
|
|
43978
|
+
function intAttr(value) {
|
|
43979
|
+
if (value == null) return void 0;
|
|
43980
|
+
const n = Number.parseInt(value, 10);
|
|
43981
|
+
return Number.isInteger(n) ? n : void 0;
|
|
43982
|
+
}
|
|
43983
|
+
function isElement(node) {
|
|
43984
|
+
return node.type === "element";
|
|
43985
|
+
}
|
|
43986
|
+
var HtmlTableParser = class {
|
|
43987
|
+
constructor() {
|
|
43988
|
+
__publicField(this, "keepUnknownTags", false);
|
|
43989
|
+
}
|
|
43990
|
+
/**
|
|
43991
|
+
* Parse an HTML string and return one table bit per top-level `<table>`.
|
|
43992
|
+
*/
|
|
43993
|
+
parse(html, options) {
|
|
43994
|
+
this.keepUnknownTags = options?.keepUnknownTags ?? false;
|
|
43995
|
+
const tableFormat = options?.tableFormat ?? "table-extended";
|
|
43996
|
+
const onWarning = options?.onWarning;
|
|
43997
|
+
const tables = this.collectTopLevelTables(parseHtml(html));
|
|
43998
|
+
const bits = [];
|
|
43999
|
+
for (const table of tables) {
|
|
44000
|
+
const bit = this.tableToBit(table, tableFormat, onWarning);
|
|
44001
|
+
if (bit) bits.push(bit);
|
|
44002
|
+
}
|
|
44003
|
+
return bits;
|
|
44004
|
+
}
|
|
44005
|
+
// --- table extraction -----------------------------------------------------
|
|
44006
|
+
/** Collect every `<table>` element, NOT descending into nested tables. */
|
|
44007
|
+
collectTopLevelTables(nodes) {
|
|
44008
|
+
const tables = [];
|
|
44009
|
+
const visit = (node) => {
|
|
44010
|
+
if (!isElement(node)) return;
|
|
44011
|
+
if (node.name === "table") {
|
|
44012
|
+
tables.push(node);
|
|
44013
|
+
return;
|
|
44014
|
+
}
|
|
44015
|
+
node.children.forEach(visit);
|
|
44016
|
+
};
|
|
44017
|
+
nodes.forEach(visit);
|
|
44018
|
+
return tables;
|
|
44019
|
+
}
|
|
44020
|
+
tableToBit(table, tableFormat, onWarning) {
|
|
44021
|
+
const header = [];
|
|
44022
|
+
const body = [];
|
|
44023
|
+
const footer = [];
|
|
44024
|
+
let caption;
|
|
44025
|
+
for (const child of table.children) {
|
|
44026
|
+
if (!isElement(child)) continue;
|
|
44027
|
+
if (child.name === "caption") {
|
|
44028
|
+
const capContent = this.inlineNodes(child.children, []);
|
|
44029
|
+
const trimmed = this.trimInline(capContent);
|
|
44030
|
+
if (trimmed.length > 0) caption = trimmed;
|
|
44031
|
+
} else if (SECTION_TAGS.has(child.name)) {
|
|
44032
|
+
const target = child.name === "thead" ? header : child.name === "tfoot" ? footer : body;
|
|
44033
|
+
for (const tr of childElements(child, ROW_TAGS)) {
|
|
44034
|
+
target.push(this.rowToCells(tr));
|
|
44035
|
+
}
|
|
44036
|
+
} else if (ROW_TAGS.has(child.name)) {
|
|
44037
|
+
body.push(this.rowToCells(child));
|
|
44038
|
+
}
|
|
44039
|
+
}
|
|
44040
|
+
if (header.length === 0 && body.length === 0 && footer.length === 0) {
|
|
44041
|
+
return void 0;
|
|
44042
|
+
}
|
|
44043
|
+
const tableExtended = {};
|
|
44044
|
+
if (header.length > 0) tableExtended.header = { rows: header };
|
|
44045
|
+
if (body.length > 0) tableExtended.body = { rows: body };
|
|
44046
|
+
if (footer.length > 0) tableExtended.footer = { rows: footer };
|
|
44047
|
+
let tableData = tableExtended;
|
|
44048
|
+
if (tableFormat === "table") {
|
|
44049
|
+
if (this.isLossyAsBasic(tableExtended)) {
|
|
44050
|
+
onWarning?.(
|
|
44051
|
+
"Converting an HTML table to [.table] loses rowspan/colspan/scope and multi-section structure; use --tableFormat table-extended to preserve them."
|
|
44052
|
+
);
|
|
44053
|
+
}
|
|
44054
|
+
tableData = convertExtendedToBasicTableFormat(tableExtended);
|
|
44055
|
+
}
|
|
44056
|
+
const bit = {
|
|
44057
|
+
type: tableFormat,
|
|
44058
|
+
format: "bitmark++",
|
|
44059
|
+
table: tableData
|
|
44060
|
+
};
|
|
44061
|
+
if (caption) bit.caption = caption;
|
|
44062
|
+
return bit;
|
|
44063
|
+
}
|
|
44064
|
+
rowToCells(tr) {
|
|
44065
|
+
const cells = [];
|
|
44066
|
+
for (const cell of childElements(tr, CELL_TAGS)) {
|
|
44067
|
+
cells.push(this.cellToJson(cell));
|
|
44068
|
+
}
|
|
44069
|
+
return { cells };
|
|
44070
|
+
}
|
|
44071
|
+
cellToJson(cell) {
|
|
44072
|
+
const json = {
|
|
44073
|
+
content: this.blockNodes(cell.children)
|
|
44074
|
+
};
|
|
44075
|
+
if (cell.name === "th") json.title = true;
|
|
44076
|
+
const rowspan = intAttr(cell.attrs.rowspan);
|
|
44077
|
+
if (rowspan != null && rowspan >= 2) json.rowspan = rowspan;
|
|
44078
|
+
const colspan = intAttr(cell.attrs.colspan);
|
|
44079
|
+
if (colspan != null && colspan >= 2) json.colspan = colspan;
|
|
44080
|
+
const scope = cell.attrs.scope?.toLowerCase();
|
|
44081
|
+
if (scope && VALID_SCOPES.has(scope)) {
|
|
44082
|
+
json.scope = scope;
|
|
44083
|
+
}
|
|
44084
|
+
const width = this.widthFromCell(cell);
|
|
44085
|
+
if (width != null) json.colwidth = width;
|
|
44086
|
+
return json;
|
|
44087
|
+
}
|
|
44088
|
+
widthFromCell(cell) {
|
|
44089
|
+
const attrWidth = intAttr(cell.attrs.width);
|
|
44090
|
+
if (attrWidth != null && attrWidth > 0) return attrWidth;
|
|
44091
|
+
const style = cell.attrs.style;
|
|
44092
|
+
if (style) {
|
|
44093
|
+
const m = style.match(/width\s*:\s*(\d+)\s*px/i);
|
|
44094
|
+
if (m) {
|
|
44095
|
+
const n = Number.parseInt(m[1], 10);
|
|
44096
|
+
if (Number.isInteger(n) && n > 0) return n;
|
|
44097
|
+
}
|
|
44098
|
+
}
|
|
44099
|
+
return void 0;
|
|
44100
|
+
}
|
|
44101
|
+
isLossyAsBasic(table) {
|
|
44102
|
+
if (table.footer) return true;
|
|
44103
|
+
if (table.header && table.header.rows.length > 1) return true;
|
|
44104
|
+
const sections = [table.header, table.body, table.footer];
|
|
44105
|
+
for (const section of sections) {
|
|
44106
|
+
if (!section) continue;
|
|
44107
|
+
for (const row of section.rows) {
|
|
44108
|
+
for (const cell of row.cells) {
|
|
44109
|
+
if (cell.rowspan || cell.colspan || cell.scope) return true;
|
|
44110
|
+
}
|
|
44111
|
+
}
|
|
44112
|
+
}
|
|
44113
|
+
return false;
|
|
44114
|
+
}
|
|
44115
|
+
// --- content conversion (HTML -> TextAst) ---------------------------------
|
|
44116
|
+
/**
|
|
44117
|
+
* Convert a cell/li's child nodes into block-level TextAst nodes (paragraphs, lists, images).
|
|
44118
|
+
*/
|
|
44119
|
+
blockNodes(nodes) {
|
|
44120
|
+
const blocks = [];
|
|
44121
|
+
let inline = [];
|
|
44122
|
+
const flush = () => {
|
|
44123
|
+
const trimmed = this.trimInline(inline);
|
|
44124
|
+
inline = [];
|
|
44125
|
+
if (trimmed.length === 0) return;
|
|
44126
|
+
if (trimmed.length === 1 && trimmed[0].type === "imageInline") {
|
|
44127
|
+
blocks.push({ ...trimmed[0], type: "image" });
|
|
44128
|
+
} else {
|
|
44129
|
+
blocks.push({ type: "paragraph", content: trimmed, attrs: {} });
|
|
44130
|
+
}
|
|
44131
|
+
};
|
|
44132
|
+
for (const node of nodes) {
|
|
44133
|
+
if (!isElement(node)) {
|
|
44134
|
+
inline.push(...this.inlineText(node.value, []));
|
|
44135
|
+
continue;
|
|
44136
|
+
}
|
|
44137
|
+
const name = node.name;
|
|
44138
|
+
if (name === "p") {
|
|
44139
|
+
flush();
|
|
44140
|
+
const content = this.trimInline(this.inlineNodes(node.children, []));
|
|
44141
|
+
if (content.length > 0) {
|
|
44142
|
+
blocks.push({ type: "paragraph", content, attrs: {} });
|
|
44143
|
+
}
|
|
44144
|
+
} else if (this.isListTag(name)) {
|
|
44145
|
+
flush();
|
|
44146
|
+
const list = this.listNode(node);
|
|
44147
|
+
if (list) blocks.push(list);
|
|
44148
|
+
} else {
|
|
44149
|
+
inline.push(...this.inlineFromElement(node, []));
|
|
44150
|
+
}
|
|
44151
|
+
}
|
|
44152
|
+
flush();
|
|
44153
|
+
return blocks;
|
|
44154
|
+
}
|
|
44155
|
+
/** Convert child nodes to a flat list of inline TextNodes, applying the given marks. */
|
|
44156
|
+
inlineNodes(nodes, marks) {
|
|
44157
|
+
const out = [];
|
|
44158
|
+
for (const node of nodes) {
|
|
44159
|
+
if (!isElement(node)) {
|
|
44160
|
+
out.push(...this.inlineText(node.value, marks));
|
|
44161
|
+
} else {
|
|
44162
|
+
out.push(...this.inlineFromElement(node, marks));
|
|
44163
|
+
}
|
|
44164
|
+
}
|
|
44165
|
+
return out;
|
|
44166
|
+
}
|
|
44167
|
+
inlineFromElement(el, marks) {
|
|
44168
|
+
const name = el.name;
|
|
44169
|
+
if (name === "br") {
|
|
44170
|
+
return [{ type: "hardBreak" }];
|
|
44171
|
+
}
|
|
44172
|
+
if (name === "img") {
|
|
44173
|
+
return [this.imageNode(el, true)];
|
|
44174
|
+
}
|
|
44175
|
+
const markType = MARK_TAGS[name];
|
|
44176
|
+
if (markType) {
|
|
44177
|
+
return this.inlineNodes(el.children, [...marks, { type: markType }]);
|
|
44178
|
+
}
|
|
44179
|
+
if (name === "a") {
|
|
44180
|
+
const linkMark = {
|
|
44181
|
+
type: "link",
|
|
44182
|
+
attrs: {
|
|
44183
|
+
href: el.attrs.href ?? "",
|
|
44184
|
+
...el.attrs.target ? { target: el.attrs.target } : {}
|
|
44185
|
+
}
|
|
44186
|
+
};
|
|
44187
|
+
return this.inlineNodes(el.children, [...marks, linkMark]);
|
|
44188
|
+
}
|
|
44189
|
+
if (this.keepUnknownTags) {
|
|
44190
|
+
const open = this.serializeOpenTag(el);
|
|
44191
|
+
const close = `</${name}>`;
|
|
44192
|
+
return [
|
|
44193
|
+
...this.inlineText(open, marks),
|
|
44194
|
+
...this.inlineNodes(el.children, marks),
|
|
44195
|
+
...this.inlineText(close, marks)
|
|
44196
|
+
];
|
|
44197
|
+
}
|
|
44198
|
+
return this.inlineNodes(el.children, marks);
|
|
44199
|
+
}
|
|
44200
|
+
inlineText(raw, marks) {
|
|
44201
|
+
const text = decodeEntities(raw).replace(/\s+/g, " ");
|
|
44202
|
+
if (text === "") return [];
|
|
44203
|
+
const node = { text, type: "text" };
|
|
44204
|
+
if (marks.length > 0) node.marks = marks.map((m) => ({ ...m }));
|
|
44205
|
+
return [node];
|
|
44206
|
+
}
|
|
44207
|
+
serializeOpenTag(el) {
|
|
44208
|
+
const attrs = Object.entries(el.attrs).map(([k, v]) => v === "" ? ` ${k}` : ` ${k}="${v}"`).join("");
|
|
44209
|
+
return `<${el.name}${attrs}>`;
|
|
44210
|
+
}
|
|
44211
|
+
// --- lists ----------------------------------------------------------------
|
|
44212
|
+
isListTag(name) {
|
|
44213
|
+
return name === "ul" || name === "ol";
|
|
44214
|
+
}
|
|
44215
|
+
listNode(el) {
|
|
44216
|
+
const items = childElements(el, LI_TAGS);
|
|
44217
|
+
if (items.length === 0) return void 0;
|
|
44218
|
+
const isTask = el.name === "ul" && items.some((li) => {
|
|
44219
|
+
const firstEl = li.children.find(isElement);
|
|
44220
|
+
return firstEl?.name === "input" && firstEl.attrs.type?.toLowerCase() === "checkbox";
|
|
44221
|
+
});
|
|
44222
|
+
if (isTask) {
|
|
44223
|
+
return {
|
|
44224
|
+
type: "taskList",
|
|
44225
|
+
content: items.map((li) => this.taskItemNode(li))
|
|
44226
|
+
};
|
|
44227
|
+
}
|
|
44228
|
+
const type = this.listType(el);
|
|
44229
|
+
const node = {
|
|
44230
|
+
type,
|
|
44231
|
+
content: items.map((li) => this.listItemNode(li))
|
|
44232
|
+
};
|
|
44233
|
+
if (el.name === "ol") {
|
|
44234
|
+
const start = intAttr(el.attrs.start);
|
|
44235
|
+
if (start != null) {
|
|
44236
|
+
node.attrs = { start };
|
|
44237
|
+
}
|
|
44238
|
+
}
|
|
44239
|
+
return node;
|
|
44240
|
+
}
|
|
44241
|
+
listType(el) {
|
|
44242
|
+
if (el.name === "ol") {
|
|
44243
|
+
switch (el.attrs.type) {
|
|
44244
|
+
case "i":
|
|
44245
|
+
return "orderedListRomanLower";
|
|
44246
|
+
case "I":
|
|
44247
|
+
return "orderedListRoman";
|
|
44248
|
+
case "a":
|
|
44249
|
+
return "letteredListLower";
|
|
44250
|
+
case "A":
|
|
44251
|
+
return "letteredList";
|
|
44252
|
+
default:
|
|
44253
|
+
return "orderedList";
|
|
44254
|
+
}
|
|
44255
|
+
}
|
|
44256
|
+
const style = el.attrs.style ?? "";
|
|
44257
|
+
if (/list-style(-type)?\s*:\s*none/i.test(style)) return "noBulletList";
|
|
44258
|
+
return "bulletList";
|
|
44259
|
+
}
|
|
44260
|
+
listItemNode(li) {
|
|
44261
|
+
let content = this.blockNodes(li.children);
|
|
44262
|
+
if (content.length === 0) {
|
|
44263
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
44264
|
+
}
|
|
44265
|
+
return { type: "listItem", content };
|
|
44266
|
+
}
|
|
44267
|
+
taskItemNode(li) {
|
|
44268
|
+
const checkbox = li.children.find(
|
|
44269
|
+
(c) => isElement(c) && c.name === "input" && c.attrs.type?.toLowerCase() === "checkbox"
|
|
44270
|
+
);
|
|
44271
|
+
const checked = checkbox ? "checked" in checkbox.attrs : false;
|
|
44272
|
+
const rest = li.children.filter((c) => c !== checkbox);
|
|
44273
|
+
let content = this.blockNodes(rest);
|
|
44274
|
+
if (content.length === 0) {
|
|
44275
|
+
content = [{ type: "paragraph", content: [], attrs: {} }];
|
|
44276
|
+
}
|
|
44277
|
+
return { type: "taskItem", attrs: { checked }, content };
|
|
44278
|
+
}
|
|
44279
|
+
// --- images ---------------------------------------------------------------
|
|
44280
|
+
imageNode(el, inline) {
|
|
44281
|
+
const attrs = { src: el.attrs.src ?? "" };
|
|
44282
|
+
attrs.alt = el.attrs.alt ?? null;
|
|
44283
|
+
attrs.title = el.attrs.title ?? null;
|
|
44284
|
+
const width = intAttr(el.attrs.width);
|
|
44285
|
+
if (width != null) attrs.width = width;
|
|
44286
|
+
const height = intAttr(el.attrs.height);
|
|
44287
|
+
if (height != null) attrs.height = height;
|
|
44288
|
+
if (el.attrs.class) attrs.class = el.attrs.class;
|
|
44289
|
+
return { type: inline ? "imageInline" : "image", attrs };
|
|
44290
|
+
}
|
|
44291
|
+
// --- whitespace -----------------------------------------------------------
|
|
44292
|
+
/** Trim leading/trailing whitespace from inline content (edges only). */
|
|
44293
|
+
trimInline(nodes) {
|
|
44294
|
+
const out = nodes.slice();
|
|
44295
|
+
const isWs = (n) => n.type === "text" && /^\s*$/.test(n.text ?? "");
|
|
44296
|
+
while (out.length > 0 && isWs(out[0])) out.shift();
|
|
44297
|
+
if (out.length > 0 && out[0].type === "text") {
|
|
44298
|
+
out[0] = { ...out[0], text: (out[0].text ?? "").replace(/^\s+/, "") };
|
|
44299
|
+
}
|
|
44300
|
+
while (out.length > 0 && isWs(out[out.length - 1])) out.pop();
|
|
44301
|
+
if (out.length > 0 && out[out.length - 1].type === "text") {
|
|
44302
|
+
const last = out.length - 1;
|
|
44303
|
+
out[last] = { ...out[last], text: (out[last].text ?? "").replace(/\s+$/, "") };
|
|
44304
|
+
}
|
|
44305
|
+
return out.filter((n) => !(n.type === "text" && n.text === ""));
|
|
44306
|
+
}
|
|
44307
|
+
};
|
|
44308
|
+
|
|
43375
44309
|
// src/BitmarkParserGenerator.ts
|
|
43376
44310
|
var Input = {
|
|
43377
44311
|
/**
|
|
@@ -43413,7 +44347,11 @@ var InputFormat = {
|
|
|
43413
44347
|
/**
|
|
43414
44348
|
* Input is plain text
|
|
43415
44349
|
*/
|
|
43416
|
-
plainText: "plainText"
|
|
44350
|
+
plainText: "plainText",
|
|
44351
|
+
/**
|
|
44352
|
+
* Input is HTML (used by convertHtmlTable)
|
|
44353
|
+
*/
|
|
44354
|
+
html: "html"
|
|
43417
44355
|
};
|
|
43418
44356
|
var BitmarkParserGenerator = class {
|
|
43419
44357
|
constructor() {
|
|
@@ -43948,6 +44886,87 @@ var BitmarkParserGenerator = class {
|
|
|
43948
44886
|
const res = generator.generate(data);
|
|
43949
44887
|
return res;
|
|
43950
44888
|
}
|
|
44889
|
+
/**
|
|
44890
|
+
* Convert between HTML tables and bitmark tables.
|
|
44891
|
+
*
|
|
44892
|
+
* Direction is auto-detected (override with `options.inputFormat`):
|
|
44893
|
+
* - HTML input: every `<table>` is extracted and emitted as a `[.table-extended]` (or `[.table]`)
|
|
44894
|
+
* bit; output as bitmark (default), JSON, AST, or HTML (re-emit).
|
|
44895
|
+
* - bitmark / JSON / AST input: each `table` / `table-extended` bit is rendered as an HTML
|
|
44896
|
+
* `<table>` fragment.
|
|
44897
|
+
*
|
|
44898
|
+
* Cell content is reproduced verbatim except inline conversion to bitmark marks (bold, italic,
|
|
44899
|
+
* superscript, etc.), with lists and images mapped to their bitmark equivalents.
|
|
44900
|
+
*
|
|
44901
|
+
* @param input - HTML, bitmark, JSON or AST string; or a parsed JSON/AST value; or a file path.
|
|
44902
|
+
* @param options - the conversion options
|
|
44903
|
+
* @returns the converted output as a string (or object for JSON/AST), or void when writing a file
|
|
44904
|
+
* @throws Error if any error occurs
|
|
44905
|
+
*/
|
|
44906
|
+
convertHtmlTable(input, options) {
|
|
44907
|
+
const opts = Object.assign({}, options);
|
|
44908
|
+
if (env.isBrowser && opts.outputFile) {
|
|
44909
|
+
throw new Error("Cannot write to file in browser environment");
|
|
44910
|
+
}
|
|
44911
|
+
let inStr = input;
|
|
44912
|
+
const inputIsString = typeof input === "string";
|
|
44913
|
+
if (env.isNode && inputIsString && fs4.existsSync(inStr)) {
|
|
44914
|
+
inStr = fs4.readFileSync(inStr, { encoding: "utf8" });
|
|
44915
|
+
}
|
|
44916
|
+
const isHtmlString = (s) => {
|
|
44917
|
+
const t = s.replace(/^\s+/, "");
|
|
44918
|
+
return t.startsWith("<") && /<table/i.test(t);
|
|
44919
|
+
};
|
|
44920
|
+
let htmlInput;
|
|
44921
|
+
if (opts.inputFormat === InputFormat.html) {
|
|
44922
|
+
htmlInput = true;
|
|
44923
|
+
} else if (opts.inputFormat != null) {
|
|
44924
|
+
htmlInput = false;
|
|
44925
|
+
} else {
|
|
44926
|
+
htmlInput = inputIsString && isHtmlString(inStr);
|
|
44927
|
+
}
|
|
44928
|
+
if (htmlInput) {
|
|
44929
|
+
const parser2 = new HtmlTableParser();
|
|
44930
|
+
const bits = parser2.parse(inStr, {
|
|
44931
|
+
tableFormat: opts.tableFormat ?? "table-extended",
|
|
44932
|
+
keepUnknownTags: opts.keepUnknownTags,
|
|
44933
|
+
onWarning: (m) => console.warn(m)
|
|
44934
|
+
});
|
|
44935
|
+
const outputFormat2 = opts.outputFormat ?? Output.bitmark;
|
|
44936
|
+
if (outputFormat2 === "html") {
|
|
44937
|
+
const json2 = this.convert(bits, { outputFormat: Output.json });
|
|
44938
|
+
return this.outputHtml(new HtmlTableGenerator().generate(json2), opts);
|
|
44939
|
+
}
|
|
44940
|
+
return this.convert(bits, {
|
|
44941
|
+
outputFormat: Enum23(Output).fromValue(outputFormat2),
|
|
44942
|
+
outputFile: opts.outputFile,
|
|
44943
|
+
fileOptions: opts.fileOptions,
|
|
44944
|
+
jsonOptions: opts.jsonOptions,
|
|
44945
|
+
bitmarkOptions: opts.bitmarkOptions
|
|
44946
|
+
});
|
|
44947
|
+
}
|
|
44948
|
+
const outputFormat = opts.outputFormat ?? "html";
|
|
44949
|
+
if (outputFormat !== "html") {
|
|
44950
|
+
throw new Error(
|
|
44951
|
+
"convertHtmlTable: non-HTML input can only be converted to HTML. Use convert() for bitmark/JSON/AST conversions."
|
|
44952
|
+
);
|
|
44953
|
+
}
|
|
44954
|
+
const json = this.convert(inputIsString ? inStr : input, { outputFormat: Output.json });
|
|
44955
|
+
return this.outputHtml(new HtmlTableGenerator().generate(json), opts);
|
|
44956
|
+
}
|
|
44957
|
+
/**
|
|
44958
|
+
* Write an HTML string to the configured output file, or return it.
|
|
44959
|
+
*/
|
|
44960
|
+
outputHtml(html, opts) {
|
|
44961
|
+
if (opts.outputFile) {
|
|
44962
|
+
const output = opts.outputFile.toString();
|
|
44963
|
+
const flag = opts.fileOptions?.append ? "a" : "w";
|
|
44964
|
+
fs4.ensureDirSync(path4.dirname(output));
|
|
44965
|
+
fs4.writeFileSync(output, html, { flag });
|
|
44966
|
+
return;
|
|
44967
|
+
}
|
|
44968
|
+
return html;
|
|
44969
|
+
}
|
|
43951
44970
|
/**
|
|
43952
44971
|
* Breakscape bitmark text.
|
|
43953
44972
|
*
|
|
@@ -44243,6 +45262,8 @@ export {
|
|
|
44243
45262
|
Builder,
|
|
44244
45263
|
CardSetVersion,
|
|
44245
45264
|
FileWriter,
|
|
45265
|
+
HtmlTableGenerator,
|
|
45266
|
+
HtmlTableParser,
|
|
44246
45267
|
InfoFormat,
|
|
44247
45268
|
InfoType,
|
|
44248
45269
|
Input,
|