2 hours ago
pdfkit

v0.20.0

Highlights

TLDR: "A PDF generation library for Node.js" -> "A JavaScript PDF generation library"

Standard Font Support rewritten

Standard font support has been rewritten to use pre-parsed font metrics instead of parsing raw AFM definitions at runtime. The new approach is more efficient (less runtime overhead and memory usage) and reduces the size of the browser bundle significantly. Standalone build which bundles all standard fonts is down to 1.3MB from 2.3MB.

In Node, font metrics are loaded lazily as before, while in browser builds, except the standalone one, each font must be imported from pdfkit/standard-fonts/* and registered with registerStdFonts(). Previously, to use a standard font in browser was necessary to use a bundler.

See usage example in output helpers section below.

Removal of Node specific dependencies

Buffer is no longer used internally. Uint8Array is now the minimum denominator for binary data in both Node and browsers. Since Buffer is a Uint8Array subclass, this change is fully backward compatible.

Native fs, zlib and ReadableStream are conditionally imported only in Node. Browser builds use minimal implementations. This approach gives us the best of both worlds: Node builds still use the native modules, while browser ones are portable.

Many thanks to @diegomura for his help in removing the Node specific dependencies.

registerFile API

The new registerFile(path, data) API allows registering in-memory files globally. The data argument must be a Uint8Array. Passing undefined as data unregisters the path.

In browsers, it can be used as a simplified virtual file system. In Node, this is useful for registering fonts, images and other resources that are not available on disk. The native file system is still used when the path is not registered.

import { PDFDocument, registerFile } from 'pdfkit';

const response = await fetch('/fonts/Roboto-Regular.ttf');
const fontData = new Uint8Array(await response.arrayBuffer());

registerFile('fonts/Roboto-Regular.ttf', fontData);

const doc = new PDFDocument();

// register an alias for the font path
doc.registerFont('Roboto', 'fonts/Roboto-Regular.ttf');
// or use the path directly
doc.font('fonts/Roboto-Regular.ttf');

// Optionally unregister the path when it is no longer needed.
registerFile('fonts/Roboto-Regular.ttf', undefined);

toBytes and toBlob output helpers

Experimental toBytes(document) and toBlob(document) output helpers are available under pdfkit/output. They return a Promise that resolves to a contiguous Uint8Array or a Blob, respectively. These helpers are useful when a binary API, worker or parser needs one contiguous Uint8Array or a Blob.

import { PDFDocument, registerStdFonts } from 'pdfkit';
import Helvetica from 'pdfkit/standard-fonts/Helvetica';
import HelveticaBold from 'pdfkit/standard-fonts/HelveticaBold';
import { toBlob } from 'pdfkit/output';

registerStdFonts(Helvetica, HelveticaBold);
const doc = new PDFDocument();
const output = toBlob(doc);

// Add your content to the document here, as usual.

doc.end();
const blob = await output;
const url = URL.createObjectURL(blob);
iframe.src = url;

// Revoke the URL when the iframe no longer needs the PDF.
// URL.revokeObjectURL(url);

Named exports

Added named exports for PDFDocument from the main Node and browser entry points while preserving the default PDFDocument export. This will make it easier to transition to ESM in the future. LineWrapper and registerFile are also exported as named exports.

by @blikblum (written by hand)

CHANGELOG

  • [BREAKING CHANGE] Remove the virtual file system (pdfkit/virtual-fs). Browser builds no longer depend on fs: use registerFile to register Uint8Array data under a path, pass a Uint8Array or ArrayBuffer directly to registerFont, image and file, or pass a data URL directly to image and file
  • Add registerFile(path, data, options) to globally register in-memory files in Node and browsers, with optional birthtime and ctime metadata. Passing undefined as data unregisters the path
  • [BREAKING CHANGE] Export PDFDocument, LineWrapper and registerFile as named exports from the main Node and browser entry points while preserving the default PDFDocument export
  • Add experimental toBlob(document) and toBytes(document) output helpers under pdfkit/output
  • Accept already-parsed fontkit Font instances in doc.font() and registerFont
  • Load the PDF/A ICC profile from disk only when needed in Node, while continuing to bundle it in browser builds
  • Add tools to convert raw AFM standard-font definitions into parsed or compact runtime JavaScript modules
  • [BREAKING CHANGE] Use generated standard-font data instead of parsing raw AFM definitions at runtime. Node loads font metrics lazily; browser applications must import each font they use from pdfkit/standard-fonts/* and register it with registerStdFonts()
  • [BREAKING CHANGE] Restrict AcroForm options to documented mappings and explicit escape hatches.
  • [BREAKING CHANGE] Stop automatically uppercasing annotation option keys.
  • [BREAKING CHANGE] Throw from addNamedEmbeddedFile when no ref is given, instead of writing an unparseable undefined token into the /EmbeddedFiles name tree
  • Do not mutate options passed to doc.annotate() and its convenience methods (link, note, strike, lineAnnotation, rectAnnotation, ellipseAnnotation, textAnnotation, fileAnnotation)
  • Persist font options when adding a new page. Fixes #1739
  • Use Uint8Array instead of Node's Buffer internally
  • Fix date text field formatting emitting invalid JavaScript, so the format was never applied. Fixes #1546
  • Fix indentAllLines applying the indent again on every paragraph and every page break, and keep it applied across continued text. Fixes #1606
  • Fix a hole in a sparse array being skipped entirely, which shifted every later entry down one
  • Encrypt strings inside name trees. Fixes #1513
3 hours ago
planby

v2.1.0

v2.1.0

Feature

Planby now ships an agent skill — a compact, source-verified description of the API that AI coding assistants read before writing code, so they stop inventing useEpg options that don't exist.

npm install planby
npx planby init-ai

One command wires the skill into every assistant you use:

Agent What it writes
Claude Code / Agent SDK .claude/skills/planby
Cursor .cursor/rules/planby.mdc
Windsurf .windsurf/rules/planby.md
Codex, Gemini CLI, Antigravity, … a section in AGENTS.md

Each file points at the skill bundled inside node_modules/planby, so the guidance always matches the version you installed. Re-run it after upgrading.

The skill documents the useEpg hook and every one of its options, the Channel/Program schemas, the theme and what each color actually controls, the three render functions, and branding with styled(). It ships two runnable examples that are type-checked against the published types on every release, and it knows which features belong to Planby PRO so it says so instead of generating code that cannot work.

See Using Planby with AI assistants in the README.

Smaller ESM bundle

Dropped the Create React App-era @emotion/styled/macro imports. The macro was only being expanded in the CommonJS build, so the ESM bundle carried its machinery for nothing:

Bundle (gzip) 2.0.0 2.1.0
planby.esm.js 18.8 kB 10.9 kB (−42%)
planby.cjs.production.min.js 7.1 kB 7.2 kB

Stable class name for the timeline label

TimelineTime now renders with a stable planby-timeline-time class instead of a generated hash, so it can be targeted from globalStyles.

Fixed

  • The test suite runs again (9/9 suites, 21/21 tests). react, react-dom and the Testing Library packages were never declared in devDependencies, Jest ran DOM tests in a node environment, and tsdx's bundled Jest conflicted with the root ts-jest.
  • Packing now builds through prepack instead of prepare. prepare is an npm-only lifecycle hook and never ran under Yarn, so yarn npm publish could ship a package with an empty dist/.

Contributing

CONTRIBUTING.md now documents the development setup — Corepack, the pinned Yarn version, the everyday commands, and the rule that a change to the public API must update skills/planby/ in the same pull request.

Compatibility

No breaking changes. The public API is unchanged and the peer range stays at react >= 19.

Committers:

  • Karol Kozer (@karolkozer )
3 hours ago
cropperjs

v2.2.0

See CHANGELOG.md for details.

4 hours ago
query

Release 2026-08-23 11:00

Release 2026-08-23 11:00

Changes

Fix

  • query-core: accept partial dehydrated state (#11260) (134890dbd) by @schiller-manuel

Packages

  • @tanstack/angular-query-experimental@5.102.1
  • @tanstack/eslint-plugin-query@5.102.1
  • @tanstack/lit-query@0.2.13
  • @tanstack/preact-query@5.102.1
  • @tanstack/preact-query-devtools@5.102.1
  • @tanstack/preact-query-persist-client@5.102.1
  • @tanstack/query-async-storage-persister@5.102.1
  • @tanstack/query-broadcast-client-experimental@5.102.1
  • @tanstack/query-core@5.102.1
  • @tanstack/query-devtools@5.102.1
  • @tanstack/query-persist-client-core@5.102.1
  • @tanstack/query-sync-storage-persister@5.102.1
  • @tanstack/react-query@5.102.1
  • @tanstack/react-query-devtools@5.102.1
  • @tanstack/react-query-next-experimental@5.102.1
  • @tanstack/react-query-persist-client@5.102.1
  • @tanstack/solid-query@5.102.1
  • @tanstack/solid-query-devtools@5.102.1
  • @tanstack/solid-query-persist-client@5.102.1
  • @tanstack/svelte-query@6.1.40
  • @tanstack/svelte-query-devtools@6.1.40
  • @tanstack/svelte-query-persist-client@6.1.40
  • @tanstack/vue-query@5.102.1
  • @tanstack/vue-query-devtools@6.1.40
4 hours ago
react-query

Release 2026-08-23 11:00

Release 2026-08-23 11:00

Changes

Fix

  • query-core: accept partial dehydrated state (#11260) (134890dbd) by @schiller-manuel

Packages

  • @tanstack/angular-query-experimental@5.102.1
  • @tanstack/eslint-plugin-query@5.102.1
  • @tanstack/lit-query@0.2.13
  • @tanstack/preact-query@5.102.1
  • @tanstack/preact-query-devtools@5.102.1
  • @tanstack/preact-query-persist-client@5.102.1
  • @tanstack/query-async-storage-persister@5.102.1
  • @tanstack/query-broadcast-client-experimental@5.102.1
  • @tanstack/query-core@5.102.1
  • @tanstack/query-devtools@5.102.1
  • @tanstack/query-persist-client-core@5.102.1
  • @tanstack/query-sync-storage-persister@5.102.1
  • @tanstack/react-query@5.102.1
  • @tanstack/react-query-devtools@5.102.1
  • @tanstack/react-query-next-experimental@5.102.1
  • @tanstack/react-query-persist-client@5.102.1
  • @tanstack/solid-query@5.102.1
  • @tanstack/solid-query-devtools@5.102.1
  • @tanstack/solid-query-persist-client@5.102.1
  • @tanstack/svelte-query@6.1.40
  • @tanstack/svelte-query-devtools@6.1.40
  • @tanstack/svelte-query-persist-client@6.1.40
  • @tanstack/vue-query@5.102.1
  • @tanstack/vue-query-devtools@6.1.40
4 hours ago
react-query

@tanstack/solid-query-persist-client@5.102.1

Patch Changes

  • Updated dependencies []:
    • @tanstack/query-persist-client-core@5.102.1
    • @tanstack/solid-query@5.102.1
4 hours ago
react-query

@tanstack/react-query@5.102.1

Patch Changes

  • Updated dependencies [134890d]:
    • @tanstack/query-core@5.102.1
4 hours ago
react-query

@tanstack/solid-query-devtools@5.102.1

Patch Changes

  • Updated dependencies []:
    • @tanstack/query-devtools@5.102.1
    • @tanstack/solid-query@5.102.1
4 hours ago
react-query

@tanstack/svelte-query@6.1.40

Patch Changes

  • Updated dependencies [134890d]:
    • @tanstack/query-core@5.102.1
4 hours ago
react-query

@tanstack/svelte-query-persist-client@6.1.40

Patch Changes

  • Updated dependencies []:
    • @tanstack/query-persist-client-core@5.102.1
    • @tanstack/svelte-query@6.1.40