@sushichan044/kg-core 0.9.0 → 0.9.2
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/README.md +8 -3
- package/dist/{composed-manuscript-C0f3mxKs.d.mts → composed-manuscript-QgIdae8p.d.mts} +52 -52
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/lint.d.mts +1 -1
- package/dist/{novel-composer-DhycV9B3.d.mts → novel-composer-BCt9g172.d.mts} +1 -1
- package/dist/{novel-composer-CtovfhET.mjs → novel-composer-CNBT4TDN.mjs} +192 -23
- package/dist/plugin.d.mts +2 -2
- package/dist/plugin.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,9 +95,14 @@ stage, or by hanging a comma or full stop; a short line is answered by opening u
|
|
|
95
95
|
where JLReq 3.8.4 and appendix 表6
|
|
96
96
|
allow it — the word space first, up to a half, then the Japanese-to-Western quarter em,
|
|
97
97
|
also up to a half, then a solid pair between kana, kanji, and the marks that go with
|
|
98
|
-
them, up to a quarter.
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
them, up to a quarter. If those stages cannot fill the line, the remaining width is
|
|
99
|
+
added equally to the admitted pairs in 表6 that are solid at rest, including pairs used by
|
|
100
|
+
the third stage. Intrinsic spaces keep their finite limits: a word space and a mixed
|
|
101
|
+
Japanese-to-Western, numeral, or unit-symbol gap stop at a half em, while punctuation and
|
|
102
|
+
explicit full-em spaces retain their own width. This keeps the unbounded stage from producing
|
|
103
|
+
conspicuous holes around short upright Western words or already-spaced marks.
|
|
104
|
+
Line-head and line-end space, inseparable pairs, and source-authored full-em gaps after
|
|
105
|
+
question or exclamation marks stay fixed. A line with no admitted gap is forced. The choice is made for the
|
|
101
106
|
paragraph rather than line by line,
|
|
102
107
|
minimizing in order the number of forced lines, then stretched, then hanging, then
|
|
103
108
|
shrunk lines that spent visible space. Which space may be reduced, and in which
|
|
@@ -914,7 +914,7 @@ declare const ParsedManuscriptSchema: v.SchemaWithPipe<readonly [v.StrictObjectS
|
|
|
914
914
|
}>;
|
|
915
915
|
mark: string;
|
|
916
916
|
}>]>], undefined>, undefined>, v.ReadonlyAction<(Readonly<{
|
|
917
|
-
kind: "
|
|
917
|
+
kind: "ruby";
|
|
918
918
|
readonly range: Readonly<{
|
|
919
919
|
source: Readonly<{
|
|
920
920
|
start: number;
|
|
@@ -929,8 +929,18 @@ declare const ParsedManuscriptSchema: v.SchemaWithPipe<readonly [v.StrictObjectS
|
|
|
929
929
|
end: number;
|
|
930
930
|
}> & v.Brand<"GraphemeRange">;
|
|
931
931
|
}>;
|
|
932
|
+
reading: Readonly<{
|
|
933
|
+
kind: "group";
|
|
934
|
+
text: string;
|
|
935
|
+
}> | Readonly<{
|
|
936
|
+
kind: "mono";
|
|
937
|
+
readonly segments: readonly string[];
|
|
938
|
+
}> | Readonly<{
|
|
939
|
+
kind: "jukugo";
|
|
940
|
+
readonly segments: readonly string[];
|
|
941
|
+
}>;
|
|
932
942
|
}> | Readonly<{
|
|
933
|
-
kind: "
|
|
943
|
+
kind: "bold";
|
|
934
944
|
readonly range: Readonly<{
|
|
935
945
|
source: Readonly<{
|
|
936
946
|
start: number;
|
|
@@ -945,18 +955,8 @@ declare const ParsedManuscriptSchema: v.SchemaWithPipe<readonly [v.StrictObjectS
|
|
|
945
955
|
end: number;
|
|
946
956
|
}> & v.Brand<"GraphemeRange">;
|
|
947
957
|
}>;
|
|
948
|
-
reading: Readonly<{
|
|
949
|
-
kind: "group";
|
|
950
|
-
text: string;
|
|
951
|
-
}> | Readonly<{
|
|
952
|
-
kind: "mono";
|
|
953
|
-
readonly segments: readonly string[];
|
|
954
|
-
}> | Readonly<{
|
|
955
|
-
kind: "jukugo";
|
|
956
|
-
readonly segments: readonly string[];
|
|
957
|
-
}>;
|
|
958
958
|
}> | Readonly<{
|
|
959
|
-
kind: "
|
|
959
|
+
kind: "italic";
|
|
960
960
|
readonly range: Readonly<{
|
|
961
961
|
source: Readonly<{
|
|
962
962
|
start: number;
|
|
@@ -1010,7 +1010,7 @@ declare const ParsedManuscriptSchema: v.SchemaWithPipe<readonly [v.StrictObjectS
|
|
|
1010
1010
|
}>;
|
|
1011
1011
|
}>[];
|
|
1012
1012
|
readonly annotations: readonly (Readonly<{
|
|
1013
|
-
kind: "
|
|
1013
|
+
kind: "ruby";
|
|
1014
1014
|
readonly range: Readonly<{
|
|
1015
1015
|
source: Readonly<{
|
|
1016
1016
|
start: number;
|
|
@@ -1025,8 +1025,18 @@ declare const ParsedManuscriptSchema: v.SchemaWithPipe<readonly [v.StrictObjectS
|
|
|
1025
1025
|
end: number;
|
|
1026
1026
|
}> & v.Brand<"GraphemeRange">;
|
|
1027
1027
|
}>;
|
|
1028
|
+
reading: Readonly<{
|
|
1029
|
+
kind: "group";
|
|
1030
|
+
text: string;
|
|
1031
|
+
}> | Readonly<{
|
|
1032
|
+
kind: "mono";
|
|
1033
|
+
readonly segments: readonly string[];
|
|
1034
|
+
}> | Readonly<{
|
|
1035
|
+
kind: "jukugo";
|
|
1036
|
+
readonly segments: readonly string[];
|
|
1037
|
+
}>;
|
|
1028
1038
|
}> | Readonly<{
|
|
1029
|
-
kind: "
|
|
1039
|
+
kind: "bold";
|
|
1030
1040
|
readonly range: Readonly<{
|
|
1031
1041
|
source: Readonly<{
|
|
1032
1042
|
start: number;
|
|
@@ -1041,18 +1051,8 @@ declare const ParsedManuscriptSchema: v.SchemaWithPipe<readonly [v.StrictObjectS
|
|
|
1041
1051
|
end: number;
|
|
1042
1052
|
}> & v.Brand<"GraphemeRange">;
|
|
1043
1053
|
}>;
|
|
1044
|
-
reading: Readonly<{
|
|
1045
|
-
kind: "group";
|
|
1046
|
-
text: string;
|
|
1047
|
-
}> | Readonly<{
|
|
1048
|
-
kind: "mono";
|
|
1049
|
-
readonly segments: readonly string[];
|
|
1050
|
-
}> | Readonly<{
|
|
1051
|
-
kind: "jukugo";
|
|
1052
|
-
readonly segments: readonly string[];
|
|
1053
|
-
}>;
|
|
1054
1054
|
}> | Readonly<{
|
|
1055
|
-
kind: "
|
|
1055
|
+
kind: "italic";
|
|
1056
1056
|
readonly range: Readonly<{
|
|
1057
1057
|
source: Readonly<{
|
|
1058
1058
|
start: number;
|
|
@@ -1503,7 +1503,7 @@ declare const ParsedManuscript: {
|
|
|
1503
1503
|
}>;
|
|
1504
1504
|
mark: string;
|
|
1505
1505
|
}>]>], undefined>, undefined>, v.ReadonlyAction<(Readonly<{
|
|
1506
|
-
kind: "
|
|
1506
|
+
kind: "ruby";
|
|
1507
1507
|
readonly range: Readonly<{
|
|
1508
1508
|
source: Readonly<{
|
|
1509
1509
|
start: number;
|
|
@@ -1518,8 +1518,18 @@ declare const ParsedManuscript: {
|
|
|
1518
1518
|
end: number;
|
|
1519
1519
|
}> & v.Brand<"GraphemeRange">;
|
|
1520
1520
|
}>;
|
|
1521
|
+
reading: Readonly<{
|
|
1522
|
+
kind: "group";
|
|
1523
|
+
text: string;
|
|
1524
|
+
}> | Readonly<{
|
|
1525
|
+
kind: "mono";
|
|
1526
|
+
readonly segments: readonly string[];
|
|
1527
|
+
}> | Readonly<{
|
|
1528
|
+
kind: "jukugo";
|
|
1529
|
+
readonly segments: readonly string[];
|
|
1530
|
+
}>;
|
|
1521
1531
|
}> | Readonly<{
|
|
1522
|
-
kind: "
|
|
1532
|
+
kind: "bold";
|
|
1523
1533
|
readonly range: Readonly<{
|
|
1524
1534
|
source: Readonly<{
|
|
1525
1535
|
start: number;
|
|
@@ -1534,18 +1544,8 @@ declare const ParsedManuscript: {
|
|
|
1534
1544
|
end: number;
|
|
1535
1545
|
}> & v.Brand<"GraphemeRange">;
|
|
1536
1546
|
}>;
|
|
1537
|
-
reading: Readonly<{
|
|
1538
|
-
kind: "group";
|
|
1539
|
-
text: string;
|
|
1540
|
-
}> | Readonly<{
|
|
1541
|
-
kind: "mono";
|
|
1542
|
-
readonly segments: readonly string[];
|
|
1543
|
-
}> | Readonly<{
|
|
1544
|
-
kind: "jukugo";
|
|
1545
|
-
readonly segments: readonly string[];
|
|
1546
|
-
}>;
|
|
1547
1547
|
}> | Readonly<{
|
|
1548
|
-
kind: "
|
|
1548
|
+
kind: "italic";
|
|
1549
1549
|
readonly range: Readonly<{
|
|
1550
1550
|
source: Readonly<{
|
|
1551
1551
|
start: number;
|
|
@@ -1599,7 +1599,7 @@ declare const ParsedManuscript: {
|
|
|
1599
1599
|
}>;
|
|
1600
1600
|
}>[];
|
|
1601
1601
|
readonly annotations: readonly (Readonly<{
|
|
1602
|
-
kind: "
|
|
1602
|
+
kind: "ruby";
|
|
1603
1603
|
readonly range: Readonly<{
|
|
1604
1604
|
source: Readonly<{
|
|
1605
1605
|
start: number;
|
|
@@ -1614,8 +1614,18 @@ declare const ParsedManuscript: {
|
|
|
1614
1614
|
end: number;
|
|
1615
1615
|
}> & v.Brand<"GraphemeRange">;
|
|
1616
1616
|
}>;
|
|
1617
|
+
reading: Readonly<{
|
|
1618
|
+
kind: "group";
|
|
1619
|
+
text: string;
|
|
1620
|
+
}> | Readonly<{
|
|
1621
|
+
kind: "mono";
|
|
1622
|
+
readonly segments: readonly string[];
|
|
1623
|
+
}> | Readonly<{
|
|
1624
|
+
kind: "jukugo";
|
|
1625
|
+
readonly segments: readonly string[];
|
|
1626
|
+
}>;
|
|
1617
1627
|
}> | Readonly<{
|
|
1618
|
-
kind: "
|
|
1628
|
+
kind: "bold";
|
|
1619
1629
|
readonly range: Readonly<{
|
|
1620
1630
|
source: Readonly<{
|
|
1621
1631
|
start: number;
|
|
@@ -1630,18 +1640,8 @@ declare const ParsedManuscript: {
|
|
|
1630
1640
|
end: number;
|
|
1631
1641
|
}> & v.Brand<"GraphemeRange">;
|
|
1632
1642
|
}>;
|
|
1633
|
-
reading: Readonly<{
|
|
1634
|
-
kind: "group";
|
|
1635
|
-
text: string;
|
|
1636
|
-
}> | Readonly<{
|
|
1637
|
-
kind: "mono";
|
|
1638
|
-
readonly segments: readonly string[];
|
|
1639
|
-
}> | Readonly<{
|
|
1640
|
-
kind: "jukugo";
|
|
1641
|
-
readonly segments: readonly string[];
|
|
1642
|
-
}>;
|
|
1643
1643
|
}> | Readonly<{
|
|
1644
|
-
kind: "
|
|
1644
|
+
kind: "italic";
|
|
1645
1645
|
readonly range: Readonly<{
|
|
1646
1646
|
source: Readonly<{
|
|
1647
1647
|
start: number;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ManuscriptResult, c as DiagnosticSeverity, d as ManuscriptRangeInput, i as ParsedManuscript, l as DiagnosticOrigin, n as ValidationIssue, o as ManuscriptDiagnostic, r as NamespacedId, s as ManuscriptDiagnosticInput, t as ComposedManuscript, u as ManuscriptRange } from "./composed-manuscript-
|
|
2
|
-
import { d as NovelCompositionSettings, f as ManuscriptComposer, i as NovelLayout, l as VerticalTextPresentation, p as ManuscriptParser, r as novelComposer, t as NovelComposedManuscript, u as FontPresetId } from "./novel-composer-
|
|
1
|
+
import { a as ManuscriptResult, c as DiagnosticSeverity, d as ManuscriptRangeInput, i as ParsedManuscript, l as DiagnosticOrigin, n as ValidationIssue, o as ManuscriptDiagnostic, r as NamespacedId, s as ManuscriptDiagnosticInput, t as ComposedManuscript, u as ManuscriptRange } from "./composed-manuscript-QgIdae8p.mjs";
|
|
2
|
+
import { d as NovelCompositionSettings, f as ManuscriptComposer, i as NovelLayout, l as VerticalTextPresentation, p as ManuscriptParser, r as novelComposer, t as NovelComposedManuscript, u as FontPresetId } from "./novel-composer-BCt9g172.mjs";
|
|
3
3
|
import * as v from "valibot";
|
|
4
4
|
//#region src/parser/parse-error.d.ts
|
|
5
5
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as ManuscriptResult, d as NamespacedId, f as ManuscriptRange, h as readonlyObject, l as ManuscriptDiagnostic, o as graphemeSegmenter, s as ValidationIssue } from "./question-or-exclamation-spacing-B5o23ZLf.mjs";
|
|
2
|
-
import { c as ManuscriptOffsets, d as FontSizePt, f as FontPresetId, i as PaperSize, l as ManuscriptAppearanceSettings, n as novelComposer, o as NovelCompositionSettings, p as ParsedManuscript, r as ManuscriptGeometry, s as NovelFlowSettings, u as PaperSizeId } from "./novel-composer-
|
|
2
|
+
import { c as ManuscriptOffsets, d as FontSizePt, f as FontPresetId, i as PaperSize, l as ManuscriptAppearanceSettings, n as novelComposer, o as NovelCompositionSettings, p as ParsedManuscript, r as ManuscriptGeometry, s as NovelFlowSettings, u as PaperSizeId } from "./novel-composer-CNBT4TDN.mjs";
|
|
3
3
|
import { n as assertNever, t as describeCause } from "./describe-cause-BV8mZ3Um.mjs";
|
|
4
4
|
import * as v from "valibot";
|
|
5
5
|
const Rejection = { schema: readonlyObject({ reason: v.string() }) };
|
package/dist/lint.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ManuscriptResult, i as ParsedManuscript, n as ValidationIssue, o as ManuscriptDiagnostic, r as NamespacedId, t as ComposedManuscript } from "./composed-manuscript-
|
|
1
|
+
import { a as ManuscriptResult, i as ParsedManuscript, n as ValidationIssue, o as ManuscriptDiagnostic, r as NamespacedId, t as ComposedManuscript } from "./composed-manuscript-QgIdae8p.mjs";
|
|
2
2
|
import * as v from "valibot";
|
|
3
3
|
//#region src/proofreading/invalid-rule-options.d.ts
|
|
4
4
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ManuscriptResult, i as ParsedManuscript, t as ComposedManuscript } from "./composed-manuscript-
|
|
1
|
+
import { a as ManuscriptResult, i as ParsedManuscript, t as ComposedManuscript } from "./composed-manuscript-QgIdae8p.mjs";
|
|
2
2
|
import * as v from "valibot";
|
|
3
3
|
//#region src/result/rejection.d.ts
|
|
4
4
|
declare const RejectionSchema: v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
@@ -377,10 +377,6 @@ const REDUCTION_STAGE = {
|
|
|
377
377
|
* {@link REDUCTION_STAGE}: the lower the number, the earlier the paragraph optimizer takes it. A
|
|
378
378
|
* line is either reduced or expanded, never both, so the two scales never meet.
|
|
379
379
|
*
|
|
380
|
-
* Stage 4 spreads whatever a、b and c could not absorb across every character gap that is not
|
|
381
|
-
* unbreakable, and is deliberately not implemented: it would justify every line that currently
|
|
382
|
-
* falls short, which reads as prose combed out to the margin rather than a novel.
|
|
383
|
-
*
|
|
384
380
|
* Nothing here takes priority 0. Expanding is always visible, and priority 0 means an adjustment
|
|
385
381
|
* the optimizer is charged nothing for.
|
|
386
382
|
*/
|
|
@@ -396,7 +392,11 @@ const EXPANSION_STAGE = {
|
|
|
396
392
|
/**
|
|
397
393
|
* Stage 3: everywhere else 表6 admits, from solid up to a quarter em.
|
|
398
394
|
*/
|
|
399
|
-
solid: 3
|
|
395
|
+
solid: 3,
|
|
396
|
+
/**
|
|
397
|
+
* Stage 4: the unbounded remainder, spread equally across every colored or gray cell of 表6.
|
|
398
|
+
*/
|
|
399
|
+
final: 4
|
|
400
400
|
};
|
|
401
401
|
/**
|
|
402
402
|
* 無印 in 表1 with no colour in 表6: the pair is set solid and line adjustment leaves it alone.
|
|
@@ -635,6 +635,125 @@ const EXPANDABLE_AFTER = [
|
|
|
635
635
|
"cl-30"
|
|
636
636
|
];
|
|
637
637
|
/**
|
|
638
|
+
* The gray, blue and pink cells of 表6: all pairs that join the fourth and final expansion stage.
|
|
639
|
+
* The finite capacities above cover the blue and pink cells at stages three and two; once those
|
|
640
|
+
* stages are exhausted, JLReq 3.8.4 d adds the remainder equally across every cell named here.
|
|
641
|
+
*
|
|
642
|
+
* A cl-08/cl-08 cell is blue only when the two characters are different kinds of mark (注4). This
|
|
643
|
+
* profile cannot distinguish the two halves of one 2倍ダッシュ from different marks, so it keeps the
|
|
644
|
+
* pair joined, as it already does for the finite third stage.
|
|
645
|
+
*/
|
|
646
|
+
const FINAL_EXPANSION_BASIC_AFTER = /* @__PURE__ */ new Set([
|
|
647
|
+
"cl-01",
|
|
648
|
+
"cl-08",
|
|
649
|
+
"cl-12",
|
|
650
|
+
"cl-13",
|
|
651
|
+
"cl-14",
|
|
652
|
+
"cl-15",
|
|
653
|
+
"cl-16",
|
|
654
|
+
"cl-19",
|
|
655
|
+
"cl-24",
|
|
656
|
+
"cl-25",
|
|
657
|
+
"cl-26",
|
|
658
|
+
"cl-27",
|
|
659
|
+
"cl-30"
|
|
660
|
+
]);
|
|
661
|
+
const FINAL_EXPANSION_WIDE_AFTER = /* @__PURE__ */ new Set([
|
|
662
|
+
...FINAL_EXPANSION_BASIC_AFTER,
|
|
663
|
+
"cl-09",
|
|
664
|
+
"cl-10",
|
|
665
|
+
"cl-11"
|
|
666
|
+
]);
|
|
667
|
+
const FINAL_EXPANSION_AFTER = new Map([
|
|
668
|
+
...[
|
|
669
|
+
"cl-02",
|
|
670
|
+
"cl-03",
|
|
671
|
+
"cl-04",
|
|
672
|
+
"cl-05",
|
|
673
|
+
"cl-06",
|
|
674
|
+
"cl-07",
|
|
675
|
+
"cl-14"
|
|
676
|
+
].map((left) => [left, FINAL_EXPANSION_BASIC_AFTER]),
|
|
677
|
+
...[
|
|
678
|
+
"cl-09",
|
|
679
|
+
"cl-10",
|
|
680
|
+
"cl-11",
|
|
681
|
+
"cl-13",
|
|
682
|
+
"cl-15",
|
|
683
|
+
"cl-16",
|
|
684
|
+
"cl-19",
|
|
685
|
+
"cl-30"
|
|
686
|
+
].map((left) => [left, FINAL_EXPANSION_WIDE_AFTER]),
|
|
687
|
+
["cl-08", new Set([...FINAL_EXPANSION_WIDE_AFTER].filter((characterClass) => characterClass !== "cl-08"))],
|
|
688
|
+
["cl-12", /* @__PURE__ */ new Set([
|
|
689
|
+
"cl-08",
|
|
690
|
+
"cl-09",
|
|
691
|
+
"cl-10",
|
|
692
|
+
"cl-11",
|
|
693
|
+
"cl-12",
|
|
694
|
+
"cl-13",
|
|
695
|
+
"cl-15",
|
|
696
|
+
"cl-16",
|
|
697
|
+
"cl-19",
|
|
698
|
+
"cl-25",
|
|
699
|
+
"cl-26",
|
|
700
|
+
"cl-27",
|
|
701
|
+
"cl-30"
|
|
702
|
+
])],
|
|
703
|
+
["cl-24", /* @__PURE__ */ new Set([
|
|
704
|
+
"cl-01",
|
|
705
|
+
"cl-08",
|
|
706
|
+
"cl-09",
|
|
707
|
+
"cl-10",
|
|
708
|
+
"cl-11",
|
|
709
|
+
"cl-12",
|
|
710
|
+
"cl-14",
|
|
711
|
+
"cl-15",
|
|
712
|
+
"cl-16",
|
|
713
|
+
"cl-19",
|
|
714
|
+
"cl-25",
|
|
715
|
+
"cl-26",
|
|
716
|
+
"cl-30"
|
|
717
|
+
])],
|
|
718
|
+
["cl-25", /* @__PURE__ */ new Set([
|
|
719
|
+
"cl-01",
|
|
720
|
+
"cl-08",
|
|
721
|
+
"cl-09",
|
|
722
|
+
"cl-10",
|
|
723
|
+
"cl-11",
|
|
724
|
+
"cl-12",
|
|
725
|
+
"cl-13",
|
|
726
|
+
"cl-14",
|
|
727
|
+
"cl-15",
|
|
728
|
+
"cl-16",
|
|
729
|
+
"cl-19",
|
|
730
|
+
"cl-24",
|
|
731
|
+
"cl-26",
|
|
732
|
+
"cl-30"
|
|
733
|
+
])],
|
|
734
|
+
["cl-26", new Set(japaneseCharacterClasses.filter((characterClass) => characterClass !== "cl-02"))],
|
|
735
|
+
["cl-27", /* @__PURE__ */ new Set([
|
|
736
|
+
"cl-01",
|
|
737
|
+
"cl-08",
|
|
738
|
+
"cl-09",
|
|
739
|
+
"cl-10",
|
|
740
|
+
"cl-11",
|
|
741
|
+
"cl-12",
|
|
742
|
+
"cl-13",
|
|
743
|
+
"cl-14",
|
|
744
|
+
"cl-15",
|
|
745
|
+
"cl-16",
|
|
746
|
+
"cl-19",
|
|
747
|
+
"cl-26",
|
|
748
|
+
"cl-30"
|
|
749
|
+
])]
|
|
750
|
+
]);
|
|
751
|
+
function canExpandAtFinalStage(left, right) {
|
|
752
|
+
if (left === "cl-14" || left === "cl-26" || left === "cl-27" || right === "cl-14" || right === "cl-26" || right === "cl-27") return false;
|
|
753
|
+
if (FINAL_EXPANSION_AFTER.get(left)?.has(right) !== true) return false;
|
|
754
|
+
return pairSpacing(left, right).naturalWidthEm === 0;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
638
757
|
* The classes JLReq 3.1.2 sets on a half em rather than a full one.
|
|
639
758
|
*/
|
|
640
759
|
const HALF_EM_CLASSES = /* @__PURE__ */ new Set([
|
|
@@ -922,6 +1041,8 @@ const defaultJapaneseTypesettingProfile = {
|
|
|
922
1041
|
},
|
|
923
1042
|
absorbsPrecedingEm: .25
|
|
924
1043
|
} : null,
|
|
1044
|
+
finalStretchPriority: EXPANSION_STAGE.final,
|
|
1045
|
+
canExpandAtFinalStage,
|
|
925
1046
|
breakPenalty,
|
|
926
1047
|
/**
|
|
927
1048
|
* Hanging punctuation (ぶら下げ組, JLReq 3.8.2) lets a full stop or comma sit outside the text area
|
|
@@ -951,6 +1072,15 @@ function skipSourceGaps(atoms, start) {
|
|
|
951
1072
|
function previousVisible(atoms, end) {
|
|
952
1073
|
for (let index = end - 1; index >= 0; index -= 1) if (atoms[index]?.sourceGap === false) return index;
|
|
953
1074
|
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Whether a shorter line ending somewhere inside `(contentStart, end)` was ever an option — checked
|
|
1077
|
+
* as a plain short-circuiting scan rather than building the boundary list first, since this runs
|
|
1078
|
+
* once per over-long candidate the optimizer considers.
|
|
1079
|
+
*/
|
|
1080
|
+
function hasEarlierBoundary(boundaryAllowed, contentStart, end) {
|
|
1081
|
+
for (let boundary = contentStart + 1; boundary < end; boundary += 1) if (boundaryAllowed(boundary - 1, boundary)) return true;
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
954
1084
|
function opportunities(atoms, classes, start, end, profile, lineHead) {
|
|
955
1085
|
const result = [];
|
|
956
1086
|
const firstClass = classes[start];
|
|
@@ -961,6 +1091,7 @@ function opportunities(atoms, classes, start, end, profile, lineHead) {
|
|
|
961
1091
|
boundary: start
|
|
962
1092
|
},
|
|
963
1093
|
spacing: startSpacing,
|
|
1094
|
+
finalStretch: false,
|
|
964
1095
|
absorbsPrecedingEm: 0
|
|
965
1096
|
});
|
|
966
1097
|
for (let index = start; index < end; index += 1) {
|
|
@@ -973,6 +1104,7 @@ function opportunities(atoms, classes, start, end, profile, lineHead) {
|
|
|
973
1104
|
index
|
|
974
1105
|
},
|
|
975
1106
|
spacing,
|
|
1107
|
+
finalStretch: false,
|
|
976
1108
|
absorbsPrecedingEm: 0
|
|
977
1109
|
});
|
|
978
1110
|
}
|
|
@@ -988,6 +1120,7 @@ function opportunities(atoms, classes, start, end, profile, lineHead) {
|
|
|
988
1120
|
boundary: right
|
|
989
1121
|
},
|
|
990
1122
|
spacing: profile.pairSpacing(leftClass, rightClass),
|
|
1123
|
+
finalStretch: profile.canExpandAtFinalStage(leftClass, rightClass),
|
|
991
1124
|
absorbsPrecedingEm: 0
|
|
992
1125
|
});
|
|
993
1126
|
}
|
|
@@ -999,6 +1132,7 @@ function opportunities(atoms, classes, start, end, profile, lineHead) {
|
|
|
999
1132
|
boundary: end
|
|
1000
1133
|
},
|
|
1001
1134
|
spacing: endSpacing.spacing,
|
|
1135
|
+
finalStretch: false,
|
|
1002
1136
|
absorbsPrecedingEm: endSpacing.absorbsPrecedingEm
|
|
1003
1137
|
});
|
|
1004
1138
|
return result;
|
|
@@ -1072,17 +1206,20 @@ function adjustmentUnits(values, adjustment) {
|
|
|
1072
1206
|
* Within a stage the amount is therefore split in proportion to what each space can give, rather
|
|
1073
1207
|
* than taken out of the earliest space until it runs dry. Across stages the order stays a
|
|
1074
1208
|
* waterfall: a later stage is reached only once every stage before it is spent out. The composer
|
|
1075
|
-
* sets one character size, so a share of the stage's capacity is a share by character size.
|
|
1209
|
+
* sets one character size, so a share of the stage's capacity is a share by character size. JLReq
|
|
1210
|
+
* 3.8.4's final stage has no upper bound: after the finite stages are full, the unresolved
|
|
1211
|
+
* remainder is added equally to every pair the profile admits, including the earlier-stage pairs.
|
|
1076
1212
|
*
|
|
1077
1213
|
* An all-or-nothing unit larger than what is still needed is skipped rather than partly spent, and
|
|
1078
1214
|
* never revisited: `remaining` only falls, so a unit that did not fit at its own stage cannot fit
|
|
1079
1215
|
* at a later one. One forward pass is therefore exact and no search over subsets is needed.
|
|
1080
1216
|
*/
|
|
1081
|
-
function resolveSpacings(values, units, adjustment, amountEm) {
|
|
1217
|
+
function resolveSpacings(values, units, adjustment, amountEm, finalStretchPriority) {
|
|
1082
1218
|
const usedBySlot = /* @__PURE__ */ new Map();
|
|
1083
1219
|
let remaining = amountEm;
|
|
1084
1220
|
let priorityCost = 0;
|
|
1085
1221
|
let freeEm = 0;
|
|
1222
|
+
let finalStretchPerSlotEm = 0;
|
|
1086
1223
|
const spend = (unit, fraction) => {
|
|
1087
1224
|
for (const { slot, amountEm: partEm } of unit.parts) {
|
|
1088
1225
|
const key = slotKey(slot);
|
|
@@ -1109,6 +1246,20 @@ function resolveSpacings(values, units, adjustment, amountEm) {
|
|
|
1109
1246
|
const fraction = Math.min(remaining, stageCapacityEm) / stageCapacityEm;
|
|
1110
1247
|
for (const unit of stage) if (unit.granularity === "continuous") spend(unit, fraction);
|
|
1111
1248
|
}
|
|
1249
|
+
if (adjustment === "stretch" && remaining > EPSILON) {
|
|
1250
|
+
let finalSlotCount = 0;
|
|
1251
|
+
for (const { finalStretch } of values) if (finalStretch) finalSlotCount += 1;
|
|
1252
|
+
if (finalSlotCount > 0) {
|
|
1253
|
+
finalStretchPerSlotEm = remaining / finalSlotCount;
|
|
1254
|
+
for (const { slot, finalStretch } of values) {
|
|
1255
|
+
if (!finalStretch) continue;
|
|
1256
|
+
const key = slotKey(slot);
|
|
1257
|
+
usedBySlot.set(key, (usedBySlot.get(key) ?? 0) + finalStretchPerSlotEm);
|
|
1258
|
+
}
|
|
1259
|
+
priorityCost += remaining * finalStretchPriority;
|
|
1260
|
+
remaining = 0;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1112
1263
|
return {
|
|
1113
1264
|
spacings: splitBySlot(values, (slot, spacing) => {
|
|
1114
1265
|
const used = usedBySlot.get(slotKey(slot)) ?? 0;
|
|
@@ -1116,6 +1267,7 @@ function resolveSpacings(values, units, adjustment, amountEm) {
|
|
|
1116
1267
|
}),
|
|
1117
1268
|
priorityCost,
|
|
1118
1269
|
freeEm,
|
|
1270
|
+
finalStretchPerSlotEm,
|
|
1119
1271
|
unabsorbedEm: Math.max(0, remaining)
|
|
1120
1272
|
};
|
|
1121
1273
|
}
|
|
@@ -1159,11 +1311,11 @@ function hangingSpacings(values, end) {
|
|
|
1159
1311
|
characterSpacings
|
|
1160
1312
|
};
|
|
1161
1313
|
}
|
|
1162
|
-
function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
1314
|
+
function candidate(atoms, classes, boxPrefixEm, start, end, lineLengthEm, profile) {
|
|
1163
1315
|
const contentStart = skipSourceGaps(atoms, start);
|
|
1164
1316
|
const suppressedIndexes = Array.from({ length: contentStart - start }, (_, index) => start + index);
|
|
1165
1317
|
const pairValues = opportunities(atoms, classes, contentStart, end, profile, start === 0 ? "paragraph-start" : "turned-over");
|
|
1166
|
-
const naturalSizeEm =
|
|
1318
|
+
const naturalSizeEm = (boxPrefixEm[end] ?? 0) - (boxPrefixEm[contentStart] ?? 0) + pairValues.reduce((total, value) => total + value.spacing.naturalWidthEm, 0);
|
|
1167
1319
|
const terminal = skipSourceGaps(atoms, end) === atoms.length;
|
|
1168
1320
|
const overflow = naturalSizeEm - lineLengthEm;
|
|
1169
1321
|
const underflow = lineLengthEm - naturalSizeEm;
|
|
@@ -1174,6 +1326,7 @@ function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
|
1174
1326
|
const lastClass = lastVisible === void 0 ? void 0 : classes[lastVisible];
|
|
1175
1327
|
const lastAdvance = lastVisible === void 0 ? 0 : atoms[lastVisible]?.boxAdvanceEm ?? 0;
|
|
1176
1328
|
const trailingSpacing = pairValues.find(({ slot }) => slot.kind === "gap" && slot.boundary === end)?.spacing.naturalWidthEm ?? 0;
|
|
1329
|
+
const hasFinalStretch = pairValues.some(({ finalStretch }) => finalStretch);
|
|
1177
1330
|
if (terminal && overflow <= EPSILON) return {
|
|
1178
1331
|
start,
|
|
1179
1332
|
contentStart,
|
|
@@ -1198,7 +1351,7 @@ function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
|
1198
1351
|
deformationRatio: 0,
|
|
1199
1352
|
priorityCost: 0
|
|
1200
1353
|
};
|
|
1201
|
-
const shrunk = overflow > 0 && overflow <= capacity + EPSILON ? resolveSpacings(pairValues, units, "shrink", overflow) : null;
|
|
1354
|
+
const shrunk = overflow > 0 && overflow <= capacity + EPSILON ? resolveSpacings(pairValues, units, "shrink", overflow, profile.finalStretchPriority) : null;
|
|
1202
1355
|
if (shrunk !== null && shrunk.unabsorbedEm <= EPSILON) {
|
|
1203
1356
|
const chargeableCapacity = capacity - freeShrinkCapacity;
|
|
1204
1357
|
const chargeableShrink = Math.max(0, overflow - shrunk.freeEm);
|
|
@@ -1227,7 +1380,7 @@ function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
|
1227
1380
|
deformationRatio: overflow / Math.max(lastAdvance, EPSILON),
|
|
1228
1381
|
priorityCost: 0
|
|
1229
1382
|
};
|
|
1230
|
-
const stretched = !terminal && underflow > EPSILON && underflow <= capacity + EPSILON ? resolveSpacings(pairValues, units, "stretch", underflow) : null;
|
|
1383
|
+
const stretched = !terminal && underflow > EPSILON && (underflow <= capacity + EPSILON || hasFinalStretch) ? resolveSpacings(pairValues, units, "stretch", underflow, profile.finalStretchPriority) : null;
|
|
1231
1384
|
if (stretched !== null && stretched.unabsorbedEm <= EPSILON) return {
|
|
1232
1385
|
start,
|
|
1233
1386
|
contentStart,
|
|
@@ -1237,7 +1390,7 @@ function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
|
1237
1390
|
inlineSizeEm: lineLengthEm,
|
|
1238
1391
|
break: { kind: "stretched" },
|
|
1239
1392
|
hangingIndex: null,
|
|
1240
|
-
deformationRatio: capacity === 0 ? 0 : underflow / capacity,
|
|
1393
|
+
deformationRatio: stretched.finalStretchPerSlotEm > 0 ? 1 + stretched.finalStretchPerSlotEm : capacity === 0 ? 0 : underflow / capacity,
|
|
1241
1394
|
priorityCost: stretched.priorityCost
|
|
1242
1395
|
};
|
|
1243
1396
|
return {
|
|
@@ -1287,6 +1440,22 @@ function addScore(left, right) {
|
|
|
1287
1440
|
left[6] + right[6]
|
|
1288
1441
|
];
|
|
1289
1442
|
}
|
|
1443
|
+
/**
|
|
1444
|
+
* The line-end offsets a state's path took, earliest first. Rebuilt on demand by walking `previous`
|
|
1445
|
+
* rather than carried on every `State`: every candidate line attempted would otherwise pay for a
|
|
1446
|
+
* copy of its whole path, when `isBetter` only ever reads it on the exact-score tie this comparison
|
|
1447
|
+
* breaks — for `boundaryAllowed` predicates permissive enough to fully saturate the optimizer's
|
|
1448
|
+
* search window, ties are rare enough that this deferred cost is negligible.
|
|
1449
|
+
*/
|
|
1450
|
+
function breaksOf(state, states) {
|
|
1451
|
+
const result = [];
|
|
1452
|
+
let cursor = state;
|
|
1453
|
+
while (cursor?.line !== null && cursor?.line !== void 0) {
|
|
1454
|
+
result.push(cursor.line.end);
|
|
1455
|
+
cursor = cursor.previous === null ? void 0 : states.get(cursor.previous.index)?.get(cursor.previous.fitness);
|
|
1456
|
+
}
|
|
1457
|
+
return result.reverse();
|
|
1458
|
+
}
|
|
1290
1459
|
function compareBreaks(left, right) {
|
|
1291
1460
|
const length = Math.min(left.length, right.length);
|
|
1292
1461
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -1295,17 +1464,19 @@ function compareBreaks(left, right) {
|
|
|
1295
1464
|
}
|
|
1296
1465
|
return left.length - right.length;
|
|
1297
1466
|
}
|
|
1298
|
-
function isBetter(candidateState, current) {
|
|
1467
|
+
function isBetter(candidateState, current, states) {
|
|
1299
1468
|
if (current === void 0) return true;
|
|
1300
1469
|
for (let index = 0; index < candidateState.score.length; index += 1) {
|
|
1301
1470
|
const difference = (candidateState.score[index] ?? 0) - (current.score[index] ?? 0);
|
|
1302
1471
|
if (Math.abs(difference) > EPSILON) return difference < 0;
|
|
1303
1472
|
}
|
|
1304
|
-
return compareBreaks(candidateState
|
|
1473
|
+
return compareBreaks(breaksOf(candidateState, states), breaksOf(current, states)) < 0;
|
|
1305
1474
|
}
|
|
1306
1475
|
function layoutParagraph(atoms, lineLengthEm, profile, boundaryAllowed) {
|
|
1307
1476
|
if (atoms.length === 0) return [];
|
|
1308
1477
|
const classes = atoms.map(({ characterClass }) => characterClass);
|
|
1478
|
+
const boxPrefixEm = Array.from({ length: atoms.length + 1 }).fill(0);
|
|
1479
|
+
for (let index = 0; index < atoms.length; index += 1) boxPrefixEm[index + 1] = (boxPrefixEm[index] ?? 0) + (atoms[index]?.boxAdvanceEm ?? 0);
|
|
1309
1480
|
const states = /* @__PURE__ */ new Map([[0, /* @__PURE__ */ new Map([[0, {
|
|
1310
1481
|
score: [
|
|
1311
1482
|
0,
|
|
@@ -1318,8 +1489,7 @@ function layoutParagraph(atoms, lineLengthEm, profile, boundaryAllowed) {
|
|
|
1318
1489
|
],
|
|
1319
1490
|
fitness: 0,
|
|
1320
1491
|
previous: null,
|
|
1321
|
-
line: null
|
|
1322
|
-
breaks: []
|
|
1492
|
+
line: null
|
|
1323
1493
|
}]])]]);
|
|
1324
1494
|
for (let start = 0; start < atoms.length; start += 1) {
|
|
1325
1495
|
const activeStates = states.get(start);
|
|
@@ -1327,7 +1497,7 @@ function layoutParagraph(atoms, lineLengthEm, profile, boundaryAllowed) {
|
|
|
1327
1497
|
const contentStart = skipSourceGaps(atoms, start);
|
|
1328
1498
|
if (contentStart === atoms.length) {
|
|
1329
1499
|
const terminalStates = states.get(atoms.length) ?? /* @__PURE__ */ new Map();
|
|
1330
|
-
for (const state of activeStates.values()) if (isBetter(state, terminalStates.get(state.fitness))) terminalStates.set(state.fitness, state);
|
|
1500
|
+
for (const state of activeStates.values()) if (isBetter(state, terminalStates.get(state.fitness), states)) terminalStates.set(state.fitness, state);
|
|
1331
1501
|
states.set(atoms.length, terminalStates);
|
|
1332
1502
|
continue;
|
|
1333
1503
|
}
|
|
@@ -1336,8 +1506,8 @@ function layoutParagraph(atoms, lineLengthEm, profile, boundaryAllowed) {
|
|
|
1336
1506
|
const left = previousVisible(atoms, end);
|
|
1337
1507
|
if (atoms[end - 1]?.sourceGap === true) continue;
|
|
1338
1508
|
if (end < atoms.length && right < atoms.length && (left === void 0 || !boundaryAllowed(left, right))) continue;
|
|
1339
|
-
const line = candidate(atoms, classes, start, end, lineLengthEm, profile);
|
|
1340
|
-
if (line.break.kind === "forced" && line.inlineSizeEm > lineLengthEm + EPSILON &&
|
|
1509
|
+
const line = candidate(atoms, classes, boxPrefixEm, start, end, lineLengthEm, profile);
|
|
1510
|
+
if (line.break.kind === "forced" && line.inlineSizeEm > lineLengthEm + EPSILON && hasEarlierBoundary(boundaryAllowed, contentStart, end)) {
|
|
1341
1511
|
if (line.inlineSizeEm > lineLengthEm * 2 && end > contentStart + 1) break;
|
|
1342
1512
|
continue;
|
|
1343
1513
|
}
|
|
@@ -1349,18 +1519,17 @@ function layoutParagraph(atoms, lineLengthEm, profile, boundaryAllowed) {
|
|
|
1349
1519
|
index: start,
|
|
1350
1520
|
fitness: state.fitness
|
|
1351
1521
|
},
|
|
1352
|
-
line
|
|
1353
|
-
breaks: [...state.breaks, end]
|
|
1522
|
+
line
|
|
1354
1523
|
};
|
|
1355
1524
|
const statesAtEnd = states.get(end) ?? /* @__PURE__ */ new Map();
|
|
1356
|
-
if (isBetter(nextState, statesAtEnd.get(nextState.fitness))) {
|
|
1525
|
+
if (isBetter(nextState, statesAtEnd.get(nextState.fitness), states)) {
|
|
1357
1526
|
statesAtEnd.set(nextState.fitness, nextState);
|
|
1358
1527
|
states.set(end, statesAtEnd);
|
|
1359
1528
|
}
|
|
1360
1529
|
if (line.inlineSizeEm > lineLengthEm * 2 && line.break.kind === "forced" && end > contentStart + 1) break;
|
|
1361
1530
|
}
|
|
1362
1531
|
}
|
|
1363
|
-
const terminal = [...states.get(atoms.length)?.values() ?? []].reduce((best, state) => isBetter(state, best) ? state : best, void 0);
|
|
1532
|
+
const terminal = [...states.get(atoms.length)?.values() ?? []].reduce((best, state) => isBetter(state, best, states) ? state : best, void 0);
|
|
1364
1533
|
if (terminal === void 0) return [];
|
|
1365
1534
|
const lines = [];
|
|
1366
1535
|
let cursor = terminal;
|
package/dist/plugin.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as ManuscriptResult, i as ParsedManuscript, n as ValidationIssue, r as NamespacedId } from "./composed-manuscript-
|
|
2
|
-
import { a as InlineMeasureRequest, c as logicalInlineMeasurer, f as ManuscriptComposer, m as Rejection, n as createNovelComposer, o as InlineMeasurement, p as ManuscriptParser, s as InlineMeasurer } from "./novel-composer-
|
|
1
|
+
import { a as ManuscriptResult, i as ParsedManuscript, n as ValidationIssue, r as NamespacedId } from "./composed-manuscript-QgIdae8p.mjs";
|
|
2
|
+
import { a as InlineMeasureRequest, c as logicalInlineMeasurer, f as ManuscriptComposer, m as Rejection, n as createNovelComposer, o as InlineMeasurement, p as ManuscriptParser, s as InlineMeasurer } from "./novel-composer-BCt9g172.mjs";
|
|
3
3
|
export { type InlineMeasureRequest, type InlineMeasurement, type InlineMeasurer, type ManuscriptComposer, type ManuscriptParser, ManuscriptResult, NamespacedId, ParsedManuscript, type Rejection, ValidationIssue, createNovelComposer, logicalInlineMeasurer };
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { c as ManuscriptResult, d as NamespacedId, s as ValidationIssue } from "./question-or-exclamation-spacing-B5o23ZLf.mjs";
|
|
2
|
-
import { a as logicalInlineMeasurer, p as ParsedManuscript, t as createNovelComposer } from "./novel-composer-
|
|
2
|
+
import { a as logicalInlineMeasurer, p as ParsedManuscript, t as createNovelComposer } from "./novel-composer-CNBT4TDN.mjs";
|
|
3
3
|
export { ManuscriptResult, NamespacedId, ParsedManuscript, ValidationIssue, createNovelComposer, logicalInlineMeasurer };
|