@openpresentation/opf-render 0.3.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/svg.js +19 -45
  2. package/package.json +2 -2
package/dist/svg.js CHANGED
@@ -1,4 +1,4 @@
1
- import { fitList, fitRichText, composeSlide, resolveCanvasDimensions, resolveFontFamilies, resolveTextStyle, textWidthMeasurer, fitText } from "@openpresentation/opf/composition";
1
+ import { layoutTable, fitList, fitRichText, composeSlide, resolveCanvasDimensions, resolveFontFamilies, resolveTextStyle, textWidthMeasurer, fitText } from "@openpresentation/opf/composition";
2
2
  import {
3
3
  catalogs as bundledCatalogs,
4
4
  validatePresentation
@@ -911,48 +911,22 @@ function renderTimeline(item, box, bound, options) {
911
911
 
912
912
  function renderTable(item, box, bound, options) {
913
913
  const scale = Math.min(bound.design.dimensions.width, bound.design.dimensions.height) / 720;
914
- const table = item.value ?? {};
915
- const columns = Array.isArray(table.columns) ? table.columns : [];
916
- const rows = Array.isArray(table.rows) ? table.rows : [];
917
- const allRows = columns.length ? [columns, ...rows] : rows;
918
- const columnCount = Math.max(1, ...allRows.map((row) => Array.isArray(row) ? row.length : 1));
919
- const rowCount = Math.max(1, allRows.length);
920
- const cellWidth = box.width / columnCount;
921
- const cellHeight = Math.min(54 * scale, box.height / rowCount);
914
+ const layout = layoutTable(item.value, box, {scale, minFontSize:(bound.composition ?? bound.geometry.composition).minFontSize, fontFamily:bound.design.fonts.body, textMeasurement:options.textMeasurement, path:item.path});
922
915
  const children = [];
923
-
924
- allRows.forEach((row, rowIndex) => {
925
- const cells = Array.isArray(row) ? row : [row];
926
- for (let columnIndex = 0; columnIndex < columnCount; columnIndex += 1) {
927
- const x = box.x + columnIndex * cellWidth;
928
- const y = box.y + rowIndex * cellHeight;
929
- const cellPath = rowIndex === 0 && columns.length ? `${item.path}.columns.${columnIndex}` : `${item.path}.rows.${rowIndex - (columns.length ? 1 : 0)}.${columnIndex}`;
930
- children.push(tag("rect", {
931
- x: stableNumber(x),
932
- y: stableNumber(y),
933
- width: stableNumber(cellWidth),
934
- height: stableNumber(cellHeight),
935
- fill: rowIndex === 0 && columns.length ? bound.design.colors.primary : bound.design.colors.surface,
936
- stroke: bound.design.colors.border,
937
- "stroke-width": 1,
938
- ...traceAttrs(options, cellPath)
939
- }));
940
- const rich = Array.isArray(cells[columnIndex]);
941
- children.push((rich ? renderRichTextBox : renderTextBox)(rich ? cells[columnIndex] : flattenText(cells[columnIndex] ?? ""), {
942
- x: x + 10 * scale,
943
- y: y + 8 * scale,
944
- width: Math.max(scale, cellWidth - 20 * scale),
945
- height: Math.max(scale, cellHeight - 12 * scale)
946
- }, bound, {
947
- path: cellPath,
948
- fontSize: 15,
949
- fontFamily: bound.design.fonts.body,
950
- fontWeight: rowIndex === 0 && columns.length ? 700 : 400,
951
- fill: rowIndex === 0 && columns.length ? "#FFFFFF" : bound.design.colors.text,
952
- options
953
- }));
954
- }
955
- });
916
+ for (const row of layout.rows) for (const cell of row.cells) {
917
+ children.push(tag("rect", {
918
+ x: stableNumber(cell.box.x), y: stableNumber(cell.box.y),
919
+ width: stableNumber(cell.box.width), height: stableNumber(cell.box.height),
920
+ fill: cell.header ? bound.design.colors.primary : bound.design.colors.surface,
921
+ stroke: bound.design.colors.border, "stroke-width":1,
922
+ ...traceAttrs(options, cell.path)
923
+ }));
924
+ children.push((cell.rich ? renderRichTextBox : renderTextBox)(cell.rich ? cell.value : flattenText(cell.value ?? ""), cell.textBox, bound, {
925
+ path:cell.path, fontSize:15, fontFamily:bound.design.fonts.body,
926
+ fontWeight:cell.header ? 700 : 400, textStyle:cell.textStyle, fit:cell.fit,
927
+ fill:cell.header ? "#FFFFFF" : bound.design.colors.text, options
928
+ }));
929
+ }
956
930
 
957
931
  return tag("g", traceAttrs(options, item.path), children.join("\n"));
958
932
  }
@@ -1168,7 +1142,7 @@ function renderEmbeddedFonts(fonts = []) {
1168
1142
 
1169
1143
  function renderRichTextBox(value, box, bound, config) {
1170
1144
  const scale=Math.min(bound.design.dimensions.width,bound.design.dimensions.height)/720;
1171
- const fit=fitRichText(value,box,config.fontSize*scale,((bound.composition??bound.geometry.composition).minFontSize??16)*scale,{style:{fontFamily:config.fontFamily,fontWeight:config.fontWeight??400,path:config.path},textMeasurement:config.options.textMeasurement});
1145
+ const fit=config.fit??fitRichText(value,box,config.fontSize*scale,((bound.composition??bound.geometry.composition).minFontSize??16)*scale,{style:{fontFamily:config.fontFamily,fontWeight:config.fontWeight??400,path:config.path},textMeasurement:config.options.textMeasurement});
1172
1146
  if(fit.overflow){const diagnostic={code:'text-overflow',path:config.path,message:'Mixed-style text exceeds its cell at the minimum font size.'};reportDiagnostic(diagnostic,config.options);if((bound.composition??bound.geometry.composition).overflow==='error')throw new OPFRenderError('layout-overflow',diagnostic.message,{issues:[diagnostic]});}
1173
1147
  return renderRichLines(value,fit,box,bound,config);
1174
1148
  }
@@ -1196,8 +1170,8 @@ function renderRichLines(value,fit,box,bound,config) {
1196
1170
 
1197
1171
  function renderTextBox(text, box, bound, config) {
1198
1172
  const scale = Math.min(bound.design.dimensions.width, bound.design.dimensions.height) / 720;
1199
- const style = resolveTextStyle({fontFamily:config.fontFamily,fontWeight:config.fontWeight ?? 400,italic:config.italic ?? false,path:config.path},config.options.textMeasurement);
1200
- const fit = fitText(String(text ?? ""), box, config.fontSize * scale,
1173
+ const style = config.textStyle ?? resolveTextStyle({fontFamily:config.fontFamily,fontWeight:config.fontWeight ?? 400,italic:config.italic ?? false,path:config.path},config.options.textMeasurement);
1174
+ const fit = config.fit ?? fitText(String(text ?? ""), box, config.fontSize * scale,
1201
1175
  ((bound.composition ?? bound.geometry.composition).minFontSize ?? 16) * scale, textWidthMeasurer(style,config.options.textMeasurement));
1202
1176
  if (fit.overflow) {
1203
1177
  const diagnostic = { code: "text-overflow", path: config.path,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpresentation/opf-render",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Deterministic local OPF renderer for SVG, PNG, and PDF output.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -72,7 +72,7 @@
72
72
  "@expo-google-fonts/roboto": "^0.4.3",
73
73
  "@expo-google-fonts/roboto-mono": "^0.4.2",
74
74
  "@expo-google-fonts/tinos": "0.4.2",
75
- "@openpresentation/opf": "^0.5.0",
75
+ "@openpresentation/opf": "^0.6.0",
76
76
  "@resvg/resvg-js": "^2.6.2",
77
77
  "fontkit": "^2.0.4",
78
78
  "pdf-lib": "^1.17.1",