Skip to content

Releases: OpenPresentation/opf-render

@openpresentation/opf-render 0.24.1

Choose a tag to compare

@github-actions github-actions released this 20 Oct 02:11
c01a48a
  • RR-96: the example baseline follows core 0.24.0 (gallery 4 theme records with variants; no slide changes). 0.24.0 was tagged but never published, because its publish run still checked the core 0.23 corpus; 0.24.1 is the first 0.24 release of the renderer.

@openpresentation/opf-render 0.23.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 16:39
ec22c6e
  • RR-95: README note on the chart preview and an opf-pptx 0.22.0 export: since 0.22.2 they draw the same series colors (the deck color scheme and chart.colors), the same value axis for column, bar, line and area charts (core's composed axis) and the same 20 px chart text.
  • RR-96 (output-changing for decks and slides that set design.variant or a picture or gradient tone; borders, gridlines, axis lines, chart text and the code panel change for every deck): every slide is drawn from core's resolved roles for its variant, as PowerPoint does with its colour map. design.variant (deck and slide, the "dark1" shorthand, the accent order) sets the background (bg1), text (tx1), surface (bg2), the series colour order and the neutrals; a variant hides the background of a less specific level. Table and chart frames, gridlines (tx1 at 15%), axis lines (25%), chart text (65%), the pie and treemap outlines, the video play icon, the code panel and its text, the metric neutral trend and the table header text come from the scheme-derived neutrals, so no fixed grey or white is left in the drawing code. A picture background that names its tone takes that tone's variant and a 40% scrim of the slide background (the renderer's own, core exposes none). Needs @openpresentation/opf 0.23.0.
  • RR-96 (adopts core RR-96, opf#732; test and baseline changes only, no renderer code): core derives borders, chart gridlines and axis lines from the color scheme (the text color mixed into the background, roles.neutrals) instead of a fixed slate, so every card, table rule and chart changes color, not geometry, and the example corpus gains the color-variants deck. The tests that encoded the old colors expect the new ones (neutral-scaffolding, and the traced SVG digests of chart-table-data and chart-finite-statistics). The example and template baselines select new ones, rr96-scheme-neutrals, whenever core derives the neutrals (schemeNeutralsDerived()); golden-gate compares the selected baseline with every slide of the installed examples instead of a fixed 807. Requires the unreleased core 0.23.0.

@openpresentation/opf-render 0.22.2

Choose a tag to compare

@github-actions github-actions released this 19 Oct 02:23
4a72ad1
  • RR-89 (output-changing for every chart without highlight): chart series are drawn in core's chartSeriesPalette of the deck's resolved colour scheme (accent1 to accent6, then the same six accents tinted 40% toward white), so design.colorScheme recolours the series instead of every deck drawing the cool-horizon blues; a deck without a colour scheme of its own keeps the engine default's accents. The palette still goes through core's chartPaletteForFill (contrast against the chart panel), and chart.highlight colours are unchanged. chart.colors entries (hex, scheme slot, role or var: reference) replace the palette colour at their position, before the same adjustment; chart.highlight still wins. The renderer's own CHART_SERIES_COLORS copy is deleted. Needs @openpresentation/opf 0.22.0.
  • RR-90 (output-changing for every chart): chart axis, legend, category and data-label text is core's chartTextSize instead of 14 px floored to the 16 px (12 pt) minimum: 20 px (15 pt) in a roomy chart box, shrunk (at most a 1/18 of the box height and 1/30 of its width, whole pixels) only when the box is small, and never below composition.minFontSize. A chart no longer renders at 12 pt beside 24 pt bullets. Needs @openpresentation/opf 0.22.0.
  • RR-92 (no pixel change for the usual chart): a column, bar, line or area chart draws the value axis core composes for its box (item.chart.valueAxis: min, max, majorUnit), the same axis the PPTX export writes, so the preview and PowerPoint or Keynote show the same gridlines. In a short box core estimates the plot from the box rather than from the laid-out plot, so the major unit can differ by one 1/2/5 step from before; every other chart type keeps its renderer-side scale. The renderer's local niceScale, maxIntervalsFor and stackCategoryValues are replaced by core's. Needs @openpresentation/opf 0.22.0.

@openpresentation/opf-render 0.22.1

Choose a tag to compare

@github-actions github-actions released this 19 Oct 00:42
e118a49
  • RR-90: 0.22.1 is the first published 0.22 renderer. The 0.22.0 tag exists but was never published: its publish run found the example baseline stale against core 0.22. 0.22.1 carries the refreshed baseline (#260) and the same code as 0.22.0, which requires core ^0.22.0.

@openpresentation/opf-render 0.20.4

Choose a tag to compare

@github-actions github-actions released this 17 Oct 07:12
e179673
  • RR-87: establish Git trust only for the exact checked-out workspace in the publishing job before verifying its merged release identity. Preserve the full source, tag and manifest checks; no runtime or export behavior changes.

@openpresentation/opf-render 0.20.2

Choose a tag to compare

@github-actions github-actions released this 16 Oct 10:03
837dbca
  • RR-85: Select the reviewed metric-centering example baseline for ordinary checks and trusted publication when the installed core defaults metrics to center. Preserve historical baseline bytes, explicit reviewed overrides and exact raster checks.

@openpresentation/opf-render 0.20.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 12:06
83c1e6e

Renderer 0.20.0 requires published core 0.20.1 and supports Gallery 3 nested-array layout records, neutral structural defaults, typed numeric alignment and zero-based magnitude axes. The temporary unreleased-core declaration has been removed for this release.

  • Layout templates now author areas as nested arrays of region-name cells. String rows are outside the contract; grid geometry and explicit region pins retain their existing meaning.
  • Adopt the published Gallery 3 catalog contract for renderer development fixtures with an authentic registry lock. Engine versions and existing core/renderer contracts remain unchanged until the coordinated 0.20 release preparation.

Declare the matching unreleased core 0.20 requirement so the established RR-55 gate waits for genuine registry core before standalone packed checks; coordinated source and packed/browser qualification remains required. Release preparation removes this declaration and release checks refuse it.

  • Structural card, table and chart rules use quiet neutral defaults instead of the scheme’s fifth brand accent. Authored border colors remain unchanged. Tables align typed numeric values and numeric-column headers to the right by default, retaining explicit cell and design alignment and original cell values. Preview and native export share the same resolved defaults.

Bar, column and filled-area magnitude axes include zero by default, including near-equal positive or negative values; line/scatter automatic domains remain unchanged.

@openpresentation/opf-render 0.19.1

Choose a tag to compare

@github-actions github-actions released this 12 Oct 11:54
7980fea

The 0.19 renderer train uses 0.19.1 after the 0.19.0 publisher stopped before npm publication. It includes the adaptive v2 layout renderer and the corrected ordinary release checks.

  • Ordinary renderer release tests select the existing reviewed v2 example baseline, matching installed core 0.19 examples. Explicit historical baseline overrides and all source, raster, missing-baseline and empty-corpus guards remain strict; no golden bytes or tolerances change.

@openpresentation/opf-render 0.18.2

Choose a tag to compare

@github-actions github-actions released this 11 Oct 17:17
de0a503
  • FF-46 (opf#362; tests only): per-name host fixtures for the 22 proprietary script, emoji, math and code-table names that pass the native visual comparison. test/script-name-hosts.mjs (Node) and test/script-name-hosts-browser.mjs (Chromium, offline) take each name of test/fixtures/script-name-families.json (Aparajita, Arabic Typesetting, Cambria Math, David, FangSong, Gautami, Gisha, Kalinga, Microsoft JhengHei, Microsoft YaHei, MingLiU, Miriam, Nyala, PMingLiU, Segoe UI Emoji, SimHei, SimSun, Sylfaen, Symbol, Tunga, Webdings, Wingdings) and check that it resolves to its policy route with the policy sizeAdjust, that every script sample draws in its route face with no other fallback (Sylfaen's Armenian and Georgian in their designated Noto faces; every mapped symbol code in the chain face that has it) at the route file's own advances, and that the drawn face is the pinned file. Both write artifacts/script-name-hosts/*.json, the evidence the core font tracker reads.
  • opf#361 (output changes only for size-adjusted families): the renderer applies font-policy.json's sizeAdjust and lineAscent rows wherever they are, so with core's opf#361 rows the previews of Angsana New (0.75, line ascent 0.83 / 0.86), DilleniaUPC (0.68, 0.82 / 0.85), Sakkal Majalla (0.89, 0.76 / 0.81), Malgun Gothic (1.07) and Nirmala UI (1.07, 0.97 / 0.94) draw and measure their script text at the size PowerPoint draws it, and Arabic Typesetting lines move down 0.04 em (0.02 em on a line with a Latin run) for its corrected line ascent 0.74 / 0.80.
    • White space that follows a size-adjusted run now stays in that run (createScriptFonts().plan), as PowerPoint keeps it in the script font: the space between two Hangul words of a Malgun Gothic title is measured and drawn at the run's adjusted size instead of a separate run at the composed size, which a browser drew wider than its measured advance (the FF-19 browser check caught it once Malgun Gothic carried a multiplier).
    • test/arabic-size-adjust.mjs, test/script-fonts-browser.mjs and test/script-corpora-slides-browser.mjs read the multipliers and title sizes from the installed core's policy instead of hard-coding Arabic Typesetting's, and the first checks the five new rows exactly when they are present.
    • No golden moves: the 807 example slides render identical SVG on the golden path with core's current policy and with the opf#361 rows.
  • opf-render#189 changes the default output of PNG and raster PDF for Indic, Thai, Lao, Khmer and Myanmar text. The raster path now places each complex-script cluster at HarfBuzz's pen position (fonts.outlines.shape, the shaper browsers use) instead of fontkit's.
    • Who it affects: conversions that have HarfBuzz, which the Node fonts handle and the bundled faces always have. The default toPng and raster PDF therefore change for this text.
    • Fallback to fontkit's pens: without a shaper, output stays byte-identical. A run HarfBuzz cannot map back to its characters also falls back.
    • Why: fontkit kerns after a decomposed Thai sara am differently from HarfBuzz, so a cluster after it (ใจ after น้ำ) was about 0.7 px off at 25 px.
    • Script corpora: six samples change, measured as mean pixel difference against HarfBuzz's own outlines, before → after. All six now draw exactly like HarfBuzz's outlines, and no other sample changes:
      • thai-title: 0.46 → 0
      • thai-sara-am: 1.48 → 0
      • thai-no-spaces: 0.47 → 0
      • taml-title: 5.7 → 0
      • telu-title: 2.79 → 0
      • mymr-medials: 12.96 → 0
    • Against Chromium: seven of eight Thai checks (three lines and the issue's own line, at 25 and 60 px) come closer. For example, thai-sara-am at 60 px drops from 266 channel values off by more than 64 to 43. What remains is the anti-aliasing difference that HarfBuzz's own outlines show too.
    • One regression: thai-no-spaces at 25 px moves slightly away from Chromium (mean difference 1.298 → 1.329). The output there is exactly HarfBuzz's; fontkit's old offset happened to land nearer Chromium's pixels.
    • Raster goldens: unchanged, because no golden deck has complex-script text.
  • Preserve named reference glyphs when subsetting embedded fonts so small text in macOS browser SVG previews draws like the whole face, while retaining compact, deterministic subsets.
  • RR-81: regenerate explicitly pinned v2 example and template candidates in the prescribed Playwright image, with separate read-only generation and guarded baseline-only writes.
  • Preserve the host color scheme across the slideshow player's CSS reset and use system Highlight for forced-colors focus outlines, so dark and light embeds retain the correct accessible system palette.

@openpresentation/opf-render 0.18.1

Choose a tag to compare

@github-actions github-actions released this 11 Oct 04:49
d425933
  • render#171 (tooling and docs only, no change to the package): npm run bench:soak (scripts/soak.mjs) is a repeatable sustained-load benchmark for long-lived render and export workers. Each worker process holds one fonts handle (loadFonts with the office pack and scripts: 'auto'), blocks the network and repeats ensure, toSvg, toPng and, when @openpresentation/opf-pptx is installed, toPptx over core's example decks and a script-corpora deck, at concurrency 1 and 4 for 500 or more jobs per worker. It samples RSS and retained heap after a forced GC, reports p50 and p95 latency per operation, tests the steady-state window for monotonic memory growth (Mann-Kendall plus Theil-Sen, criterion in the script header), and compares the SVG, PNG and PPTX hashes of every repeat of a deck; the JSON report and Markdown summary go to the git-ignored artifacts/soak/. It is not part of npm test. The README section "Long-lived workers: measured memory and latency" publishes the first measurement with its hardware and Node version.
  • render#123: the vector PDF writer moves to pako 3.0.2 (from 1.0.11), whose exports are named only (import { deflate } from "pako"). Output is byte-identical: flate passes legacyHash: true, so pako 3 keeps writing canonical zlib streams as pako 1 did (its new default, the hash of Chromium zlib, writes about 1% larger streams with the same inflated content and would change every PDF's bytes and /ID). The /export-browser bundle tree-shakes pako's inflate side away: 20 KB smaller minified (6 KB gzipped).
  • render#191: dependency refresh. Upgrade the font packages with the renderer: install @expo-google-fonts/noto-sans-jp, -kr, -sc and -tc 0.4.4, noto-color-emoji 0.4.7 and noto-emoji 0.4.8 in the same step. They are exact-pinned optional peers: npm with an exact older pin refuses the upgrade (ERESOLVE), and pnpm or npm --legacy-peer-deps installs it with a peer warning, after which loadFonts rejects the old files with font-integrity-mismatch. With npm, a caret pin (^0.4.3) moves with the renderer; other package managers can keep the locked older version, so bump the six packages explicitly (-sc, -tc and noto-emoji change only metadata, but their exact peer pins moved too). The script and emoji font pins move to @expo-google-fonts/noto-sans-jp, -kr, -sc and -tc 0.4.4, noto-color-emoji 0.4.7 and noto-emoji 0.4.8 (optional peers; src/font-manifest.js re-pinned, licenses unchanged and verified OFL-1.1). The Noto Sans JP and KR faces are rebuilt files of the same 2.004 release with the same outlines and advances and renumbered glyph ids, so over the core examples and the script corpora SVG with embedded fonts and the raster goldens are unchanged; text-as-paths glyph ids (opf-g-<face hash>-<glyph id>) and the vector PDF's six-letter subset tags change for Japanese and Korean text. Noto Color Emoji moves from 2.051 to 2.057 (nine new emoji, redrawn glyphs), so a slide that embeds or exports it changes bytes. <opf-deck> thumbnails: the slide drawing is no longer inside the thumbnail button but under it, so the button's name ("Go to Slide 2 of 5: Agenda") is not contradicted by the slide's own text (WCAG 2.5.3, axe-core 4.14 label-content-name-mismatch); the strip looks and behaves the same (a host that paints a background on ::part(thumbnail) now paints it over the drawing). harfbuzzjs 1.6.3 (HarfBuzz 14.6.0): shaping is unchanged (text-as-paths byte-identical over the examples and script corpora); hb-subset writes some cmap subtables differently, so 70 of the 807 example SVGs with embedded subsets change by a few bytes (same glyph mapping, same pixels). Development dependencies: axe-core 4.14.0, @napi-rs/canvas 1.0.10, pdfjs-dist 6.4.299.
  • opf#364 (docs): the README now says to pass the same fonts handle (from loadFonts()) to preview, validation, pagination and export so they agree with the drawn faces, and that a call without it uses core's built-in estimate (0.54 em per character, 0.62 em for capitals and digits, 0.32 em for a space, 1 em for CJK, zero for combining marks), which is too narrow for some scripts (opf#566).
  • RR-20 (release workflow only): publishing opf-render to npm now creates its GitHub Release. A release job in npm-publish.yml runs after the npm publish on a tag push, takes the notes from the version's ## X.Y.Z section of CHANGELOG.md (the job fails if the section is missing), and creates the release opf-render-vX.Y.Z titled @openpresentation/opf-render X.Y.Z, marked as the latest release. Only that job holds contents: write; the publish job keeps id-token: write. GitHub Releases start at 0.18; older versions get none.
  • opf-render#125 (output-changing only where earlier measurement had left a stale glyph): a text measurement no longer depends on what the same process measured or drew before. fontkit caches one glyph object per glyph id with the code points of the call that created it, and its layout read a character's code points back from that cache. Bounding the outline of Bengali ra (U+09B0, a composite drawn with the nukta glyph as a component) cached the nukta (U+09BC) with no code points, so every later Bengali run with a nukta was shaped as a broken cluster with a dotted circle: আয় বেড়েছে কিন্তু খরচ অপরিবর্তিত in Noto Sans Bengali at 25 px measured 380.4 or 367.65 px instead of 354.9 (the width HarfBuzz gives, and a fresh process's), and the font-switch matrix drew deck pairwise-50 differently by run order. The registry's faces now give every glyph request exactly the code points it asked for, as the PDF writer's faces already did, so a measurement and the SVG drawn from it are a function of the document and the registry alone. A fresh process measured the right width before and after; only renders that followed an affected outline change.
  • opf-render#188 (output-changing for complex-script and combining-mark PDFs only): the vector PDF is shaped by HarfBuzz, the browser's shaper, as text: "paths" outlines are (RR-64 phase 2), instead of fontkit: with a fonts handle that carries the shaper (the Node loadFonts handle always, a browser handle given shapeWasm; exposed as fonts.outlines.shape) and, in Node without a handle, with the bundled one the conversion loads. Over the 30 script corpora every glyph the PDF shows now has HarfBuzz's id and position, where fontkit drew other glyphs on 10 samples (Bengali conjuncts, Thai and Lao tone marks, Khmer coeng, Myanmar medials, Syriac marks, Japanese combining sound marks) and put Telugu conjuncts 0.8 px off at 25 px. The PDF still draws the SVG's lines and pinned widths; the layout's measurement stays fontkit. Each character stays with the glyph it became (HarfBuzz cluster level 2), so the glyph-to-Unicode map and /ActualText spans read back as before. The writer also draws a glyph's small horizontal GPOS placement (up to 0.025 em, it was dropped: Arabic, Hebrew, Devanagari, Tibetan and combining Latin and Cyrillic marks up to 0.6 px off at 25 px) and continues the line after a glyph it shows alone with that glyph's shaped advance (a zero-width joiner after a mark put the rest of a run its nominal width off). Latin text without combining marks is byte-identical.
  • opf-render#189 (output-changing for PNG and raster PDF of Indic, Thai, Lao, Khmer and Myanmar text only): the raster path pins each complex-script cluster at the fontkit pen of its first character in the run shaped as a whole, not at the advance of the run's prefix shaped alone, which ended without the context of the next character. A Thai leading vowel kerned to its consonant (ไ ด, เ ต) put the consonant with its tone and vowel marks 0.25 px right of the browser's place at 25 px (รายได้เติบโตในทุกภูมิภาค at 60 px: 1,329 channel values off by more than 64 from HarfBuzz's outlines drawn by the same resvg, none now; against Chromium 1,554, now 210, the anti-aliasing difference HarfBuzz's own outlines show too). The script corpora's thai-digits, laoo-words, taml-pulli and telu-zwnj now draw exactly as HarfBuzz's outlines; the approved raster goldens do not change. The raster path's own fontkit faces also pin each glyph's code points (pinGlyphCodePoints, opf-render#125): after an outlined Devanagari letter with a nukta component (ऱ, क़), a later decomposed nukta no longer shapes with a dotted circle.
  • render#199: a Next.js app that imports @openpresentation/opf-render and /fonts-node builds with Turbopack and no next.config. Since RR-64 and RR-65, next build failed because Turbopack compiled harfbuzzjs/dist/harfbuzz.wasm (located with require.resolve) as a WebAssembly module; and in a server bundle, the font packages (require.resolve of a computed name, which a bundler turns into a stub that always throws) and the vendored fonts/ directory (new URL with a computed path) were not found. The Node entries (/fonts-node, /preview-fonts-node) now locate these files at run time through Node's own resolution, in a form bundlers leave alone, so a Next.js server (Turbopack or webpack, route handler or server component) renders the same bytes as plain Node: subset faces, HarfBuzz-shaped outlines and the office pack. Plain Node output is unchanged. loadFonts now reports harfbuzz-unavailable through onDiagnostic when a harfbuzzjs .wasm cannot be loaded (a deployment that did not ship the package) and still loads the fonts, with whole faces and fontkit shaping; a missing file used to reject loadFonts. npm run test:next-bundle builds and serves such an app against the packed package.
  • render#220: a symbol-encoded family (Wingdings, Symbol, Webdings) named as a font-scheme role also maps its codes in list bodies (text: [{ text }] or text: ["..."]), under heading/body and major/minor roles, as #207 made it do for string bodies. Core composes each list paragraph from its block's resolved style, and resolving that open symbo...
Read more