renderpdf-js 0.0.0-stage → 0.1.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.
@@ -0,0 +1,20 @@
1
+ import type { RegisteredFont } from './api-types.js';
2
+ import type { LayoutSnapshot } from './types.js';
3
+ /** Prepare browser resources, then snapshot the supported static DOM subset without changing it.
4
+ * @param root Connected, visible HTMLElement whose existing browser layout is exported.
5
+ * @param fonts Explicit faces used both by the browser and PDF embedding.
6
+ * @param options Whether safe local effects may choose raster boundaries automatically.
7
+ */
8
+ export declare function snapshotLayout(root: HTMLElement, fonts: readonly RegisteredFont[], options?: {
9
+ /** Strict mode keeps native errors unless a boundary has explicit data-raster markup. */
10
+ fallback?: 'auto' | 'strict';
11
+ }): Promise<LayoutSnapshot>;
12
+ /** Measure settled browser resources synchronously so a source guard can share the same task.
13
+ * @param root Connected, visible HTMLElement with its fonts and source images already prepared.
14
+ * @param fonts Exact registered faces used both by the browser and PDF embedding.
15
+ * @param options Whether safe local effects may choose raster boundaries automatically.
16
+ */
17
+ export declare function measurePreparedLayout(root: HTMLElement, fonts: readonly RegisteredFont[], options?: {
18
+ /** Strict mode keeps native errors unless a boundary has explicit data-raster markup. */
19
+ fallback?: 'auto' | 'strict';
20
+ }): LayoutSnapshot;
package/dist/page.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import type { PageGeometry, RenderPDFOptions } from './api-types.js';
2
+ /** Resolve physical paper dimensions and validate the small public option surface. */
3
+ export declare function resolvePage(
4
+ /** Caller-owned options; resolving them never changes their values. */
5
+ options: RenderPDFOptions): PageGeometry;
@@ -0,0 +1,17 @@
1
+ import type { RenderWarning } from './diagnostics.js';
2
+ import type { LayoutSnapshot } from './types.js';
3
+ /** One source-coordinate interval mapped into a PDF page. */
4
+ export interface PageSlice {
5
+ /** Inclusive source top in CSS pixels. */
6
+ start: number;
7
+ /** Exclusive source bottom in CSS pixels. */
8
+ end: number;
9
+ }
10
+ /** Map one continuous source into pages with required cuts and best-effort CSS avoidance. */
11
+ export declare function paginate(
12
+ /** Browser-measured display list plus optional CSS page-break metadata. */
13
+ snapshot: LayoutSnapshot,
14
+ /** Usable height after top/bottom page margins, in CSS pixels. */
15
+ contentHeight: number,
16
+ /** Optional observer for a preference that cannot fit without splitting native content. */
17
+ onWarning?: (warning: RenderWarning) => void): PageSlice[];
package/dist/pdf.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type { PageGeometry, RegisteredFont } from './api-types.js';
2
+ import type { PageSlice } from './pagination.js';
3
+ import type { LayoutSnapshot } from './types.js';
4
+ /** Bounded writer settings independent of DOM layout measurement. */
5
+ export interface PDFWriteOptions {
6
+ /** Physical pixels per CSS pixel for explicitly selected raster regions. */
7
+ rasterScale?: number;
8
+ /** Include extraction-only text inside a region already painted as a bitmap. */
9
+ includeRasterText?: boolean;
10
+ /** Stop before beginning subsequent asynchronous writing stages. */
11
+ signal?: AbortSignal;
12
+ }
13
+ /** Serialized PDF and the exact source intervals used for page ownership. */
14
+ export interface PDFWriteResult {
15
+ /** Complete PDF file owned by this export. */
16
+ bytes: Uint8Array;
17
+ /** Shared source offsets for visible objects and extraction text. */
18
+ slices: PageSlice[];
19
+ }
20
+ /** Serialize a measured display list with consistent ordered paint and page mapping. */
21
+ export declare function writePDF(
22
+ /** Prepared source geometry; this adapter never performs DOM measurement. */
23
+ snapshot: LayoutSnapshot,
24
+ /** Exact font programs already registered for source browser layout. */
25
+ fonts: readonly RegisteredFont[],
26
+ /** Validated physical page and per-edge margins, in CSS pixels. */
27
+ geometry: PageGeometry,
28
+ /** Validated source intervals planned before diagnostics and any PDF allocation. */
29
+ slices: PageSlice[],
30
+ /** Optional raster quality and cancellation controls. */
31
+ options?: PDFWriteOptions): Promise<PDFWriteResult>;
@@ -0,0 +1,9 @@
1
+ /** Identify only effects that a bounded subtree can reproduce without surrounding pixels.
2
+ * @param style Browser-computed declarations; native layout and typography remain unchanged.
3
+ */
4
+ export declare function automaticRasterReason(style: CSSStyleDeclaration): string | undefined;
5
+ /** Require a single formatting box that can be cloned into an independent rectangular viewport.
6
+ * @param element Candidate selected for its own local visual effects.
7
+ * @param style Browser-computed display mode for the candidate.
8
+ */
9
+ export declare function assertAutomaticRasterBoundary(element: HTMLElement, style: CSSStyleDeclaration): void;
@@ -0,0 +1,17 @@
1
+ /** Wait for one browser stage while releasing the cancellation listener on every outcome. */
2
+ export declare function withCancellation<T>(
3
+ /** Work whose underlying browser API may not itself accept an AbortSignal. */
4
+ pending: Promise<T>,
5
+ /** Optional application cancellation. */
6
+ signal?: AbortSignal): Promise<T>;
7
+ /** Observe caller ownership throughout preparation, capture and asynchronous PDF writing. */
8
+ export declare function prepareSource(
9
+ /** Connected browser element; a live source is measured without cloning application state. */
10
+ root: HTMLElement,
11
+ /** Optional cancellation for fonts and image preparation. */
12
+ signal?: AbortSignal): {
13
+ ready: () => Promise<void>;
14
+ captureBaseline: () => void;
15
+ assertUnchanged: () => void;
16
+ dispose: () => void;
17
+ };
@@ -0,0 +1,20 @@
1
+ import type { RegisteredFont } from './api-types.js';
2
+ /**
3
+ * Captures one explicitly isolated, self-contained HTML region as PNG bytes.
4
+ * Gradients, rounded corners and inset shadows remain browser-painted. Effects
5
+ * involving a backdrop, external assets or pixels beyond the box fail explicitly.
6
+ */
7
+ export declare function captureRaster(
8
+ /** Connected source region; capture never mutates its DOM. */
9
+ element: HTMLElement,
10
+ /** Font bytes also used to lay out the original browser document. */
11
+ fonts: readonly RegisteredFont[],
12
+ /** Physical bitmap pixels per CSS pixel. */
13
+ scale: number,
14
+ /** Fractional CSS origin retained inside a bitmap placed on an integer pixel grid. */
15
+ offset?: {
16
+ /** Horizontal transparent padding in CSS pixels, from zero inclusive to one exclusive. */
17
+ x: number;
18
+ /** Vertical transparent padding in CSS pixels, from zero inclusive to one exclusive. */
19
+ y: number;
20
+ }): Promise<Uint8Array>;
@@ -0,0 +1,21 @@
1
+ import type { RenderPDFOptions, RenderPDFResult } from './api-types.js';
2
+ import { type RenderWarning } from './diagnostics.js';
3
+ /** Measure a stable browser element and export supported paint as selectable, paginated PDF. */
4
+ export declare function renderDocument(
5
+ /** Connected source in the current browser document; its width and markup stay caller-owned. */
6
+ element: HTMLElement,
7
+ /** Explicit fonts and the small supported page, raster and diagnostic options. */
8
+ options: RenderPDFOptions,
9
+ /** Research-only switch for comparing visible pixels without the invisible text layer. */
10
+ includeRasterText?: boolean): Promise<{
11
+ snapshot: import("./types.js").LayoutSnapshot;
12
+ warnings: RenderWarning[];
13
+ bytes: Uint8Array;
14
+ slices: import("./pagination.js").PageSlice[];
15
+ }>;
16
+ /** Export a stable browser element through the minimal public PDF API. */
17
+ export declare function renderPDF(
18
+ /** Connected source; browser layout and caller-owned markup remain unchanged. */
19
+ element: HTMLElement,
20
+ /** Explicit font programs and supported conversion options. */
21
+ options: RenderPDFOptions): Promise<RenderPDFResult>;
@@ -0,0 +1,10 @@
1
+ import type { RenderPDFResult } from './api-types.js';
2
+ import type { RenderWarning } from './diagnostics.js';
3
+ /** Retain immutable PDF output and expose browser-native forms without re-rendering the source. */
4
+ export declare function createResult(
5
+ /** Complete successfully written PDF bytes; never expose this owned buffer directly. */
6
+ bytes: Uint8Array,
7
+ /** Physical PDF page count from the shared page mapping. */
8
+ pageCount: number,
9
+ /** Export diagnostics, copied and frozen to preserve the original outcome. */
10
+ warnings: readonly RenderWarning[]): RenderPDFResult;
package/dist/text.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { PDFHexString } from 'pdf-lib';
2
+ import type { PDFDocument, PDFFont } from 'pdf-lib';
3
+ /** One encoded glyph at its shaped origin, in unscaled font units. */
4
+ export interface PositionedGlyph {
5
+ /** Authoritative PDF encoding returned by the public font adapter. */
6
+ encoded: PDFHexString;
7
+ /** Horizontal pen position including the font's placement offset. */
8
+ x: number;
9
+ /** Vertical pen position including the font's placement offset, positive upward. */
10
+ y: number;
11
+ }
12
+ /** Reusable shaping state for one exact static font during a single export. */
13
+ export declare class PositionedFont {
14
+ readonly font: PDFFont;
15
+ /** Original font metrics and OpenType positioning owned by this export. */
16
+ private readonly program;
17
+ /** Identical words share shaping work without sharing browser coordinates. */
18
+ private readonly words;
19
+ /** Used glyph mappings include GSUB ligatures without Unicode cmap entries. */
20
+ private readonly unicode;
21
+ /** Used substituted glyphs also need nominal PDF widths even without cmap entries. */
22
+ private readonly widths;
23
+ /** Font units per em, used to convert shaped origins without stretching outlines. */
24
+ readonly unitsPerEm: number;
25
+ /** Own a shaper matching the font program embedded through pdf-lib.
26
+ * @param font Public PDF font whose encoding remains authoritative.
27
+ * @param bytes Exact registered program shared with browser layout.
28
+ */
29
+ constructor(font: PDFFont, bytes: Uint8Array);
30
+ /** Shape one browser-measured word while retaining kerning, ligatures and marks.
31
+ * @param text Complete word; splitting into characters would lose OpenType context.
32
+ * @param kerning Whether CSS admits kerning for this line.
33
+ */
34
+ shape(text: string, kerning?: boolean): readonly PositionedGlyph[];
35
+ /** Preserve extraction for every used shaped glyph, including uncoded ligatures.
36
+ * @param document Export document owning the public font reference and object context.
37
+ */
38
+ embedUnicode(document: PDFDocument): Promise<void>;
39
+ }
@@ -0,0 +1,96 @@
1
+ import type { RenderWarning } from './diagnostics.js';
2
+ /** A rectangle relative to the source root, measured in CSS pixels. */
3
+ export interface Bounds {
4
+ /** Horizontal distance from the root's left edge. */
5
+ x: number;
6
+ /** Vertical distance from the root's top edge. */
7
+ y: number;
8
+ /** Browser-measured width. */
9
+ width: number;
10
+ /** Browser-measured height. */
11
+ height: number;
12
+ }
13
+ /** A browser-measured line of selectable text. */
14
+ export interface TextOperation {
15
+ /** Discriminant for ordered paint dispatch. */
16
+ kind: 'text';
17
+ /** Line fragment bounds in root CSS pixels. */
18
+ bounds: Bounds;
19
+ /** Browser-resolved visible text for this line. */
20
+ text: string;
21
+ /** Browser-measured words retain native origins without accumulating run-width drift. */
22
+ runs: {
23
+ /** Word text, retaining ligatures and non-breaking spaces within each run. */
24
+ text: string;
25
+ /** Horizontal word origin relative to the source root, in CSS pixels. */
26
+ x: number;
27
+ /** Browser-measured word advance width in CSS pixels. */
28
+ width: number;
29
+ }[];
30
+ /** Baseline position relative to the root's top edge. */
31
+ baseline: number;
32
+ /** CSS font size in pixels. */
33
+ fontSize: number;
34
+ /** Exact registered family selected by the browser-facing font contract. */
35
+ family: string;
36
+ /** Registered face weight. */
37
+ weight: number;
38
+ /** Registered face style. */
39
+ style: 'normal' | 'italic';
40
+ /** Disable OpenType kerning when the browser explicitly selects font-kerning: none. */
41
+ kerning?: boolean;
42
+ /** Computed CSS rgb/rgba text color. */
43
+ color: string;
44
+ /** True for extraction-only text inside a raster subtree. */
45
+ invisible: boolean;
46
+ }
47
+ /** A supported axis-aligned box painted by native PDF operations. */
48
+ export interface BoxOperation {
49
+ /** Discriminant for ordered paint dispatch. */
50
+ kind: 'box';
51
+ /** Border-box geometry in root CSS pixels. */
52
+ bounds: Bounds;
53
+ /** Computed solid background. */
54
+ background: string;
55
+ /** Uniform border color. */
56
+ borderColor: string;
57
+ /** Uniform border width in CSS pixels. */
58
+ borderWidth: number;
59
+ }
60
+ /** An explicitly isolated DOM subtree captured at its paint-order position. */
61
+ export interface RasterOperation {
62
+ /** Discriminant for ordered paint dispatch. */
63
+ kind: 'raster';
64
+ /** Region in root CSS pixels; effects must stay within this box. */
65
+ bounds: Bounds;
66
+ /** Live source used only by the browser capture adapter. */
67
+ element: HTMLElement;
68
+ }
69
+ /** An image source embedded once as a PDF image object. */
70
+ export interface ImageOperation {
71
+ /** Discriminant for ordered paint dispatch. */
72
+ kind: 'image';
73
+ /** Browser-measured image border box. */
74
+ bounds: Bounds;
75
+ /** Decoded image source; experiment fixtures use self-contained PNGs. */
76
+ element: HTMLImageElement;
77
+ }
78
+ /** A flattened, ordered experiment display list, not a general CSS paint tree. */
79
+ export type PaintOperation = TextOperation | BoxOperation | RasterOperation | ImageOperation;
80
+ /** Immutable geometry metadata plus a bounded list of ordered paint operations. */
81
+ export interface LayoutSnapshot {
82
+ /** Measured root width in CSS pixels. */
83
+ width: number;
84
+ /** Measured root height in CSS pixels. */
85
+ height: number;
86
+ /** Operations in the supported static DOM paint order. */
87
+ operations: PaintOperation[];
88
+ /** Explicitly diagnosed approximations and unsupported behavior. */
89
+ warnings: RenderWarning[];
90
+ /** Indivisible browser-measured table rows and spanning cells, in root CSS pixels. */
91
+ atomicBounds?: Bounds[];
92
+ /** Forced CSS page boundaries in source coordinates; zero/end boundaries create no empty pages. */
93
+ forcedBreaks?: number[];
94
+ /** Preferred indivisible blocks; oversized preferences may relax with an explicit warning. */
95
+ avoidBreakBounds?: Bounds[];
96
+ }
package/package.json CHANGED
@@ -1,6 +1,78 @@
1
1
  {
2
2
  "name": "renderpdf-js",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Browser-only HTML to PDF renderer with explicit fonts and local raster regions",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/MichalekJan93/renderPDF.js.git"
9
+ },
10
+ "homepage": "https://github.com/MichalekJan93/renderPDF.js#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/MichalekJan93/renderPDF.js/issues"
13
+ },
14
+ "keywords": [
15
+ "pdf",
16
+ "html",
17
+ "browser",
18
+ "typescript",
19
+ "html-to-pdf"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public",
23
+ "registry": "https://registry.npmjs.org/"
24
+ },
25
+ "type": "module",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
30
+ }
31
+ },
32
+ "types": "./dist/index.d.ts",
33
+ "sideEffects": false,
34
+ "files": [
35
+ "dist/index.js",
36
+ "dist/*.d.ts",
37
+ "README.md",
38
+ "LICENSE",
39
+ "assets/renderpdf-logo.png"
40
+ ],
41
+ "engines": {
42
+ "node": ">=22.13.0"
43
+ },
44
+ "scripts": {
45
+ "dev": "vp dev --host 127.0.0.1",
46
+ "build": "npm run build:library",
47
+ "build:library": "npm run typecheck && vp build --config vite.library.config.ts && tsc -p tsconfig.build.json",
48
+ "prepack": "npm run build:library && npm run check:package",
49
+ "check:package": "node scripts/check-package.ts",
50
+ "typecheck": "vp check --no-fmt --no-lint",
51
+ "test": "vp test",
52
+ "test:browser": "playwright test",
53
+ "benchmark": "npm run build:library && playwright test --config playwright.benchmark.config.ts",
54
+ "lint": "vp lint",
55
+ "format": "vp fmt",
56
+ "format:check": "vp fmt --check",
57
+ "check": "vp check && npm test && npm run test:browser && npm run build && npm run check:package"
58
+ },
59
+ "dependencies": {
60
+ "@pdf-lib/fontkit": "^1.1.1",
61
+ "html-to-image": "^1.11.13",
62
+ "pdf-lib": "^1.17.1"
63
+ },
64
+ "devDependencies": {
65
+ "@playwright/test": "^1.64.1",
66
+ "@types/node": "^26.6.5",
67
+ "@types/pngjs": "^6.0.5",
68
+ "pdfjs-dist": "^6.4.299",
69
+ "pixelmatch": "^8.0.0",
70
+ "pngjs": "^7.0.0",
71
+ "typescript": "^6.0.3",
72
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
73
+ "vite-plus": "1.4.0"
74
+ },
75
+ "overrides": {
76
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.4.0"
77
+ }
78
+ }