@office-kit/pptx-preview 0.15.0 → 0.17.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 +44 -6
- package/dist/{index-74n14k3Y.d.ts → index-C8dvep3H.d.ts} +44 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/{src-pb3C61GD.js → src-ayE1F9lH.js} +227 -54
- package/dist/src-ayE1F9lH.js.map +1 -0
- package/package.json +3 -3
- package/dist/src-pb3C61GD.js.map +0 -1
package/README.md
CHANGED
|
@@ -42,6 +42,28 @@ const svg = renderSlideToSvg(pres, getSlides(pres)[0]);
|
|
|
42
42
|
// → '<svg …>…</svg>' (text laid out via <foreignObject> — the browser wraps it)
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
Pass `{ textLayout: 'svg', measureText }` to lay text out as pure SVG
|
|
46
|
+
`<text>` instead of `<foreignObject>` (for example when the SVG is shown as an
|
|
47
|
+
`<img>` or sanitized). In that mode each run's font is replaced with one of the
|
|
48
|
+
bundled metric-compatible substitutes (`substituteFamily`: Carlito, Caladea,
|
|
49
|
+
Liberation Sans / Serif / Mono). To keep a family the viewer can load — say
|
|
50
|
+
through `@font-face` rules you embed in the SVG — pass `resolveFamily`, and a
|
|
51
|
+
`measureText` that knows that font's metrics so line breaks match its glyphs
|
|
52
|
+
(in a browser, for example, one that wraps `CanvasRenderingContext2D.measureText`
|
|
53
|
+
once the font has loaded). Return a single family name; the renderer quotes it
|
|
54
|
+
in the SVG when CSS requires that:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { renderSlideToSvg, substituteFamily } from '@office-kit/pptx-preview';
|
|
58
|
+
|
|
59
|
+
const svg = renderSlideToSvg(pres, slide, {
|
|
60
|
+
textLayout: 'svg',
|
|
61
|
+
measureText,
|
|
62
|
+
resolveFamily: (family) =>
|
|
63
|
+
family === 'Lora' || family === 'Inter' ? family : substituteFamily(family),
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
45
67
|
`renderSlideLayoutToSvg(pres, layout, { master })` draws what a slide master
|
|
46
68
|
editor shows behind the placeholders: the layout's background and decorative
|
|
47
69
|
shapes over its master's (the master's are left out when the layout hides
|
|
@@ -95,7 +117,7 @@ const measureText = buildFontkitMeasurer({
|
|
|
95
117
|
});
|
|
96
118
|
|
|
97
119
|
const issues = auditTextLayout(pres, { measureText, reportSoftWraps: true });
|
|
98
|
-
// → [{ kind: 'overflow-y', slideIndex: 2, shapeName: 'Title 1', overflowPx: 14.3, approximate: false }, …]
|
|
120
|
+
// → [{ kind: 'overflow-y', slideIndex: 2, shapeName: 'Title 1', overflowPx: 14.3, shapeOverflowPx: 9.5, lineHeightPx: 52.8, approximate: false }, …]
|
|
99
121
|
```
|
|
100
122
|
|
|
101
123
|
`auditTextLayout` measures every shape's text body — placeholders, text boxes,
|
|
@@ -103,11 +125,20 @@ autoshapes, shapes inside groups — with the same engine the preview renders
|
|
|
103
125
|
with, honouring the effective bodyPr cascade (insets, wrap, anchor, vertical
|
|
104
126
|
text, columns) and `normAutofit` shrinking. It returns one issue per finding:
|
|
105
127
|
|
|
106
|
-
| `kind`
|
|
107
|
-
|
|
|
108
|
-
| `overflow-x`
|
|
109
|
-
| `overflow-y`
|
|
110
|
-
| `soft-wrap`
|
|
128
|
+
| `kind` | Meaning | Extra fields |
|
|
129
|
+
| ----------------- | ----------------------------------------------------------------------------------- | ------------------------------ |
|
|
130
|
+
| `overflow-x` | Text ink escapes the box horizontally (typically `wrap="none"`) | `overflowPx` and the two below |
|
|
131
|
+
| `overflow-y` | Wrapped text is taller than the box (or escapes the top when bottom-anchored) | `overflowPx` and the two below |
|
|
132
|
+
| `soft-wrap` | A paragraph wrapped onto more lines than its authored `<a:br>` count (段落ち) | `paragraphIndex`, `extraLines` |
|
|
133
|
+
| `word-break` | A wrap split a word (Latin / Greek / Cyrillic letters or digits, or a katakana run) | `paragraphIndex`, `text` |
|
|
134
|
+
| `short-last-line` | A wrapped paragraph ends on a line of one or two characters (泣き別れ) | `paragraphIndex`, `text` |
|
|
135
|
+
| `small-font` | The shape draws text below `minFontSizePt`, after autofit shrinking | `sizePt` |
|
|
136
|
+
|
|
137
|
+
`overflowPx` is measured against the text area (the box minus its insets);
|
|
138
|
+
`shapeOverflowPx` is how much ink lies outside the shape itself, both sides
|
|
139
|
+
added (a centre-anchored body spills above and below; 0 while the spill stays
|
|
140
|
+
inside the insets, where nobody sees it); `lineHeightPx` is the
|
|
141
|
+
tallest line's height, about how far one misjudged wrap moves the text.
|
|
111
142
|
|
|
112
143
|
Every issue also carries `slideIndex`, `shapeName`, and `approximate` —
|
|
113
144
|
`true` when a width had to be estimated (the heuristic measurer, or glyphs the
|
|
@@ -124,6 +155,13 @@ Options:
|
|
|
124
155
|
- `reportSoftWraps` — opt into `soft-wrap` issues. Off by default because
|
|
125
156
|
wrapping is normal for body text; turn it on when auditing titles or labels
|
|
126
157
|
meant to stay on one line.
|
|
158
|
+
- `reportBadWraps` — opt into `word-break` and `short-last-line` issues
|
|
159
|
+
(horizontal text only). A word inside a kanji compound cannot be told apart
|
|
160
|
+
from its neighbours, so only the scripts listed above are checked.
|
|
161
|
+
A `word-break` issue is reported once per word; its `text` is the word with
|
|
162
|
+
`|` at each line break. `short-last-line` counts characters, not words, so a
|
|
163
|
+
Latin last line of `to` is reported and one of `the` is not.
|
|
164
|
+
- `minFontSizePt` — report `small-font` for shapes with text below this size.
|
|
127
165
|
|
|
128
166
|
Accuracy: the bundled fonts are metric-compatible with the common default fonts, so
|
|
129
167
|
verdicts for Calibri / Cambria / Arial / Times / Courier decks match real glyph
|
|
@@ -2,8 +2,10 @@ import { BulletStyle, PresentationData, SlideData, SlideLayoutData, SlideShapeDa
|
|
|
2
2
|
|
|
3
3
|
//#region src/text-layout.d.ts
|
|
4
4
|
/** What a measurer needs to size one run. Pixels at 96 DPI; the caller has
|
|
5
|
-
* already applied EMU→px, pt→px and the autofit fontScale. `family` is
|
|
6
|
-
*
|
|
5
|
+
* already applied EMU→px, pt→px and the autofit fontScale. `family` is a
|
|
6
|
+
* single family name, not a CSS list: what `RenderSlideOptions.resolveFamily`
|
|
7
|
+
* returned, by default a bundled substitute (see `substituteFamily`). The
|
|
8
|
+
* text audit passes the authored name instead. */
|
|
7
9
|
interface FontSpec {
|
|
8
10
|
readonly family: string;
|
|
9
11
|
readonly sizePx: number;
|
|
@@ -45,6 +47,17 @@ interface RenderSlideOptions {
|
|
|
45
47
|
/** `false` paints only the slide's own shapes on a transparent surface:
|
|
46
48
|
* no background fill and no master or layout graphics. Defaults to `true`. */
|
|
47
49
|
readonly background?: boolean;
|
|
50
|
+
/** Maps an authored font name (a run's font, a bullet font, or the theme
|
|
51
|
+
* face; `null` when none applies) to the family written to the SVG's
|
|
52
|
+
* `<text font-family>` and handed to `measureText`. Return one family name,
|
|
53
|
+
* unquoted; the renderer quotes it in the SVG when CSS requires that. Only consulted when
|
|
54
|
+
* `textLayout` is `'svg'`; the foreignObject path writes the authored name
|
|
55
|
+
* into a CSS font stack itself. Defaults to `substituteFamily`, which maps
|
|
56
|
+
* every family to one of the bundled metric-compatible substitutes. Keep a
|
|
57
|
+
* family only when the SVG's viewer can load it (for example through an
|
|
58
|
+
* `@font-face` rule the host embeds), and pair it with a `measureText` that
|
|
59
|
+
* knows its metrics so line breaks match the glyphs. */
|
|
60
|
+
readonly resolveFamily?: (family: string | null) => string;
|
|
48
61
|
}
|
|
49
62
|
declare const SANS = "Carlito";
|
|
50
63
|
declare const SERIF = "Caladea";
|
|
@@ -95,14 +108,29 @@ interface IssueBase {
|
|
|
95
108
|
readonly approximate: boolean;
|
|
96
109
|
}
|
|
97
110
|
type TextAuditIssue = (IssueBase & {
|
|
98
|
-
readonly kind: 'overflow-x' | 'overflow-y'; /** How far the text ink escapes the box, in px at 96 DPI. */
|
|
111
|
+
readonly kind: 'overflow-x' | 'overflow-y'; /** How far the text ink escapes the text area (the box minus its insets), in px at 96 DPI. */
|
|
99
112
|
readonly overflowPx: number;
|
|
113
|
+
/** How much ink lies outside the shape itself along that axis, both sides added
|
|
114
|
+
* (a centred body spills half above, half below); 0 while it stays within the insets. */
|
|
115
|
+
readonly shapeOverflowPx: number; /** The tallest line's height in px: about how far one misjudged wrap moves the text. */
|
|
116
|
+
readonly lineHeightPx: number;
|
|
100
117
|
}) | (IssueBase & {
|
|
101
118
|
readonly kind: 'soft-wrap';
|
|
102
119
|
readonly paragraphIndex: number;
|
|
103
120
|
/** Lines beyond the paragraph's authored line count (1 + explicit
|
|
104
121
|
* breaks) — i.e. how many times the text wrapped on its own. */
|
|
105
122
|
readonly extraLines: number;
|
|
123
|
+
}) | (IssueBase & {
|
|
124
|
+
/** A wrap split a word: Latin / Greek / Cyrillic letters or digits, or a katakana run. */readonly kind: 'word-break';
|
|
125
|
+
readonly paragraphIndex: number; /** The split word, with `|` where the line breaks. */
|
|
126
|
+
readonly text: string;
|
|
127
|
+
}) | (IssueBase & {
|
|
128
|
+
/** A wrapped paragraph whose last line holds only a character or two (泣き別れ). */readonly kind: 'short-last-line';
|
|
129
|
+
readonly paragraphIndex: number; /** The text of that last line. */
|
|
130
|
+
readonly text: string;
|
|
131
|
+
}) | (IssueBase & {
|
|
132
|
+
readonly kind: 'small-font'; /** The smallest font size drawn in the shape, after autofit shrinking. */
|
|
133
|
+
readonly sizePt: number;
|
|
106
134
|
});
|
|
107
135
|
interface AuditTextLayoutOptions {
|
|
108
136
|
/** Measurer for run widths / vertical metrics. Defaults to the heuristic
|
|
@@ -116,11 +144,19 @@ interface AuditTextLayoutOptions {
|
|
|
116
144
|
* breaks author (段落ち). Off by default: wrapping is normal for body
|
|
117
145
|
* text, so this is opt-in for single-line-intent content like titles. */
|
|
118
146
|
readonly reportSoftWraps?: boolean;
|
|
147
|
+
/** Also report wraps that split a word (`word-break`) and wrapped
|
|
148
|
+
* paragraphs that end on a line of one or two characters
|
|
149
|
+
* (`short-last-line`). Horizontal text only. */
|
|
150
|
+
readonly reportBadWraps?: boolean;
|
|
151
|
+
/** Report shapes drawing text below this size in points (`small-font`). */
|
|
152
|
+
readonly minFontSizePt?: number;
|
|
119
153
|
}
|
|
120
154
|
/**
|
|
121
155
|
* Measures every text body in the deck and reports text that escapes its box
|
|
122
156
|
* (`overflow-x` / `overflow-y`) and, opt-in, paragraphs that soft-wrap
|
|
123
|
-
* (`soft-wrap`, 段落ち)
|
|
157
|
+
* (`soft-wrap`, 段落ち), wraps that split a word or strand a line of one or
|
|
158
|
+
* two characters (`word-break`, `short-last-line`), and text below a minimum
|
|
159
|
+
* size (`small-font`).
|
|
124
160
|
*
|
|
125
161
|
* Table cell text is not audited (v1 covers shape text bodies, including
|
|
126
162
|
* placeholders and shapes inside groups).
|
|
@@ -226,7 +262,9 @@ interface ShapeAutoFitScaleOptions {
|
|
|
226
262
|
};
|
|
227
263
|
/** Measurer for run widths, defaulting to the heuristic one the renderer
|
|
228
264
|
* uses in a browser. Pass the same measurer the render call uses, or the
|
|
229
|
-
* two disagree about how much text fits.
|
|
265
|
+
* two disagree about how much text fits. Families are resolved with
|
|
266
|
+
* `substituteFamily`, as the foreignObject render does; an svg render
|
|
267
|
+
* with its own `resolveFamily` can measure a different face. */
|
|
230
268
|
readonly measureText?: TextMeasurer;
|
|
231
269
|
}
|
|
232
270
|
/**
|
|
@@ -257,4 +295,4 @@ declare function shapeTextAnchorOffset(pres: PresentationData, shape: SlideShape
|
|
|
257
295
|
declare function textUnderlineStyle(underline: TextFormat['underline'], color: string, includeDecorationColor?: boolean): string;
|
|
258
296
|
//#endregion
|
|
259
297
|
export { substituteFamily as A, RenderSlideOptions as C, TextLayoutMode as D, TIMES as E, TextMeasurer as O, MeasureResult as S, SERIF as T, renderSlideSvg as _, VerticalTextStyle as a, FontSpec as b, TextRectFractions as c, decimalSeparatorOf as d, paragraphNumberLabels as f, renderSlideLayoutSvg as g, auditTextLayout as h, shapeTextAnchorOffset as i, defaultMeasurer as k, resolveTextBodyRect as l, TextAuditIssue as m, ShapeAutoFitScaleOptions as n, textColumnsStyle as o, AuditTextLayoutOptions as p, shapeAutoFitScale as r, verticalTextStyle as s, textUnderlineStyle as t, shapeTextRect as u, renderTextEffectsSvg as v, SANS as w, MONO as x, ARIAL as y };
|
|
260
|
-
//# sourceMappingURL=index-
|
|
298
|
+
//# sourceMappingURL=index-C8dvep3H.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-
|
|
1
|
+
import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-C8dvep3H.js";
|
|
2
2
|
export { ARIAL, type AuditTextLayoutOptions, type FontSpec, MONO, type MeasureResult, type RenderSlideOptions, SANS, SERIF, type ShapeAutoFitScaleOptions, TIMES, type TextAuditIssue, type TextLayoutMode, type TextMeasurer, type TextRectFractions, type VerticalTextStyle, auditTextLayout, decimalSeparatorOf, defaultMeasurer, paragraphNumberLabels, renderSlideLayoutSvg as renderSlideLayoutToSvg, renderSlideSvg as renderSlideToSvg, renderTextEffectsSvg, resolveTextBodyRect, shapeAutoFitScale, shapeTextAnchorOffset, shapeTextRect, substituteFamily, textColumnsStyle, textUnderlineStyle, verticalTextStyle };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-
|
|
1
|
+
import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-ayE1F9lH.js";
|
|
2
2
|
export { ARIAL, MONO, SANS, SERIF, TIMES, auditTextLayout, decimalSeparatorOf, defaultMeasurer, paragraphNumberLabels, renderSlideLayoutSvg as renderSlideLayoutToSvg, renderSlideSvg as renderSlideToSvg, renderTextEffectsSvg, resolveTextBodyRect, shapeAutoFitScale, shapeTextAnchorOffset, shapeTextRect, substituteFamily, textColumnsStyle, textUnderlineStyle, verticalTextStyle };
|
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-
|
|
1
|
+
import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-C8dvep3H.js";
|
|
2
2
|
import { PresentationData, SlideData } from "@office-kit/pptx";
|
|
3
3
|
|
|
4
4
|
//#region src/measure.d.ts
|
package/dist/node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, c as AVG_GLYPH_W_RATIO, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, m as isCjk, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-
|
|
1
|
+
import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, c as AVG_GLYPH_W_RATIO, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, m as isCjk, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-ayE1F9lH.js";
|
|
2
2
|
import { getSlideSize } from "@office-kit/pptx";
|
|
3
3
|
import { Resvg } from "@resvg/resvg-js";
|
|
4
4
|
import * as fontkit from "fontkit";
|