@sushichan044/kg-core 0.8.0 → 0.9.1
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 +35 -5
- package/dist/index.mjs +1 -1
- package/dist/{novel-composer-CROZLBqt.mjs → novel-composer-CtovfhET.mjs} +342 -111
- package/dist/plugin.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,10 +84,18 @@ a closing bracket, comma, or full stop, a quarter em on either side of a middle
|
|
|
84
84
|
a quarter em between Japanese and a numeral, unit symbol, or Western character, and
|
|
85
85
|
solid where two of those punctuation marks meet.
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
A western word space is not a character with a box but an アキ of its own: a third em
|
|
88
|
+
by rule rather than by measurement, nothing at all at a line head or a line end, and
|
|
89
|
+
the first _visible_ space either direction of the adjustment reaches for — only the
|
|
90
|
+
line-end space, which the reader cannot see at all, is spent ahead of it. It leaves the
|
|
91
|
+
composer as a `glue` item carrying the source text it came from.
|
|
92
|
+
|
|
93
|
+
An overflowing line is answered by reducing the space between characters, stage by
|
|
94
|
+
stage, or by hanging a comma or full stop; a short line is answered by opening up space
|
|
95
|
+
where JLReq 3.8.4 and appendix 表6
|
|
96
|
+
allow it — the word space first, up to a half, then the Japanese-to-Western quarter em,
|
|
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. Space around
|
|
91
99
|
brackets, commas, full stops, middle dots, hyphens, and an ideographic space is never
|
|
92
100
|
opened up. A line that admits none of these is forced. The choice is made for the
|
|
93
101
|
paragraph rather than line by line,
|
|
@@ -95,11 +103,33 @@ minimizing in order the number of forced lines, then stretched, then hanging, th
|
|
|
95
103
|
shrunk lines that spent visible space. Which space may be reduced, and in which
|
|
96
104
|
order, follows JLReq 3.8.3 and appendix 表3: the space at the line end goes first and
|
|
97
105
|
costs the paragraph nothing, because it is invisible once that character lands there;
|
|
98
|
-
then a middle dot's quarters, then the half
|
|
106
|
+
then the word space, down to a quarter em; then a middle dot's quarters, then the half
|
|
107
|
+
em before an opening bracket or after a
|
|
99
108
|
closing bracket or comma, then the Japanese-to-Western quarter down to an eighth. The
|
|
100
109
|
half em after a mid-line full stop marks the end of a sentence and is never reduced,
|
|
101
110
|
and neither is the half em that keeps a line-head opening bracket off the edge.
|
|
102
111
|
|
|
112
|
+
JLReq puts the word space ahead of the line end; the composer swaps the two, because
|
|
113
|
+
a stage here says how visible an adjustment is and the line end is the only space the
|
|
114
|
+
reader cannot see at all.
|
|
115
|
+
|
|
116
|
+
The アキ at a line end is the one exception to spending a space in part. JLReq 3.1.9
|
|
117
|
+
admits the full アキ or ベタ組 and forbids anything between, so a line whose overflow is
|
|
118
|
+
smaller than it leaves it whole and finds the difference elsewhere — or breaks
|
|
119
|
+
elsewhere. A 中点類 at a line end gives up the quarter em before it together with the
|
|
120
|
+
quarter after, as one amount.
|
|
121
|
+
|
|
122
|
+
Every stage is spent 文字サイズ比で均等に, as JLReq 3.8.3 and 3.8.4 both put it: the amount
|
|
123
|
+
is split across all the spaces of that stage in proportion to what each of them can
|
|
124
|
+
give, rather than taken out of the earliest space until it runs dry. A stage opens
|
|
125
|
+
only once every stage before it is spent out.
|
|
126
|
+
|
|
127
|
+
JLReq 3.1.5 states the white before a line-head opening bracket as a pair of amounts:
|
|
128
|
+
one for 改行行頭, the head of a line that starts a paragraph, and one for 折返し行頭, the
|
|
129
|
+
head of a line the composer turned over. The specification lists three such pairs, and
|
|
130
|
+
the composer takes the one Japanese novels are set with — scheme ③: a half em at
|
|
131
|
+
改行行頭, and 天付き, flush against the edge, at 折返し行頭.
|
|
132
|
+
|
|
103
133
|
The composer also owns Japanese line-start and line-end restrictions, inseparable
|
|
104
134
|
punctuation, question/exclamation gap suppression, and ruby placement.
|
|
105
135
|
|
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-CtovfhET.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() }) };
|
|
@@ -337,14 +337,17 @@ function classify({ value, presentation }) {
|
|
|
337
337
|
* The stages JLReq 3.8.3 spends inter-character space in, as glue priorities: the lower the number,
|
|
338
338
|
* the earlier the paragraph optimizer takes it.
|
|
339
339
|
*
|
|
340
|
-
* JLReq
|
|
341
|
-
*
|
|
340
|
+
* JLReq puts the western word space first and the line-end reduction second; this profile swaps the
|
|
341
|
+
* two, because a priority here says how visible an adjustment is rather than where 3.8.3's list
|
|
342
|
+
* puts it. Priority 0 is capacity the paragraph optimizer spends for nothing, and a line that spent
|
|
343
|
+
* only priority 0 reads as tightly set as an unadjusted one. That is true of the line end and of
|
|
344
|
+
* nothing else: the half em after a closing bracket, full stop or comma — and the quarter em after
|
|
345
|
+
* a middle dot — falls outside the text area once that character sits at the line end, so taking it
|
|
346
|
+
* changes nothing on the page (3.1.9). A 欧文間隔 sits between two words the reader is looking at, so
|
|
347
|
+
* narrowing it does change the page. Spending the invisible space first can only leave the word
|
|
348
|
+
* spaces nearer their 三分アキ than JLReq's order would, never further from it.
|
|
342
349
|
*
|
|
343
|
-
*
|
|
344
|
-
* what allows that: the half em after a closing bracket, full stop or comma — and the quarter em
|
|
345
|
-
* after a middle dot — cannot be seen once that character sits at the line end. JLReq orders it
|
|
346
|
-
* second rather than first, but only after the word space this profile does not adjust at all.
|
|
347
|
-
* Stages two and three are one priority here because a line has a single line end, so the two never
|
|
350
|
+
* Stages two and three are one priority because a line has a single line end, so the two never
|
|
348
351
|
* compete.
|
|
349
352
|
*/
|
|
350
353
|
const REDUCTION_STAGE = {
|
|
@@ -353,37 +356,47 @@ const REDUCTION_STAGE = {
|
|
|
353
356
|
*/
|
|
354
357
|
lineEnd: 0,
|
|
355
358
|
/**
|
|
359
|
+
* Stage 1: the western word space, from its 三分アキ down to a 四分アキ.
|
|
360
|
+
*/
|
|
361
|
+
wordSpace: 1,
|
|
362
|
+
/**
|
|
356
363
|
* Stage 4: the quarter em on either side of a mid-line middle dot.
|
|
357
364
|
*/
|
|
358
|
-
middleDot:
|
|
365
|
+
middleDot: 2,
|
|
359
366
|
/**
|
|
360
367
|
* Stage 5: the half em before an opening bracket and after a closing bracket or comma.
|
|
361
368
|
*/
|
|
362
|
-
punctuation:
|
|
369
|
+
punctuation: 3,
|
|
363
370
|
/**
|
|
364
371
|
* Stage 6: the quarter em between Japanese and a numeral, unit symbol or western character.
|
|
365
372
|
*/
|
|
366
|
-
mixedText:
|
|
373
|
+
mixedText: 4
|
|
367
374
|
};
|
|
368
375
|
/**
|
|
369
376
|
* The stages JLReq 3.8.4 adds inter-character space in, as glue priorities on the same reading as
|
|
370
377
|
* {@link REDUCTION_STAGE}: the lower the number, the earlier the paragraph optimizer takes it. A
|
|
371
378
|
* line is either reduced or expanded, never both, so the two scales never meet.
|
|
372
379
|
*
|
|
373
|
-
* Stage
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
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
|
+
* Nothing here takes priority 0. Expanding is always visible, and priority 0 means an adjustment
|
|
385
|
+
* the optimizer is charged nothing for.
|
|
377
386
|
*/
|
|
378
387
|
const EXPANSION_STAGE = {
|
|
388
|
+
/**
|
|
389
|
+
* Stage 1: the western word space, from its 三分アキ up to a 二分アキ.
|
|
390
|
+
*/
|
|
391
|
+
wordSpace: 1,
|
|
379
392
|
/**
|
|
380
393
|
* Stage 2: the quarter em between Japanese and a numeral, unit symbol or western character.
|
|
381
394
|
*/
|
|
382
|
-
mixedText:
|
|
395
|
+
mixedText: 2,
|
|
383
396
|
/**
|
|
384
397
|
* Stage 3: everywhere else 表6 admits, from solid up to a quarter em.
|
|
385
398
|
*/
|
|
386
|
-
solid:
|
|
399
|
+
solid: 3
|
|
387
400
|
};
|
|
388
401
|
/**
|
|
389
402
|
* 無印 in 表1 with no colour in 表6: the pair is set solid and line adjustment leaves it alone.
|
|
@@ -400,7 +413,8 @@ const SOLID_EXPANDABLE = {
|
|
|
400
413
|
naturalWidthEm: 0,
|
|
401
414
|
stretch: {
|
|
402
415
|
priority: EXPANSION_STAGE.solid,
|
|
403
|
-
amountEm: .25
|
|
416
|
+
amountEm: .25,
|
|
417
|
+
granularity: "continuous"
|
|
404
418
|
}
|
|
405
419
|
};
|
|
406
420
|
/**
|
|
@@ -411,7 +425,8 @@ const HALF = {
|
|
|
411
425
|
naturalWidthEm: .5,
|
|
412
426
|
shrink: {
|
|
413
427
|
priority: REDUCTION_STAGE.punctuation,
|
|
414
|
-
amountEm: .5
|
|
428
|
+
amountEm: .5,
|
|
429
|
+
granularity: "continuous"
|
|
415
430
|
}
|
|
416
431
|
};
|
|
417
432
|
/**
|
|
@@ -429,7 +444,8 @@ const QUARTER = {
|
|
|
429
444
|
naturalWidthEm: .25,
|
|
430
445
|
shrink: {
|
|
431
446
|
priority: REDUCTION_STAGE.middleDot,
|
|
432
|
-
amountEm: .25
|
|
447
|
+
amountEm: .25,
|
|
448
|
+
granularity: "continuous"
|
|
433
449
|
}
|
|
434
450
|
};
|
|
435
451
|
/**
|
|
@@ -448,11 +464,13 @@ const MIXED_TEXT_QUARTER = {
|
|
|
448
464
|
naturalWidthEm: .25,
|
|
449
465
|
shrink: {
|
|
450
466
|
priority: REDUCTION_STAGE.mixedText,
|
|
451
|
-
amountEm: .125
|
|
467
|
+
amountEm: .125,
|
|
468
|
+
granularity: "continuous"
|
|
452
469
|
},
|
|
453
470
|
stretch: {
|
|
454
471
|
priority: EXPANSION_STAGE.mixedText,
|
|
455
|
-
amountEm: .25
|
|
472
|
+
amountEm: .25,
|
|
473
|
+
granularity: "continuous"
|
|
456
474
|
}
|
|
457
475
|
};
|
|
458
476
|
/**
|
|
@@ -464,7 +482,8 @@ const UNIT_SYMBOL_QUARTER = {
|
|
|
464
482
|
naturalWidthEm: .25,
|
|
465
483
|
shrink: {
|
|
466
484
|
priority: REDUCTION_STAGE.mixedText,
|
|
467
|
-
amountEm: .125
|
|
485
|
+
amountEm: .125,
|
|
486
|
+
granularity: "continuous"
|
|
468
487
|
}
|
|
469
488
|
};
|
|
470
489
|
/**
|
|
@@ -475,7 +494,8 @@ const TWO_QUARTERS = {
|
|
|
475
494
|
naturalWidthEm: .5,
|
|
476
495
|
shrink: {
|
|
477
496
|
priority: REDUCTION_STAGE.middleDot,
|
|
478
|
-
amountEm: .5
|
|
497
|
+
amountEm: .5,
|
|
498
|
+
granularity: "continuous"
|
|
479
499
|
}
|
|
480
500
|
};
|
|
481
501
|
/**
|
|
@@ -486,7 +506,8 @@ const FIXED_HALF_AND_QUARTER = {
|
|
|
486
506
|
naturalWidthEm: .75,
|
|
487
507
|
shrink: {
|
|
488
508
|
priority: REDUCTION_STAGE.middleDot,
|
|
489
|
-
amountEm: .25
|
|
509
|
+
amountEm: .25,
|
|
510
|
+
granularity: "continuous"
|
|
490
511
|
}
|
|
491
512
|
};
|
|
492
513
|
/**
|
|
@@ -501,7 +522,8 @@ const HALF_AND_QUARTER = {
|
|
|
501
522
|
naturalWidthEm: .75,
|
|
502
523
|
shrink: {
|
|
503
524
|
priority: REDUCTION_STAGE.punctuation,
|
|
504
|
-
amountEm: .75
|
|
525
|
+
amountEm: .75,
|
|
526
|
+
granularity: "continuous"
|
|
505
527
|
}
|
|
506
528
|
};
|
|
507
529
|
/**
|
|
@@ -512,6 +534,40 @@ const DASH_JOINT = {
|
|
|
512
534
|
naturalWidthEm: 0
|
|
513
535
|
};
|
|
514
536
|
/**
|
|
537
|
+
* 欧文間隔(cl-26)の三分アキ. JLReq states the western word space as a third em by rule rather than by
|
|
538
|
+
* measurement, and makes it the first space a line adjustment reaches for: down to a 四分アキ when the
|
|
539
|
+
* line is over (3.8.3 a), up to a 二分アキ when it is short (3.8.4 a).
|
|
540
|
+
*
|
|
541
|
+
* The two capacities are written as differences from the limits rather than as `1/12` and `1/6`,
|
|
542
|
+
* because a third of an em is not representable in binary while the limits JLReq states are: this
|
|
543
|
+
* way `naturalWidthEm - shrink.amountEm` is exactly 0.25 and `naturalWidthEm + stretch.amountEm`
|
|
544
|
+
* exactly 0.5.
|
|
545
|
+
*/
|
|
546
|
+
const WORD_SPACE = {
|
|
547
|
+
kind: "glue",
|
|
548
|
+
naturalWidthEm: 1 / 3,
|
|
549
|
+
shrink: {
|
|
550
|
+
priority: REDUCTION_STAGE.wordSpace,
|
|
551
|
+
amountEm: 1 / 3 - 1 / 4,
|
|
552
|
+
granularity: "continuous"
|
|
553
|
+
},
|
|
554
|
+
stretch: {
|
|
555
|
+
priority: EXPANSION_STAGE.wordSpace,
|
|
556
|
+
amountEm: 1 / 2 - 1 / 3,
|
|
557
|
+
granularity: "continuous"
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
/**
|
|
561
|
+
* 表1 注13 と 表3 注4: a word space at a line head or a line end has no width and is no adjustment
|
|
562
|
+
* opportunity, since the white would fall outside the text area where no reader can see it. 注13
|
|
563
|
+
* adds ただし,この部分が移動し,これとは異なる配置になった場合は,欧文間隔(cl-26)の空き量を確保する — which is why the answer is given per
|
|
564
|
+
* candidate line and not once per source line.
|
|
565
|
+
*/
|
|
566
|
+
const EDGE_WORD_SPACE = {
|
|
567
|
+
kind: "glue",
|
|
568
|
+
naturalWidthEm: 0
|
|
569
|
+
};
|
|
570
|
+
/**
|
|
515
571
|
* The classes that take a quarter em against a numeral, unit symbol or western character (3.2.6).
|
|
516
572
|
* Dividing punctuation is on the list in that direction only, because the space before a `?` or `!`
|
|
517
573
|
* is solid (3.1.6).
|
|
@@ -807,6 +863,10 @@ const defaultJapaneseTypesettingProfile = {
|
|
|
807
863
|
* trailing half of its em, a middle dot in the centre, and the rest in the leading half.
|
|
808
864
|
*/
|
|
809
865
|
boxMetrics: (characterClass, measuredAdvanceEm) => {
|
|
866
|
+
if (characterClass === "cl-26") return {
|
|
867
|
+
advanceEm: 0,
|
|
868
|
+
renderOffsetEm: 0
|
|
869
|
+
};
|
|
810
870
|
const advanceEm = HALF_EM_CLASSES.has(characterClass) ? Math.min(.5, measuredAdvanceEm) : measuredAdvanceEm;
|
|
811
871
|
const inkOverhangEm = measuredAdvanceEm - advanceEm;
|
|
812
872
|
return {
|
|
@@ -815,16 +875,18 @@ const defaultJapaneseTypesettingProfile = {
|
|
|
815
875
|
};
|
|
816
876
|
},
|
|
817
877
|
pairSpacing,
|
|
878
|
+
spacingCharacter: (characterClass, position) => characterClass !== "cl-26" ? null : position === "mid-line" ? WORD_SPACE : EDGE_WORD_SPACE,
|
|
818
879
|
/**
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
*
|
|
880
|
+
* The white before an opening bracket at a line head. JLReq 3.1.5 pairs 改行行頭 with 折返し行頭 and lists
|
|
881
|
+
* three schemes for the two together: ① 全角アキ and 天付き, ② 全角半アキ and 二分アキ, ③ 二分アキ and 天付き. This
|
|
882
|
+
* profile takes ③, the scheme 講談社, 新潮社, 文藝春秋, 中央公論新社 and 筑摩書房 set novels with; ① is what JIS X
|
|
883
|
+
* 4051 and 岩波書店 use. A line of dialogue therefore starts one half em in when it opens a
|
|
884
|
+
* paragraph, and flush against the edge when the composer turned it over.
|
|
823
885
|
*
|
|
824
886
|
* The white is not shrinkable. 表3 excludes the line head from line adjustment altogether, and
|
|
825
887
|
* shrinking it is exactly what pushed a line-head bracket flush against the edge in #94.
|
|
826
888
|
*/
|
|
827
|
-
lineStartSpacing: (first) => first === "cl-01" ? {
|
|
889
|
+
lineStartSpacing: (first, lineHead) => first === "cl-01" && lineHead === "paragraph-start" ? {
|
|
828
890
|
kind: "glue",
|
|
829
891
|
naturalWidthEm: .5
|
|
830
892
|
} : null,
|
|
@@ -832,21 +894,33 @@ const defaultJapaneseTypesettingProfile = {
|
|
|
832
894
|
* The half em trailing a closing bracket, full stop or comma at the line end, and the quarter em
|
|
833
895
|
* trailing a middle dot there (JLReq 3.1.9). Priority 0: spending it changes nothing the reader
|
|
834
896
|
* can see.
|
|
897
|
+
*
|
|
898
|
+
* Both are all-or-nothing. 3.1.9 admits the full アキ or ベタ組 and forbids anything in between, so a
|
|
899
|
+
* line whose overflow is smaller than the アキ has to find the difference somewhere else — or break
|
|
900
|
+
* elsewhere. A line-end middle dot takes the quarter before it into the same amount (表3 注5).
|
|
835
901
|
*/
|
|
836
902
|
lineEndSpacing: (last) => last === "cl-02" || last === "cl-06" || last === "cl-07" ? {
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
903
|
+
spacing: {
|
|
904
|
+
kind: "glue",
|
|
905
|
+
naturalWidthEm: .5,
|
|
906
|
+
shrink: {
|
|
907
|
+
priority: REDUCTION_STAGE.lineEnd,
|
|
908
|
+
amountEm: .5,
|
|
909
|
+
granularity: "all-or-nothing"
|
|
910
|
+
}
|
|
911
|
+
},
|
|
912
|
+
absorbsPrecedingEm: 0
|
|
843
913
|
} : last === "cl-05" ? {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
914
|
+
spacing: {
|
|
915
|
+
kind: "glue",
|
|
916
|
+
naturalWidthEm: .25,
|
|
917
|
+
shrink: {
|
|
918
|
+
priority: REDUCTION_STAGE.lineEnd,
|
|
919
|
+
amountEm: .25,
|
|
920
|
+
granularity: "all-or-nothing"
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
absorbsPrecedingEm: .25
|
|
850
924
|
} : null,
|
|
851
925
|
breakPenalty,
|
|
852
926
|
/**
|
|
@@ -862,6 +936,13 @@ const EPSILON = 1e-9;
|
|
|
862
936
|
* Spending capacity at this priority changes nothing the reader can see.
|
|
863
937
|
*/
|
|
864
938
|
const FREE_SHRINK_PRIORITY = 0;
|
|
939
|
+
/**
|
|
940
|
+
* Interleave the two kinds onto one number so the allocator can key a plain `Map` without building
|
|
941
|
+
* a string per boundary — this runs once per adjustment unit of every candidate line.
|
|
942
|
+
*/
|
|
943
|
+
function slotKey(slot) {
|
|
944
|
+
return slot.kind === "gap" ? slot.boundary * 2 : slot.index * 2 + 1;
|
|
945
|
+
}
|
|
865
946
|
function skipSourceGaps(atoms, start) {
|
|
866
947
|
let cursor = start;
|
|
867
948
|
while (atoms[cursor]?.sourceGap === true) cursor += 1;
|
|
@@ -870,14 +951,31 @@ function skipSourceGaps(atoms, start) {
|
|
|
870
951
|
function previousVisible(atoms, end) {
|
|
871
952
|
for (let index = end - 1; index >= 0; index -= 1) if (atoms[index]?.sourceGap === false) return index;
|
|
872
953
|
}
|
|
873
|
-
function opportunities(atoms, classes, start, end, profile) {
|
|
954
|
+
function opportunities(atoms, classes, start, end, profile, lineHead) {
|
|
874
955
|
const result = [];
|
|
875
956
|
const firstClass = classes[start];
|
|
876
|
-
const startSpacing = firstClass === void 0 ? null : profile.lineStartSpacing(firstClass);
|
|
957
|
+
const startSpacing = firstClass === void 0 ? null : profile.lineStartSpacing(firstClass, lineHead);
|
|
877
958
|
if (startSpacing !== null) result.push({
|
|
878
|
-
|
|
879
|
-
|
|
959
|
+
slot: {
|
|
960
|
+
kind: "gap",
|
|
961
|
+
boundary: start
|
|
962
|
+
},
|
|
963
|
+
spacing: startSpacing,
|
|
964
|
+
absorbsPrecedingEm: 0
|
|
880
965
|
});
|
|
966
|
+
for (let index = start; index < end; index += 1) {
|
|
967
|
+
const characterClass = classes[index];
|
|
968
|
+
if (characterClass === void 0 || atoms[index]?.sourceGap === true) continue;
|
|
969
|
+
const spacing = profile.spacingCharacter(characterClass, index === start || index === end - 1 ? "line-edge" : "mid-line");
|
|
970
|
+
if (spacing !== null) result.push({
|
|
971
|
+
slot: {
|
|
972
|
+
kind: "character",
|
|
973
|
+
index
|
|
974
|
+
},
|
|
975
|
+
spacing,
|
|
976
|
+
absorbsPrecedingEm: 0
|
|
977
|
+
});
|
|
978
|
+
}
|
|
881
979
|
for (let right = start + 1; right < end; right += 1) {
|
|
882
980
|
const leftAtom = atoms[right - 1];
|
|
883
981
|
const rightAtom = atoms[right];
|
|
@@ -885,73 +983,203 @@ function opportunities(atoms, classes, start, end, profile) {
|
|
|
885
983
|
const rightClass = classes[right];
|
|
886
984
|
if (leftAtom === void 0 || rightAtom === void 0 || leftClass === void 0 || rightClass === void 0 || leftAtom.sourceGap || rightAtom.sourceGap || !leftAtom.pairSpacingAfter) continue;
|
|
887
985
|
result.push({
|
|
888
|
-
|
|
889
|
-
|
|
986
|
+
slot: {
|
|
987
|
+
kind: "gap",
|
|
988
|
+
boundary: right
|
|
989
|
+
},
|
|
990
|
+
spacing: profile.pairSpacing(leftClass, rightClass),
|
|
991
|
+
absorbsPrecedingEm: 0
|
|
890
992
|
});
|
|
891
993
|
}
|
|
892
994
|
const lastClass = classes[end - 1];
|
|
893
995
|
const endSpacing = lastClass === void 0 ? null : profile.lineEndSpacing(lastClass);
|
|
894
996
|
if (endSpacing !== null) result.push({
|
|
895
|
-
|
|
896
|
-
|
|
997
|
+
slot: {
|
|
998
|
+
kind: "gap",
|
|
999
|
+
boundary: end
|
|
1000
|
+
},
|
|
1001
|
+
spacing: endSpacing.spacing,
|
|
1002
|
+
absorbsPrecedingEm: endSpacing.absorbsPrecedingEm
|
|
897
1003
|
});
|
|
898
1004
|
return result;
|
|
899
1005
|
}
|
|
900
|
-
|
|
901
|
-
|
|
1006
|
+
/**
|
|
1007
|
+
* Break the line's spaces into the indivisible amounts the line adjustment may spend.
|
|
1008
|
+
*
|
|
1009
|
+
* A line end the profile says absorbs the space before it claims that much of the preceding
|
|
1010
|
+
* boundary's capacity, and the two become one unit at the line-end stage — JLReq 3.8.3's third
|
|
1011
|
+
* stage, which is free. Whatever the preceding boundary has left over stays an opportunity of its
|
|
1012
|
+
* own stage, so the half em of a `、` before a line-end `・` is still spent where 3.8.3 puts it.
|
|
1013
|
+
*/
|
|
1014
|
+
function adjustmentUnits(values, adjustment) {
|
|
1015
|
+
const select = (spacing) => adjustment === "shrink" ? spacing.shrink : spacing.stretch;
|
|
1016
|
+
const units = [];
|
|
1017
|
+
const straddle = values.find(({ absorbsPrecedingEm }) => absorbsPrecedingEm > 0);
|
|
1018
|
+
let absorbedBoundary;
|
|
1019
|
+
let absorbedEm = 0;
|
|
1020
|
+
let absorbingBoundary;
|
|
1021
|
+
const straddleSlot = straddle?.slot.kind === "gap" ? straddle.slot : void 0;
|
|
1022
|
+
const straddleOwn = straddle === void 0 ? void 0 : select(straddle.spacing);
|
|
1023
|
+
if (straddle !== void 0 && straddleSlot !== void 0 && straddleOwn !== void 0) {
|
|
1024
|
+
const precedingBoundary = straddleSlot.boundary - 1;
|
|
1025
|
+
const preceding = values.find(({ slot }) => slot.kind === "gap" && slot.boundary === precedingBoundary);
|
|
1026
|
+
const availableEm = preceding === void 0 ? 0 : select(preceding.spacing)?.amountEm ?? 0;
|
|
1027
|
+
absorbingBoundary = straddleSlot.boundary;
|
|
1028
|
+
if (availableEm + EPSILON >= straddle.absorbsPrecedingEm) {
|
|
1029
|
+
absorbedBoundary = precedingBoundary;
|
|
1030
|
+
absorbedEm = straddle.absorbsPrecedingEm;
|
|
1031
|
+
units.push({
|
|
1032
|
+
parts: [{
|
|
1033
|
+
slot: {
|
|
1034
|
+
kind: "gap",
|
|
1035
|
+
boundary: precedingBoundary
|
|
1036
|
+
},
|
|
1037
|
+
amountEm: absorbedEm
|
|
1038
|
+
}, {
|
|
1039
|
+
slot: straddleSlot,
|
|
1040
|
+
amountEm: straddleOwn.amountEm
|
|
1041
|
+
}],
|
|
1042
|
+
priority: straddleOwn.priority,
|
|
1043
|
+
amountEm: absorbedEm + straddleOwn.amountEm,
|
|
1044
|
+
granularity: straddleOwn.granularity
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
for (const { slot, spacing } of values) {
|
|
1049
|
+
if (slot.kind === "gap" && slot.boundary === absorbingBoundary) continue;
|
|
1050
|
+
const own = select(spacing);
|
|
1051
|
+
if (own === void 0) continue;
|
|
1052
|
+
const claimedEm = slot.kind === "gap" && slot.boundary === absorbedBoundary ? absorbedEm : 0;
|
|
1053
|
+
const amountEm = own.amountEm - claimedEm;
|
|
1054
|
+
if (amountEm <= EPSILON) continue;
|
|
1055
|
+
units.push({
|
|
1056
|
+
parts: [{
|
|
1057
|
+
slot,
|
|
1058
|
+
amountEm
|
|
1059
|
+
}],
|
|
1060
|
+
priority: own.priority,
|
|
1061
|
+
amountEm,
|
|
1062
|
+
granularity: own.granularity
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
return units;
|
|
902
1066
|
}
|
|
903
|
-
|
|
904
|
-
|
|
1067
|
+
/**
|
|
1068
|
+
* Spend `amountEm` over the line's units of adjustment, stage by stage.
|
|
1069
|
+
*
|
|
1070
|
+
* Every stage of JLReq 3.8.3 and 3.8.4 is stated as 文字サイズ比で均等に — the English text of 3.8.3 a puts
|
|
1071
|
+
* it as "The same width reduction is applied to all spaces on the target line at the same time."
|
|
1072
|
+
* Within a stage the amount is therefore split in proportion to what each space can give, rather
|
|
1073
|
+
* than taken out of the earliest space until it runs dry. Across stages the order stays a
|
|
1074
|
+
* 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.
|
|
1076
|
+
*
|
|
1077
|
+
* An all-or-nothing unit larger than what is still needed is skipped rather than partly spent, and
|
|
1078
|
+
* never revisited: `remaining` only falls, so a unit that did not fit at its own stage cannot fit
|
|
1079
|
+
* at a later one. One forward pass is therefore exact and no search over subsets is needed.
|
|
1080
|
+
*/
|
|
1081
|
+
function resolveSpacings(values, units, adjustment, amountEm) {
|
|
1082
|
+
const usedBySlot = /* @__PURE__ */ new Map();
|
|
905
1083
|
let remaining = amountEm;
|
|
906
1084
|
let priorityCost = 0;
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
|
|
1085
|
+
let freeEm = 0;
|
|
1086
|
+
const spend = (unit, fraction) => {
|
|
1087
|
+
for (const { slot, amountEm: partEm } of unit.parts) {
|
|
1088
|
+
const key = slotKey(slot);
|
|
1089
|
+
usedBySlot.set(key, (usedBySlot.get(key) ?? 0) + partEm * fraction);
|
|
1090
|
+
}
|
|
1091
|
+
const spentEm = unit.amountEm * fraction;
|
|
1092
|
+
priorityCost += spentEm * unit.priority;
|
|
1093
|
+
if (unit.priority === FREE_SHRINK_PRIORITY) freeEm += spentEm;
|
|
1094
|
+
remaining -= spentEm;
|
|
1095
|
+
};
|
|
1096
|
+
const stages = /* @__PURE__ */ new Map();
|
|
1097
|
+
for (const unit of units) {
|
|
1098
|
+
const stage = stages.get(unit.priority);
|
|
1099
|
+
if (stage === void 0) stages.set(unit.priority, [unit]);
|
|
1100
|
+
else stage.push(unit);
|
|
1101
|
+
}
|
|
1102
|
+
for (const priority of [...stages.keys()].sort((left, right) => left - right)) {
|
|
915
1103
|
if (remaining <= EPSILON) break;
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
remaining
|
|
1104
|
+
const stage = stages.get(priority) ?? [];
|
|
1105
|
+
let stageCapacityEm = 0;
|
|
1106
|
+
for (const unit of stage) if (unit.granularity === "continuous") stageCapacityEm += unit.amountEm;
|
|
1107
|
+
else if (unit.amountEm <= remaining + EPSILON) spend(unit, 1);
|
|
1108
|
+
if (stageCapacityEm <= EPSILON || remaining <= EPSILON) continue;
|
|
1109
|
+
const fraction = Math.min(remaining, stageCapacityEm) / stageCapacityEm;
|
|
1110
|
+
for (const unit of stage) if (unit.granularity === "continuous") spend(unit, fraction);
|
|
920
1111
|
}
|
|
921
1112
|
return {
|
|
922
|
-
spacings: values
|
|
923
|
-
const used =
|
|
924
|
-
return
|
|
925
|
-
boundary,
|
|
926
|
-
kind: spacing.kind,
|
|
927
|
-
naturalWidthEm: spacing.naturalWidthEm,
|
|
928
|
-
widthEm: adjustment === "shrink" ? spacing.naturalWidthEm - used : spacing.naturalWidthEm + used
|
|
929
|
-
};
|
|
1113
|
+
spacings: splitBySlot(values, (slot, spacing) => {
|
|
1114
|
+
const used = usedBySlot.get(slotKey(slot)) ?? 0;
|
|
1115
|
+
return adjustment === "shrink" ? spacing.naturalWidthEm - used : spacing.naturalWidthEm + used;
|
|
930
1116
|
}),
|
|
931
|
-
priorityCost
|
|
1117
|
+
priorityCost,
|
|
1118
|
+
freeEm,
|
|
1119
|
+
unabsorbedEm: Math.max(0, remaining)
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
function splitBySlot(values, widthOf) {
|
|
1123
|
+
const pairSpacings = [];
|
|
1124
|
+
const characterSpacings = [];
|
|
1125
|
+
for (const { slot, spacing } of values) {
|
|
1126
|
+
const resolved = {
|
|
1127
|
+
kind: spacing.kind,
|
|
1128
|
+
naturalWidthEm: spacing.naturalWidthEm,
|
|
1129
|
+
widthEm: widthOf(slot, spacing)
|
|
1130
|
+
};
|
|
1131
|
+
if (slot.kind === "gap") pairSpacings.push({
|
|
1132
|
+
boundary: slot.boundary,
|
|
1133
|
+
...resolved
|
|
1134
|
+
});
|
|
1135
|
+
else characterSpacings.push({
|
|
1136
|
+
index: slot.index,
|
|
1137
|
+
...resolved
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
return {
|
|
1141
|
+
pairSpacings,
|
|
1142
|
+
characterSpacings
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* The same spaces at the width the profile gives them, for a line no adjustment reaches.
|
|
1147
|
+
*/
|
|
1148
|
+
function naturalSpacings(values) {
|
|
1149
|
+
return splitBySlot(values, (_slot, spacing) => spacing.naturalWidthEm);
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* The same, minus the アキ the line end would have taken: a hanging character sits outside the text
|
|
1153
|
+
* area and the space that would have followed it goes with it.
|
|
1154
|
+
*/
|
|
1155
|
+
function hangingSpacings(values, end) {
|
|
1156
|
+
const { pairSpacings, characterSpacings } = naturalSpacings(values);
|
|
1157
|
+
return {
|
|
1158
|
+
pairSpacings: pairSpacings.filter(({ boundary }) => boundary !== end),
|
|
1159
|
+
characterSpacings
|
|
932
1160
|
};
|
|
933
1161
|
}
|
|
934
1162
|
function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
935
1163
|
const contentStart = skipSourceGaps(atoms, start);
|
|
936
1164
|
const suppressedIndexes = Array.from({ length: contentStart - start }, (_, index) => start + index);
|
|
937
|
-
const pairValues = opportunities(atoms, classes, contentStart, end, profile);
|
|
1165
|
+
const pairValues = opportunities(atoms, classes, contentStart, end, profile, start === 0 ? "paragraph-start" : "turned-over");
|
|
938
1166
|
const naturalSizeEm = atoms.slice(contentStart, end).reduce((total, atom) => total + atom.boxAdvanceEm, 0) + pairValues.reduce((total, value) => total + value.spacing.naturalWidthEm, 0);
|
|
939
1167
|
const terminal = skipSourceGaps(atoms, end) === atoms.length;
|
|
940
|
-
const shrinkCapacity = capacity(pairValues, ({ shrink }) => shrink);
|
|
941
|
-
const freeShrinkCapacity = capacity(pairValues, ({ shrink }) => shrink?.priority === FREE_SHRINK_PRIORITY ? shrink : void 0);
|
|
942
|
-
const stretchCapacity = capacity(pairValues, ({ stretch }) => stretch);
|
|
943
1168
|
const overflow = naturalSizeEm - lineLengthEm;
|
|
944
1169
|
const underflow = lineLengthEm - naturalSizeEm;
|
|
1170
|
+
const units = adjustmentUnits(pairValues, overflow > 0 ? "shrink" : "stretch");
|
|
1171
|
+
const capacity = units.reduce((total, { amountEm }) => total + amountEm, 0);
|
|
1172
|
+
const freeShrinkCapacity = units.reduce((total, { priority, amountEm }) => total + (priority === FREE_SHRINK_PRIORITY ? amountEm : 0), 0);
|
|
945
1173
|
const lastVisible = previousVisible(atoms, end);
|
|
946
1174
|
const lastClass = lastVisible === void 0 ? void 0 : classes[lastVisible];
|
|
947
1175
|
const lastAdvance = lastVisible === void 0 ? 0 : atoms[lastVisible]?.boxAdvanceEm ?? 0;
|
|
948
|
-
const trailingSpacing = pairValues.find(({
|
|
1176
|
+
const trailingSpacing = pairValues.find(({ slot }) => slot.kind === "gap" && slot.boundary === end)?.spacing.naturalWidthEm ?? 0;
|
|
949
1177
|
if (terminal && overflow <= EPSILON) return {
|
|
950
1178
|
start,
|
|
951
1179
|
contentStart,
|
|
952
1180
|
end,
|
|
953
1181
|
suppressedIndexes,
|
|
954
|
-
|
|
1182
|
+
...naturalSpacings(pairValues),
|
|
955
1183
|
inlineSizeEm: naturalSizeEm,
|
|
956
1184
|
break: { kind: "paragraph-end" },
|
|
957
1185
|
hangingIndex: null,
|
|
@@ -963,28 +1191,28 @@ function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
|
963
1191
|
contentStart,
|
|
964
1192
|
end,
|
|
965
1193
|
suppressedIndexes,
|
|
966
|
-
|
|
1194
|
+
...naturalSpacings(pairValues),
|
|
967
1195
|
inlineSizeEm: naturalSizeEm,
|
|
968
1196
|
break: { kind: "natural" },
|
|
969
1197
|
hangingIndex: null,
|
|
970
1198
|
deformationRatio: 0,
|
|
971
1199
|
priorityCost: 0
|
|
972
1200
|
};
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
const chargeableCapacity =
|
|
976
|
-
const chargeableShrink = Math.max(0, overflow -
|
|
1201
|
+
const shrunk = overflow > 0 && overflow <= capacity + EPSILON ? resolveSpacings(pairValues, units, "shrink", overflow) : null;
|
|
1202
|
+
if (shrunk !== null && shrunk.unabsorbedEm <= EPSILON) {
|
|
1203
|
+
const chargeableCapacity = capacity - freeShrinkCapacity;
|
|
1204
|
+
const chargeableShrink = Math.max(0, overflow - shrunk.freeEm);
|
|
977
1205
|
return {
|
|
978
1206
|
start,
|
|
979
1207
|
contentStart,
|
|
980
1208
|
end,
|
|
981
1209
|
suppressedIndexes,
|
|
982
|
-
|
|
1210
|
+
...shrunk.spacings,
|
|
983
1211
|
inlineSizeEm: lineLengthEm,
|
|
984
1212
|
break: { kind: "shrunk" },
|
|
985
1213
|
hangingIndex: null,
|
|
986
1214
|
deformationRatio: chargeableCapacity <= EPSILON ? 0 : chargeableShrink / chargeableCapacity,
|
|
987
|
-
priorityCost:
|
|
1215
|
+
priorityCost: shrunk.priorityCost
|
|
988
1216
|
};
|
|
989
1217
|
}
|
|
990
1218
|
if (!terminal && overflow > 0 && lastVisible !== void 0 && lastClass !== void 0 && profile.canHang(lastClass) && naturalSizeEm - lastAdvance - trailingSpacing <= lineLengthEm + EPSILON) return {
|
|
@@ -992,34 +1220,32 @@ function candidate(atoms, classes, start, end, lineLengthEm, profile) {
|
|
|
992
1220
|
contentStart,
|
|
993
1221
|
end,
|
|
994
1222
|
suppressedIndexes,
|
|
995
|
-
|
|
1223
|
+
...hangingSpacings(pairValues, end),
|
|
996
1224
|
inlineSizeEm: naturalSizeEm - lastAdvance - trailingSpacing,
|
|
997
1225
|
break: { kind: "hanging" },
|
|
998
1226
|
hangingIndex: lastVisible,
|
|
999
1227
|
deformationRatio: overflow / Math.max(lastAdvance, EPSILON),
|
|
1000
1228
|
priorityCost: 0
|
|
1001
1229
|
};
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
};
|
|
1016
|
-
}
|
|
1230
|
+
const stretched = !terminal && underflow > EPSILON && underflow <= capacity + EPSILON ? resolveSpacings(pairValues, units, "stretch", underflow) : null;
|
|
1231
|
+
if (stretched !== null && stretched.unabsorbedEm <= EPSILON) return {
|
|
1232
|
+
start,
|
|
1233
|
+
contentStart,
|
|
1234
|
+
end,
|
|
1235
|
+
suppressedIndexes,
|
|
1236
|
+
...stretched.spacings,
|
|
1237
|
+
inlineSizeEm: lineLengthEm,
|
|
1238
|
+
break: { kind: "stretched" },
|
|
1239
|
+
hangingIndex: null,
|
|
1240
|
+
deformationRatio: capacity === 0 ? 0 : underflow / capacity,
|
|
1241
|
+
priorityCost: stretched.priorityCost
|
|
1242
|
+
};
|
|
1017
1243
|
return {
|
|
1018
1244
|
start,
|
|
1019
1245
|
contentStart,
|
|
1020
1246
|
end,
|
|
1021
1247
|
suppressedIndexes,
|
|
1022
|
-
|
|
1248
|
+
...naturalSpacings(pairValues),
|
|
1023
1249
|
inlineSizeEm: naturalSizeEm,
|
|
1024
1250
|
break: { kind: "forced" },
|
|
1025
1251
|
hangingIndex: null,
|
|
@@ -1759,7 +1985,9 @@ function positionedLine(atoms, sourceGapIndexes, plan) {
|
|
|
1759
1985
|
}];
|
|
1760
1986
|
});
|
|
1761
1987
|
const spacings = new Map(plan.pairSpacings.map((spacing) => [spacing.boundary, spacing]));
|
|
1988
|
+
const characterSpacings = new Map(plan.characterSpacings.map((spacing) => [spacing.index, spacing]));
|
|
1762
1989
|
let offsetEm = 0;
|
|
1990
|
+
const adjustmentOf = (widthEm, naturalWidthEm) => widthEm < naturalWidthEm ? "shrunk" : widthEm > naturalWidthEm ? "stretched" : "natural";
|
|
1763
1991
|
const positionSpacing = (spacing) => {
|
|
1764
1992
|
if (spacing.kind === "kern") items.push({
|
|
1765
1993
|
kind: "kern",
|
|
@@ -1772,7 +2000,7 @@ function positionedLine(atoms, sourceGapIndexes, plan) {
|
|
|
1772
2000
|
offsetEm,
|
|
1773
2001
|
widthEm: spacing.widthEm,
|
|
1774
2002
|
naturalWidthEm: spacing.naturalWidthEm,
|
|
1775
|
-
adjustment: spacing.widthEm
|
|
2003
|
+
adjustment: adjustmentOf(spacing.widthEm, spacing.naturalWidthEm)
|
|
1776
2004
|
});
|
|
1777
2005
|
offsetEm += spacing.widthEm;
|
|
1778
2006
|
};
|
|
@@ -1781,18 +2009,21 @@ function positionedLine(atoms, sourceGapIndexes, plan) {
|
|
|
1781
2009
|
if (spacing !== void 0) positionSpacing(spacing);
|
|
1782
2010
|
const atom = atoms[index];
|
|
1783
2011
|
if (atom === void 0) continue;
|
|
1784
|
-
|
|
2012
|
+
const characterSpacing = characterSpacings.get(index);
|
|
2013
|
+
if (sourceGapIndexes.has(index) || characterSpacing !== void 0) {
|
|
2014
|
+
const naturalWidthEm = characterSpacing?.naturalWidthEm ?? atom.boxAdvanceEm;
|
|
2015
|
+
const widthEm = characterSpacing?.widthEm ?? atom.boxAdvanceEm;
|
|
1785
2016
|
items.push({
|
|
1786
2017
|
kind: "glue",
|
|
1787
2018
|
origin: "source",
|
|
1788
2019
|
value: atom.grapheme.value,
|
|
1789
2020
|
range: atom.grapheme.range,
|
|
1790
2021
|
offsetEm,
|
|
1791
|
-
widthEm
|
|
1792
|
-
naturalWidthEm
|
|
1793
|
-
adjustment:
|
|
2022
|
+
widthEm,
|
|
2023
|
+
naturalWidthEm,
|
|
2024
|
+
adjustment: adjustmentOf(widthEm, naturalWidthEm)
|
|
1794
2025
|
});
|
|
1795
|
-
offsetEm +=
|
|
2026
|
+
offsetEm += widthEm;
|
|
1796
2027
|
continue;
|
|
1797
2028
|
}
|
|
1798
2029
|
const hanging = plan.hangingIndex === index;
|
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-CtovfhET.mjs";
|
|
3
3
|
export { ManuscriptResult, NamespacedId, ParsedManuscript, ValidationIssue, createNovelComposer, logicalInlineMeasurer };
|