reamkit 1.23.0 → 1.25.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/README.md +22 -11
- package/dist/esm/core/bmp.d.ts +33 -0
- package/dist/esm/core/bmp.js +276 -0
- package/dist/esm/core/converter/facade.d.ts +3 -3
- package/dist/esm/core/converter/facade.js +12 -0
- package/dist/esm/core/converter/ream.d.ts +48 -4
- package/dist/esm/core/converter/ream.js +25 -4
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +54 -0
- package/dist/esm/core/drawingml/chart-geometry.js +3 -2
- package/dist/esm/core/drawingml/diagram/colors.d.ts +52 -0
- package/dist/esm/core/drawingml/diagram/colors.js +125 -0
- package/dist/esm/core/drawingml/diagram/data-model.d.ts +47 -0
- package/dist/esm/core/drawingml/diagram/data-model.js +119 -0
- package/dist/esm/core/drawingml/diagram/layout-engine.d.ts +46 -0
- package/dist/esm/core/drawingml/diagram/layout-engine.js +948 -0
- package/dist/esm/core/drawingml/diagram/run.d.ts +37 -0
- package/dist/esm/core/drawingml/diagram/run.js +50 -0
- package/dist/esm/core/drawingml/diagram/to-drawing.d.ts +16 -0
- package/dist/esm/core/drawingml/diagram/to-drawing.js +86 -0
- package/dist/esm/core/drawingml/preset-geometry.js +116 -6
- package/dist/esm/core/drawingml/text-warp.d.ts +58 -0
- package/dist/esm/core/drawingml/text-warp.js +355 -0
- package/dist/esm/core/drawingml/theme-parser.js +9 -3
- package/dist/esm/core/font/measure.d.ts +12 -0
- package/dist/esm/core/font/measure.js +36 -0
- package/dist/esm/core/images.d.ts +30 -2
- package/dist/esm/core/images.js +121 -5
- package/dist/esm/core/metafile/emf.js +144 -16
- package/dist/esm/core/metafile/picture.d.ts +49 -0
- package/dist/esm/core/metafile/picture.js +70 -1
- package/dist/esm/core/metafile/wmf.js +53 -4
- package/dist/esm/core/ole/escher-blip.js +11 -1
- package/dist/esm/core/outline.d.ts +17 -0
- package/dist/esm/core/outline.js +30 -0
- package/dist/esm/core/style-cascade/resolver.js +1 -0
- package/dist/esm/core/style-cascade/types.d.ts +3 -1
- package/dist/esm/excel/print-model.js +2 -2
- package/dist/esm/excel/sheet-drawing.js +1 -1
- package/dist/esm/excel/sheet-to-flow.d.ts +10 -0
- package/dist/esm/excel/sheet-to-flow.js +30 -3
- package/dist/esm/html/html-writer.js +5 -3
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/layout/page-doc.d.ts +35 -0
- package/dist/esm/layout/page-doc.js +14 -1
- package/dist/esm/layout/styled-layout.js +217 -30
- package/dist/esm/markdown/markdown-writer.d.ts +41 -0
- package/dist/esm/markdown/markdown-writer.js +733 -0
- package/dist/esm/pdf/shading.js +8 -6
- package/dist/esm/pdf/styled-page-emitter.js +62 -4
- package/dist/esm/pdf/vector-graphics.js +1 -1
- package/dist/esm/pdf-reader/annots.d.ts +24 -0
- package/dist/esm/pdf-reader/annots.js +126 -0
- package/dist/esm/pdf-reader/content.d.ts +131 -5
- package/dist/esm/pdf-reader/content.js +169 -12
- package/dist/esm/pdf-reader/display.d.ts +56 -0
- package/dist/esm/pdf-reader/display.js +162 -0
- package/dist/esm/pdf-reader/document.d.ts +36 -1
- package/dist/esm/pdf-reader/document.js +92 -25
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +31 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +94 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +61 -6
- package/dist/esm/pdf-reader/flow-build.js +128 -22
- package/dist/esm/pdf-reader/font.js +185 -4
- package/dist/esm/pdf-reader/image-decode.js +56 -5
- package/dist/esm/pdf-reader/images.d.ts +6 -0
- package/dist/esm/pdf-reader/images.js +25 -5
- package/dist/esm/pdf-reader/jpeg.d.ts +18 -0
- package/dist/esm/pdf-reader/jpeg.js +419 -0
- package/dist/esm/pdf-reader/layout.d.ts +1 -1
- package/dist/esm/pdf-reader/layout.js +221 -32
- package/dist/esm/pdf-reader/pattern-tint.d.ts +17 -0
- package/dist/esm/pdf-reader/pattern-tint.js +181 -0
- package/dist/esm/pdf-reader/reader.d.ts +9 -1
- package/dist/esm/pdf-reader/reader.js +22 -6
- package/dist/esm/pdf-reader/shading.d.ts +14 -0
- package/dist/esm/pdf-reader/shading.js +27 -1
- package/dist/esm/pdf-reader/tagged.js +156 -17
- package/dist/esm/pdf-reader/text.d.ts +13 -1
- package/dist/esm/pdf-reader/text.js +70 -3
- package/dist/esm/pdf-reader/vector.d.ts +25 -1
- package/dist/esm/pdf-reader/vector.js +168 -12
- package/dist/esm/pptx/ppt/ppt-reader.js +95 -27
- package/dist/esm/pptx/ppt/ppt-text.d.ts +41 -0
- package/dist/esm/pptx/ppt/ppt-text.js +327 -37
- package/dist/esm/pptx/pptx-reader.js +90 -10
- package/dist/esm/pptx/slide-parser.d.ts +4 -1
- package/dist/esm/pptx/slide-parser.js +104 -13
- package/dist/esm/pptx/sp-helpers.d.ts +7 -3
- package/dist/esm/pptx/sp-helpers.js +45 -7
- package/dist/esm/pptx/table-style.d.ts +7 -0
- package/dist/esm/pptx/table-style.js +59 -7
- package/dist/esm/svg/svg-writer.js +1 -0
- package/dist/esm/word/document-parser.d.ts +4 -1
- package/dist/esm/word/document-parser.js +4 -1
- package/dist/esm/word/docx-reader.js +26 -13
- package/dist/esm/word/docx-writer.js +15 -1
- package/dist/esm/word/drawing-parser.d.ts +20 -0
- package/dist/esm/word/drawing-parser.js +44 -5
- package/dist/esm/word/table-parser.js +3 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FEATURES } from "../core/ir/features.js";
|
|
2
|
+
import { headingLevelOf } from "../core/outline.js";
|
|
2
3
|
import { detectImageFormat } from "../core/images.js";
|
|
3
4
|
import { PathBuilder, flipTransform, svgPathData } from "../core/vector.js";
|
|
4
5
|
import { EMPTY_STYLE_SHEET, resolveParagraphProperties, resolveRunProperties } from "../core/style-cascade/resolver.js";
|
|
@@ -321,8 +322,8 @@ function emitOneShape(out, shape, ctx) {
|
|
|
321
322
|
}
|
|
322
323
|
function emitParagraph(out, p, ctx) {
|
|
323
324
|
const resolved = resolveParagraphProperties(p.properties, EMPTY_STYLE_SHEET);
|
|
324
|
-
const lvl = resolved
|
|
325
|
-
const tag = lvl !== void 0
|
|
325
|
+
const lvl = headingLevelOf(resolved);
|
|
326
|
+
const tag = lvl !== void 0 ? `h${String(lvl)}` : "p";
|
|
326
327
|
const style = paragraphCss(resolved);
|
|
327
328
|
const dir = resolved.bidi ? " dir=\"rtl\"" : "";
|
|
328
329
|
const anchored = (p.bookmarks ?? []).filter((b) => ctx.referencedAnchors.has(b));
|
|
@@ -653,7 +654,8 @@ var MIME_BY_FORMAT = {
|
|
|
653
654
|
png: "image/png",
|
|
654
655
|
jpeg2000: "image/jp2",
|
|
655
656
|
gif: "image/gif",
|
|
656
|
-
tiff: "image/tiff"
|
|
657
|
+
tiff: "image/tiff",
|
|
658
|
+
bmp: "image/bmp"
|
|
657
659
|
};
|
|
658
660
|
function dataUri(resource, store) {
|
|
659
661
|
if (resource === void 0) return void 0;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -49,6 +49,9 @@ export type { FontProvider, FontRequest, FontAnswer } from './core/fonts/provide
|
|
|
49
49
|
export { svgWriter, writeSvg } from './svg/svg-writer.js';
|
|
50
50
|
export type { SvgWriteOptions } from './svg/svg-writer.js';
|
|
51
51
|
export { htmlWriter, writeHtml } from './html/html-writer.js';
|
|
52
|
+
export { markdownWriter, writeMarkdown } from './markdown/markdown-writer.js';
|
|
53
|
+
export type { StreamFilter, StreamFilters } from './pdf-reader/document.js';
|
|
54
|
+
export type { MarkdownWriteOptions } from './markdown/markdown-writer.js';
|
|
52
55
|
export { docxWriter, writeDocx } from './word/docx-writer.js';
|
|
53
56
|
export { layoutStyledDocument } from './layout/styled-layout.js';
|
|
54
57
|
export type { LaidOutDocument } from './layout/page-doc.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -17,8 +17,9 @@ import { readXlsx, xlsxReader } from "./excel/xlsx-reader.js";
|
|
|
17
17
|
import { NO_FONT, callerFontProvider, chainProviders, embeddedDocFontProvider, isEmbeddingRestricted, localFontProvider, readOs2FsType, remoteFontProvider } from "./core/fonts/provider.js";
|
|
18
18
|
import { docxWriter, writeDocx } from "./word/docx-writer.js";
|
|
19
19
|
import { htmlWriter, writeHtml } from "./html/html-writer.js";
|
|
20
|
+
import { markdownWriter, writeMarkdown } from "./markdown/markdown-writer.js";
|
|
20
21
|
import { svgWriter, writeSvg } from "./svg/svg-writer.js";
|
|
21
22
|
import { createConverter } from "./core/converter/facade.js";
|
|
22
23
|
import { WrongPasswordError, isEncryptedPackage } from "./core/crypto/offcrypto.js";
|
|
23
24
|
import { Ream } from "./core/converter/ream.js";
|
|
24
|
-
export { ConversionLossError, FEATURES, FontRegistry, NO_FONT, Ream, ResourceStore, WrongPasswordError, callerFontProvider, chainProviders, createConverter, createHyphenator, createLanguageHyphenator, docxReader, docxWriter, eighthPtToPt, embeddedDocFontProvider, emuToPt, fetchFontSet, formatLoss, getHyphenator, halfPtToPt, htmlWriter, inchToPt, isEmbeddingRestricted, isEncryptedPackage, layoutStyledDocument, localFontProvider, mmToPt, parseTtf, pt, pxToPt, readDocx, readOs2FsType, readXlsx, remoteFontProvider, renderStyledPdf, resolveFamilyKey, signPdf, splitPatternBundle, subsetTtf, svgWriter, twipsToPt, writeDocx, writeHtml, writeSvg, xlsxReader };
|
|
25
|
+
export { ConversionLossError, FEATURES, FontRegistry, NO_FONT, Ream, ResourceStore, WrongPasswordError, callerFontProvider, chainProviders, createConverter, createHyphenator, createLanguageHyphenator, docxReader, docxWriter, eighthPtToPt, embeddedDocFontProvider, emuToPt, fetchFontSet, formatLoss, getHyphenator, halfPtToPt, htmlWriter, inchToPt, isEmbeddingRestricted, isEncryptedPackage, layoutStyledDocument, localFontProvider, markdownWriter, mmToPt, parseTtf, pt, pxToPt, readDocx, readOs2FsType, readXlsx, remoteFontProvider, renderStyledPdf, resolveFamilyKey, signPdf, splitPatternBundle, subsetTtf, svgWriter, twipsToPt, writeDocx, writeHtml, writeMarkdown, writeSvg, xlsxReader };
|
|
@@ -326,6 +326,32 @@ export interface TextLineItem extends PageItemBase {
|
|
|
326
326
|
* the plot's own tick labels. Absent ⇒ horizontal.
|
|
327
327
|
*/
|
|
328
328
|
readonly rotationDeg?: number;
|
|
329
|
+
/**
|
|
330
|
+
* §20.1.9.10 `a:prstTxWarp` — the line is WordArt: each glyph is placed on
|
|
331
|
+
* its own, bent through the preset's curve and stretched onto the shape's
|
|
332
|
+
* box. Absent ⇒ the line is set flat, one text matrix for the whole of it.
|
|
333
|
+
*/
|
|
334
|
+
readonly warp?: TextLineWarp;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* What placing a warped line needs: the preset, the shape box the warped block
|
|
338
|
+
* is stretched onto, and the box the UN-warped block occupies — both in the
|
|
339
|
+
* page's top-left frame, so a glyph's position in the second maps straight into
|
|
340
|
+
* the first.
|
|
341
|
+
*/
|
|
342
|
+
export interface TextLineWarp {
|
|
343
|
+
readonly preset: string;
|
|
344
|
+
readonly adjust?: number;
|
|
345
|
+
readonly boxX: Pt;
|
|
346
|
+
readonly boxY: Pt;
|
|
347
|
+
readonly boxWidth: Pt;
|
|
348
|
+
readonly boxHeight: Pt;
|
|
349
|
+
/** The un-warped block's left edge and width (its widest line). */
|
|
350
|
+
readonly srcX: Pt;
|
|
351
|
+
readonly srcWidth: Pt;
|
|
352
|
+
/** The un-warped block's ink top and total ink height. */
|
|
353
|
+
readonly srcTop: Pt;
|
|
354
|
+
readonly srcHeight: Pt;
|
|
329
355
|
}
|
|
330
356
|
/** One edge of a table-cell frame; `(x, y)` is the cell box's top-left corner. */
|
|
331
357
|
export interface BorderItem extends PageItemBase {
|
|
@@ -422,6 +448,15 @@ export interface PagePaintPlan {
|
|
|
422
448
|
* per {@link PageItemBase.pictureId}. They paint where the shape pass does.
|
|
423
449
|
*/
|
|
424
450
|
readonly pictures: ReadonlyArray<ReadonlyArray<PageItem>>;
|
|
451
|
+
/**
|
|
452
|
+
* §19.3.1 — the items of a page that STATES its own paint order, each run in
|
|
453
|
+
* the order it paints, the runs sorted by the order they were given. A slide
|
|
454
|
+
* is such a page: its shape tree is a z-order, and a picture standing after a
|
|
455
|
+
* rectangle in it is drawn over that rectangle. Split by kind instead — every
|
|
456
|
+
* image, then every shape — the six logos of 54542_cropped_bitmap.pptx were
|
|
457
|
+
* painted first and the six panels they sit on were painted over them.
|
|
458
|
+
*/
|
|
459
|
+
readonly ordered: ReadonlyArray<ReadonlyArray<PageItem>>;
|
|
425
460
|
}
|
|
426
461
|
export declare function paintPlan(commands: ReadonlyArray<PageItem>): PagePaintPlan;
|
|
427
462
|
export interface LaidOutDocument {
|
|
@@ -7,11 +7,23 @@ function paintPlan(commands) {
|
|
|
7
7
|
const lines = [];
|
|
8
8
|
const pictures = /* @__PURE__ */ new Map();
|
|
9
9
|
const behind = [];
|
|
10
|
+
const ordered = /* @__PURE__ */ new Map();
|
|
11
|
+
const orderOf = /* @__PURE__ */ new Map();
|
|
10
12
|
for (const c of commands) {
|
|
11
13
|
if (c.behind === true) {
|
|
12
14
|
behind.push(c);
|
|
13
15
|
continue;
|
|
14
16
|
}
|
|
17
|
+
if (c.z !== void 0 && c.type !== "fill" && c.type !== "border" && (c.type !== "line" || c.pictureId !== void 0)) {
|
|
18
|
+
const key = c.pictureId !== void 0 ? `p${c.pictureId}` : `i${orderOf.size}`;
|
|
19
|
+
const run = ordered.get(key);
|
|
20
|
+
if (run) run.push(c);
|
|
21
|
+
else {
|
|
22
|
+
ordered.set(key, [c]);
|
|
23
|
+
orderOf.set(key, c.z);
|
|
24
|
+
}
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
15
27
|
if (c.pictureId !== void 0) {
|
|
16
28
|
const group = pictures.get(c.pictureId);
|
|
17
29
|
if (group) group.push(c);
|
|
@@ -44,7 +56,8 @@ function paintPlan(commands) {
|
|
|
44
56
|
borders,
|
|
45
57
|
shapes,
|
|
46
58
|
lines,
|
|
47
|
-
pictures: [...pictures.values()]
|
|
59
|
+
pictures: [...pictures.values()],
|
|
60
|
+
ordered: [...ordered.entries()].sort((a, b) => (orderOf.get(a[0]) ?? 0) - (orderOf.get(b[0]) ?? 0)).map(([, run]) => run)
|
|
48
61
|
};
|
|
49
62
|
}
|
|
50
63
|
function assertNeverPageItem(item) {
|
|
@@ -4,6 +4,7 @@ import { shapeText } from "../core/font/opentype-layout.js";
|
|
|
4
4
|
import { createFontMeasure } from "../core/font/measure.js";
|
|
5
5
|
import { halfPtToPt, pt } from "../core/ir/units.js";
|
|
6
6
|
import { ResourceStore } from "../core/ir/resources.js";
|
|
7
|
+
import { headingLevelOf } from "../core/outline.js";
|
|
7
8
|
import { prepareImage } from "../core/images.js";
|
|
8
9
|
import { PathBuilder, flipTransform } from "../core/vector.js";
|
|
9
10
|
import { isEmf, readEmf } from "../core/metafile/emf.js";
|
|
@@ -1030,8 +1031,8 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1030
1031
|
const fillImage = shape.fill.kind === "picture" && shape.fill.imageResource !== void 0 ? imageResources?.get(shape.fill.imageResource) : void 0;
|
|
1031
1032
|
const fillImageResourceName = fillImage?.resourceName;
|
|
1032
1033
|
const fillImageTile = shape.fill.kind === "picture" && shape.fill.tiled === true && fillImage?.prepared ? shape.fill.tileSizePt ?? {
|
|
1033
|
-
widthPt: fillImage.prepared.widthPx * 72 / 96 * (shape.fill.tileScale?.sx ?? 1),
|
|
1034
|
-
heightPt: fillImage.prepared.heightPx * 72 / 96 * (shape.fill.tileScale?.sy ?? 1)
|
|
1034
|
+
widthPt: fillImage.prepared.widthPx * 72 / (fillImage.prepared.dpiX ?? 96) * (shape.fill.tileScale?.sx ?? 1),
|
|
1035
|
+
heightPt: fillImage.prepared.heightPx * 72 / (fillImage.prepared.dpiY ?? 96) * (shape.fill.tileScale?.sy ?? 1)
|
|
1035
1036
|
} : void 0;
|
|
1036
1037
|
const fillColorHex = shape.fill.kind === "solid" ? shape.fill.colorHex : fillGradient ? gradientToSolid(fillGradient) : void 0;
|
|
1037
1038
|
const stroke = buildStroke(shape.line);
|
|
@@ -1049,8 +1050,10 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1049
1050
|
const textLineGaps = /* @__PURE__ */ new Map();
|
|
1050
1051
|
let textHeightPt = 0;
|
|
1051
1052
|
const vertical = text?.vertical;
|
|
1053
|
+
const upright = text?.upright;
|
|
1054
|
+
const warp = text?.warp;
|
|
1052
1055
|
if (text && text.content.length > 0) {
|
|
1053
|
-
const innerWidth = vertical ? Math.max(1, heightPt - insetTopPt - insetBottomPt) : Math.max(1, widthPt - insetLeftPt - insetRightPt);
|
|
1056
|
+
const innerWidth = warp ? Number.MAX_SAFE_INTEGER : vertical ? Math.max(1, heightPt - insetTopPt - insetBottomPt) : Math.max(1, widthPt - insetLeftPt - insetRightPt);
|
|
1054
1057
|
for (const el of text.content) {
|
|
1055
1058
|
if (el.kind === "image") {
|
|
1056
1059
|
const res = el.image.resource ? imageResources?.get(el.image.resource) : void 0;
|
|
@@ -1143,6 +1146,16 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1143
1146
|
}
|
|
1144
1147
|
}
|
|
1145
1148
|
if (text?.autoFit && !vertical && textLines.length > 0) heightPt = textHeightPt + insetTopPt + insetBottomPt;
|
|
1149
|
+
if (text?.shrinkToFit === true && text.fitToBox !== true && warp === void 0 && textLines.length > 0 && fitPass < MAX_FIT_PASSES) {
|
|
1150
|
+
const innerW = Math.max(1, widthPt - insetLeftPt - insetRightPt);
|
|
1151
|
+
const innerH = Math.max(1, heightPt - insetTopPt - insetBottomPt);
|
|
1152
|
+
const widest = textLines.reduce((a, l) => Math.max(a, l.contentWidthPt), 0);
|
|
1153
|
+
const k = Math.min(1, innerW / Math.max(1, widest), innerH / Math.max(1, textHeightPt));
|
|
1154
|
+
if (Number.isFinite(k) && k > .05 && k < .98) return layoutShapeBlock({
|
|
1155
|
+
...shape,
|
|
1156
|
+
text: scaleTextBody(text, k)
|
|
1157
|
+
}, options, fontResources, imageResources, contentWidth, maxHeight, box, fitPass + 1);
|
|
1158
|
+
}
|
|
1146
1159
|
if (text?.fitToBox === true && textLines.length > 0 && fitPass < MAX_FIT_PASSES) {
|
|
1147
1160
|
const innerW = Math.max(1, widthPt - insetLeftPt - insetRightPt);
|
|
1148
1161
|
const innerH = Math.max(1, heightPt - insetTopPt - insetBottomPt);
|
|
@@ -1166,6 +1179,10 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1166
1179
|
text: scaleTextBody(text, k)
|
|
1167
1180
|
}, options, fontResources, imageResources, contentWidth, maxHeight, box, fitPass + 1);
|
|
1168
1181
|
}
|
|
1182
|
+
const warpInk = warp && textLines.length > 0 ? {
|
|
1183
|
+
above: lineInk(textLines[0]).above,
|
|
1184
|
+
below: lineInk(textLines[textLines.length - 1]).below
|
|
1185
|
+
} : void 0;
|
|
1169
1186
|
const paths = buildShapePaths(shape.geometry, widthPt, heightPt);
|
|
1170
1187
|
const markerPaths = lineEndPaths(paths, shape.line, stroke?.widthPt ?? 0);
|
|
1171
1188
|
const scale = shape.width > 0 ? widthPt / shape.width : 1;
|
|
@@ -1187,6 +1204,7 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1187
1204
|
...markerPaths.length > 0 ? { markerPaths } : {},
|
|
1188
1205
|
...fillImageResourceName ? { fillImageResourceName } : {},
|
|
1189
1206
|
...fillImageTile ? { fillImageTile } : {},
|
|
1207
|
+
...fillImageTile && shape.fill.kind === "picture" && shape.fill.tileFromCentre === true ? { fillImageTileFromCentre: true } : {},
|
|
1190
1208
|
...fillImageResourceName && shape.fill.imageCrop ? { fillImageCrop: shape.fill.imageCrop } : {},
|
|
1191
1209
|
...fillImageResourceName && shape.fill.imageFillRect ? { fillImageRect: shape.fill.imageFillRect } : {},
|
|
1192
1210
|
...fillImageResourceName && shape.fill.duotone ? { fillImageDuotone: shape.fill.duotone } : {},
|
|
@@ -1202,6 +1220,12 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1202
1220
|
spacingBeforePt: pp.spacingBefore ?? 0,
|
|
1203
1221
|
spacingAfterPt: pp.spacingAfter ?? 0,
|
|
1204
1222
|
textLines,
|
|
1223
|
+
...warp && warpInk ? { textWarp: {
|
|
1224
|
+
preset: warp.preset,
|
|
1225
|
+
...warp.adjust !== void 0 ? { adjust: warp.adjust } : {},
|
|
1226
|
+
inkAbovePt: warpInk.above,
|
|
1227
|
+
inkBelowPt: warpInk.below
|
|
1228
|
+
} } : {},
|
|
1205
1229
|
...textCharts.size > 0 ? { textCharts } : {},
|
|
1206
1230
|
...textShapes.size > 0 ? { textShapes } : {},
|
|
1207
1231
|
...textTables.size > 0 ? { textTables } : {},
|
|
@@ -1213,6 +1237,7 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
1213
1237
|
insetTopPt,
|
|
1214
1238
|
insetBottomPt,
|
|
1215
1239
|
anchor: text?.anchor ?? "t",
|
|
1240
|
+
...upright ? { upright } : {},
|
|
1216
1241
|
...vertical ? { vertical } : {},
|
|
1217
1242
|
...shape.altText ? { altText: shape.altText } : {},
|
|
1218
1243
|
...shape.float ? { float: shape.float } : {}
|
|
@@ -1863,6 +1888,9 @@ function chartPageItems(laid, x, bottomYUp, pageHeight, structId) {
|
|
|
1863
1888
|
var nextPictureId = 1;
|
|
1864
1889
|
function emitShapeText(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
1865
1890
|
if (sh.textLines.length === 0) return;
|
|
1891
|
+
const turnDeg = sh.upright === true || sh.flipH || sh.flipV ? 0 : -(sh.rotation60k || 0) / 6e4;
|
|
1892
|
+
const centreX = x + sh.widthPt / 2;
|
|
1893
|
+
const centreY = bottomYUp + sh.heightPt / 2;
|
|
1866
1894
|
if (sh.vertical) {
|
|
1867
1895
|
const up = sh.vertical === "vert270";
|
|
1868
1896
|
const innerHeight = Math.max(1, sh.heightPt - sh.insetTopPt - sh.insetBottomPt);
|
|
@@ -1872,18 +1900,23 @@ function emitShapeText(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
|
1872
1900
|
const lineOffset = alignmentOffset(line.resolved.alignment, line.contentWidthPt, innerHeight);
|
|
1873
1901
|
const off = lineBaselineOffset(line, line.resolved);
|
|
1874
1902
|
const baselineAcross = up ? across + h - off : across + off;
|
|
1903
|
+
const origin = spinAboutCentre(up ? x + baselineAcross : x + sh.widthPt - baselineAcross, up ? bottomYUp + sh.insetBottomPt + lineOffset : bottomYUp + sh.heightPt - sh.insetTopPt - lineOffset, centreX, centreY, turnDeg);
|
|
1875
1904
|
sink.push({
|
|
1876
1905
|
type: "line",
|
|
1877
1906
|
line,
|
|
1878
|
-
originX: pt(
|
|
1879
|
-
baselineY: pt(pageHeight -
|
|
1880
|
-
rotationDeg: up ? 90 : -90,
|
|
1907
|
+
originX: pt(origin.x),
|
|
1908
|
+
baselineY: pt(pageHeight - origin.y),
|
|
1909
|
+
rotationDeg: (up ? 90 : -90) + turnDeg,
|
|
1881
1910
|
...figId !== void 0 ? { structId: figId } : {}
|
|
1882
1911
|
});
|
|
1883
1912
|
across += h;
|
|
1884
1913
|
}
|
|
1885
1914
|
return;
|
|
1886
1915
|
}
|
|
1916
|
+
if (sh.textWarp) {
|
|
1917
|
+
emitWarpedText(sh, sh.textWarp, x, bottomYUp, sink, pageHeight, figId);
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1887
1920
|
const shapeTop = bottomYUp + sh.heightPt;
|
|
1888
1921
|
const innerWidth = Math.max(1, sh.widthPt - sh.insetLeftPt - sh.insetRightPt);
|
|
1889
1922
|
let textY;
|
|
@@ -1913,16 +1946,102 @@ function emitShapeText(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
|
1913
1946
|
return;
|
|
1914
1947
|
}
|
|
1915
1948
|
const indentLeft = line.resolved.indentLeft + (line.firstLine ? line.resolved.indentFirstLine : 0);
|
|
1949
|
+
const origin = spinAboutCentre(x + sh.insetLeftPt + indentLeft + lineOffset, textY + lineBaselineOffset(line, line.resolved), centreX, centreY, turnDeg);
|
|
1916
1950
|
sink.push({
|
|
1917
1951
|
type: "line",
|
|
1918
1952
|
line,
|
|
1919
|
-
originX: pt(x
|
|
1920
|
-
baselineY: pt(pageHeight -
|
|
1953
|
+
originX: pt(origin.x),
|
|
1954
|
+
baselineY: pt(pageHeight - origin.y),
|
|
1955
|
+
...turnDeg !== 0 ? { rotationDeg: turnDeg } : {},
|
|
1921
1956
|
...figId !== void 0 ? { structId: figId } : {}
|
|
1922
1957
|
});
|
|
1923
1958
|
textY -= sh.textLineGaps?.get(i) ?? 0;
|
|
1924
1959
|
});
|
|
1925
1960
|
}
|
|
1961
|
+
/**
|
|
1962
|
+
* A point spun about another, counter-clockwise in the y-up page frame.
|
|
1963
|
+
*
|
|
1964
|
+
* @param px The point's x.
|
|
1965
|
+
* @param py The point's y (y-up).
|
|
1966
|
+
* @param cx The centre's x.
|
|
1967
|
+
* @param cy The centre's y (y-up).
|
|
1968
|
+
* @param deg How far to turn, counter-clockwise; zero returns the point.
|
|
1969
|
+
* @returns The turned point.
|
|
1970
|
+
*/
|
|
1971
|
+
function spinAboutCentre(px, py, cx, cy, deg) {
|
|
1972
|
+
if (deg === 0) return {
|
|
1973
|
+
x: px,
|
|
1974
|
+
y: py
|
|
1975
|
+
};
|
|
1976
|
+
const rad = deg * Math.PI / 180;
|
|
1977
|
+
const cos = Math.cos(rad);
|
|
1978
|
+
const sin = Math.sin(rad);
|
|
1979
|
+
const dx = px - cx;
|
|
1980
|
+
const dy = py - cy;
|
|
1981
|
+
return {
|
|
1982
|
+
x: cx + dx * cos - dy * sin,
|
|
1983
|
+
y: cy + dx * sin + dy * cos
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
/**
|
|
1987
|
+
* §20.1.9.10 — place a WordArt body's lines in the block's own frame and hand
|
|
1988
|
+
* each one the warp that maps that frame onto the shape's box.
|
|
1989
|
+
*
|
|
1990
|
+
* The block is laid out flat: its lines stack by their own heights, each
|
|
1991
|
+
* aligned within the widest of them, and its ink starts at the box's top-left
|
|
1992
|
+
* corner. Nothing here bends anything — the emitter does that, glyph by glyph,
|
|
1993
|
+
* from the two frames this records.
|
|
1994
|
+
*
|
|
1995
|
+
* @param sh The laid-out shape.
|
|
1996
|
+
* @param warp The shape's warp and the block's ink reach.
|
|
1997
|
+
* @param x The shape's left edge on the page.
|
|
1998
|
+
* @param bottomYUp The shape's bottom edge, y-up from the page's bottom.
|
|
1999
|
+
* @param sink Where the line items are pushed.
|
|
2000
|
+
* @param pageHeight The page's height, for the y-up ⇄ top-left conversion.
|
|
2001
|
+
* @param figId The tagged-PDF Figure this text belongs to, when it has one.
|
|
2002
|
+
*/
|
|
2003
|
+
function emitWarpedText(sh, warp, x, bottomYUp, sink, pageHeight, figId) {
|
|
2004
|
+
const boxX = x + sh.insetLeftPt;
|
|
2005
|
+
const boxY = pageHeight - (bottomYUp + sh.heightPt) + sh.insetTopPt;
|
|
2006
|
+
const boxWidth = Math.max(1, sh.widthPt - sh.insetLeftPt - sh.insetRightPt);
|
|
2007
|
+
const boxHeight = Math.max(1, sh.heightPt - sh.insetTopPt - sh.insetBottomPt);
|
|
2008
|
+
const srcWidth = Math.max(1, ...sh.textLines.map((l) => l.contentWidthPt));
|
|
2009
|
+
const baselines = [];
|
|
2010
|
+
let top = 0;
|
|
2011
|
+
sh.textLines.forEach((line, i) => {
|
|
2012
|
+
const h = computeLineHeight(line, line.resolved);
|
|
2013
|
+
baselines.push(top + h - lineBaselineOffset(line, line.resolved));
|
|
2014
|
+
top += h + (sh.textLineGaps?.get(i) ?? 0);
|
|
2015
|
+
});
|
|
2016
|
+
const first = baselines[0] ?? 0;
|
|
2017
|
+
const last = baselines[baselines.length - 1] ?? 0;
|
|
2018
|
+
const srcTop = boxY;
|
|
2019
|
+
const srcHeight = Math.max(1, last - first + warp.inkAbovePt + warp.inkBelowPt);
|
|
2020
|
+
const shift = srcTop + warp.inkAbovePt - first;
|
|
2021
|
+
sh.textLines.forEach((line, i) => {
|
|
2022
|
+
if (sh.textCharts?.has(i) === true || sh.textShapes?.has(i) === true) return;
|
|
2023
|
+
if (sh.textTables?.has(i) === true) return;
|
|
2024
|
+
sink.push({
|
|
2025
|
+
type: "line",
|
|
2026
|
+
line,
|
|
2027
|
+
originX: pt(boxX + alignmentOffset(line.resolved.alignment, line.contentWidthPt, srcWidth)),
|
|
2028
|
+
baselineY: pt(baselines[i] + shift),
|
|
2029
|
+
warp: {
|
|
2030
|
+
preset: warp.preset,
|
|
2031
|
+
...warp.adjust !== void 0 ? { adjust: warp.adjust } : {},
|
|
2032
|
+
boxX: pt(boxX),
|
|
2033
|
+
boxY: pt(boxY),
|
|
2034
|
+
boxWidth: pt(boxWidth),
|
|
2035
|
+
boxHeight: pt(boxHeight),
|
|
2036
|
+
srcX: pt(boxX),
|
|
2037
|
+
srcWidth: pt(srcWidth),
|
|
2038
|
+
srcTop: pt(srcTop),
|
|
2039
|
+
srcHeight: pt(srcHeight)
|
|
2040
|
+
},
|
|
2041
|
+
...figId !== void 0 ? { structId: figId } : {}
|
|
2042
|
+
});
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
1926
2045
|
/** The page a table is being drawn onto, as a cell's floats need to see it. */
|
|
1927
2046
|
function cellAnchorCtx(asm) {
|
|
1928
2047
|
return {
|
|
@@ -1962,6 +2081,19 @@ function emitCellFloat(cf, ctx, frame) {
|
|
|
1962
2081
|
if (float.wrap !== "none") ctx.exclude(float, x, topYUp, cf.block.widthPt, cf.block.heightPt);
|
|
1963
2082
|
}
|
|
1964
2083
|
function emitShapeItems(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
2084
|
+
const castsUnderPicture = sh.fillImageResourceName !== void 0 ? sh.shadow : void 0;
|
|
2085
|
+
const shadowedFill = castsUnderPicture !== void 0;
|
|
2086
|
+
const group = shadowedFill ? { pictureId: nextPictureId++ } : {};
|
|
2087
|
+
if (castsUnderPicture) sink.push({
|
|
2088
|
+
type: "shape",
|
|
2089
|
+
shape: {
|
|
2090
|
+
paths: sh.paths,
|
|
2091
|
+
shadow: castsUnderPicture,
|
|
2092
|
+
transform: flipTransform(buildShapeTransform(x, bottomYUp, sh.widthPt, sh.heightPt, sh.rotation60k, sh.flipH, sh.flipV), pageHeight)
|
|
2093
|
+
},
|
|
2094
|
+
...group,
|
|
2095
|
+
...figId !== void 0 ? { structId: figId } : {}
|
|
2096
|
+
});
|
|
1965
2097
|
if (sh.fillImageResourceName) {
|
|
1966
2098
|
const clip = {
|
|
1967
2099
|
paths: sh.paths,
|
|
@@ -1974,12 +2106,13 @@ function emitShapeItems(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
|
1974
2106
|
y: pageHeight - (bottomYUp + sh.heightPt),
|
|
1975
2107
|
width: sh.widthPt,
|
|
1976
2108
|
height: sh.heightPt
|
|
1977
|
-
})) {
|
|
2109
|
+
}, sh.fillImageTileFromCentre === true)) {
|
|
1978
2110
|
if (item.type !== "image") continue;
|
|
1979
2111
|
sink.push({
|
|
1980
2112
|
...item,
|
|
1981
2113
|
clip,
|
|
1982
2114
|
...fig,
|
|
2115
|
+
...group,
|
|
1983
2116
|
...sh.fillAlpha !== void 0 ? { alpha: sh.fillAlpha } : {}
|
|
1984
2117
|
});
|
|
1985
2118
|
}
|
|
@@ -2000,7 +2133,8 @@ function emitShapeItems(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
|
2000
2133
|
...sh.fillAlpha !== void 0 ? { alpha: sh.fillAlpha } : {},
|
|
2001
2134
|
...sh.fillImageDuotone ? { duotone: sh.fillImageDuotone } : {},
|
|
2002
2135
|
clip,
|
|
2003
|
-
...fig
|
|
2136
|
+
...fig,
|
|
2137
|
+
...group
|
|
2004
2138
|
});
|
|
2005
2139
|
}
|
|
2006
2140
|
}
|
|
@@ -2021,9 +2155,10 @@ function emitShapeItems(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
|
2021
2155
|
...sh.fillGradient ? { fillGradient: sh.fillGradient } : {},
|
|
2022
2156
|
...sh.fillAlpha !== void 0 ? { fillAlpha: sh.fillAlpha } : {},
|
|
2023
2157
|
...sh.stroke ? { stroke: sh.stroke } : {},
|
|
2024
|
-
...sh.shadow ? { shadow: sh.shadow } : {},
|
|
2158
|
+
...sh.shadow && !shadowedFill ? { shadow: sh.shadow } : {},
|
|
2025
2159
|
transform: flipTransform(buildShapeTransform(x, bottomYUp, sh.widthPt, sh.heightPt, sh.rotation60k, sh.flipH, sh.flipV), pageHeight)
|
|
2026
2160
|
},
|
|
2161
|
+
...group,
|
|
2027
2162
|
...figId !== void 0 ? { structId: figId } : {}
|
|
2028
2163
|
});
|
|
2029
2164
|
for (const child of sh.children ?? []) emitShapeItems(child.laid, x + child.xPt, bottomYUp + sh.heightPt - child.yPt - child.laid.heightPt, sink, pageHeight, figId);
|
|
@@ -3647,6 +3782,30 @@ function alignmentOffset(alignment, lineWidth, available) {
|
|
|
3647
3782
|
return 0;
|
|
3648
3783
|
}
|
|
3649
3784
|
/**
|
|
3785
|
+
* How far a line's INK reaches either side of its baseline — the union of its
|
|
3786
|
+
* glyphs' own bounding boxes, not the line box its font metrics describe. Only
|
|
3787
|
+
* WordArt needs this: it stretches the marks it draws onto its shape, and the
|
|
3788
|
+
* empty band an ascender or descender reserves is not one of them.
|
|
3789
|
+
*
|
|
3790
|
+
* @param line The laid-out line.
|
|
3791
|
+
* @returns Points above the baseline the ink rises, and below it that it drops.
|
|
3792
|
+
*/
|
|
3793
|
+
function lineInk(line) {
|
|
3794
|
+
let above = 0;
|
|
3795
|
+
let below = 0;
|
|
3796
|
+
for (const tok of line.tokens) {
|
|
3797
|
+
if (tok.kind !== "text" || tok.isSpace) continue;
|
|
3798
|
+
const ink = tok.font.measure.textInkPt(tok.text, tok.fontSizePt);
|
|
3799
|
+
const rise = tok.risePt ?? 0;
|
|
3800
|
+
above = Math.max(above, ink.above + rise);
|
|
3801
|
+
below = Math.max(below, ink.below - rise);
|
|
3802
|
+
}
|
|
3803
|
+
return {
|
|
3804
|
+
above,
|
|
3805
|
+
below
|
|
3806
|
+
};
|
|
3807
|
+
}
|
|
3808
|
+
/**
|
|
3650
3809
|
* §17.4.85 `w:vMerge` — a vertical merge is ONE cell, so its continuation rows
|
|
3651
3810
|
* are painted with the START cell's shading. Word writes the fill on the cell
|
|
3652
3811
|
* that opens the merge and nothing on the rest; painting only what is written,
|
|
@@ -4066,7 +4225,9 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
4066
4225
|
const padRightBase = cellMar?.right ?? tableMar?.right ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
4067
4226
|
const padLeftPt = padLeftBase + (cell.properties.icon ? CF_ICON_GUTTER_PT : 0);
|
|
4068
4227
|
const padRightPt = padRightBase;
|
|
4228
|
+
const turned = mergeRole === "middle" || mergeRole === "end" ? void 0 : cell.properties.textDirection;
|
|
4069
4229
|
const innerWidth = Math.max(1, widthPt - padLeftPt - padRightPt);
|
|
4230
|
+
const measureWidth = turned ? NO_WRAP_MEASURE_WIDTH : innerWidth;
|
|
4070
4231
|
const lines = [];
|
|
4071
4232
|
const nestedTables = [];
|
|
4072
4233
|
const cellShapes = [];
|
|
@@ -4085,7 +4246,7 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
4085
4246
|
if (mergeRole !== "middle" && mergeRole !== "end") {
|
|
4086
4247
|
for (const el of cell.content) if (el.kind === "paragraph") {
|
|
4087
4248
|
const noWrap = cell.properties.noWrap === true;
|
|
4088
|
-
const block = layoutParagraphBlock(el.paragraph, options, fontResources, imageResources, noWrap ? NO_WRAP_MEASURE_WIDTH :
|
|
4249
|
+
const block = layoutParagraphBlock(el.paragraph, options, fontResources, imageResources, noWrap ? NO_WRAP_MEASURE_WIDTH : measureWidth);
|
|
4089
4250
|
const cutAt = widthPt - padLeftPt;
|
|
4090
4251
|
if (noWrap && (block.lines[0]?.contentWidthPt ?? 0) > cutAt) clipped = true;
|
|
4091
4252
|
const keep = noWrap ? clipLineToWidth(block.lines, cutAt, cell.properties.hashOnOverflow === true) : block.lines;
|
|
@@ -4136,7 +4297,9 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
4136
4297
|
}
|
|
4137
4298
|
const colEnd = colStart + colSpan - 1;
|
|
4138
4299
|
const borders = resolveCellBorders(cell.properties.borders, tableProps.borders, rowIdx, colStart, colEnd, rowCount, colCount, mergeRole, leftNeighborBorders, aboveNeighborBorders);
|
|
4139
|
-
const
|
|
4300
|
+
const alongPt = turned ? lines.reduce((a, l) => Math.max(a, l.contentWidthPt), 0) : 0;
|
|
4301
|
+
const heightPt = turned ? alongPt : contentHeightPt;
|
|
4302
|
+
const totalHeightPt = mergeRole === "middle" || mergeRole === "end" ? 0 : padTopPt + heightPt + padBottomPt;
|
|
4140
4303
|
return {
|
|
4141
4304
|
widthPt,
|
|
4142
4305
|
padTopPt,
|
|
@@ -4153,8 +4316,9 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
4153
4316
|
...nestedTables.length > 0 ? { nestedTables } : {},
|
|
4154
4317
|
...cellShapes.length > 0 ? { shapes: cellShapes } : {},
|
|
4155
4318
|
...cellFloats.length > 0 ? { floats: cellFloats } : {},
|
|
4156
|
-
contentHeightPt,
|
|
4319
|
+
contentHeightPt: heightPt,
|
|
4157
4320
|
totalHeightPt,
|
|
4321
|
+
...turned ? { textDirection: turned } : {},
|
|
4158
4322
|
...cell.properties.verticalAlign ? { verticalAlign: cell.properties.verticalAlign } : {},
|
|
4159
4323
|
colStart,
|
|
4160
4324
|
colSpan,
|
|
@@ -4209,16 +4373,8 @@ function resolveCellBorders(cellBorders, tableBorders, rowIdx, colStart, colEnd,
|
|
|
4209
4373
|
return out;
|
|
4210
4374
|
}
|
|
4211
4375
|
function paragraphStructType(resolved) {
|
|
4212
|
-
const lvl = resolved
|
|
4213
|
-
|
|
4214
|
-
return headingFromStyleId(resolved.styleId) ?? "P";
|
|
4215
|
-
}
|
|
4216
|
-
function headingFromStyleId(styleId) {
|
|
4217
|
-
if (!styleId) return null;
|
|
4218
|
-
const m = /^Heading\s*([1-9])$/i.exec(styleId);
|
|
4219
|
-
if (m) return `H${Math.min(Number(m[1]), 6)}`;
|
|
4220
|
-
if (/^(Title|Subtitle)$/i.test(styleId)) return "H1";
|
|
4221
|
-
return null;
|
|
4376
|
+
const lvl = headingLevelOf(resolved);
|
|
4377
|
+
return lvl !== void 0 ? `H${String(lvl)}` : "P";
|
|
4222
4378
|
}
|
|
4223
4379
|
function dominantParagraphLang(lines) {
|
|
4224
4380
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -4807,16 +4963,24 @@ var PageAssembler = class PageAssembler {
|
|
|
4807
4963
|
* one: stretched over the page it is a blur, and its 128 pixels are 96 points
|
|
4808
4964
|
* at the resolution Office measures a picture in.
|
|
4809
4965
|
*/
|
|
4810
|
-
static tileItems = (resourceName, natural, box) => {
|
|
4966
|
+
static tileItems = (resourceName, natural, box, fromCentre = false) => {
|
|
4811
4967
|
const tw = Math.max(1, natural.widthPt);
|
|
4812
4968
|
const th = Math.max(1, natural.heightPt);
|
|
4813
|
-
const
|
|
4814
|
-
|
|
4969
|
+
const first = (start, span, step) => {
|
|
4970
|
+
if (!fromCentre) return start;
|
|
4971
|
+
let at = start + span / 2 - step / 2;
|
|
4972
|
+
while (at > start) at -= step;
|
|
4973
|
+
return at;
|
|
4974
|
+
};
|
|
4975
|
+
const x0 = first(box.x, box.width, tw);
|
|
4976
|
+
const y0 = first(box.y, box.height, th);
|
|
4977
|
+
const cols = Math.min(200, Math.max(1, Math.ceil((box.x + box.width - x0) / tw)));
|
|
4978
|
+
const rows = Math.min(200, Math.max(1, Math.ceil((box.y + box.height - y0) / th)));
|
|
4815
4979
|
const out = [];
|
|
4816
4980
|
for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) out.push({
|
|
4817
4981
|
type: "image",
|
|
4818
|
-
x: pt(
|
|
4819
|
-
y: pt(
|
|
4982
|
+
x: pt(x0 + c * tw),
|
|
4983
|
+
y: pt(y0 + r * th),
|
|
4820
4984
|
width: pt(tw),
|
|
4821
4985
|
height: pt(th),
|
|
4822
4986
|
imageResourceName: resourceName
|
|
@@ -5191,7 +5355,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
|
|
|
5191
5355
|
const chunks = !row.cantSplit && row.heightPt > room && asm.colHasContent() && room > 0 ? splitRowIntoChunks(row, room, page) : row.heightPt > page ? splitRowIntoChunks(row, page) : [row];
|
|
5192
5356
|
for (let ci = 0; ci < chunks.length; ci++) {
|
|
5193
5357
|
const chunk = chunks[ci];
|
|
5194
|
-
const forcedBreak = ci === 0 && row.breakBefore && !isLeadingHeader && asm.
|
|
5358
|
+
const forcedBreak = ci === 0 && row.breakBefore && !isLeadingHeader && asm.pageHasContent();
|
|
5195
5359
|
const overflow = asm.cursorY - chunk.heightPt < asm.bottomLimit() && asm.colHasContent();
|
|
5196
5360
|
if (forcedBreak || overflow) {
|
|
5197
5361
|
if (forcedBreak) asm.flushPage();
|
|
@@ -5484,6 +5648,29 @@ function emitRowChunk(out, row, marginLeft, cursorY, pageHeight, colCount, cellS
|
|
|
5484
5648
|
});
|
|
5485
5649
|
}
|
|
5486
5650
|
};
|
|
5651
|
+
if (cell.textDirection !== void 0) {
|
|
5652
|
+
const up = cell.textDirection === "vert270";
|
|
5653
|
+
const along = Math.max(1, boxHeightPt - cell.padTopPt - cell.padBottomPt);
|
|
5654
|
+
const cellBottomYUp = rowTop - boxHeightPt;
|
|
5655
|
+
let across = cell.padLeftPt;
|
|
5656
|
+
for (const line of cell.lines) {
|
|
5657
|
+
const h = computeLineHeight(line, line.resolved);
|
|
5658
|
+
const lineOffset = alignmentOffset(line.resolved.alignment, line.contentWidthPt, along);
|
|
5659
|
+
const off = lineBaselineOffset(line, line.resolved);
|
|
5660
|
+
const baselineAcross = up ? across + h - off : across + off;
|
|
5661
|
+
out.push({
|
|
5662
|
+
type: "line",
|
|
5663
|
+
line,
|
|
5664
|
+
originX: pt(up ? cellX + baselineAcross : cellX + cell.widthPt - baselineAcross),
|
|
5665
|
+
baselineY: pt(pageHeight - (up ? cellBottomYUp + cell.padBottomPt + lineOffset : rowTop - cell.padTopPt - lineOffset)),
|
|
5666
|
+
rotationDeg: up ? 90 : -90,
|
|
5667
|
+
...structId !== void 0 ? { structId } : {}
|
|
5668
|
+
});
|
|
5669
|
+
across += h;
|
|
5670
|
+
}
|
|
5671
|
+
drawNestedBefore(cell.lines.length);
|
|
5672
|
+
continue;
|
|
5673
|
+
}
|
|
5487
5674
|
for (const [lineIdx, line] of cell.lines.entries()) {
|
|
5488
5675
|
drawNestedBefore(lineIdx);
|
|
5489
5676
|
textY -= cell.lineGaps?.get(lineIdx) ?? 0;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DocumentWriter, WriteResult } from '../core/ir/adapters.js';
|
|
2
|
+
import { FlowDoc } from '../core/ir/flow.js';
|
|
3
|
+
/** Options for {@link writeMarkdown}. */
|
|
4
|
+
export interface MarkdownWriteOptions {
|
|
5
|
+
/**
|
|
6
|
+
* How a picture reaches the output. `'dataUri'` (the default) inlines the
|
|
7
|
+
* bytes as a `data:` URI, keeping the single-blob {@link WriteResult}
|
|
8
|
+
* contract and the zero-I/O promise; `'link'` emits a relative
|
|
9
|
+
* `./media/…` path and records that the bytes were not written anywhere;
|
|
10
|
+
* `'drop'` omits pictures entirely.
|
|
11
|
+
*/
|
|
12
|
+
readonly images?: 'dataUri' | 'link' | 'drop';
|
|
13
|
+
/**
|
|
14
|
+
* What a page break becomes. `'drop'` (the default) leaves it out and
|
|
15
|
+
* reports it: a paginated document breaks its pages wherever the layout
|
|
16
|
+
* needs to, and a rule at every one of them would litter the text. `'rule'`
|
|
17
|
+
* writes a `---` thematic break instead, which is what a SLIDE DECK wants —
|
|
18
|
+
* the `.pptx` and `.ppt` readers mark each slide boundary with a page break,
|
|
19
|
+
* and it is the only structure a deck has.
|
|
20
|
+
*/
|
|
21
|
+
readonly pageBreaks?: 'rule' | 'drop';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Render a {@link FlowDoc} to GitHub-Flavored Markdown (ir-design §7).
|
|
25
|
+
*
|
|
26
|
+
* A flow medium: no pagination, no layout engine and no fonts, so this is a
|
|
27
|
+
* pure, zero-I/O transform. Markdown says far less than the document model
|
|
28
|
+
* does — alignment, indents, colour, font metrics, tab stops and page
|
|
29
|
+
* geometry have no expression at all — so those are dropped and reported as
|
|
30
|
+
* {@link Loss} entries, deduplicated so one recurring omission reports once.
|
|
31
|
+
*
|
|
32
|
+
* @param flow The format-neutral interlayer document tree.
|
|
33
|
+
* @param options Picture handling; see {@link MarkdownWriteOptions}.
|
|
34
|
+
* @returns The encoded Markdown bytes plus the recorded {@link Loss} list.
|
|
35
|
+
*/
|
|
36
|
+
export declare function writeMarkdown(flow: FlowDoc, options?: MarkdownWriteOptions): WriteResult;
|
|
37
|
+
/**
|
|
38
|
+
* The flow-medium {@link DocumentWriter} adapter (id `'md'`), wrapping
|
|
39
|
+
* {@link writeMarkdown}, with the set of {@link FEATURES} it renders.
|
|
40
|
+
*/
|
|
41
|
+
export declare const markdownWriter: DocumentWriter<FlowDoc>;
|