postext 1.8.6 → 1.9.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/__bench__/cjkChapter.bench.test.d.ts +2 -0
- package/dist/__bench__/cjkChapter.bench.test.d.ts.map +1 -0
- package/dist/__bench__/cjkChapter.bench.test.js +71 -0
- package/dist/__bench__/cjkChapter.bench.test.js.map +1 -0
- package/dist/__tests__/bundle.test.js +16 -0
- package/dist/__tests__/bundle.test.js.map +1 -1
- package/dist/__tests__/canvasDirection.test.d.ts +2 -0
- package/dist/__tests__/canvasDirection.test.d.ts.map +1 -0
- package/dist/__tests__/canvasDirection.test.js +45 -0
- package/dist/__tests__/canvasDirection.test.js.map +1 -0
- package/dist/__tests__/chineseLocale.test.d.ts +2 -0
- package/dist/__tests__/chineseLocale.test.d.ts.map +1 -0
- package/dist/__tests__/chineseLocale.test.js +253 -0
- package/dist/__tests__/chineseLocale.test.js.map +1 -0
- package/dist/__tests__/chineseNumbering.test.d.ts +2 -0
- package/dist/__tests__/chineseNumbering.test.d.ts.map +1 -0
- package/dist/__tests__/chineseNumbering.test.js +376 -0
- package/dist/__tests__/chineseNumbering.test.js.map +1 -0
- package/dist/__tests__/cjk/annotations.test.d.ts +2 -0
- package/dist/__tests__/cjk/annotations.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/annotations.test.js +483 -0
- package/dist/__tests__/cjk/annotations.test.js.map +1 -0
- package/dist/__tests__/cjk/annotationsRender.test.d.ts +2 -0
- package/dist/__tests__/cjk/annotationsRender.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/annotationsRender.test.js +263 -0
- package/dist/__tests__/cjk/annotationsRender.test.js.map +1 -0
- package/dist/__tests__/cjk/composer.test.d.ts +2 -0
- package/dist/__tests__/cjk/composer.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/composer.test.js +237 -0
- package/dist/__tests__/cjk/composer.test.js.map +1 -0
- package/dist/__tests__/cjk/composerEdges.test.d.ts +2 -0
- package/dist/__tests__/cjk/composerEdges.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/composerEdges.test.js +352 -0
- package/dist/__tests__/cjk/composerEdges.test.js.map +1 -0
- package/dist/__tests__/cjk/dashRule.test.d.ts +2 -0
- package/dist/__tests__/cjk/dashRule.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/dashRule.test.js +261 -0
- package/dist/__tests__/cjk/dashRule.test.js.map +1 -0
- package/dist/__tests__/cjk/fuzz.test.d.ts +2 -0
- package/dist/__tests__/cjk/fuzz.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/fuzz.test.js +102 -0
- package/dist/__tests__/cjk/fuzz.test.js.map +1 -0
- package/dist/__tests__/cjk/grid.test.d.ts +2 -0
- package/dist/__tests__/cjk/grid.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/grid.test.js +261 -0
- package/dist/__tests__/cjk/grid.test.js.map +1 -0
- package/dist/__tests__/cjk/justifyRender.test.d.ts +2 -0
- package/dist/__tests__/cjk/justifyRender.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/justifyRender.test.js +139 -0
- package/dist/__tests__/cjk/justifyRender.test.js.map +1 -0
- package/dist/__tests__/cjk/latinFastPath.test.d.ts +2 -0
- package/dist/__tests__/cjk/latinFastPath.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/latinFastPath.test.js +208 -0
- package/dist/__tests__/cjk/latinFastPath.test.js.map +1 -0
- package/dist/__tests__/cjk/markCutsLatin.test.d.ts +2 -0
- package/dist/__tests__/cjk/markCutsLatin.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/markCutsLatin.test.js +69 -0
- package/dist/__tests__/cjk/markCutsLatin.test.js.map +1 -0
- package/dist/__tests__/cjk/markRuns.test.d.ts +2 -0
- package/dist/__tests__/cjk/markRuns.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/markRuns.test.js +347 -0
- package/dist/__tests__/cjk/markRuns.test.js.map +1 -0
- package/dist/__tests__/cjk/punctuation.test.d.ts +2 -0
- package/dist/__tests__/cjk/punctuation.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/punctuation.test.js +440 -0
- package/dist/__tests__/cjk/punctuation.test.js.map +1 -0
- package/dist/__tests__/cjk/punctuationRender.test.d.ts +2 -0
- package/dist/__tests__/cjk/punctuationRender.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/punctuationRender.test.js +135 -0
- package/dist/__tests__/cjk/punctuationRender.test.js.map +1 -0
- package/dist/__tests__/cjk/rubyDescenders.test.d.ts +2 -0
- package/dist/__tests__/cjk/rubyDescenders.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/rubyDescenders.test.js +77 -0
- package/dist/__tests__/cjk/rubyDescenders.test.js.map +1 -0
- package/dist/__tests__/cjk/runt.test.d.ts +2 -0
- package/dist/__tests__/cjk/runt.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/runt.test.js +103 -0
- package/dist/__tests__/cjk/runt.test.js.map +1 -0
- package/dist/__tests__/cjk/sharedMarks.test.d.ts +2 -0
- package/dist/__tests__/cjk/sharedMarks.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/sharedMarks.test.js +347 -0
- package/dist/__tests__/cjk/sharedMarks.test.js.map +1 -0
- package/dist/__tests__/cjk/uprightDots.test.d.ts +2 -0
- package/dist/__tests__/cjk/uprightDots.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/uprightDots.test.js +47 -0
- package/dist/__tests__/cjk/uprightDots.test.js.map +1 -0
- package/dist/__tests__/cjk/wordJoiner.test.d.ts +2 -0
- package/dist/__tests__/cjk/wordJoiner.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/wordJoiner.test.js +47 -0
- package/dist/__tests__/cjk/wordJoiner.test.js.map +1 -0
- package/dist/__tests__/cjk/zhuyinTones.test.d.ts +2 -0
- package/dist/__tests__/cjk/zhuyinTones.test.d.ts.map +1 -0
- package/dist/__tests__/cjk/zhuyinTones.test.js +72 -0
- package/dist/__tests__/cjk/zhuyinTones.test.js.map +1 -0
- package/dist/__tests__/contentLocale.test.d.ts +2 -0
- package/dist/__tests__/contentLocale.test.d.ts.map +1 -0
- package/dist/__tests__/contentLocale.test.js +167 -0
- package/dist/__tests__/contentLocale.test.js.map +1 -0
- package/dist/__tests__/defaults/cjk.test.d.ts +2 -0
- package/dist/__tests__/defaults/cjk.test.d.ts.map +1 -0
- package/dist/__tests__/defaults/cjk.test.js +70 -0
- package/dist/__tests__/defaults/cjk.test.js.map +1 -0
- package/dist/__tests__/design/designTextRender.test.js +31 -0
- package/dist/__tests__/design/designTextRender.test.js.map +1 -1
- package/dist/__tests__/design/imageAltText.test.d.ts +2 -0
- package/dist/__tests__/design/imageAltText.test.d.ts.map +1 -0
- package/dist/__tests__/design/imageAltText.test.js +126 -0
- package/dist/__tests__/design/imageAltText.test.js.map +1 -0
- package/dist/__tests__/exports.test.js +61 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/headingLetterSpacing.test.js +1 -1
- package/dist/__tests__/headingLetterSpacing.test.js.map +1 -1
- package/dist/__tests__/indexChinese.test.d.ts +2 -0
- package/dist/__tests__/indexChinese.test.d.ts.map +1 -0
- package/dist/__tests__/indexChinese.test.js +190 -0
- package/dist/__tests__/indexChinese.test.js.map +1 -0
- package/dist/__tests__/parse/annotations.test.d.ts +2 -0
- package/dist/__tests__/parse/annotations.test.d.ts.map +1 -0
- package/dist/__tests__/parse/annotations.test.js +175 -0
- package/dist/__tests__/parse/annotations.test.js.map +1 -0
- package/dist/__tests__/parse/attrQuoting.test.js +10 -8
- package/dist/__tests__/parse/attrQuoting.test.js.map +1 -1
- package/dist/__tests__/parse/chineseText.test.d.ts +2 -0
- package/dist/__tests__/parse/chineseText.test.d.ts.map +1 -0
- package/dist/__tests__/parse/chineseText.test.js +352 -0
- package/dist/__tests__/parse/chineseText.test.js.map +1 -0
- package/dist/__tests__/parts.test.js +25 -0
- package/dist/__tests__/parts.test.js.map +1 -1
- package/dist/__tests__/pipeline/colonListRoom.test.js +20 -0
- package/dist/__tests__/pipeline/colonListRoom.test.js.map +1 -1
- package/dist/__tests__/presets/hongloumeng.test.d.ts +2 -0
- package/dist/__tests__/presets/hongloumeng.test.d.ts.map +1 -0
- package/dist/__tests__/presets/hongloumeng.test.js +484 -0
- package/dist/__tests__/presets/hongloumeng.test.js.map +1 -0
- package/dist/__tests__/vertical/canvasPaint.test.d.ts +2 -0
- package/dist/__tests__/vertical/canvasPaint.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/canvasPaint.test.js +229 -0
- package/dist/__tests__/vertical/canvasPaint.test.js.map +1 -0
- package/dist/__tests__/vertical/compositionPaint.test.d.ts +2 -0
- package/dist/__tests__/vertical/compositionPaint.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/compositionPaint.test.js +538 -0
- package/dist/__tests__/vertical/compositionPaint.test.js.map +1 -0
- package/dist/__tests__/vertical/geometry.test.d.ts +2 -0
- package/dist/__tests__/vertical/geometry.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/geometry.test.js +276 -0
- package/dist/__tests__/vertical/geometry.test.js.map +1 -0
- package/dist/__tests__/vertical/htmlSmoke.test.d.ts +2 -0
- package/dist/__tests__/vertical/htmlSmoke.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/htmlSmoke.test.js +25 -0
- package/dist/__tests__/vertical/htmlSmoke.test.js.map +1 -0
- package/dist/__tests__/vertical/htmlTurnedCells.test.d.ts +2 -0
- package/dist/__tests__/vertical/htmlTurnedCells.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/htmlTurnedCells.test.js +99 -0
- package/dist/__tests__/vertical/htmlTurnedCells.test.js.map +1 -0
- package/dist/__tests__/vertical/htmlVertical.test.d.ts +2 -0
- package/dist/__tests__/vertical/htmlVertical.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/htmlVertical.test.js +145 -0
- package/dist/__tests__/vertical/htmlVertical.test.js.map +1 -0
- package/dist/__tests__/vertical/lineAxis.test.d.ts +2 -0
- package/dist/__tests__/vertical/lineAxis.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/lineAxis.test.js +128 -0
- package/dist/__tests__/vertical/lineAxis.test.js.map +1 -0
- package/dist/__tests__/vertical/measurePaint.test.d.ts +2 -0
- package/dist/__tests__/vertical/measurePaint.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/measurePaint.test.js +259 -0
- package/dist/__tests__/vertical/measurePaint.test.js.map +1 -0
- package/dist/__tests__/vertical/orientation.test.d.ts +2 -0
- package/dist/__tests__/vertical/orientation.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/orientation.test.js +153 -0
- package/dist/__tests__/vertical/orientation.test.js.map +1 -0
- package/dist/__tests__/vertical/stub.d.ts +8 -0
- package/dist/__tests__/vertical/stub.d.ts.map +1 -0
- package/dist/__tests__/vertical/stub.js +37 -0
- package/dist/__tests__/vertical/stub.js.map +1 -0
- package/dist/__tests__/vertical/tateChuYoko.test.d.ts +2 -0
- package/dist/__tests__/vertical/tateChuYoko.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/tateChuYoko.test.js +270 -0
- package/dist/__tests__/vertical/tateChuYoko.test.js.map +1 -0
- package/dist/__tests__/vertical/uprightResources.test.d.ts +2 -0
- package/dist/__tests__/vertical/uprightResources.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/uprightResources.test.js +182 -0
- package/dist/__tests__/vertical/uprightResources.test.js.map +1 -0
- package/dist/__tests__/vertical/verticalDesignText.test.d.ts +2 -0
- package/dist/__tests__/vertical/verticalDesignText.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/verticalDesignText.test.js +190 -0
- package/dist/__tests__/vertical/verticalDesignText.test.js.map +1 -0
- package/dist/__tests__/vertical/verticalSpans.d.ts +25 -0
- package/dist/__tests__/vertical/verticalSpans.d.ts.map +1 -0
- package/dist/__tests__/vertical/verticalSpans.js +39 -0
- package/dist/__tests__/vertical/verticalSpans.js.map +1 -0
- package/dist/__tests__/vertical/verticalTwins.test.d.ts +2 -0
- package/dist/__tests__/vertical/verticalTwins.test.d.ts.map +1 -0
- package/dist/__tests__/vertical/verticalTwins.test.js +71 -0
- package/dist/__tests__/vertical/verticalTwins.test.js.map +1 -0
- package/dist/bundle/adapters.d.ts +14 -5
- package/dist/bundle/adapters.d.ts.map +1 -1
- package/dist/bundle/adapters.js +4 -3
- package/dist/bundle/adapters.js.map +1 -1
- package/dist/bundle/codec.d.ts.map +1 -1
- package/dist/bundle/codec.js +27 -4
- package/dist/bundle/codec.js.map +1 -1
- package/dist/bundle/index.d.ts +1 -1
- package/dist/bundle/index.d.ts.map +1 -1
- package/dist/bundle/manifest.d.ts +6 -4
- package/dist/bundle/manifest.d.ts.map +1 -1
- package/dist/bundle/manifest.js +31 -32
- package/dist/bundle/manifest.js.map +1 -1
- package/dist/bundle/types.d.ts +7 -2
- package/dist/bundle/types.d.ts.map +1 -1
- package/dist/canvas-backend/annotations.d.ts +31 -0
- package/dist/canvas-backend/annotations.d.ts.map +1 -0
- package/dist/canvas-backend/annotations.js +120 -0
- package/dist/canvas-backend/annotations.js.map +1 -0
- package/dist/canvas-backend/blockRender.d.ts.map +1 -1
- package/dist/canvas-backend/blockRender.js +195 -15
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/decorations.d.ts +5 -0
- package/dist/canvas-backend/decorations.d.ts.map +1 -1
- package/dist/canvas-backend/decorations.js +27 -0
- package/dist/canvas-backend/decorations.js.map +1 -1
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +32 -16
- package/dist/canvas-backend/headerFooter.js.map +1 -1
- package/dist/canvas-backend/index.d.ts +2 -0
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +62 -2
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.js +42 -5
- package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
- package/dist/canvas-backend/segmentText.d.ts +23 -0
- package/dist/canvas-backend/segmentText.d.ts.map +1 -0
- package/dist/canvas-backend/segmentText.js +41 -0
- package/dist/canvas-backend/segmentText.js.map +1 -0
- package/dist/canvas-backend/verticalText.d.ts +113 -0
- package/dist/canvas-backend/verticalText.d.ts.map +1 -0
- package/dist/canvas-backend/verticalText.js +437 -0
- package/dist/canvas-backend/verticalText.js.map +1 -0
- package/dist/chineseNumerals.d.ts +39 -0
- package/dist/chineseNumerals.d.ts.map +1 -0
- package/dist/chineseNumerals.js +192 -0
- package/dist/chineseNumerals.js.map +1 -0
- package/dist/cjkMarks.d.ts +61 -0
- package/dist/cjkMarks.d.ts.map +1 -0
- package/dist/cjkMarks.js +441 -0
- package/dist/cjkMarks.js.map +1 -0
- package/dist/columnClip.d.ts +13 -4
- package/dist/columnClip.d.ts.map +1 -1
- package/dist/columnClip.js +33 -5
- package/dist/columnClip.js.map +1 -1
- package/dist/configWarnings.d.ts.map +1 -1
- package/dist/configWarnings.js +18 -3
- package/dist/configWarnings.js.map +1 -1
- package/dist/defaults/bodyText.d.ts +4 -1
- package/dist/defaults/bodyText.d.ts.map +1 -1
- package/dist/defaults/bodyText.js +27 -5
- package/dist/defaults/bodyText.js.map +1 -1
- package/dist/defaults/calloutStyles.js +1 -1
- package/dist/defaults/calloutStyles.js.map +1 -1
- package/dist/defaults/captionStyle.d.ts.map +1 -1
- package/dist/defaults/captionStyle.js +14 -0
- package/dist/defaults/captionStyle.js.map +1 -1
- package/dist/defaults/cjk.d.ts +33 -0
- package/dist/defaults/cjk.d.ts.map +1 -0
- package/dist/defaults/cjk.js +234 -0
- package/dist/defaults/cjk.js.map +1 -0
- package/dist/defaults/headerFooter.d.ts.map +1 -1
- package/dist/defaults/headerFooter.js +2 -0
- package/dist/defaults/headerFooter.js.map +1 -1
- package/dist/defaults/headingStyles.d.ts.map +1 -1
- package/dist/defaults/headingStyles.js +4 -0
- package/dist/defaults/headingStyles.js.map +1 -1
- package/dist/defaults/headings.d.ts.map +1 -1
- package/dist/defaults/headings.js +13 -6
- package/dist/defaults/headings.js.map +1 -1
- package/dist/defaults/index.d.ts +1 -0
- package/dist/defaults/index.d.ts.map +1 -1
- package/dist/defaults/index.js +10 -1
- package/dist/defaults/index.js.map +1 -1
- package/dist/defaults/indexConfig.d.ts +2 -1
- package/dist/defaults/indexConfig.d.ts.map +1 -1
- package/dist/defaults/indexConfig.js +5 -0
- package/dist/defaults/indexConfig.js.map +1 -1
- package/dist/defaults/layout.d.ts.map +1 -1
- package/dist/defaults/layout.js +7 -0
- package/dist/defaults/layout.js.map +1 -1
- package/dist/defaults/orderedLists.d.ts +5 -2
- package/dist/defaults/orderedLists.d.ts.map +1 -1
- package/dist/defaults/orderedLists.js +20 -5
- package/dist/defaults/orderedLists.js.map +1 -1
- package/dist/defaults/page.d.ts +8 -2
- package/dist/defaults/page.d.ts.map +1 -1
- package/dist/defaults/page.js +24 -7
- package/dist/defaults/page.js.map +1 -1
- package/dist/defaults/resourceTypes.d.ts +3 -3
- package/dist/defaults/resourceTypes.d.ts.map +1 -1
- package/dist/defaults/resourceTypes.js +23 -9
- package/dist/defaults/resourceTypes.js.map +1 -1
- package/dist/defaults/tableStyle.d.ts.map +1 -1
- package/dist/defaults/tableStyle.js +8 -5
- package/dist/defaults/tableStyle.js.map +1 -1
- package/dist/design/layout.d.ts +33 -0
- package/dist/design/layout.d.ts.map +1 -1
- package/dist/design/layout.js +124 -18
- package/dist/design/layout.js.map +1 -1
- package/dist/design/placeholders.d.ts.map +1 -1
- package/dist/design/placeholders.js +5 -1
- package/dist/design/placeholders.js.map +1 -1
- package/dist/design/richText.d.ts +24 -4
- package/dist/design/richText.d.ts.map +1 -1
- package/dist/design/richText.js +77 -16
- package/dist/design/richText.js.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +635 -25
- package/dist/html-backend.js.map +1 -1
- package/dist/htmlAnnotations.d.ts +29 -0
- package/dist/htmlAnnotations.d.ts.map +1 -0
- package/dist/htmlAnnotations.js +86 -0
- package/dist/htmlAnnotations.js.map +1 -0
- package/dist/hyphenate.js +2 -1
- package/dist/hyphenate.js.map +1 -1
- package/dist/index.d.ts +28 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -8
- package/dist/index.js.map +1 -1
- package/dist/knuthPlass/pretextAdapter.d.ts +4 -1
- package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -1
- package/dist/knuthPlass/pretextAdapter.js +9 -5
- package/dist/knuthPlass/pretextAdapter.js.map +1 -1
- package/dist/knuthPlass/richAdapter.d.ts +15 -2
- package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
- package/dist/knuthPlass/richAdapter.js +16 -6
- package/dist/knuthPlass/richAdapter.js.map +1 -1
- package/dist/knuthPlass/tracking.d.ts +1 -1
- package/dist/knuthPlass/tracking.d.ts.map +1 -1
- package/dist/knuthPlass/tracking.js +4 -3
- package/dist/knuthPlass/tracking.js.map +1 -1
- package/dist/knuthPlass/types.d.ts +3 -0
- package/dist/knuthPlass/types.d.ts.map +1 -1
- package/dist/lineInk.d.ts +13 -0
- package/dist/lineInk.d.ts.map +1 -1
- package/dist/lineInk.js +28 -1
- package/dist/lineInk.js.map +1 -1
- package/dist/locale.d.ts +91 -3
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +245 -1
- package/dist/locale.js.map +1 -1
- package/dist/looseLines.d.ts +11 -1
- package/dist/looseLines.d.ts.map +1 -1
- package/dist/looseLines.js +26 -1
- package/dist/looseLines.js.map +1 -1
- package/dist/measure/cache.d.ts.map +1 -1
- package/dist/measure/cache.js +51 -3
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/canvas.d.ts +25 -0
- package/dist/measure/canvas.d.ts.map +1 -1
- package/dist/measure/canvas.js +90 -1
- package/dist/measure/canvas.js.map +1 -1
- package/dist/measure/cjk.d.ts +8 -13
- package/dist/measure/cjk.d.ts.map +1 -1
- package/dist/measure/cjk.js +29 -53
- package/dist/measure/cjk.js.map +1 -1
- package/dist/measure/cjkAnnotate.d.ts +96 -0
- package/dist/measure/cjkAnnotate.d.ts.map +1 -0
- package/dist/measure/cjkAnnotate.js +237 -0
- package/dist/measure/cjkAnnotate.js.map +1 -0
- package/dist/measure/cjkClasses.d.ts +133 -0
- package/dist/measure/cjkClasses.d.ts.map +1 -0
- package/dist/measure/cjkClasses.js +273 -0
- package/dist/measure/cjkClasses.js.map +1 -0
- package/dist/measure/cjkCompose.d.ts +86 -0
- package/dist/measure/cjkCompose.d.ts.map +1 -0
- package/dist/measure/cjkCompose.js +2022 -0
- package/dist/measure/cjkCompose.js.map +1 -0
- package/dist/measure/cjkPunctuation.d.ts +248 -0
- package/dist/measure/cjkPunctuation.d.ts.map +1 -0
- package/dist/measure/cjkPunctuation.js +492 -0
- package/dist/measure/cjkPunctuation.js.map +1 -0
- package/dist/measure/graphemes.d.ts +13 -0
- package/dist/measure/graphemes.d.ts.map +1 -0
- package/dist/measure/graphemes.js +38 -0
- package/dist/measure/graphemes.js.map +1 -0
- package/dist/measure/index.d.ts +3 -0
- package/dist/measure/index.d.ts.map +1 -1
- package/dist/measure/index.js +2 -0
- package/dist/measure/index.js.map +1 -1
- package/dist/measure/links.d.ts +6 -2
- package/dist/measure/links.d.ts.map +1 -1
- package/dist/measure/links.js +15 -5
- package/dist/measure/links.js.map +1 -1
- package/dist/measure/markCuts.d.ts +37 -0
- package/dist/measure/markCuts.d.ts.map +1 -0
- package/dist/measure/markCuts.js +77 -0
- package/dist/measure/markCuts.js.map +1 -0
- package/dist/measure/plain.d.ts.map +1 -1
- package/dist/measure/plain.js +33 -11
- package/dist/measure/plain.js.map +1 -1
- package/dist/measure/rich.d.ts +88 -1
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +233 -111
- package/dist/measure/rich.js.map +1 -1
- package/dist/measure/rubyLift.d.ts +11 -0
- package/dist/measure/rubyLift.d.ts.map +1 -0
- package/dist/measure/rubyLift.js +57 -0
- package/dist/measure/rubyLift.js.map +1 -0
- package/dist/measure/spaces.d.ts +12 -2
- package/dist/measure/spaces.d.ts.map +1 -1
- package/dist/measure/spaces.js +21 -7
- package/dist/measure/spaces.js.map +1 -1
- package/dist/measure/types.d.ts +20 -1
- package/dist/measure/types.d.ts.map +1 -1
- package/dist/measure/types.js.map +1 -1
- package/dist/measure/vertical.d.ts +104 -0
- package/dist/measure/vertical.d.ts.map +1 -0
- package/dist/measure/vertical.js +184 -0
- package/dist/measure/vertical.js.map +1 -0
- package/dist/numberWords.d.ts +3 -10
- package/dist/numberWords.d.ts.map +1 -1
- package/dist/numberWords.js +21 -9
- package/dist/numberWords.js.map +1 -1
- package/dist/numbering.d.ts +23 -5
- package/dist/numbering.d.ts.map +1 -1
- package/dist/numbering.js +99 -14
- package/dist/numbering.js.map +1 -1
- package/dist/parse/annotations.d.ts +101 -0
- package/dist/parse/annotations.d.ts.map +1 -0
- package/dist/parse/annotations.js +556 -0
- package/dist/parse/annotations.js.map +1 -0
- package/dist/parse/attrs.d.ts +48 -1
- package/dist/parse/attrs.d.ts.map +1 -1
- package/dist/parse/attrs.js +121 -8
- package/dist/parse/attrs.js.map +1 -1
- package/dist/parse/blockParser.d.ts.map +1 -1
- package/dist/parse/blockParser.js +50 -24
- package/dist/parse/blockParser.js.map +1 -1
- package/dist/parse/index.d.ts +3 -1
- package/dist/parse/index.d.ts.map +1 -1
- package/dist/parse/index.js +1 -0
- package/dist/parse/index.js.map +1 -1
- package/dist/parse/injectSpans.d.ts +3 -1
- package/dist/parse/injectSpans.d.ts.map +1 -1
- package/dist/parse/injectSpans.js +29 -8
- package/dist/parse/injectSpans.js.map +1 -1
- package/dist/parse/inlineFormatting.d.ts +38 -6
- package/dist/parse/inlineFormatting.d.ts.map +1 -1
- package/dist/parse/inlineFormatting.js +139 -26
- package/dist/parse/inlineFormatting.js.map +1 -1
- package/dist/parse/inlineSnippet.d.ts +2 -1
- package/dist/parse/inlineSnippet.d.ts.map +1 -1
- package/dist/parse/inlineSnippet.js +6 -2
- package/dist/parse/inlineSnippet.js.map +1 -1
- package/dist/parse/orientationMarks.d.ts +49 -0
- package/dist/parse/orientationMarks.d.ts.map +1 -0
- package/dist/parse/orientationMarks.js +138 -0
- package/dist/parse/orientationMarks.js.map +1 -0
- package/dist/parse/softBreaks.d.ts +56 -0
- package/dist/parse/softBreaks.d.ts.map +1 -0
- package/dist/parse/softBreaks.js +271 -0
- package/dist/parse/softBreaks.js.map +1 -0
- package/dist/parse/sourceMapping.d.ts.map +1 -1
- package/dist/parse/sourceMapping.js +41 -0
- package/dist/parse/sourceMapping.js.map +1 -1
- package/dist/parse/types.d.ts +84 -0
- package/dist/parse/types.d.ts.map +1 -1
- package/dist/pipeline/annotations.d.ts +56 -0
- package/dist/pipeline/annotations.d.ts.map +1 -0
- package/dist/pipeline/annotations.js +181 -0
- package/dist/pipeline/annotations.js.map +1 -0
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +158 -47
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/buildBlockKind.d.ts +3 -0
- package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
- package/dist/pipeline/buildBlockKind.js +5 -3
- package/dist/pipeline/buildBlockKind.js.map +1 -1
- package/dist/pipeline/buildHelpers.d.ts +36 -6
- package/dist/pipeline/buildHelpers.d.ts.map +1 -1
- package/dist/pipeline/buildHelpers.js +55 -8
- package/dist/pipeline/buildHelpers.js.map +1 -1
- package/dist/pipeline/buildMeasurement.d.ts +4 -0
- package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
- package/dist/pipeline/buildMeasurement.js +3 -1
- package/dist/pipeline/buildMeasurement.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +25 -11
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/cjkGrid.d.ts +133 -0
- package/dist/pipeline/cjkGrid.d.ts.map +1 -0
- package/dist/pipeline/cjkGrid.js +191 -0
- package/dist/pipeline/cjkGrid.js.map +1 -0
- package/dist/pipeline/config.d.ts +13 -9
- package/dist/pipeline/config.d.ts.map +1 -1
- package/dist/pipeline/config.js +43 -18
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts +10 -0
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +174 -2
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/floatPlacement.d.ts +9 -3
- package/dist/pipeline/floatPlacement.d.ts.map +1 -1
- package/dist/pipeline/floatPlacement.js +17 -6
- package/dist/pipeline/floatPlacement.js.map +1 -1
- package/dist/pipeline/headerFooter.d.ts +5 -2
- package/dist/pipeline/headerFooter.d.ts.map +1 -1
- package/dist/pipeline/headerFooter.js +123 -28
- package/dist/pipeline/headerFooter.js.map +1 -1
- package/dist/pipeline/headingDesignCuts.d.ts.map +1 -1
- package/dist/pipeline/headingDesignCuts.js +3 -1
- package/dist/pipeline/headingDesignCuts.js.map +1 -1
- package/dist/pipeline/headingStyles.d.ts +9 -3
- package/dist/pipeline/headingStyles.d.ts.map +1 -1
- package/dist/pipeline/headingStyles.js +23 -5
- package/dist/pipeline/headingStyles.js.map +1 -1
- package/dist/pipeline/indexDirective.d.ts.map +1 -1
- package/dist/pipeline/indexDirective.js +64 -20
- package/dist/pipeline/indexDirective.js.map +1 -1
- package/dist/pipeline/indexGroups.d.ts +55 -0
- package/dist/pipeline/indexGroups.d.ts.map +1 -0
- package/dist/pipeline/indexGroups.js +151 -0
- package/dist/pipeline/indexGroups.js.map +1 -0
- package/dist/pipeline/lists.d.ts +17 -0
- package/dist/pipeline/lists.d.ts.map +1 -1
- package/dist/pipeline/lists.js +43 -51
- package/dist/pipeline/lists.js.map +1 -1
- package/dist/pipeline/measureContentBlock.d.ts +3 -0
- package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
- package/dist/pipeline/measureContentBlock.js +31 -4
- package/dist/pipeline/measureContentBlock.js.map +1 -1
- package/dist/pipeline/outline.d.ts.map +1 -1
- package/dist/pipeline/outline.js +13 -8
- package/dist/pipeline/outline.js.map +1 -1
- package/dist/pipeline/parts.d.ts +6 -3
- package/dist/pipeline/parts.d.ts.map +1 -1
- package/dist/pipeline/parts.js +28 -5
- package/dist/pipeline/parts.js.map +1 -1
- package/dist/pipeline/placeholders.d.ts +11 -0
- package/dist/pipeline/placeholders.d.ts.map +1 -1
- package/dist/pipeline/placeholders.js +48 -18
- package/dist/pipeline/placeholders.js.map +1 -1
- package/dist/pipeline/placement.d.ts +10 -6
- package/dist/pipeline/placement.d.ts.map +1 -1
- package/dist/pipeline/placement.js +33 -16
- package/dist/pipeline/placement.js.map +1 -1
- package/dist/pipeline/resourceLayout.d.ts +18 -1
- package/dist/pipeline/resourceLayout.d.ts.map +1 -1
- package/dist/pipeline/resourceLayout.js +109 -21
- package/dist/pipeline/resourceLayout.js.map +1 -1
- package/dist/pipeline/toc.d.ts.map +1 -1
- package/dist/pipeline/toc.js +6 -5
- package/dist/pipeline/toc.js.map +1 -1
- package/dist/pipeline/verticalMetrics.d.ts +14 -0
- package/dist/pipeline/verticalMetrics.d.ts.map +1 -0
- package/dist/pipeline/verticalMetrics.js +154 -0
- package/dist/pipeline/verticalMetrics.js.map +1 -0
- package/dist/types.d.ts +344 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +396 -6
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js +49 -0
- package/dist/vdt.js.map +1 -1
- package/dist/writingMode.d.ts +156 -0
- package/dist/writingMode.d.ts.map +1 -0
- package/dist/writingMode.js +291 -0
- package/dist/writingMode.js.map +1 -0
- package/package.json +1 -1
package/dist/html-backend.js
CHANGED
|
@@ -2,7 +2,48 @@ import { footnoteRuleSegments } from './columnRule';
|
|
|
2
2
|
import { tableCellFillRects, tableFrameOutline } from './vdt';
|
|
3
3
|
import { dimensionToPx } from './units';
|
|
4
4
|
import { documentInkHex, isSingleInkSvgUrl, singleInkColorMatrix } from './svg/singleInk';
|
|
5
|
-
import { lineTrailingTracking } from './lineInk';
|
|
5
|
+
import { lineInkExtent, lineTrailingTracking } from './lineInk';
|
|
6
|
+
import { CHARACTER_GRID_COLOR, cjkGridCells } from './pipeline/cjkGrid';
|
|
7
|
+
import { renderLangOf } from './locale';
|
|
8
|
+
import { hasCJK } from './measure/cjk';
|
|
9
|
+
import { DEFAULT_CENTRAL_BASELINE } from './vdt';
|
|
10
|
+
import { holdsTurnedMark, segmentOrientation, verticalRuns } from './writingMode';
|
|
11
|
+
import { graphemesOf } from './measure/graphemes';
|
|
12
|
+
import { fontFamilyOf } from './measure/vertical';
|
|
13
|
+
import { lineMarksHtml, rubyHtml, verticalLineMarksHtml, warichuHtml } from './htmlAnnotations';
|
|
14
|
+
/**
|
|
15
|
+
* Declarations of every box of CJK text measured with no punctuation
|
|
16
|
+
* trimming: the browser adds and removes nothing. Chrome's
|
|
17
|
+
* `text-spacing-trim: normal` (and fonts' `chws`) would set the first of
|
|
18
|
+
* two marks that meet half width (`)》`, `”“`), and `text-autospace` would
|
|
19
|
+
* add space between Han and Latin, where the layout measured them apart
|
|
20
|
+
* (`measureTextWidth`, `markCuts`) and the CJK composer adjusted the marks
|
|
21
|
+
* itself; the renderers position what it set. Set on a line of the CJK
|
|
22
|
+
* composer (`VDTLine.cjkComposed`), on each word of another line that holds
|
|
23
|
+
* CJK text (each was measured alone), on a design text line or run and a
|
|
24
|
+
* list marker that holds CJK text. Absent from any other box, so the
|
|
25
|
+
* output of other documents is unchanged.
|
|
26
|
+
*/
|
|
27
|
+
const CJK_TEXT_DECL = "text-spacing-trim:space-all;text-autospace:no-autospace;font-feature-settings:'chws' 0,'halt' 0,'vchw' 0;";
|
|
28
|
+
/** The part of {@link CJK_TEXT_DECL} a `font` shorthand resets: repeated
|
|
29
|
+
* after it on an inner box in another face. */
|
|
30
|
+
const CJK_FEATURES_DECL = "font-feature-settings:'chws' 0,'halt' 0,'vchw' 0;";
|
|
31
|
+
/** A dash of a 破折号 stretched over its em (`VDTLineSegment.inkScale`):
|
|
32
|
+
* scaled from its start, with the glyph the layout measured. Under
|
|
33
|
+
* `lang="zh-Hans"` a face may swap its own Chinese form in (`locl`: Noto
|
|
34
|
+
* Serif SC's full-width dash), which the scale was not computed for. */
|
|
35
|
+
const DASH_FEATURES_DECL = "font-feature-settings:'chws' 0,'halt' 0,'vchw' 0,'locl' 0;";
|
|
36
|
+
const inkScaleDecl = (scale) => `transform:scaleX(${scale.toFixed(4)});transform-origin:0 0;${DASH_FEATURES_DECL}`;
|
|
37
|
+
/** Whether a line box carries {@link CJK_TEXT_DECL}: a line of the CJK
|
|
38
|
+
* composer, which it measured character by character, or a line with no
|
|
39
|
+
* segments (one span) holding CJK text. A word-by-word line holding CJK
|
|
40
|
+
* text sets it on the words that hold some (`segmentCjk`). */
|
|
41
|
+
function lineCjkDecl(line) {
|
|
42
|
+
return line.cjkComposed === true || ((!line.segments || line.segments.length === 0) && hasCJK(line.text));
|
|
43
|
+
}
|
|
44
|
+
function segmentCjk(seg, lineDecl) {
|
|
45
|
+
return lineDecl ? 'line' : hasCJK(seg.text) ? 'own' : false;
|
|
46
|
+
}
|
|
6
47
|
/**
|
|
7
48
|
* The resources this document anchors in its HTML (`id="pt-res-<id>"`):
|
|
8
49
|
* those whose embed (a first slice, for a split table) is on one of its
|
|
@@ -152,7 +193,45 @@ function renderMathSegmentSvg(seg, xPx, line, block) {
|
|
|
152
193
|
* which aligns on that baseline without growing or shifting the line
|
|
153
194
|
* box. A face with other vertical metrics would otherwise float its own
|
|
154
195
|
* baseline higher or lower than the surrounding text. */
|
|
155
|
-
function renderTextSegment(seg, x, top, fontDecl, colorDecl, color
|
|
196
|
+
function renderTextSegment(seg, x, top, fontDecl, colorDecl, color,
|
|
197
|
+
/** The tracking the line box already carries (block + line); a segment's
|
|
198
|
+
* own (a justified CJK line) is added to it. */
|
|
199
|
+
tracking = 0,
|
|
200
|
+
/** Whether the browser's punctuation spacing is off for the segment
|
|
201
|
+
* (see {@link CJK_TEXT_DECL}): set by its line (`'line'`) or on its own
|
|
202
|
+
* box (`'own'`); a box in another face repeats the features either way. */
|
|
203
|
+
cjk = false) {
|
|
204
|
+
const spacingDecl = seg.tracking !== undefined ? `letter-spacing:${tracking + seg.tracking}px;` : '';
|
|
205
|
+
// A compressed CJK mark is painted before its box (`inkOffset`).
|
|
206
|
+
const left = seg.inkOffset !== undefined ? x + seg.inkOffset : x;
|
|
207
|
+
const scaleDecl = seg.inkScale !== undefined ? inkScaleDecl(seg.inkScale) : '';
|
|
208
|
+
const pos = `position:absolute;left:${left.toFixed(3)}px;top:${top};white-space:pre;${spacingDecl}${cjk === 'own' ? CJK_TEXT_DECL : ''}${scaleDecl}`;
|
|
209
|
+
// Text set with emphasis dots is emphasis (#193); the dots are the
|
|
210
|
+
// line's marks.
|
|
211
|
+
const text = seg.cjkMarks?.dots ? `<em style="font-style:inherit;">${esc(seg.text)}</em>` : esc(seg.text);
|
|
212
|
+
const featuresDecl = !fontDecl ? '' : scaleDecl ? DASH_FEATURES_DECL : cjk ? CJK_FEATURES_DECL : '';
|
|
213
|
+
if (seg.refResourceId !== undefined) {
|
|
214
|
+
// Anchors carry an explicit color so the UA link blue never leaks in.
|
|
215
|
+
const inner = `<a href="${refAnchorHref(seg.refResourceId)}" style="text-decoration:none;${fontDecl}${featuresDecl}${fontDecl ? 'line-height:0;' : ''}color:${color};">${text}</a>`;
|
|
216
|
+
return `<span style="${pos}">${inner}</span>`;
|
|
217
|
+
}
|
|
218
|
+
if (fontDecl) {
|
|
219
|
+
return `<span style="${pos}"><span style="${fontDecl}${featuresDecl}line-height:0;${colorDecl}">${text}</span></span>`;
|
|
220
|
+
}
|
|
221
|
+
return `<span style="${pos}${colorDecl}">${text}</span>`;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* {@link renderTextSegment} for a segment of a line set word by word (not
|
|
225
|
+
* `VDTLine.cjkComposed`), which carries none of the composer's fields
|
|
226
|
+
* (`tracking`, `inkOffset`, `inkScale`): the markup every such segment had
|
|
227
|
+
* before the CJK features. One that holds CJK text (`cjk`) or carries
|
|
228
|
+
* Chinese marks goes to {@link renderMarkedWordSegment}: the browser's
|
|
229
|
+
* punctuation spacing off on its own box (see {@link CJK_TEXT_DECL}), its
|
|
230
|
+
* text in `<em>` when it is set with emphasis dots.
|
|
231
|
+
*/
|
|
232
|
+
function renderWordTextSegment(seg, x, top, fontDecl, colorDecl, color, cjk) {
|
|
233
|
+
if (cjk || seg.cjkMarks)
|
|
234
|
+
return renderMarkedWordSegment(seg, x, top, fontDecl, colorDecl, color, cjk);
|
|
156
235
|
const pos = `position:absolute;left:${x.toFixed(3)}px;top:${top};white-space:pre;`;
|
|
157
236
|
const text = esc(seg.text);
|
|
158
237
|
if (seg.refResourceId !== undefined) {
|
|
@@ -165,6 +244,24 @@ function renderTextSegment(seg, x, top, fontDecl, colorDecl, color) {
|
|
|
165
244
|
}
|
|
166
245
|
return `<span style="${pos}${colorDecl}">${text}</span>`;
|
|
167
246
|
}
|
|
247
|
+
/** {@link renderWordTextSegment} for a segment that holds CJK text (`cjk`)
|
|
248
|
+
* or carries Chinese marks. */
|
|
249
|
+
function renderMarkedWordSegment(seg, x, top, fontDecl, colorDecl, color, cjk) {
|
|
250
|
+
const pos = `position:absolute;left:${x.toFixed(3)}px;top:${top};white-space:pre;${cjk ? CJK_TEXT_DECL : ''}`;
|
|
251
|
+
// Text set with emphasis dots is emphasis (#193); the dots are the
|
|
252
|
+
// line's marks.
|
|
253
|
+
const text = seg.cjkMarks?.dots ? `<em style="font-style:inherit;">${esc(seg.text)}</em>` : esc(seg.text);
|
|
254
|
+
const featuresDecl = fontDecl && cjk ? CJK_FEATURES_DECL : '';
|
|
255
|
+
if (seg.refResourceId !== undefined) {
|
|
256
|
+
// Anchors carry an explicit color so the UA link blue never leaks in.
|
|
257
|
+
const inner = `<a href="${refAnchorHref(seg.refResourceId)}" style="text-decoration:none;${fontDecl}${featuresDecl}${fontDecl ? 'line-height:0;' : ''}color:${color};">${text}</a>`;
|
|
258
|
+
return `<span style="${pos}">${inner}</span>`;
|
|
259
|
+
}
|
|
260
|
+
if (fontDecl) {
|
|
261
|
+
return `<span style="${pos}"><span style="${fontDecl}${featuresDecl}line-height:0;${colorDecl}">${text}</span></span>`;
|
|
262
|
+
}
|
|
263
|
+
return `<span style="${pos}${colorDecl}">${text}</span>`;
|
|
264
|
+
}
|
|
168
265
|
/** A `:ref` painted as several runs (a label in small capitals: one run per
|
|
169
266
|
* case) from `segs[start]` on. Every run is placed as measured, and all of
|
|
170
267
|
* them sit in one anchor, so the reference stays one link. `paint` renders
|
|
@@ -212,7 +309,20 @@ function linkRuns() {
|
|
|
212
309
|
function segmentHref(seg) {
|
|
213
310
|
return seg.refResourceId === undefined ? seg.href : undefined;
|
|
214
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* The segments of a horizontal line. A line of the CJK composer goes to
|
|
314
|
+
* {@link renderComposedSegments}. Any other line was set word by word and
|
|
315
|
+
* carries none of the composer's fields (a segment's `tracking`,
|
|
316
|
+
* `inkOffset`, `inkScale`, `hangs`, `autospace`, `ruby`, `warichu`): its
|
|
317
|
+
* markup is the one every line had before the CJK features, the browser's
|
|
318
|
+
* punctuation spacing turned off on each segment that holds CJK text. Only
|
|
319
|
+
* a line whose text holds CJK characters has its segments looked into: the
|
|
320
|
+
* line's `text` holds the text of every segment, except the leader of a
|
|
321
|
+
* contents entry (`tocEntry`).
|
|
322
|
+
*/
|
|
215
323
|
function renderSegments(line, block, targets) {
|
|
324
|
+
if (line.cjkComposed)
|
|
325
|
+
return renderComposedSegments(line, block, targets);
|
|
216
326
|
// The tracking after the last glyph is advance, not ink: centring and
|
|
217
327
|
// right alignment leave it out (EF-153), as the canvas does.
|
|
218
328
|
const trailing = lineTrailingTracking(line, (block.letterSpacing ?? 0) + (line.letterSpacing ?? 0));
|
|
@@ -255,13 +365,14 @@ function renderSegments(line, block, targets) {
|
|
|
255
365
|
const links = linkRuns();
|
|
256
366
|
let x = leadingGap;
|
|
257
367
|
const segs = line.segments;
|
|
368
|
+
const cjk = block.tocEntry !== undefined || hasCJK(line.text);
|
|
258
369
|
const paintText = (seg, at, inLink = false) => {
|
|
259
370
|
const font = quoteFontString(pickSegmentFont(seg, block));
|
|
260
371
|
const color = pickSegmentColor(seg, block);
|
|
261
372
|
const fontDecl = font !== quoteFontString(block.fontString) ? `font:${font};` : '';
|
|
262
373
|
const colorDecl = color !== block.color ? `color:${color};` : '';
|
|
263
374
|
const top = seg.baselineShift ? `${seg.baselineShift.toFixed(3)}px` : '0';
|
|
264
|
-
return
|
|
375
|
+
return renderWordTextSegment(inLink ? { ...seg, refResourceId: undefined } : seg, at, top, fontDecl, colorDecl, color, cjk && hasCJK(seg.text));
|
|
265
376
|
};
|
|
266
377
|
for (let i = 0; i < segs.length; i++) {
|
|
267
378
|
const seg = segs[i];
|
|
@@ -296,6 +407,116 @@ function renderSegments(line, block, targets) {
|
|
|
296
407
|
x += seg.width;
|
|
297
408
|
}
|
|
298
409
|
parts.push(links.end());
|
|
410
|
+
// Emphasis dots, proper-name and book-title lines (#193).
|
|
411
|
+
if (line.marks)
|
|
412
|
+
parts.push(lineMarksHtml(line, block.color));
|
|
413
|
+
return parts.join('');
|
|
414
|
+
}
|
|
415
|
+
/** {@link renderSegments} for a line of the CJK composer: hung marks and
|
|
416
|
+
* Han–Latin spaces kept out of the justification, each segment with its
|
|
417
|
+
* own tracking, ink offset and scale, warichu notes and ruby readings. */
|
|
418
|
+
function renderComposedSegments(line, block, targets) {
|
|
419
|
+
// The tracking after the last glyph is advance, not ink: centring and
|
|
420
|
+
// right alignment leave it out (EF-153), as the canvas does.
|
|
421
|
+
const lineTracking = (block.letterSpacing ?? 0) + (line.letterSpacing ?? 0);
|
|
422
|
+
const trailing = lineTrailingTracking(line, lineTracking);
|
|
423
|
+
if (!line.segments || line.segments.length === 0) {
|
|
424
|
+
const plainIndent = line.bbox.x - block.bbox.x;
|
|
425
|
+
const plainWidth = line.bbox.width - trailing;
|
|
426
|
+
const plainLeft = block.textAlign === 'right'
|
|
427
|
+
? Math.max(0, block.bbox.width - plainIndent - plainWidth)
|
|
428
|
+
: block.textAlign === 'center'
|
|
429
|
+
? Math.max(0, (block.bbox.width - plainIndent - plainWidth) / 2)
|
|
430
|
+
: 0;
|
|
431
|
+
return `<span style="position:absolute;left:${plainLeft.toFixed(3)}px;top:0;white-space:pre;">${esc(line.text)}</span>`;
|
|
432
|
+
}
|
|
433
|
+
// Match canvas justification: stretch inter-word spaces to fill effective width.
|
|
434
|
+
const lineIndent = line.bbox.x - block.bbox.x;
|
|
435
|
+
const effectiveWidth = block.bbox.width - lineIndent;
|
|
436
|
+
let wordWidth = 0;
|
|
437
|
+
let spaceCount = 0;
|
|
438
|
+
for (const seg of line.segments) {
|
|
439
|
+
// A hung mark is outside the measure; a Han–Latin space keeps its
|
|
440
|
+
// width.
|
|
441
|
+
if (seg.hangs)
|
|
442
|
+
continue;
|
|
443
|
+
if (seg.kind === 'space' && !seg.autospace)
|
|
444
|
+
spaceCount++;
|
|
445
|
+
else
|
|
446
|
+
wordWidth += seg.width;
|
|
447
|
+
}
|
|
448
|
+
const contentWidth = lineInkExtent(line, 0).width;
|
|
449
|
+
// Last lines render ragged at natural width — except when overfull:
|
|
450
|
+
// Knuth-Plass may accept a final line wider than the measure on the
|
|
451
|
+
// assumption that its inter-word glue shrinks (TeX glue-setting semantics),
|
|
452
|
+
// so honor that by compressing the spaces to fit the measure exactly.
|
|
453
|
+
const useJustify = block.textAlign === 'justify' && spaceCount > 0 &&
|
|
454
|
+
((!line.isLastLine && !line.ragged) || contentWidth > effectiveWidth);
|
|
455
|
+
const justifiedSpaceWidth = useJustify
|
|
456
|
+
? (effectiveWidth - wordWidth) / spaceCount
|
|
457
|
+
: 0;
|
|
458
|
+
// Centred / right alignment — math display blocks, ragged-left paragraph
|
|
459
|
+
// styles. Distribute the leading gap.
|
|
460
|
+
const slack = Math.max(0, effectiveWidth - (contentWidth - trailing));
|
|
461
|
+
const leadingGap = block.textAlign === 'center' ? slack / 2 : block.textAlign === 'right' ? slack : 0;
|
|
462
|
+
const parts = [];
|
|
463
|
+
const links = linkRuns();
|
|
464
|
+
let x = leadingGap;
|
|
465
|
+
const segs = line.segments;
|
|
466
|
+
const lineDecl = lineCjkDecl(line);
|
|
467
|
+
const paintText = (seg, at, inLink = false) => {
|
|
468
|
+
const font = quoteFontString(pickSegmentFont(seg, block));
|
|
469
|
+
const color = pickSegmentColor(seg, block);
|
|
470
|
+
const fontDecl = font !== quoteFontString(block.fontString) ? `font:${font};` : '';
|
|
471
|
+
const colorDecl = color !== block.color ? `color:${color};` : '';
|
|
472
|
+
const top = seg.baselineShift ? `${seg.baselineShift.toFixed(3)}px` : '0';
|
|
473
|
+
return renderTextSegment(inLink ? { ...seg, refResourceId: undefined } : seg, at, top, fontDecl, colorDecl, color, lineTracking, segmentCjk(seg, lineDecl));
|
|
474
|
+
};
|
|
475
|
+
for (let i = 0; i < segs.length; i++) {
|
|
476
|
+
const seg = segs[i];
|
|
477
|
+
if (seg.kind === 'space') {
|
|
478
|
+
x += useJustify && !seg.autospace ? justifiedSpaceWidth : seg.width;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
parts.push(links.at(segmentHref(seg)));
|
|
482
|
+
if (seg.kind === 'math') {
|
|
483
|
+
parts.push(renderMathSegmentSvg(seg, x, line, block));
|
|
484
|
+
x += seg.width;
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
if (seg.kind === 'swatch') {
|
|
488
|
+
parts.push(renderSwatch(x, line.baseline - line.bbox.y, seg.width, seg.swatch?.color, block.color));
|
|
489
|
+
x += seg.width;
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
if (seg.chip) {
|
|
493
|
+
parts.push(renderChip(seg.chip, x, line.baseline - line.bbox.y, quoteFontString(block.fontString), block.color, (run) => pickSegmentColor({ kind: 'text', text: run.text, width: run.width, bold: run.bold, italic: run.italic }, block)));
|
|
494
|
+
x += seg.width;
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (seg.warichu) {
|
|
498
|
+
// A warichu note's part: its two rows (#195).
|
|
499
|
+
parts.push(warichuHtml(seg.warichu, x, pickSegmentColor(seg, block), quoteFontString));
|
|
500
|
+
x += seg.width;
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
if (seg.refResourceId !== undefined && segs[i + 1]?.refContinues) {
|
|
504
|
+
const group = renderRefRuns(segs, i, x, pickSegmentColor(seg, block), (run, at) => paintText(run, at, true), refLinks(seg.refResourceId, targets));
|
|
505
|
+
parts.push(group.html);
|
|
506
|
+
x = group.x;
|
|
507
|
+
i = group.end - 1;
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
parts.push(paintText(seg, x, seg.refResourceId !== undefined && !refLinks(seg.refResourceId, targets)));
|
|
511
|
+
// A ruby base's reading (#194).
|
|
512
|
+
if (seg.ruby)
|
|
513
|
+
parts.push(rubyHtml(seg.ruby, x, pickSegmentColor(seg, block), quoteFontString));
|
|
514
|
+
x += seg.width;
|
|
515
|
+
}
|
|
516
|
+
parts.push(links.end());
|
|
517
|
+
// Emphasis dots, proper-name and book-title lines (#193).
|
|
518
|
+
if (line.marks)
|
|
519
|
+
parts.push(lineMarksHtml(line, block.color));
|
|
299
520
|
return parts.join('');
|
|
300
521
|
}
|
|
301
522
|
/** Inline colour swatch (`:swatch{…}`): a square of `side` px on the line's
|
|
@@ -330,7 +551,8 @@ function renderChip(chip, x, baselineOffset, lineFont, lineColor, inkFor) {
|
|
|
330
551
|
const fontDecl = font !== lineFont ? `font:${font};` : '';
|
|
331
552
|
const colorDecl = color !== lineColor ? `color:${color};` : '';
|
|
332
553
|
const top = run.baselineShift ? `${run.baselineShift.toFixed(3)}px` : '0';
|
|
333
|
-
|
|
554
|
+
// A chip's runs were measured one by one, as a whole each.
|
|
555
|
+
parts.push(renderTextSegment({ kind: 'text', text: run.text, width: run.width }, tx, top, fontDecl, colorDecl, color, 0, hasCJK(run.text) ? 'own' : false));
|
|
334
556
|
tx += run.width;
|
|
335
557
|
}
|
|
336
558
|
return parts.join('');
|
|
@@ -367,14 +589,20 @@ function renderBullet(block) {
|
|
|
367
589
|
`font:${onBaseline ? lineFont : font};` +
|
|
368
590
|
`color:${color};` +
|
|
369
591
|
`white-space:pre;` +
|
|
592
|
+
(hasCJK(text) ? CJK_TEXT_DECL : '') +
|
|
370
593
|
(onBaseline
|
|
371
|
-
? `"><span style="font:${font}
|
|
594
|
+
? `"><span style="font:${font};${hasCJK(text) ? CJK_FEATURES_DECL : ''}line-height:0;">${esc(text)}</span></div>`
|
|
372
595
|
: `">${esc(text)}</div>`);
|
|
373
596
|
let html = markerDiv('pt-bullet', block.bulletOffsetX, bulletFont, bulletColor, block.bulletText);
|
|
374
597
|
// Ordered-list separator styled apart from the number (own font/colour).
|
|
375
598
|
if (block.separatorText && block.separatorX !== undefined) {
|
|
376
599
|
const separatorFont = quoteFontString(block.separatorFontString ?? block.bulletFontString ?? block.fontString);
|
|
377
600
|
const separatorColor = block.separatorColor ?? bulletColor;
|
|
601
|
+
// The prefix run before the number, in the separator's style, first in
|
|
602
|
+
// the markup so a copy reads (一).
|
|
603
|
+
if (block.prefixText && block.prefixX !== undefined) {
|
|
604
|
+
html = markerDiv('pt-separator', block.prefixX, separatorFont, separatorColor, block.prefixText) + html;
|
|
605
|
+
}
|
|
378
606
|
html += markerDiv('pt-separator', block.separatorX, separatorFont, separatorColor, block.separatorText);
|
|
379
607
|
}
|
|
380
608
|
return html;
|
|
@@ -396,8 +624,278 @@ function renderLine(line, block, targets) {
|
|
|
396
624
|
`color:${block.color};` +
|
|
397
625
|
strikethroughDecl +
|
|
398
626
|
trackingDecl +
|
|
627
|
+
(lineCjkDecl(line) ? CJK_TEXT_DECL : '') +
|
|
399
628
|
`">${renderSegments(line, block, targets)}</div>`);
|
|
400
629
|
}
|
|
630
|
+
// ---------------------------------------------------------------------------
|
|
631
|
+
// Vertical text (`VDTPage.flow`)
|
|
632
|
+
//
|
|
633
|
+
// A vertical page's flow is rendered in a box turned a quarter turn
|
|
634
|
+
// clockwise (`pt-flow`, see `renderPageDetailed`), so boxes, rules,
|
|
635
|
+
// pictures, turned resource blocks and everything else of the flow land on
|
|
636
|
+
// the sheet as the canvas paints them. Each text line is turned back
|
|
637
|
+
// upright inside it — one box per line, the line's physical rectangle — and
|
|
638
|
+
// set with `writing-mode: vertical-rl`: the browser stands Chinese
|
|
639
|
+
// characters upright, takes the fonts' vertical forms and sets Latin words
|
|
640
|
+
// sideways. Every segment is placed where the layout put it along the line
|
|
641
|
+
// (`top`), its em boxes centred on the column's central axis; tate-chu-yoko
|
|
642
|
+
// cells are `text-combine-upright: all`, `:upright` and `:sideways` runs
|
|
643
|
+
// `text-orientation`.
|
|
644
|
+
// ---------------------------------------------------------------------------
|
|
645
|
+
/** The central axis of a font (em above the baseline). */
|
|
646
|
+
function centralOf(v, fontString) {
|
|
647
|
+
return v.axes?.[fontFamilyOf(fontString)] ?? DEFAULT_CENTRAL_BASELINE;
|
|
648
|
+
}
|
|
649
|
+
/** Escaped text of a vertical run, with its tate-chu-yoko cells, the
|
|
650
|
+
* orientation its author forced, and each turned mark in a box of its
|
|
651
|
+
* cell ({@link turnedCellHtml}). `font` is the run's font string (whose
|
|
652
|
+
* family's `dashes` stretch a dash) and `tracking` the letter spacing it
|
|
653
|
+
* is set with, px, which follows each cell. */
|
|
654
|
+
function verticalTextHtml(text, v, orient, font, tracking = 0) {
|
|
655
|
+
if (orient === 'tcy')
|
|
656
|
+
return `<span style="text-combine-upright:all;">${esc(text)}</span>`;
|
|
657
|
+
if (orient === 'upright')
|
|
658
|
+
return `<span style="text-orientation:upright;">${esc(text)}</span>`;
|
|
659
|
+
if (orient === 'sideways')
|
|
660
|
+
return `<span style="text-orientation:sideways;">${esc(text)}</span>`;
|
|
661
|
+
const digits = v.uprightDigits > 0 && /[0-9]/.test(text);
|
|
662
|
+
if (!digits && !holdsTurnedMark(text))
|
|
663
|
+
return esc(text);
|
|
664
|
+
const runs = verticalRuns(graphemesOf(text), v.region, v.uprightDigits);
|
|
665
|
+
if (!runs.some((r) => r.glyph.orient === 'tcy' || r.glyph.orient === 'rotate'))
|
|
666
|
+
return esc(text);
|
|
667
|
+
const advances = font !== undefined ? v.dashes?.[fontFamilyOf(font)] : undefined;
|
|
668
|
+
// A number in one cell combined upright; a turned mark in its cell.
|
|
669
|
+
return runs.map((r) => (r.glyph.orient === 'tcy'
|
|
670
|
+
? `<span style="text-combine-upright:all;">${esc(r.text)}</span>`
|
|
671
|
+
: r.glyph.orient === 'rotate' ? turnedCellHtml(r, advances?.[r.text], tracking) : esc(r.text))).join('');
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* A mark a vertical line turns in a cell of its own (`rotate`: a dash, an
|
|
675
|
+
* ellipsis, an interpunct, a wave dash). The browser sets it sideways at
|
|
676
|
+
* its horizontal advance (Noto's · is a third of an em), where the layout
|
|
677
|
+
* gave it its cell (one em; half an em for the mainland interpunct), as
|
|
678
|
+
* the canvas and the PDF paint it: so it stands in a box the cell's
|
|
679
|
+
* length, centred in it, with the line's tracking after the box as after
|
|
680
|
+
* any cell. A dash is stretched to fill its cell, as they stretch it: by
|
|
681
|
+
* its advance the layout measured (`advance`, ems), with the glyph it
|
|
682
|
+
* measured (the face's Chinese form off, see {@link DASH_FEATURES_DECL});
|
|
683
|
+
* with no measured advance, in the font's full-width form (Noto's —).
|
|
684
|
+
*/
|
|
685
|
+
function turnedCellHtml(run, advance, tracking) {
|
|
686
|
+
const cell = run.cell ?? 1;
|
|
687
|
+
let inner = esc(run.text);
|
|
688
|
+
if (run.glyph.stretch) {
|
|
689
|
+
inner = advance !== undefined && advance > 0
|
|
690
|
+
? `<span style="${advance < cell ? `transform:scaleY(${(cell / advance).toFixed(4)});` : ''}${DASH_FEATURES_DECL}">${inner}</span>`
|
|
691
|
+
: `<span style="font-variant-east-asian:full-width;">${inner}</span>`;
|
|
692
|
+
}
|
|
693
|
+
return `<span style="display:inline-flex;justify-content:center;inline-size:${cell}em;letter-spacing:0;${tracking !== 0 ? `margin-inline-end:${tracking}px;` : ''}">${inner}</span>`;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* A box of the turned flow (`left`, `top`, `width` along the line,
|
|
697
|
+
* `height` across it) holding a box turned back upright, set vertically:
|
|
698
|
+
* `content` is placed inside that one with physical `top` (along the line)
|
|
699
|
+
* and `right` (from the box's physical right edge, the flow's top).
|
|
700
|
+
*/
|
|
701
|
+
function uprightBox(left, top, width, height, decl, content, attrs = '') {
|
|
702
|
+
return (`<div${attrs ? ` ${attrs}` : ''} style="position:absolute;left:${left.toFixed(3)}px;top:${top.toFixed(3)}px;width:${Math.max(0, width).toFixed(3)}px;height:${height.toFixed(3)}px;">` +
|
|
703
|
+
uprightInner(width, height, decl, content) +
|
|
704
|
+
`</div>`);
|
|
705
|
+
}
|
|
706
|
+
/** The box of {@link uprightBox} turned back upright: `height` wide on the
|
|
707
|
+
* sheet, `width` tall, set vertically. */
|
|
708
|
+
function uprightInner(width, height, decl, content) {
|
|
709
|
+
return (`<div style="position:absolute;left:0;top:0;width:${height.toFixed(3)}px;height:${Math.max(0, width).toFixed(3)}px;` +
|
|
710
|
+
`transform:translate(0,${height.toFixed(3)}px) rotate(-90deg);transform-origin:0 0;` +
|
|
711
|
+
`writing-mode:vertical-rl;text-orientation:mixed;${decl}">${content}</div>`);
|
|
712
|
+
}
|
|
713
|
+
/** A run of vertical text at `at` along its box, its em boxes centred
|
|
714
|
+
* `axis` px from the box's flow top (the physical right edge). The
|
|
715
|
+
* line height that centres them comes after `decl`: a `font` shorthand
|
|
716
|
+
* in it resets `line-height` to `normal`. */
|
|
717
|
+
function verticalSpan(at, axis, inner, decl = '') {
|
|
718
|
+
const lh = Math.max(0, 2 * axis);
|
|
719
|
+
return `<span style="position:absolute;top:${at.toFixed(3)}px;right:0;white-space:pre;${decl}line-height:${lh.toFixed(3)}px;">${inner}</span>`;
|
|
720
|
+
}
|
|
721
|
+
/** A run of vertical text whose em boxes are centred `axis` px from the
|
|
722
|
+
* box's flow top, on either side of it (a ruby reading or a warichu row
|
|
723
|
+
* sits outside the line's own box). */
|
|
724
|
+
function verticalSpanAt(at, axis, size, inner, decl = '') {
|
|
725
|
+
const lh = Math.max(1, 2 * size);
|
|
726
|
+
return `<span aria-hidden="true" style="position:absolute;top:${at.toFixed(3)}px;right:${(axis - lh / 2).toFixed(3)}px;white-space:pre;${decl}line-height:${lh.toFixed(3)}px;">${inner}</span>`;
|
|
727
|
+
}
|
|
728
|
+
/** Annotation runs of a vertical line (a ruby reading, a warichu note's
|
|
729
|
+
* rows, #194, #195) from `x` along it: set down the column in their own
|
|
730
|
+
* face, centred across it on their baseline (`dy`) less their face's
|
|
731
|
+
* axis, a zhuyin tone mark standing upright (`VDTAnnotationRun.upright`). */
|
|
732
|
+
function verticalAnnotationRuns(runs, x, color, v, axisOf) {
|
|
733
|
+
return runs.map((run) => {
|
|
734
|
+
const decl = `font:${quoteFontString(run.fontString)};color:${run.color ?? color};letter-spacing:0;`;
|
|
735
|
+
return verticalSpanAt(x + run.dx, axisOf(run.fontString, run.dy), extractFontSizePx(run.fontString), verticalTextHtml(run.text, v, run.upright ? 'upright' : undefined, run.fontString), decl);
|
|
736
|
+
}).join('');
|
|
737
|
+
}
|
|
738
|
+
/** A body line of a vertical page: its text segments down an upright box,
|
|
739
|
+
* its formulas, swatches and chips sideways where the canvas paints them
|
|
740
|
+
* (see the section comment). */
|
|
741
|
+
function renderVerticalLine(line, block, v, targets) {
|
|
742
|
+
const lineTracking = (block.letterSpacing ?? 0) + (line.letterSpacing ?? 0);
|
|
743
|
+
const trailing = lineTrailingTracking(line, lineTracking);
|
|
744
|
+
const lineIndent = line.bbox.x - block.bbox.x;
|
|
745
|
+
const effectiveWidth = block.bbox.width - lineIndent;
|
|
746
|
+
const baseline = line.baseline - line.bbox.y;
|
|
747
|
+
const blockFont = quoteFontString(block.fontString);
|
|
748
|
+
const axisOf = (fontString, shift = 0) => baseline + shift - centralOf(v, fontString) * extractFontSizePx(fontString);
|
|
749
|
+
const inner = [];
|
|
750
|
+
const sideways = [];
|
|
751
|
+
const segs = line.segments && line.segments.length > 0
|
|
752
|
+
? line.segments
|
|
753
|
+
: [{ kind: 'text', text: line.text, width: line.bbox.width }];
|
|
754
|
+
let wordWidth = 0;
|
|
755
|
+
let spaceCount = 0;
|
|
756
|
+
for (const seg of segs) {
|
|
757
|
+
if (seg.hangs)
|
|
758
|
+
continue;
|
|
759
|
+
if (seg.kind === 'space' && !seg.autospace)
|
|
760
|
+
spaceCount++;
|
|
761
|
+
else
|
|
762
|
+
wordWidth += seg.width;
|
|
763
|
+
}
|
|
764
|
+
const contentWidth = line.segments && line.segments.length > 0 ? lineInkExtent(line, 0).width : line.bbox.width;
|
|
765
|
+
const useJustify = block.textAlign === 'justify' && spaceCount > 0
|
|
766
|
+
&& ((!line.isLastLine && !line.ragged) || contentWidth > effectiveWidth);
|
|
767
|
+
const justifiedSpaceWidth = useJustify ? (effectiveWidth - wordWidth) / spaceCount : 0;
|
|
768
|
+
const slack = Math.max(0, effectiveWidth - (contentWidth - trailing));
|
|
769
|
+
let x = block.textAlign === 'center' ? slack / 2 : block.textAlign === 'right' ? slack : 0;
|
|
770
|
+
for (const seg of segs) {
|
|
771
|
+
if (seg.kind === 'space') {
|
|
772
|
+
x += useJustify && !seg.autospace ? justifiedSpaceWidth : seg.width;
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
if (seg.kind === 'math') {
|
|
776
|
+
sideways.push(renderMathSegmentSvg(seg, x, line, block));
|
|
777
|
+
x += seg.width;
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (seg.kind === 'swatch') {
|
|
781
|
+
sideways.push(renderSwatch(x, line.baseline - line.bbox.y, seg.width, seg.swatch?.color, block.color));
|
|
782
|
+
x += seg.width;
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
if (seg.chip) {
|
|
786
|
+
sideways.push(renderChip(seg.chip, x, line.baseline - line.bbox.y, blockFont, block.color, (run) => pickSegmentColor({ kind: 'text', text: run.text, width: run.width, bold: run.bold, italic: run.italic }, block)));
|
|
787
|
+
x += seg.width;
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
if (seg.warichu) {
|
|
791
|
+
// A warichu note's part: its two rows down the column, the upper
|
|
792
|
+
// row the right one, read once (#195).
|
|
793
|
+
const w = seg.warichu;
|
|
794
|
+
inner.push(`<span role="note" aria-label="${esc(w.upper + w.lower)}">${verticalAnnotationRuns(w.runs, x, w.color ?? pickSegmentColor(seg, block), v, axisOf)}</span>`);
|
|
795
|
+
x += seg.width;
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
const fontString = pickSegmentFont(seg, block);
|
|
799
|
+
const font = quoteFontString(fontString);
|
|
800
|
+
const color = pickSegmentColor(seg, block);
|
|
801
|
+
// A dash of a 破折号 (`inkScale`): turned with the flow (sideways) and
|
|
802
|
+
// stretched down the column from where the layout put its glyph, the
|
|
803
|
+
// face's own Chinese form off, as the canvas and the PDF paint it.
|
|
804
|
+
const stretched = seg.inkScale !== undefined;
|
|
805
|
+
const decl = (font !== blockFont ? `font:${font};` : '')
|
|
806
|
+
+ (color !== block.color ? `color:${color};` : '')
|
|
807
|
+
+ (seg.tracking !== undefined ? `letter-spacing:${lineTracking + seg.tracking}px;` : '')
|
|
808
|
+
+ (stretched ? `transform:scaleY(${seg.inkScale.toFixed(4)});transform-origin:0 0;${DASH_FEATURES_DECL}` : '');
|
|
809
|
+
const segTracking = seg.tracking !== undefined ? lineTracking + seg.tracking : lineTracking;
|
|
810
|
+
let text = verticalTextHtml(seg.text, v, stretched ? 'sideways' : segmentOrientation(seg), fontString, segTracking);
|
|
811
|
+
// Text set with emphasis dots is emphasis (#193); the dots are the
|
|
812
|
+
// line's marks.
|
|
813
|
+
if (seg.cjkMarks?.dots)
|
|
814
|
+
text = `<em style="font-style:inherit;">${text}</em>`;
|
|
815
|
+
const href = seg.refResourceId !== undefined
|
|
816
|
+
? (refLinks(seg.refResourceId, targets) ? refAnchorHref(seg.refResourceId) : undefined)
|
|
817
|
+
: seg.href;
|
|
818
|
+
if (href !== undefined)
|
|
819
|
+
text = `<a href="${esc(href)}" style="color:inherit;text-decoration:none;"${seg.href !== undefined && seg.refResourceId === undefined ? ' rel="noopener noreferrer"' : ''}>${text}</a>`;
|
|
820
|
+
inner.push(verticalSpan(x + (seg.inkOffset ?? 0), axisOf(fontString, seg.baselineShift ?? 0), text, decl));
|
|
821
|
+
// A ruby base's reading, beside the base (#194).
|
|
822
|
+
if (seg.ruby)
|
|
823
|
+
inner.push(verticalAnnotationRuns(seg.ruby.runs, x, seg.ruby.color ?? color, v, axisOf));
|
|
824
|
+
x += seg.width;
|
|
825
|
+
}
|
|
826
|
+
// Emphasis dots, proper-name and book-title lines (#193), in the turned
|
|
827
|
+
// flow with the line's box.
|
|
828
|
+
if (line.marks)
|
|
829
|
+
sideways.push(verticalLineMarksHtml(line, block.color));
|
|
830
|
+
const width = Math.max(line.bbox.width, effectiveWidth);
|
|
831
|
+
const decl = `font:${blockFont};color:${block.color};`
|
|
832
|
+
+ (block.strikethroughText ? 'text-decoration:line-through;' : '')
|
|
833
|
+
+ (lineTracking !== 0 ? `letter-spacing:${lineTracking}px;` : '')
|
|
834
|
+
+ (lineCjkDecl(line) || hasCJK(line.text) ? CJK_TEXT_DECL : '');
|
|
835
|
+
return (`<div class="pt-line" data-block="${esc(block.id)}" style="position:absolute;left:${line.bbox.x}px;top:${line.bbox.y}px;width:${width}px;height:${line.bbox.height}px;">` +
|
|
836
|
+
uprightInner(width, line.bbox.height, decl, inner.join('')) +
|
|
837
|
+
sideways.join('') +
|
|
838
|
+
`</div>`);
|
|
839
|
+
}
|
|
840
|
+
/** A list marker of a vertical line (the bullet, the number, its prefix
|
|
841
|
+
* and separator), set down the column from `x`. */
|
|
842
|
+
function renderVerticalMarker(cls, x, block, v, fontString, color, text) {
|
|
843
|
+
const line = block.lines[0];
|
|
844
|
+
const size = extractFontSizePx(fontString);
|
|
845
|
+
const lineTop = line.bbox.y;
|
|
846
|
+
const h = line.bbox.height;
|
|
847
|
+
// A marker set as text sits on its baseline; a bullet is centred on
|
|
848
|
+
// `bulletY` (its axis).
|
|
849
|
+
const axis = block.bulletBaselineY !== undefined
|
|
850
|
+
? block.bulletBaselineY - lineTop - centralOf(v, fontString) * size
|
|
851
|
+
: (block.bulletY ?? line.baseline) - lineTop;
|
|
852
|
+
const width = size * graphemesOf(text).length;
|
|
853
|
+
const decl = `font:${quoteFontString(fontString)};color:${color};${hasCJK(text) ? CJK_TEXT_DECL : ''}`;
|
|
854
|
+
return uprightBox(x, lineTop, width, h, decl, verticalSpan(0, axis, verticalTextHtml(text, v, undefined, fontString)), `class="${cls}" aria-hidden="true"`);
|
|
855
|
+
}
|
|
856
|
+
function renderVerticalBullet(block, v) {
|
|
857
|
+
if (block.type !== 'listItem' || !block.bulletText || block.bulletOffsetX === undefined || !block.lines[0])
|
|
858
|
+
return '';
|
|
859
|
+
const bulletFont = block.bulletFontString ?? block.fontString;
|
|
860
|
+
const bulletColor = block.bulletColor ?? block.color;
|
|
861
|
+
let html = renderVerticalMarker('pt-bullet', block.bulletOffsetX, block, v, bulletFont, bulletColor, block.bulletText);
|
|
862
|
+
if (block.separatorText && block.separatorX !== undefined) {
|
|
863
|
+
const sepFont = block.separatorFontString ?? bulletFont;
|
|
864
|
+
const sepColor = block.separatorColor ?? bulletColor;
|
|
865
|
+
if (block.prefixText && block.prefixX !== undefined)
|
|
866
|
+
html = renderVerticalMarker('pt-separator', block.prefixX, block, v, sepFont, sepColor, block.prefixText) + html;
|
|
867
|
+
html += renderVerticalMarker('pt-separator', block.separatorX, block, v, sepFont, sepColor, block.separatorText);
|
|
868
|
+
}
|
|
869
|
+
return html;
|
|
870
|
+
}
|
|
871
|
+
/** The lines of a design text set vertically: in the flow of a vertical
|
|
872
|
+
* page (an opener, a box title), or on its own (a running head set down
|
|
873
|
+
* the fore-edge, `VDTDesignTextBlock.writingMode`) inside the block's own
|
|
874
|
+
* turned frame. Each line's box runs from its baseline's line top. */
|
|
875
|
+
function verticalDesignLines(block, v, originX, originY) {
|
|
876
|
+
const size = extractFontSizePx(block.fontString);
|
|
877
|
+
const font = quoteFontString(block.fontString);
|
|
878
|
+
const parts = [];
|
|
879
|
+
const h = size * 2;
|
|
880
|
+
for (const line of block.lines) {
|
|
881
|
+
const top = line.baselineY - size * 1.5;
|
|
882
|
+
const axisOf = (fontString, shift = 0) => size * 1.5 + shift - centralOf(v, fontString) * extractFontSizePx(fontString);
|
|
883
|
+
const runs = line.runs ?? [{ text: line.text, fontString: block.fontString, width: line.width }];
|
|
884
|
+
let x = 0;
|
|
885
|
+
const inner = [];
|
|
886
|
+
for (const run of runs) {
|
|
887
|
+
const runFont = quoteFontString(run.fontString);
|
|
888
|
+
const decl = runFont !== font ? `font:${runFont};` : '';
|
|
889
|
+
inner.push(verticalSpan(x, axisOf(run.fontString, run.baselineShift ?? 0), verticalTextHtml(run.text, v, segmentOrientation(run), run.fontString, block.letterSpacingPx ?? 0), decl));
|
|
890
|
+
x += run.width;
|
|
891
|
+
}
|
|
892
|
+
const width = Math.max(line.width, x);
|
|
893
|
+
const decl = `font:${font};color:${block.color};${hasCJK(line.text) ? CJK_TEXT_DECL : ''}`
|
|
894
|
+
+ (line.wordSpacingPx ? `word-spacing:${line.wordSpacingPx.toFixed(3)}px;` : '');
|
|
895
|
+
parts.push(uprightBox(originX + line.xOffset, originY + top, width, h, decl, inner.join('')));
|
|
896
|
+
}
|
|
897
|
+
return parts.join('');
|
|
898
|
+
}
|
|
401
899
|
function pickResourceFont(seg, fonts) {
|
|
402
900
|
if (seg.fontString)
|
|
403
901
|
return seg.fontString;
|
|
@@ -416,8 +914,11 @@ function pickResourceFont(seg, fonts) {
|
|
|
416
914
|
function renderResourceLine(line, fonts, color, linkColor, labelColor = color, targets) {
|
|
417
915
|
const baseFont = quoteFontString(fonts.normal);
|
|
418
916
|
const parts = [];
|
|
917
|
+
const lineDecl = lineCjkDecl(line);
|
|
419
918
|
if (line.segments && line.segments.length > 0) {
|
|
420
919
|
const segs = line.segments;
|
|
920
|
+
const composed = line.cjkComposed === true;
|
|
921
|
+
const cjk = !composed && hasCJK(line.text);
|
|
421
922
|
const segColorOf = (seg) => (seg.refResourceId !== undefined
|
|
422
923
|
? linkColor
|
|
423
924
|
: seg.captionLabel
|
|
@@ -429,7 +930,11 @@ function renderResourceLine(line, fonts, color, linkColor, labelColor = color, t
|
|
|
429
930
|
const fontDecl = font !== baseFont ? `font:${font};` : '';
|
|
430
931
|
const colorDecl = segColor !== color ? `color:${segColor};` : '';
|
|
431
932
|
const top = seg.baselineShift ? `${seg.baselineShift.toFixed(3)}px` : '0';
|
|
432
|
-
|
|
933
|
+
// A line set word by word as every line was before the CJK
|
|
934
|
+
// features (see `renderSegments`).
|
|
935
|
+
return composed
|
|
936
|
+
? renderTextSegment(inLink ? { ...seg, refResourceId: undefined } : seg, at, top, fontDecl, colorDecl, segColor, line.letterSpacing ?? 0, segmentCjk(seg, lineDecl))
|
|
937
|
+
: renderWordTextSegment(inLink ? { ...seg, refResourceId: undefined } : seg, at, top, fontDecl, colorDecl, segColor, cjk && hasCJK(seg.text));
|
|
433
938
|
};
|
|
434
939
|
const links = linkRuns();
|
|
435
940
|
let x = 0;
|
|
@@ -475,6 +980,7 @@ function renderResourceLine(line, fonts, color, linkColor, labelColor = color, t
|
|
|
475
980
|
// A tracked line (a table header set with `headerLetterSpacing`) was
|
|
476
981
|
// measured with the tracking in its widths.
|
|
477
982
|
(line.letterSpacing ? `letter-spacing:${line.letterSpacing}px;` : '') +
|
|
983
|
+
(lineDecl ? CJK_TEXT_DECL : '') +
|
|
478
984
|
`">${parts.join('')}</div>`);
|
|
479
985
|
}
|
|
480
986
|
/** An image fitted to a box: `<img>` from `resourceImageUrl`, or the neutral
|
|
@@ -593,10 +1099,13 @@ function renderResourceTable(rb, bx, by, options) {
|
|
|
593
1099
|
}
|
|
594
1100
|
return parts.join('');
|
|
595
1101
|
}
|
|
596
|
-
function renderResourceBlockHtml(block,
|
|
1102
|
+
function renderResourceBlockHtml(block, paint) {
|
|
597
1103
|
const rb = block.resourceBlock;
|
|
598
1104
|
if (!rb)
|
|
599
1105
|
return '';
|
|
1106
|
+
// Its caption, notes and cells are horizontal text, in its own frame
|
|
1107
|
+
// (upright on a vertical page).
|
|
1108
|
+
const options = paint.vertical ? { ...paint, vertical: undefined } : paint;
|
|
600
1109
|
const parts = [];
|
|
601
1110
|
// A rotated block: its geometry is in the upright frame, emitted inside a
|
|
602
1111
|
// wrapper turned a quarter turn about the frame's origin on the page.
|
|
@@ -677,10 +1186,14 @@ function renderBoxAt(bbox, style) {
|
|
|
677
1186
|
boxStyleDecls(style) +
|
|
678
1187
|
`"></div>`);
|
|
679
1188
|
}
|
|
680
|
-
function renderDesignTextBlock(block) {
|
|
1189
|
+
function renderDesignTextBlock(block, options) {
|
|
681
1190
|
const parts = [];
|
|
682
1191
|
if (block.box)
|
|
683
1192
|
parts.push(renderBoxAt(block.bbox, block.box));
|
|
1193
|
+
if (options?.vertical)
|
|
1194
|
+
return parts.join('') + renderVerticalDesignText(block, options.vertical);
|
|
1195
|
+
if (block.vertical)
|
|
1196
|
+
return parts.join('') + renderTurnedDesignText(block);
|
|
684
1197
|
const font = quoteFontString(block.fontString);
|
|
685
1198
|
const fontSize = extractFontSizePx(block.fontString);
|
|
686
1199
|
const lineParts = [];
|
|
@@ -690,17 +1203,21 @@ function renderDesignTextBlock(block) {
|
|
|
690
1203
|
// in its own font; a script is shifted off the baseline. Of a subscript
|
|
691
1204
|
// and a superscript set over each other, the first sits in a box that
|
|
692
1205
|
// takes no room and the second in one as wide as the pair (EF-80).
|
|
1206
|
+
// Each run was measured whole, and so was a line without runs: the
|
|
1207
|
+
// browser's punctuation trimming is off on those that hold CJK text.
|
|
693
1208
|
const inner = line.runs
|
|
694
1209
|
? line.runs.map((run, i) => {
|
|
695
1210
|
const runFont = quoteFontString(run.fontString);
|
|
1211
|
+
const cjkDecl = hasCJK(run.text) ? CJK_TEXT_DECL : '';
|
|
696
1212
|
const fontDecl = runFont !== font ? `font:${runFont};` : '';
|
|
697
1213
|
const stackDecl = run.stacked
|
|
698
1214
|
? 'display:inline-block;width:0;'
|
|
699
1215
|
: line.runs[i - 1]?.stacked ? `display:inline-block;min-width:${run.width.toFixed(3)}px;` : '';
|
|
700
1216
|
const shiftDecl = run.baselineShift ? `position:relative;top:${run.baselineShift.toFixed(3)}px;` : '';
|
|
701
|
-
return fontDecl || stackDecl || shiftDecl ? `<span style="${fontDecl}${stackDecl}${shiftDecl}">${esc(run.text)}</span>` : esc(run.text);
|
|
1217
|
+
return fontDecl || cjkDecl || stackDecl || shiftDecl ? `<span style="${fontDecl}${cjkDecl}${stackDecl}${shiftDecl}">${esc(run.text)}</span>` : esc(run.text);
|
|
702
1218
|
}).join('')
|
|
703
1219
|
: esc(line.text);
|
|
1220
|
+
const lineDecl = !line.runs && hasCJK(line.text) ? CJK_TEXT_DECL : '';
|
|
704
1221
|
// A justified line: its word spaces widened as the canvas and the PDF
|
|
705
1222
|
// advance its runs (EF-109).
|
|
706
1223
|
const wordSpacingDecl = line.wordSpacingPx ? `word-spacing:${line.wordSpacingPx.toFixed(3)}px;` : '';
|
|
@@ -710,6 +1227,7 @@ function renderDesignTextBlock(block) {
|
|
|
710
1227
|
`top:${top.toFixed(3)}px;` +
|
|
711
1228
|
`line-height:1;white-space:pre;` +
|
|
712
1229
|
wordSpacingDecl +
|
|
1230
|
+
lineDecl +
|
|
713
1231
|
`">${inner}</span>`);
|
|
714
1232
|
}
|
|
715
1233
|
const clipDecl = block.clip ? 'overflow:hidden;' : '';
|
|
@@ -732,6 +1250,40 @@ function renderDesignTextBlock(block) {
|
|
|
732
1250
|
`">${lineParts.join('')}</div>`);
|
|
733
1251
|
return parts.join('');
|
|
734
1252
|
}
|
|
1253
|
+
/** A design text of a vertical page's flow: its lines set down the
|
|
1254
|
+
* column, clipped, tracked and outlined as a horizontal one. A line's
|
|
1255
|
+
* `xOffset` is from the block's own edge (as in `renderDesignTextBlock`),
|
|
1256
|
+
* its `baselineY` in the flow: only the latter is taken back to the box. */
|
|
1257
|
+
function renderVerticalDesignText(block, v) {
|
|
1258
|
+
const clipDecl = block.clip ? 'overflow:hidden;' : '';
|
|
1259
|
+
const trackingDecl = block.letterSpacingPx ? `letter-spacing:${block.letterSpacingPx}px;` : '';
|
|
1260
|
+
const strokeDecl = block.stroke && block.stroke.widthPx > 0
|
|
1261
|
+
? `-webkit-text-stroke:${block.stroke.widthPx}px ${block.stroke.color};` + (block.stroke.hollow ? '-webkit-text-fill-color:transparent;' : '')
|
|
1262
|
+
: '';
|
|
1263
|
+
const hidden = block.artifact ? ' aria-hidden="true"' : '';
|
|
1264
|
+
return (`<div${hidden} style="position:absolute;left:${block.bbox.x}px;top:${block.bbox.y}px;width:${block.bbox.width}px;height:${block.bbox.height}px;${clipDecl}${trackingDecl}${strokeDecl}">` +
|
|
1265
|
+
verticalDesignLines(block, v, 0, -block.bbox.y) +
|
|
1266
|
+
`</div>`);
|
|
1267
|
+
}
|
|
1268
|
+
/** A design text set vertically on a page or slot whose text is
|
|
1269
|
+
* horizontal (`VDTDesignTextBlock.vertical`): its lines in the block's own
|
|
1270
|
+
* frame, turned a quarter turn clockwise about the box's top right corner,
|
|
1271
|
+
* each line turned back upright and set vertically. */
|
|
1272
|
+
function renderTurnedDesignText(block) {
|
|
1273
|
+
const vt = block.vertical;
|
|
1274
|
+
const v = { region: vt.region, uprightDigits: vt.uprightDigits, axes: vt.centralBaselines };
|
|
1275
|
+
const clipDecl = block.clip ? 'overflow:hidden;' : '';
|
|
1276
|
+
const trackingDecl = block.letterSpacingPx ? `letter-spacing:${block.letterSpacingPx}px;` : '';
|
|
1277
|
+
const strokeDecl = block.stroke && block.stroke.widthPx > 0
|
|
1278
|
+
? `-webkit-text-stroke:${block.stroke.widthPx}px ${block.stroke.color};` + (block.stroke.hollow ? '-webkit-text-fill-color:transparent;' : '')
|
|
1279
|
+
: '';
|
|
1280
|
+
const hidden = block.artifact ? ' aria-hidden="true"' : '';
|
|
1281
|
+
const { x, y, width, height } = block.bbox;
|
|
1282
|
+
return (`<div${hidden} style="position:absolute;left:${x}px;top:${y}px;width:${width}px;height:${height}px;${clipDecl}${trackingDecl}${strokeDecl}">` +
|
|
1283
|
+
`<div style="position:absolute;left:${width}px;top:0;width:${height}px;height:${width}px;transform:rotate(90deg);transform-origin:0 0;">` +
|
|
1284
|
+
verticalDesignLines(block, v, 0, 0) +
|
|
1285
|
+
`</div></div>`);
|
|
1286
|
+
}
|
|
735
1287
|
function renderDesignRuleBlock(block) {
|
|
736
1288
|
const w = block.direction === 'vertical' ? block.thicknessPx : block.bbox.width;
|
|
737
1289
|
const h = block.direction === 'vertical' ? block.bbox.height : block.thicknessPx;
|
|
@@ -747,8 +1299,11 @@ function renderDesignBoxBlock(block) {
|
|
|
747
1299
|
// A callout stripe on a rounded frame: clipped to the frame's outline.
|
|
748
1300
|
return block.clip ? clipToOutline(html, block.clip) : html;
|
|
749
1301
|
}
|
|
750
|
-
/** Image block (
|
|
751
|
-
*
|
|
1302
|
+
/** Image block (a callout icon, a picture a design draws): `<img>` from
|
|
1303
|
+
* `resourceImageUrl` — with its alternative text when it is content
|
|
1304
|
+
* (`VDTDesignImageBlock.altText`), else `alt=""` and
|
|
1305
|
+
* `role="presentation"` — or a neutral placeholder box when the host
|
|
1306
|
+
* cannot supply the image. */
|
|
752
1307
|
function renderDesignImageBlock(block, options) {
|
|
753
1308
|
const { x, y, width, height } = block.bbox;
|
|
754
1309
|
if (width <= 0 || height <= 0)
|
|
@@ -757,7 +1312,22 @@ function renderDesignImageBlock(block, options) {
|
|
|
757
1312
|
if (url) {
|
|
758
1313
|
const svg = block.imageKind === undefined ? undefined : block.imageKind === 'svg';
|
|
759
1314
|
const filter = options ? inkFilterDecl(options, svg, url) : '';
|
|
760
|
-
|
|
1315
|
+
const alt = block.altText ? `alt="${esc(block.altText)}"` : 'alt="" role="presentation"';
|
|
1316
|
+
if (options?.vertical) {
|
|
1317
|
+
// A picture of a vertical page's flow stands upright on the sheet:
|
|
1318
|
+
// turned back inside its box, which runs `width` down the sheet and
|
|
1319
|
+
// `height` across it (sized for that when `upright`, else fitted
|
|
1320
|
+
// keeping its proportions, as the canvas draws it).
|
|
1321
|
+
const k = block.upright ? 1 : Math.min(height / width, width / height);
|
|
1322
|
+
const dw = block.upright ? height : width * k;
|
|
1323
|
+
const dh = block.upright ? width : height * k;
|
|
1324
|
+
const ox = block.upright ? 0 : (height - dw) / 2;
|
|
1325
|
+
const oy = block.upright ? 0 : (width - dh) / 2;
|
|
1326
|
+
return (`<div style="position:absolute;left:${x}px;top:${y}px;width:${width}px;height:${height}px;">` +
|
|
1327
|
+
`<img src="${esc(url)}" ${alt} style="position:absolute;left:0;top:0;width:${dw}px;height:${dh}px;` +
|
|
1328
|
+
`transform:translate(0,${height}px) rotate(-90deg) translate(${ox}px,${oy}px);transform-origin:0 0;${filter}" /></div>`);
|
|
1329
|
+
}
|
|
1330
|
+
return (`<img src="${esc(url)}" ${alt} style="position:absolute;` +
|
|
761
1331
|
`left:${x}px;top:${y}px;width:${width}px;height:${height}px;${filter}" />`);
|
|
762
1332
|
}
|
|
763
1333
|
return (`<div aria-hidden="true" style="position:absolute;` +
|
|
@@ -767,7 +1337,7 @@ function renderDesignImageBlock(block, options) {
|
|
|
767
1337
|
}
|
|
768
1338
|
function renderDesignBlock(block, options) {
|
|
769
1339
|
if (block.kind === 'text')
|
|
770
|
-
return renderDesignTextBlock(block);
|
|
1340
|
+
return renderDesignTextBlock(block, options);
|
|
771
1341
|
if (block.kind === 'rule')
|
|
772
1342
|
return renderDesignRuleBlock(block);
|
|
773
1343
|
if (block.kind === 'image')
|
|
@@ -790,9 +1360,10 @@ function renderBlockInner(block, options) {
|
|
|
790
1360
|
if (block.resourceBlock)
|
|
791
1361
|
return renderResourceBlockHtml(block, options);
|
|
792
1362
|
const parts = [];
|
|
793
|
-
|
|
1363
|
+
const v = options.vertical;
|
|
1364
|
+
parts.push(v ? renderVerticalBullet(block, v) : renderBullet(block));
|
|
794
1365
|
for (const line of block.lines) {
|
|
795
|
-
parts.push(renderLine(line, block, options.linkTargets));
|
|
1366
|
+
parts.push(v ? renderVerticalLine(line, block, v, options.linkTargets) : renderLine(line, block, options.linkTargets));
|
|
796
1367
|
}
|
|
797
1368
|
return parts.join('');
|
|
798
1369
|
}
|
|
@@ -811,7 +1382,11 @@ function renderBlock(block, options) {
|
|
|
811
1382
|
function renderPageDetailed(page, background, pageOptions, ink = null,
|
|
812
1383
|
/** With cut lines, how far the bleed box lies inside the sheet (px); 0
|
|
813
1384
|
* without them. */
|
|
814
|
-
bleedInset = 0
|
|
1385
|
+
bleedInset = 0,
|
|
1386
|
+
/** The character grid drawn over the type area (`cjk.grid.show`). */
|
|
1387
|
+
gridCells,
|
|
1388
|
+
/** `cjk.region` and `cjk.uprightDigits`, for a vertical page. */
|
|
1389
|
+
verticalRegion, verticalDigits) {
|
|
815
1390
|
const bgDecl = background && background !== 'transparent' ? `background:${background};` : '';
|
|
816
1391
|
// With cut lines nothing the page paints shows past the bleed box, as on
|
|
817
1392
|
// the canvas and in the PDF (EF-133).
|
|
@@ -819,9 +1394,13 @@ bleedInset = 0) {
|
|
|
819
1394
|
// A filter id local to the page and its ink, so every page is
|
|
820
1395
|
// self-contained (a patcher may replace pages one by one) and two
|
|
821
1396
|
// documents on one page never share a filter.
|
|
822
|
-
const
|
|
1397
|
+
const inked = ink
|
|
823
1398
|
? { ...pageOptions, ink: { id: `pt-ink-${ink.hex.replace(/[^0-9a-z]/gi, '')}-${page.index}`, matrix: ink.matrix } }
|
|
824
1399
|
: pageOptions;
|
|
1400
|
+
// A vertical page's flow sets its text down the column.
|
|
1401
|
+
const options = page.flow
|
|
1402
|
+
? { ...inked, vertical: { region: verticalRegion ?? 'mainland', uprightDigits: verticalDigits ?? 2, ...(page.flow.centralBaselines ? { axes: page.flow.centralBaselines } : {}), ...(page.flow.dashAdvances ? { dashes: page.flow.dashAdvances } : {}) } }
|
|
1403
|
+
: inked;
|
|
825
1404
|
const blocks = [];
|
|
826
1405
|
for (const col of page.columns) {
|
|
827
1406
|
for (const block of col.blocks) {
|
|
@@ -838,18 +1417,26 @@ bleedInset = 0) {
|
|
|
838
1417
|
// under the body (a part page's full-bleed background must not cover its
|
|
839
1418
|
// chapter list); header and footer paint on top.
|
|
840
1419
|
const openerHtml = page.openerBand ? renderDesignSlot(page.openerBand, options) : '';
|
|
1420
|
+
// Running heads and folios stay on the sheet, horizontal.
|
|
1421
|
+
const sheetOptions = options.vertical ? { ...options, vertical: undefined } : options;
|
|
841
1422
|
const slotParts = [];
|
|
842
1423
|
if (page.header)
|
|
843
|
-
slotParts.push(renderDesignSlot(page.header,
|
|
1424
|
+
slotParts.push(renderDesignSlot(page.header, sheetOptions));
|
|
844
1425
|
if (page.footer)
|
|
845
|
-
slotParts.push(renderDesignSlot(page.footer,
|
|
1426
|
+
slotParts.push(renderDesignSlot(page.footer, sheetOptions));
|
|
846
1427
|
// Whether or not a picture on the page uses it: a host patching blocks
|
|
847
1428
|
// one by one may bring in an SVG image the first render did not have.
|
|
848
1429
|
const defsHtml = options.ink ? inkFilterDefs(options.ink) : '';
|
|
849
1430
|
// The separators above the footnotes of the columns.
|
|
850
1431
|
const footnoteRulesHtml = footnoteRuleSegments(page).map((r) => `<div class="pt-footnote-rule" style="position:absolute;left:${r.x}px;top:${r.y - r.lineWidthPx / 2}px;width:${r.width}px;height:${r.lineWidthPx}px;background:${r.color};"></div>`).join('');
|
|
851
|
-
const
|
|
852
|
-
const
|
|
1432
|
+
const gridHtml = gridCells ? renderCharacterGridSvg(gridCells, page.flow ? page.height : page.width, page.flow ? page.width : page.height) : '';
|
|
1433
|
+
const decorationHtml = defsHtml + gridHtml + openerHtml + footnoteRulesHtml + slotParts.join('');
|
|
1434
|
+
// A vertical page's flow: one box turned a quarter turn clockwise, its
|
|
1435
|
+
// text lines turned back and set vertically (see `renderVerticalLine`).
|
|
1436
|
+
const flowHtml = gridHtml + openerHtml + blocksHtml + footnoteRulesHtml;
|
|
1437
|
+
const innerHtml = defsHtml + (page.flow
|
|
1438
|
+
? `<div class="pt-flow" style="position:absolute;left:0;top:0;width:${page.height}px;height:${page.width}px;transform:translate(${page.width}px,0) rotate(90deg);transform-origin:0 0;">${flowHtml}</div>`
|
|
1439
|
+
: flowHtml) + slotParts.join('');
|
|
853
1440
|
const outerHtml = `<div class="pt-page" data-page="${page.index}" style="` +
|
|
854
1441
|
`position:relative;` +
|
|
855
1442
|
`width:${page.width}px;` +
|
|
@@ -860,6 +1447,24 @@ bleedInset = 0) {
|
|
|
860
1447
|
`">${innerHtml}</div>`;
|
|
861
1448
|
return { outerHtml, innerHtml, blocks, decorationHtml };
|
|
862
1449
|
}
|
|
1450
|
+
/** The character grid (稿纸) as one SVG path over the page, under the
|
|
1451
|
+
* text (see `cjkGridCells`). */
|
|
1452
|
+
function renderCharacterGridSvg(cells, width, height) {
|
|
1453
|
+
const { cell } = cells;
|
|
1454
|
+
const d = [];
|
|
1455
|
+
const n = (v) => String(Math.round(v * 1000) / 1000);
|
|
1456
|
+
cells.columns.forEach((x0, c) => {
|
|
1457
|
+
const chars = cells.columnChars[c] ?? cells.chars;
|
|
1458
|
+
const w = chars * cell;
|
|
1459
|
+
for (const y of cells.rows) {
|
|
1460
|
+
d.push(`M${n(x0)} ${n(y)}h${n(w)}M${n(x0)} ${n(y + cell)}h${n(w)}`);
|
|
1461
|
+
for (let i = 0; i <= chars; i++)
|
|
1462
|
+
d.push(`M${n(x0 + i * cell)} ${n(y)}v${n(cell)}`);
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1465
|
+
return `<svg class="pt-char-grid" aria-hidden="true" width="${width}" height="${height}" style="position:absolute;left:0;top:0;pointer-events:none;">` +
|
|
1466
|
+
`<path d="${d.join('')}" fill="none" stroke="${CHARACTER_GRID_COLOR}" stroke-width="0.5"/></svg>`;
|
|
1467
|
+
}
|
|
863
1468
|
/**
|
|
864
1469
|
* CSS declarations (a `prop:value;` list) that reset the inherited text
|
|
865
1470
|
* properties to the values the engine measured with. Every line of the
|
|
@@ -889,8 +1494,9 @@ export function renderToHtmlIndexed(doc, options = {}) {
|
|
|
889
1494
|
const gap = options.columnGap ?? 24;
|
|
890
1495
|
const padding = options.padding ?? 24;
|
|
891
1496
|
const background = options.background ?? doc.config.page.backgroundColor.hex ?? 'transparent';
|
|
1497
|
+
// A right-bound book lays its pages out right to left in a row.
|
|
892
1498
|
const docStyle = mode === 'multi'
|
|
893
|
-
? `display:flex;flex-direction:row;gap:${gap}px;align-items:flex-start;padding:${padding}px;box-sizing:border-box;width:max-content;`
|
|
1499
|
+
? `display:flex;flex-direction:${doc.binding === 'right' ? 'row-reverse' : 'row'};gap:${gap}px;align-items:flex-start;padding:${padding}px;box-sizing:border-box;width:max-content;`
|
|
894
1500
|
: `display:flex;flex-direction:column;align-items:center;padding:${padding}px 0;box-sizing:border-box;`;
|
|
895
1501
|
// Single-ink diagrams: SVG pictures are filtered to the ink when the host
|
|
896
1502
|
// asks (its URLs are not recoloured already).
|
|
@@ -921,7 +1527,8 @@ export function renderToHtmlIndexed(doc, options = {}) {
|
|
|
921
1527
|
},
|
|
922
1528
|
}
|
|
923
1529
|
: { ...options, linkTargets };
|
|
924
|
-
const
|
|
1530
|
+
const gridCells = doc.config.cjk?.grid?.show ? cjkGridCells(doc.config, p.contentArea, doc.baselineGrid, p.columns, p.flow) : undefined;
|
|
1531
|
+
const detail = renderPageDetailed(p, background, pageOptions, ink, bleedInset, gridCells, doc.config.cjk?.region, doc.config.cjk?.uprightDigits);
|
|
925
1532
|
pageHtmlParts.push(detail.outerHtml);
|
|
926
1533
|
indexedPages.push({
|
|
927
1534
|
index: p.index,
|
|
@@ -932,8 +1539,11 @@ export function renderToHtmlIndexed(doc, options = {}) {
|
|
|
932
1539
|
decorationHtml: detail.decorationHtml,
|
|
933
1540
|
});
|
|
934
1541
|
}
|
|
935
|
-
// The host's inherited text properties are reset first (EF-96).
|
|
936
|
-
|
|
1542
|
+
// The host's inherited text properties are reset first (EF-96). A
|
|
1543
|
+
// Chinese, Japanese or Korean document declares its language, so the
|
|
1544
|
+
// browser picks the region's glyph forms (see `renderLangOf`).
|
|
1545
|
+
const docLang = renderLangOf(doc.config);
|
|
1546
|
+
const html = `<div class="pt-doc"${docLang ? ` lang="${docLang}"` : ''} data-mode="${mode}" style="${HTML_TEXT_RESET}${docStyle}">` +
|
|
937
1547
|
pageHtmlParts.join('') +
|
|
938
1548
|
`</div>`;
|
|
939
1549
|
return { html, mode, pages: indexedPages };
|