postext 1.28.6 → 1.29.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/__tests__/arabicLocale.test.js +9 -3
- package/dist/__tests__/arabicLocale.test.js.map +1 -1
- package/dist/__tests__/bundle/balloonPlacementPin.test.js +5 -1
- package/dist/__tests__/bundle/balloonPlacementPin.test.js.map +1 -1
- package/dist/__tests__/bundle/cjkRulesPin.test.js +15 -9
- package/dist/__tests__/bundle/cjkRulesPin.test.js.map +1 -1
- package/dist/__tests__/bundle/designOverflowPin.test.js +3 -3
- package/dist/__tests__/bundle/designOverflowPin.test.js.map +1 -1
- package/dist/__tests__/bundle/flowColumnsPin.test.js +4 -1
- package/dist/__tests__/bundle/flowColumnsPin.test.js.map +1 -1
- package/dist/__tests__/bundle/gridBalancingPin.test.js +6 -2
- package/dist/__tests__/bundle/gridBalancingPin.test.js.map +1 -1
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js +23 -17
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js.map +1 -1
- package/dist/__tests__/bundle/indexGroupSplitPin.test.js +5 -2
- package/dist/__tests__/bundle/indexGroupSplitPin.test.js.map +1 -1
- package/dist/__tests__/bundle/looseOrderPin.test.js +5 -1
- package/dist/__tests__/bundle/looseOrderPin.test.js.map +1 -1
- package/dist/__tests__/bundle/refLabelBreaksPin.test.js +5 -1
- package/dist/__tests__/bundle/refLabelBreaksPin.test.js.map +1 -1
- package/dist/__tests__/bundle/scriptContextPin.test.js +7 -2
- package/dist/__tests__/bundle/scriptContextPin.test.js.map +1 -1
- package/dist/__tests__/bundle/shapingLanguagePin.test.d.ts +2 -0
- package/dist/__tests__/bundle/shapingLanguagePin.test.d.ts.map +1 -0
- package/dist/__tests__/bundle/shapingLanguagePin.test.js +93 -0
- package/dist/__tests__/bundle/shapingLanguagePin.test.js.map +1 -0
- package/dist/__tests__/bundle/taskBoxPin.test.d.ts +2 -0
- package/dist/__tests__/bundle/taskBoxPin.test.d.ts.map +1 -0
- package/dist/__tests__/bundle/taskBoxPin.test.js +94 -0
- package/dist/__tests__/bundle/taskBoxPin.test.js.map +1 -0
- package/dist/__tests__/bundle/trailingStepPin.test.js +5 -2
- package/dist/__tests__/bundle/trailingStepPin.test.js.map +1 -1
- package/dist/__tests__/bundle/wideFloatStretchPin.test.js +5 -2
- package/dist/__tests__/bundle/wideFloatStretchPin.test.js.map +1 -1
- package/dist/__tests__/bundle.test.js +5 -5
- package/dist/__tests__/bundle.test.js.map +1 -1
- package/dist/__tests__/chineseLocale.test.js +7 -3
- package/dist/__tests__/chineseLocale.test.js.map +1 -1
- package/dist/__tests__/cjk/japaneseHtml.test.js +13 -3
- package/dist/__tests__/cjk/japaneseHtml.test.js.map +1 -1
- package/dist/__tests__/cjk/japaneseSegmentLanguage.test.js +16 -3
- package/dist/__tests__/cjk/japaneseSegmentLanguage.test.js.map +1 -1
- package/dist/__tests__/codeBlocks.test.js +1 -1
- package/dist/__tests__/exports.test.js +14 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/hardBreaks.test.js +1 -1
- package/dist/__tests__/headingInlineMarks.test.js +1 -1
- package/dist/__tests__/mathSizeMigration.test.js +4 -4
- package/dist/__tests__/mathSizeMigration.test.js.map +1 -1
- package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
- package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +3 -3
- package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js.map +1 -1
- package/dist/__tests__/pipeline/colonListRoom.test.js +3 -3
- package/dist/__tests__/pipeline/colonListRoom.test.js.map +1 -1
- package/dist/__tests__/pipeline/compoundBreaks.test.js +6 -6
- package/dist/__tests__/pipeline/compoundBreaks.test.js.map +1 -1
- package/dist/__tests__/pipeline/dashBreaks.test.js +5 -5
- package/dist/__tests__/pipeline/dashBreaks.test.js.map +1 -1
- package/dist/__tests__/pipeline/headingSplitOrphans.test.js +3 -3
- package/dist/__tests__/pipeline/headingSplitOrphans.test.js.map +1 -1
- package/dist/__tests__/pipeline/inlineFigureSpace.test.js +5 -5
- package/dist/__tests__/pipeline/inlineFigureSpace.test.js.map +1 -1
- package/dist/__tests__/pipeline/paragraphContainerTail.test.js +7 -7
- package/dist/__tests__/pipeline/paragraphContainerTail.test.js.map +1 -1
- package/dist/__tests__/pipeline/raggedOptimal.test.js +6 -6
- package/dist/__tests__/pipeline/raggedOptimal.test.js.map +1 -1
- package/dist/__tests__/rtl/htmlRtl.test.js +12 -1
- package/dist/__tests__/rtl/htmlRtl.test.js.map +1 -1
- package/dist/__tests__/shapingLanguage.test.d.ts +2 -0
- package/dist/__tests__/shapingLanguage.test.d.ts.map +1 -0
- package/dist/__tests__/shapingLanguage.test.js +335 -0
- package/dist/__tests__/shapingLanguage.test.js.map +1 -0
- package/dist/__tests__/taskBox.test.d.ts +2 -0
- package/dist/__tests__/taskBox.test.d.ts.map +1 -0
- package/dist/__tests__/taskBox.test.js +291 -0
- package/dist/__tests__/taskBox.test.js.map +1 -0
- package/dist/__tests__/verseLines.test.js +7 -7
- package/dist/__tests__/verseLines.test.js.map +1 -1
- package/dist/bundle/configVersion.d.ts +48 -7
- package/dist/bundle/configVersion.d.ts.map +1 -1
- package/dist/bundle/configVersion.js +79 -6
- package/dist/bundle/configVersion.js.map +1 -1
- package/dist/bundle/index.d.ts +2 -1
- package/dist/bundle/index.d.ts.map +1 -1
- package/dist/bundle/index.js +2 -1
- package/dist/bundle/index.js.map +1 -1
- package/dist/canvas-backend/blockRender.d.ts.map +1 -1
- package/dist/canvas-backend/blockRender.js +41 -2
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +10 -5
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/canvas-backend/trackedText.d.ts.map +1 -1
- package/dist/canvas-backend/trackedText.js +9 -5
- package/dist/canvas-backend/trackedText.js.map +1 -1
- package/dist/canvas-backend/wordRuns.d.ts +6 -0
- package/dist/canvas-backend/wordRuns.d.ts.map +1 -1
- package/dist/canvas-backend/wordRuns.js +31 -0
- package/dist/canvas-backend/wordRuns.js.map +1 -1
- package/dist/comics/lettering/letter.d.ts.map +1 -1
- package/dist/comics/lettering/letter.js +2 -1
- package/dist/comics/lettering/letter.js.map +1 -1
- package/dist/contrast.d.ts.map +1 -1
- package/dist/contrast.js +5 -0
- package/dist/contrast.js.map +1 -1
- package/dist/defaults/bodyText.d.ts.map +1 -1
- package/dist/defaults/bodyText.js +8 -0
- package/dist/defaults/bodyText.js.map +1 -1
- package/dist/defaults/unorderedLists.d.ts.map +1 -1
- package/dist/defaults/unorderedLists.js +7 -0
- package/dist/defaults/unorderedLists.js.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +45 -5
- package/dist/html-backend.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +36 -14
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +39 -12
- package/dist/locale.js.map +1 -1
- package/dist/measure/cache.js +2 -2
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/canvas.d.ts +20 -0
- package/dist/measure/canvas.d.ts.map +1 -1
- package/dist/measure/canvas.js +131 -50
- package/dist/measure/canvas.js.map +1 -1
- package/dist/measure/cjkAnnotate.js +2 -2
- package/dist/measure/cjkAnnotate.js.map +1 -1
- package/dist/measure/cjkCompose.d.ts.map +1 -1
- package/dist/measure/cjkCompose.js +225 -209
- package/dist/measure/cjkCompose.js.map +1 -1
- package/dist/measure/plain.d.ts.map +1 -1
- package/dist/measure/plain.js +4 -2
- package/dist/measure/plain.js.map +1 -1
- package/dist/measure/pretextLanguage.d.ts +12 -0
- package/dist/measure/pretextLanguage.d.ts.map +1 -0
- package/dist/measure/pretextLanguage.js +117 -0
- package/dist/measure/pretextLanguage.js.map +1 -0
- package/dist/measure/rich.d.ts +4 -0
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +164 -137
- package/dist/measure/rich.js.map +1 -1
- package/dist/measure/rubyLift.d.ts.map +1 -1
- package/dist/measure/rubyLift.js +4 -3
- package/dist/measure/rubyLift.js.map +1 -1
- package/dist/measure/spanLanguage.d.ts +11 -0
- package/dist/measure/spanLanguage.d.ts.map +1 -0
- package/dist/measure/spanLanguage.js +19 -0
- package/dist/measure/spanLanguage.js.map +1 -0
- package/dist/measure/vertical.d.ts.map +1 -1
- package/dist/measure/vertical.js +4 -3
- package/dist/measure/vertical.js.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +15 -2
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +10 -4
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/dropCap.js +2 -2
- package/dist/pipeline/dropCap.js.map +1 -1
- package/dist/pipeline/lists.d.ts +8 -0
- package/dist/pipeline/lists.d.ts.map +1 -1
- package/dist/pipeline/lists.js +16 -1
- package/dist/pipeline/lists.js.map +1 -1
- package/dist/pipeline/toc.d.ts.map +1 -1
- package/dist/pipeline/toc.js +5 -3
- package/dist/pipeline/toc.js.map +1 -1
- package/dist/taskBox.d.ts +55 -0
- package/dist/taskBox.d.ts.map +1 -0
- package/dist/taskBox.js +79 -0
- package/dist/taskBox.js.map +1 -0
- package/dist/types.d.ts +48 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +14 -0
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
import { createBoundingBox } from '../vdt';
|
|
36
36
|
import { isJapaneseLanguage } from '../locale';
|
|
37
37
|
import { lineIndentAt, lineInsetsAt, lineMeasure, markInsetLines } from './types';
|
|
38
|
-
import { measureInkBox, measureInkExtent, measureTextWidth, normalSpaceWidthFor } from './canvas';
|
|
38
|
+
import { getMeasureLanguage, measureInkBox, measureInkExtent, measureTextWidth, normalSpaceWidthFor, setMeasureLanguage } from './canvas';
|
|
39
|
+
import { spanShapingLanguage } from './spanLanguage';
|
|
39
40
|
import { atomicSpanToken, refLabelTokens, setLabelTabs, emergencySplit, expandSmallCaps, pickSpanFont, scriptMetrics, setsObject, spanScriptFields, stackedScriptPairs, textWidth, tokenSegment, URL_LIKE_RE, urlBreakIndices, } from './rich';
|
|
40
41
|
import { cjkBreakAllowed, cjkClassOf, getCjkLineBreak, isCjkGrapheme, isFullwidthAlnum, isFullwidthDigit, isJapaneseLineBreak, getCjkCircledNumbers, isLabelEndProhibited, isLineEndProhibited, isLineStartProhibited, isWordInnerMark, setCjkCircledNumbers, } from './cjkClasses';
|
|
41
42
|
import { hasCJK } from './cjk';
|
|
@@ -169,6 +170,10 @@ function spanLanguageHere(span) {
|
|
|
169
170
|
lang = d.lang;
|
|
170
171
|
if (lang === undefined)
|
|
171
172
|
return undefined;
|
|
173
|
+
// In a document shaped in its own language every run that names one
|
|
174
|
+
// carries it (#764): it was measured in it, and is painted in it.
|
|
175
|
+
if (getMeasureLanguage() !== undefined)
|
|
176
|
+
return lang;
|
|
172
177
|
return getMeasureRegion() === 'japan' || isJapaneseLanguage(lang) ? lang : undefined;
|
|
173
178
|
}
|
|
174
179
|
function styleOf(span, fonts, vertical = false) {
|
|
@@ -639,230 +644,241 @@ function buildUnits(spans, fonts, letterSpacingPx, vertical = false, route = fal
|
|
|
639
644
|
// Where each span's units start, for the kanbun marks (#430).
|
|
640
645
|
const spanStarts = [];
|
|
641
646
|
for (let si = 0; si < spans.length; si++) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
647
|
+
// A run that names its language is measured in it (#764).
|
|
648
|
+
const ownLanguage = spanShapingLanguage(spans[si]);
|
|
649
|
+
const languageBefore = getMeasureLanguage();
|
|
650
|
+
if (ownLanguage !== undefined)
|
|
651
|
+
setMeasureLanguage(ownLanguage);
|
|
652
|
+
try {
|
|
653
|
+
const span = spans[si];
|
|
654
|
+
spanStarts.push(units.length);
|
|
655
|
+
// A ruby base: one unit, sized with its reading once its neighbours
|
|
656
|
+
// are known (`sizeRubies`).
|
|
657
|
+
if (span.ruby && span.text.length > 0) {
|
|
658
|
+
units.push({ ...rubyBaseUnit(span, fonts, letterSpacingPx, vertical), ...(zwsp ? { zwspBefore: true } : {}), ...glue() });
|
|
659
|
+
zwsp = false;
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
if (vertical && (span.combineUpright || span.orientation) && span.text.length > 0 && !setsObject(span)) {
|
|
663
|
+
const first = units.length;
|
|
664
|
+
orientedUnits(span, styleOf(span, fonts, vertical), letterSpacingPx, zwsp, units);
|
|
665
|
+
if (units.length > first)
|
|
666
|
+
Object.assign(units[first], glue());
|
|
667
|
+
zwsp = false;
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
// A reference whose label is words (#702): one unit per word and per
|
|
671
|
+
// space, each carrying the reference; only the first is glued to the
|
|
672
|
+
// text before it, so a line may break after a space of the label.
|
|
673
|
+
const whole = refLabelTokens(span, fonts.normal, fonts.bold, fonts.italic, fonts.boldItalic, letterSpacingPx)
|
|
674
|
+
?? atomicSpanToken(span, fonts.normal, fonts.bold, fonts.italic, fonts.boldItalic, letterSpacingPx);
|
|
675
|
+
const atomics = whole === undefined ? [] : Array.isArray(whole) ? whole : [whole];
|
|
676
|
+
for (const [k, atomic] of atomics.entries()) {
|
|
677
|
+
const style = styleOf(span, fonts, vertical);
|
|
678
|
+
if (atomic.kind === 'space') {
|
|
679
|
+
units.push({
|
|
680
|
+
kind: 'space',
|
|
681
|
+
text: atomic.text,
|
|
682
|
+
width: atomic.width,
|
|
683
|
+
graphemes: graphemeCount(atomic.text),
|
|
684
|
+
first: 'western',
|
|
685
|
+
last: 'western',
|
|
686
|
+
firstCjk: false,
|
|
687
|
+
lastCjk: false,
|
|
688
|
+
style,
|
|
689
|
+
at: 0,
|
|
690
|
+
token: atomic,
|
|
691
|
+
});
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
const graphemes = graphemesOf(atomic.text);
|
|
695
|
+
const object = atomic.chip !== undefined || atomic.mathRender !== undefined || atomic.swatch !== undefined;
|
|
696
|
+
const firstG = graphemes[0] ?? '';
|
|
697
|
+
const lastG = graphemes[graphemes.length - 1] ?? '';
|
|
668
698
|
units.push({
|
|
669
|
-
kind: '
|
|
699
|
+
kind: 'atomic',
|
|
670
700
|
text: atomic.text,
|
|
671
701
|
width: atomic.width,
|
|
672
|
-
graphemes:
|
|
673
|
-
first: '
|
|
674
|
-
last: '
|
|
675
|
-
firstCjk:
|
|
676
|
-
lastCjk:
|
|
702
|
+
graphemes: graphemes.length,
|
|
703
|
+
first: object ? 'ideograph' : cjkClassOf(firstG),
|
|
704
|
+
last: object ? 'ideograph' : cjkClassOf(lastG),
|
|
705
|
+
firstCjk: object || isCjkGrapheme(firstG),
|
|
706
|
+
lastCjk: object || isCjkGrapheme(lastG),
|
|
677
707
|
style,
|
|
678
708
|
at: 0,
|
|
679
709
|
token: atomic,
|
|
710
|
+
...((atomic.refResourceId !== undefined || atomic.footnoteId !== undefined) && k === 0 ? { glueBefore: true } : {}),
|
|
711
|
+
...(zwsp ? { zwspBefore: true } : {}),
|
|
712
|
+
...glue(),
|
|
680
713
|
});
|
|
681
|
-
|
|
714
|
+
zwsp = false;
|
|
682
715
|
}
|
|
683
|
-
|
|
684
|
-
const object = atomic.chip !== undefined || atomic.mathRender !== undefined || atomic.swatch !== undefined;
|
|
685
|
-
const firstG = graphemes[0] ?? '';
|
|
686
|
-
const lastG = graphemes[graphemes.length - 1] ?? '';
|
|
687
|
-
units.push({
|
|
688
|
-
kind: 'atomic',
|
|
689
|
-
text: atomic.text,
|
|
690
|
-
width: atomic.width,
|
|
691
|
-
graphemes: graphemes.length,
|
|
692
|
-
first: object ? 'ideograph' : cjkClassOf(firstG),
|
|
693
|
-
last: object ? 'ideograph' : cjkClassOf(lastG),
|
|
694
|
-
firstCjk: object || isCjkGrapheme(firstG),
|
|
695
|
-
lastCjk: object || isCjkGrapheme(lastG),
|
|
696
|
-
style,
|
|
697
|
-
at: 0,
|
|
698
|
-
token: atomic,
|
|
699
|
-
...((atomic.refResourceId !== undefined || atomic.footnoteId !== undefined) && k === 0 ? { glueBefore: true } : {}),
|
|
700
|
-
...(zwsp ? { zwspBefore: true } : {}),
|
|
701
|
-
...glue(),
|
|
702
|
-
});
|
|
703
|
-
zwsp = false;
|
|
704
|
-
}
|
|
705
|
-
if (atomics.length > 0)
|
|
706
|
-
continue;
|
|
707
|
-
if (span.text.length === 0)
|
|
708
|
-
continue;
|
|
709
|
-
const style = styleOf(span, fonts, vertical);
|
|
710
|
-
const graphemes = graphemesOf(span.text);
|
|
711
|
-
const spanFirst = units.length;
|
|
712
|
-
let run = [];
|
|
713
|
-
let runAt = 0;
|
|
714
|
-
let runLink;
|
|
715
|
-
let space = '';
|
|
716
|
-
let spaceAt = 0;
|
|
717
|
-
// A lone mark that may pair with the next one (—, …), by unit index.
|
|
718
|
-
let pairOpen = -1;
|
|
719
|
-
let at = 0;
|
|
720
|
-
// The link a character at `offset` of the span is part of: its span and
|
|
721
|
-
// range, so two links to one target stay apart.
|
|
722
|
-
const links = span.links;
|
|
723
|
-
const linkAt = (offset) => {
|
|
724
|
-
if (!links || links.length === 0)
|
|
725
|
-
return undefined;
|
|
726
|
-
for (let li = 0; li < links.length; li++) {
|
|
727
|
-
const l = links[li];
|
|
728
|
-
if (offset >= l.start && offset < l.end)
|
|
729
|
-
return `${si}:${li}`;
|
|
730
|
-
}
|
|
731
|
-
return undefined;
|
|
732
|
-
};
|
|
733
|
-
const push = (u) => {
|
|
734
|
-
units.push({
|
|
735
|
-
...u,
|
|
736
|
-
style,
|
|
737
|
-
...(zwsp ? { zwspBefore: true } : {}),
|
|
738
|
-
...(style.script && units.length === spanFirst ? { glueBefore: true } : {}),
|
|
739
|
-
...glue(),
|
|
740
|
-
});
|
|
741
|
-
zwsp = false;
|
|
742
|
-
};
|
|
743
|
-
const flushRun = () => {
|
|
744
|
-
if (run.length === 0)
|
|
745
|
-
return;
|
|
746
|
-
const text = run.join('');
|
|
747
|
-
const firstG = run[0];
|
|
748
|
-
const lastG = run[run.length - 1];
|
|
749
|
-
// Vertical text: a short number at either end stands in one upright
|
|
750
|
-
// cell (`cjk.uprightDigits`), and the run is Chinese on that side;
|
|
751
|
-
// tracking follows the cell once.
|
|
752
|
-
const cells = vertical ? numberCellEdges(run) : undefined;
|
|
753
|
-
push({
|
|
754
|
-
kind: 'text',
|
|
755
|
-
text,
|
|
756
|
-
width: textWidth(text, style.font, style.smallCaps) + track(vertical && letterSpacingPx !== 0 ? verticalTrackCount(text) : run.length),
|
|
757
|
-
graphemes: run.length,
|
|
758
|
-
first: cells?.start ? 'ideograph' : cjkClassOf(firstG),
|
|
759
|
-
last: cells?.end ? 'ideograph' : cjkClassOf(lastG),
|
|
760
|
-
firstCjk: cells?.start === true,
|
|
761
|
-
lastCjk: cells?.end === true,
|
|
762
|
-
at: runAt,
|
|
763
|
-
run: true,
|
|
764
|
-
...(cells?.start ? { cellStart: true } : {}),
|
|
765
|
-
...(cells?.end ? { cellEnd: true } : {}),
|
|
766
|
-
...(URL_LIKE_RE.test(text) ? { url: true } : {}),
|
|
767
|
-
...(runLink !== undefined ? { link: runLink } : {}),
|
|
768
|
-
});
|
|
769
|
-
run = [];
|
|
770
|
-
pairOpen = -1;
|
|
771
|
-
};
|
|
772
|
-
const flushSpace = () => {
|
|
773
|
-
if (space === '')
|
|
774
|
-
return;
|
|
775
|
-
units.push({
|
|
776
|
-
kind: 'space',
|
|
777
|
-
text: space,
|
|
778
|
-
width: measureTextWidth(space, style.font) + track(graphemeCount(space)),
|
|
779
|
-
graphemes: graphemeCount(space),
|
|
780
|
-
first: 'western',
|
|
781
|
-
last: 'western',
|
|
782
|
-
firstCjk: false,
|
|
783
|
-
lastCjk: false,
|
|
784
|
-
style,
|
|
785
|
-
at: spaceAt,
|
|
786
|
-
});
|
|
787
|
-
space = '';
|
|
788
|
-
pairOpen = -1;
|
|
789
|
-
};
|
|
790
|
-
for (let i = 0; i < graphemes.length; i++) {
|
|
791
|
-
const g = graphemes[i];
|
|
792
|
-
const gAt = at;
|
|
793
|
-
at += g.length;
|
|
794
|
-
if (isBreakingSpace(g[0])) {
|
|
795
|
-
flushRun();
|
|
796
|
-
wj = false;
|
|
797
|
-
if (space === '')
|
|
798
|
-
spaceAt = gAt;
|
|
799
|
-
space += g;
|
|
716
|
+
if (atomics.length > 0)
|
|
800
717
|
continue;
|
|
801
|
-
|
|
802
|
-
flushSpace();
|
|
803
|
-
if (g === '\u200B') {
|
|
804
|
-
flushRun();
|
|
805
|
-
zwsp = true;
|
|
806
|
-
pairOpen = -1;
|
|
718
|
+
if (span.text.length === 0)
|
|
807
719
|
continue;
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
720
|
+
const style = styleOf(span, fonts, vertical);
|
|
721
|
+
const graphemes = graphemesOf(span.text);
|
|
722
|
+
const spanFirst = units.length;
|
|
723
|
+
let run = [];
|
|
724
|
+
let runAt = 0;
|
|
725
|
+
let runLink;
|
|
726
|
+
let space = '';
|
|
727
|
+
let spaceAt = 0;
|
|
728
|
+
// A lone mark that may pair with the next one (—, …), by unit index.
|
|
729
|
+
let pairOpen = -1;
|
|
730
|
+
let at = 0;
|
|
731
|
+
// The link a character at `offset` of the span is part of: its span and
|
|
732
|
+
// range, so two links to one target stay apart.
|
|
733
|
+
const links = span.links;
|
|
734
|
+
const linkAt = (offset) => {
|
|
735
|
+
if (!links || links.length === 0)
|
|
736
|
+
return undefined;
|
|
737
|
+
for (let li = 0; li < links.length; li++) {
|
|
738
|
+
const l = links[li];
|
|
739
|
+
if (offset >= l.start && offset < l.end)
|
|
740
|
+
return `${si}:${li}`;
|
|
741
|
+
}
|
|
742
|
+
return undefined;
|
|
743
|
+
};
|
|
744
|
+
const push = (u) => {
|
|
745
|
+
units.push({
|
|
746
|
+
...u,
|
|
747
|
+
style,
|
|
748
|
+
...(zwsp ? { zwspBefore: true } : {}),
|
|
749
|
+
...(style.script && units.length === spanFirst ? { glueBefore: true } : {}),
|
|
750
|
+
...glue(),
|
|
751
|
+
});
|
|
752
|
+
zwsp = false;
|
|
753
|
+
};
|
|
754
|
+
const flushRun = () => {
|
|
755
|
+
if (run.length === 0)
|
|
756
|
+
return;
|
|
757
|
+
const text = run.join('');
|
|
758
|
+
const firstG = run[0];
|
|
759
|
+
const lastG = run[run.length - 1];
|
|
760
|
+
// Vertical text: a short number at either end stands in one upright
|
|
761
|
+
// cell (`cjk.uprightDigits`), and the run is Chinese on that side;
|
|
762
|
+
// tracking follows the cell once.
|
|
763
|
+
const cells = vertical ? numberCellEdges(run) : undefined;
|
|
764
|
+
push({
|
|
765
|
+
kind: 'text',
|
|
766
|
+
text,
|
|
767
|
+
width: textWidth(text, style.font, style.smallCaps) + track(vertical && letterSpacingPx !== 0 ? verticalTrackCount(text) : run.length),
|
|
768
|
+
graphemes: run.length,
|
|
769
|
+
first: cells?.start ? 'ideograph' : cjkClassOf(firstG),
|
|
770
|
+
last: cells?.end ? 'ideograph' : cjkClassOf(lastG),
|
|
771
|
+
firstCjk: cells?.start === true,
|
|
772
|
+
lastCjk: cells?.end === true,
|
|
773
|
+
at: runAt,
|
|
774
|
+
run: true,
|
|
775
|
+
...(cells?.start ? { cellStart: true } : {}),
|
|
776
|
+
...(cells?.end ? { cellEnd: true } : {}),
|
|
777
|
+
...(URL_LIKE_RE.test(text) ? { url: true } : {}),
|
|
778
|
+
...(runLink !== undefined ? { link: runLink } : {}),
|
|
779
|
+
});
|
|
780
|
+
run = [];
|
|
812
781
|
pairOpen = -1;
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
782
|
+
};
|
|
783
|
+
const flushSpace = () => {
|
|
784
|
+
if (space === '')
|
|
785
|
+
return;
|
|
786
|
+
units.push({
|
|
787
|
+
kind: 'space',
|
|
788
|
+
text: space,
|
|
789
|
+
width: measureTextWidth(space, style.font) + track(graphemeCount(space)),
|
|
790
|
+
graphemes: graphemeCount(space),
|
|
791
|
+
first: 'western',
|
|
792
|
+
last: 'western',
|
|
793
|
+
firstCjk: false,
|
|
794
|
+
lastCjk: false,
|
|
795
|
+
style,
|
|
796
|
+
at: spaceAt,
|
|
797
|
+
});
|
|
798
|
+
space = '';
|
|
799
|
+
pairOpen = -1;
|
|
800
|
+
};
|
|
801
|
+
for (let i = 0; i < graphemes.length; i++) {
|
|
802
|
+
const g = graphemes[i];
|
|
803
|
+
const gAt = at;
|
|
804
|
+
at += g.length;
|
|
805
|
+
if (isBreakingSpace(g[0])) {
|
|
824
806
|
flushRun();
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
807
|
+
wj = false;
|
|
808
|
+
if (space === '')
|
|
809
|
+
spaceAt = gAt;
|
|
810
|
+
space += g;
|
|
811
|
+
continue;
|
|
828
812
|
}
|
|
829
|
-
|
|
830
|
-
|
|
813
|
+
flushSpace();
|
|
814
|
+
if (g === '\u200B') {
|
|
815
|
+
flushRun();
|
|
816
|
+
zwsp = true;
|
|
817
|
+
pairOpen = -1;
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
if (g === '\u2060') {
|
|
821
|
+
flushRun();
|
|
822
|
+
wj = true;
|
|
823
|
+
pairOpen = -1;
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
// A soft hyphen: the composer breaks Western words only when they are
|
|
827
|
+
// wider than the line, so it is left out, and the word stays whole.
|
|
828
|
+
if (g === '\u00AD')
|
|
829
|
+
continue;
|
|
830
|
+
const link = linkAt(gAt);
|
|
831
|
+
if (!isCjkHere(g, graphemes[i - 1], graphemes[i + 1])) {
|
|
832
|
+
// A link that starts or ends inside a run cuts it: the two parts
|
|
833
|
+
// still never part (neither is CJK) and take no space between them.
|
|
834
|
+
if (run.length > 0 && link !== runLink)
|
|
835
|
+
flushRun();
|
|
836
|
+
if (run.length === 0) {
|
|
837
|
+
runAt = gAt;
|
|
838
|
+
runLink = link;
|
|
839
|
+
}
|
|
840
|
+
run.push(g);
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
flushRun();
|
|
844
|
+
// —— and …… are one unit of two ems; a third mark opens another.
|
|
845
|
+
if (pairOpen >= 0 && units[pairOpen].text === g && !zwsp && units[pairOpen].link === link) {
|
|
846
|
+
const u = units[pairOpen];
|
|
847
|
+
u.text += g;
|
|
848
|
+
u.width += cellAdvance(g, style.font, vertical, u.first) + track(1);
|
|
849
|
+
u.graphemes = 2;
|
|
850
|
+
u.first = u.last = g === '\u2026' || g === '\u22EF' ? 'ellipsis' : 'dash';
|
|
851
|
+
pairOpen = -1;
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
let cls = cjkClassOf(g);
|
|
855
|
+
// A single em dash (or horizontal bar) joins two words as a connector
|
|
856
|
+
// (clreq §6.1.1): never at a line start.
|
|
857
|
+
if (g === '\u2014' || g === '\u2015')
|
|
858
|
+
cls = 'connector';
|
|
859
|
+
push({
|
|
860
|
+
kind: 'text',
|
|
861
|
+
text: g,
|
|
862
|
+
width: (style.smallCaps && !vertical ? textWidth(g, style.font, true) : cellAdvance(g, style.font, vertical, cls)) + track(1),
|
|
863
|
+
graphemes: 1,
|
|
864
|
+
first: cls,
|
|
865
|
+
last: cls,
|
|
866
|
+
firstCjk: true,
|
|
867
|
+
lastCjk: true,
|
|
868
|
+
at: gAt,
|
|
869
|
+
...(link !== undefined ? { link } : {}),
|
|
870
|
+
});
|
|
871
|
+
pairOpen = pairable(g) ? units.length - 1 : -1;
|
|
831
872
|
}
|
|
832
873
|
flushRun();
|
|
833
|
-
|
|
834
|
-
if (
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
pairOpen = -1;
|
|
841
|
-
continue;
|
|
842
|
-
}
|
|
843
|
-
let cls = cjkClassOf(g);
|
|
844
|
-
// A single em dash (or horizontal bar) joins two words as a connector
|
|
845
|
-
// (clreq §6.1.1): never at a line start.
|
|
846
|
-
if (g === '\u2014' || g === '\u2015')
|
|
847
|
-
cls = 'connector';
|
|
848
|
-
push({
|
|
849
|
-
kind: 'text',
|
|
850
|
-
text: g,
|
|
851
|
-
width: (style.smallCaps && !vertical ? textWidth(g, style.font, true) : cellAdvance(g, style.font, vertical, cls)) + track(1),
|
|
852
|
-
graphemes: 1,
|
|
853
|
-
first: cls,
|
|
854
|
-
last: cls,
|
|
855
|
-
firstCjk: true,
|
|
856
|
-
lastCjk: true,
|
|
857
|
-
at: gAt,
|
|
858
|
-
...(link !== undefined ? { link } : {}),
|
|
859
|
-
});
|
|
860
|
-
pairOpen = pairable(g) ? units.length - 1 : -1;
|
|
874
|
+
flushSpace();
|
|
875
|
+
if (units.length === spanFirst + 1 && units[spanFirst].kind === 'text')
|
|
876
|
+
wholeSpan.add(spanFirst);
|
|
877
|
+
}
|
|
878
|
+
finally {
|
|
879
|
+
if (ownLanguage !== undefined)
|
|
880
|
+
setMeasureLanguage(languageBefore);
|
|
861
881
|
}
|
|
862
|
-
flushRun();
|
|
863
|
-
flushSpace();
|
|
864
|
-
if (units.length === spanFirst + 1 && units[spanFirst].kind === 'text')
|
|
865
|
-
wholeSpan.add(spanFirst);
|
|
866
882
|
}
|
|
867
883
|
if (spans.some((s) => s.kunten))
|
|
868
884
|
attachKunten(spans, spanStarts, units);
|