@openpresentation/opf-pptx 0.2.1 → 0.3.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 +3 -1
- package/dist/index.js +31 -5
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -121,7 +121,9 @@ Pass the same `textMeasurement` provider used by preview and pagination to `toPp
|
|
|
121
121
|
|
|
122
122
|
PptxGenJS is pinned to 4.0.1. Its unused `image-size` dependency remains flagged by npm audit; tested OPF operations run with that parser blocked. See [dependency reachability and regression coverage](DEPENDENCY-NOTES.md).
|
|
123
123
|
|
|
124
|
-
### Native table fitting
|
|
124
|
+
### Native table fitting
|
|
125
|
+
|
|
126
|
+
Core 0.5.0 accepts `TextRun[]` cells and headers. The 0.3.0 exporter preserves their resolved fonts, emphasis, color/alpha, hyperlinks, script positions and explicit line breaks as editable native runs. It measures rich content before export without inserting measured soft wraps. These changes are not in 0.2.1; version 0.3.0 requires core 0.5.0 and renderer 0.3.0. Native table import still flattens rich runs to strings, and native PowerPoint rendering remains unverified.
|
|
125
127
|
|
|
126
128
|
The development exporter measures every cell with the same `textMeasurement` provider, font roles and effective nested `minFontSize` used by the SVG preview. Native table cells retain the original strings and values as text, with matching fitted sizes, line spacing, alignment, margins and row/column geometry. Uneven rows receive empty cells for missing columns. Theme border colors now use the same slot as the preview.
|
|
127
129
|
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {nativeBackgroundFill} from './background.js';
|
|
|
3
3
|
import {importBackground} from './background-import.js';
|
|
4
4
|
import { webpToPng } from '#image-fallback';
|
|
5
5
|
import { rasterMetadata, pictureTransform, normalizeImageOrientation } from './image-geometry.js';
|
|
6
|
-
import { composeSlide, fitText, textWidthMeasurer, resolveCanvasDimensions, resolveFontFamilies, resolveTextStyle } from "@openpresentation/opf/composition";
|
|
6
|
+
import { composeSlide, fitText, fitRichText, textWidthMeasurer, resolveCanvasDimensions, resolveFontFamilies, resolveTextStyle } from "@openpresentation/opf/composition";
|
|
7
7
|
import PptxGenJS from "pptxgenjs";
|
|
8
8
|
import { unzipSync, zipSync } from "fflate";
|
|
9
9
|
import { XMLParser } from "fast-xml-parser";
|
|
@@ -1122,16 +1122,42 @@ function addTablePayload(slide, table, region, context, options, path) {
|
|
|
1122
1122
|
const cellPath = header ? `${path}.columns.${columnIndex}` : `${path}.rows.${rowIndex - Number(hasHeaders)}.${columnIndex}`;
|
|
1123
1123
|
const text = stringifyText(row[columnIndex]);
|
|
1124
1124
|
const style = resolveTextStyle({ fontFamily: context.fonts.body, fontWeight: header ? 700 : 400, italic: false, path: cellPath }, options.textMeasurement);
|
|
1125
|
-
const
|
|
1125
|
+
const rich = Array.isArray(row[columnIndex]);
|
|
1126
|
+
const fit = rich
|
|
1127
|
+
? fitRichText(row[columnIndex], cellBox, 15 * scale, (context.composition?.minFontSize ?? 16) * scale, {style,textMeasurement:options.textMeasurement})
|
|
1128
|
+
: fitText(text, cellBox, 15 * scale, (context.composition?.minFontSize ?? 16) * scale, textWidthMeasurer(style, options.textMeasurement));
|
|
1129
|
+
const fragments = rich ? fit.richLines.flatMap(line => line.fragments) : [];
|
|
1130
|
+
const runs = rich ? row[columnIndex].flatMap((value, index) => {
|
|
1131
|
+
const run = typeof value === 'string' ? {text:value} : value;
|
|
1132
|
+
const fragment = fragments.find(item => item.runIndex === index);
|
|
1133
|
+
const runStyle = fragment?.style ?? resolveTextStyle({...style,fontFamily:run.fontFamily ?? style.fontFamily,fontWeight:run.bold === undefined ? style.fontWeight : run.bold ? 700 : 400,italic:run.italic ?? style.italic}, options.textMeasurement);
|
|
1134
|
+
const rawColor = /^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(run.color ?? '') ? run.color.slice(1) : header ? 'FFFFFF' : context.colors.text;
|
|
1135
|
+
const color = normalizeHex(rawColor), transparency = rawColor.length === 8 ? (1 - parseInt(rawColor.slice(6), 16) / 255) * 100 : 0;
|
|
1136
|
+
const runOptions = {
|
|
1137
|
+
fontFace:runStyle.fontFamily,fontSize:fragment ? fragment.fontSize * .75 : fit.fontSize * .75,
|
|
1138
|
+
bold:runStyle.fontWeight >= 600,italic:runStyle.italic,
|
|
1139
|
+
underline:run.underline ? {color} : undefined,strike:run.strikethrough ? 'sngStrike' : undefined,
|
|
1140
|
+
color,transparency,baseline:fragment?.baselineShift ? -fragment.baselineShift / fragment.fontSize * 2000 : undefined,
|
|
1141
|
+
hyperlink:run.link && /^(https?:|mailto:)/i.test(run.link) ? {url:run.link} : undefined,
|
|
1142
|
+
};
|
|
1143
|
+
// PptxGenJS marks every part of a newline-containing run as a paragraph
|
|
1144
|
+
// break, including its final part. Split explicitly so the next styled
|
|
1145
|
+
// run stays on that final line, and preserve empty/trailing lines.
|
|
1146
|
+
const parts = run.text.split(/\r*\n/);
|
|
1147
|
+
return parts.map((text, part) => ({text,options:{...runOptions,breakLine:part < parts.length - 1}}));
|
|
1148
|
+
}) : null;
|
|
1126
1149
|
return {
|
|
1127
1150
|
// Keep native wrapping and the original cell value: inserting measured
|
|
1128
1151
|
// soft wraps into the text would change a later import or copy operation.
|
|
1129
|
-
text,
|
|
1152
|
+
text: rich ? runs : text,
|
|
1130
1153
|
options: {
|
|
1131
1154
|
fontFace: style.fontFamily,
|
|
1132
1155
|
fontSize: fit.fontSize * 0.75,
|
|
1133
|
-
|
|
1134
|
-
|
|
1156
|
+
// PptxGenJS fills falsy run options from cell defaults. Rich runs
|
|
1157
|
+
// carry their resolved weight, so a bold header default must not turn
|
|
1158
|
+
// an explicit bold:false run back on.
|
|
1159
|
+
bold: rich ? false : style.fontWeight >= 600,
|
|
1160
|
+
italic: rich ? false : style.italic,
|
|
1135
1161
|
lineSpacing: fit.lineHeight * 0.75,
|
|
1136
1162
|
paraSpaceAfter: 0,
|
|
1137
1163
|
align: context.contentAlignment,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openpresentation/opf-pptx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Pure local OPF to PPTX export and PPTX to OPF import tooling.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,21 +35,21 @@
|
|
|
35
35
|
"sideEffects": false,
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "node scripts/build.mjs",
|
|
38
|
-
"typecheck": "node --check src/index.js && node --check scripts/build.mjs && node --check scripts/validate-package.mjs && node --check test/smoke.mjs && node --check src/image-geometry.js && node --check test/image-fit.mjs && node --check test/image-orientation.mjs && node --check test/table-layout.mjs && node --check test/table-import.mjs && node --check test/object-ids.mjs && node --check test/export-corpus.mjs && node --check test/image-media-type.mjs && node --check src/image-fallback-node.js && node --check src/image-fallback-browser.js && node --check test/webp-fallback.mjs && node --check scripts/build-browser-check.mjs && node --check test/webp-fallback-browser.js && node --check test/image-fallback-boundary.mjs && node --check src/background.js && node --check test/background.mjs && node --check src/image-import.js && node --check test/image-import.mjs && node --check test/native-background.mjs && node --check src/background-import.js && node --check test/background-inheritance.mjs",
|
|
38
|
+
"typecheck": "node --check src/index.js && node --check scripts/build.mjs && node --check scripts/validate-package.mjs && node --check test/smoke.mjs && node --check src/image-geometry.js && node --check test/image-fit.mjs && node --check test/image-orientation.mjs && node --check test/table-layout.mjs && node --check test/table-import.mjs && node --check test/object-ids.mjs && node --check test/export-corpus.mjs && node --check test/image-media-type.mjs && node --check src/image-fallback-node.js && node --check src/image-fallback-browser.js && node --check test/webp-fallback.mjs && node --check scripts/build-browser-check.mjs && node --check test/webp-fallback-browser.js && node --check test/image-fallback-boundary.mjs && node --check src/background.js && node --check test/background.mjs && node --check src/image-import.js && node --check test/image-import.mjs && node --check test/native-background.mjs && node --check src/background-import.js && node --check test/background-inheritance.mjs && node --check test/rich-table.mjs",
|
|
39
39
|
"test": "npm run build && node test/dependency-boundary.mjs && npm run build:browser-check",
|
|
40
40
|
"validate": "node scripts/validate-package.mjs",
|
|
41
41
|
"prepack": "npm run build",
|
|
42
42
|
"build:browser-check": "node scripts/build-browser-check.mjs"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@openpresentation/opf": "^0.
|
|
45
|
+
"@openpresentation/opf": "^0.5.0",
|
|
46
46
|
"fast-xml-parser": "^5.8.0",
|
|
47
47
|
"fflate": "^0.8.3",
|
|
48
48
|
"pptxgenjs": "4.0.1",
|
|
49
49
|
"sharp": "0.35.4"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@openpresentation/opf-render": "^0.
|
|
52
|
+
"@openpresentation/opf-render": "^0.3.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@openpresentation/opf-render": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@openpresentation/opf-render": "0.
|
|
60
|
+
"@openpresentation/opf-render": "0.3.0",
|
|
61
61
|
"esbuild": "0.28.2"
|
|
62
62
|
},
|
|
63
63
|
"imports": {
|