weasyprint-tsx 0.1.3 → 0.1.4

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 CHANGED
@@ -95,5 +95,5 @@ export default config;
95
95
  `@weasyprint-tsx/ui` provides print-optimized Preact components. See [`packages/ui/README.md`](packages/ui/README.md) for the full API.
96
96
 
97
97
  ```tsx
98
- import { H1, H2, Page, UL, LI, Table, Entry } from "@weasyprint-tsx/ui";
98
+ import { H1, H2, Page, UL, LI, Table, Entry, Chart } from "@weasyprint-tsx/ui";
99
99
  ```
package/bun.lock CHANGED
@@ -4,13 +4,10 @@
4
4
  "workspaces": {
5
5
  "": {
6
6
  "name": "@weasyprint-tsx/build",
7
- "dependencies": {
8
- "@fontsource-variable/public-sans": "^5.2.7",
9
- },
10
7
  },
11
8
  "packages/build": {
12
9
  "name": "@weasyprint-tsx/build",
13
- "version": "0.1.1",
10
+ "version": "0.1.5",
14
11
  "bin": {
15
12
  "weasyprint-tsx": "./src/cli.ts",
16
13
  },
@@ -31,15 +28,14 @@
31
28
  "bin": {
32
29
  "create-weasyprint-tsx": "cli.js",
33
30
  },
34
- "dependencies": {
35
- "highlight.js": "11.11.1",
36
- },
37
31
  },
38
32
  "packages/ui": {
39
33
  "name": "@weasyprint-tsx/ui",
40
- "version": "0.1.0",
34
+ "version": "0.1.7",
41
35
  "dependencies": {
42
- "highlight.js": "^11.11.1",
36
+ "@napi-rs/canvas": "^1.0.0",
37
+ "chart.js": "^4.5.1",
38
+ "highlight.js": "11.11.1",
43
39
  "katex": "^0.16.47",
44
40
  },
45
41
  },
@@ -55,8 +51,6 @@
55
51
 
56
52
  "@csstools/utilities": ["@csstools/utilities@3.0.0", "", { "peerDependencies": { "postcss": "^8.4" } }, "sha512-etDqA/4jYvOGBM6yfKCOsEXfH96BKztZdgGmGqKi2xHnDe0ILIBraRspwgYatJH9JsCZ5HCGoCst8w18EKOAdg=="],
57
53
 
58
- "@fontsource-variable/public-sans": ["@fontsource-variable/public-sans@5.2.7", "", {}, "sha512-4mvade2J3slKkvwRkS+p8T3szet/0vhWoSnuUJTVU81Uo2pRpSZY/Y8bSLRqpSwzIPxjVmRJ53oq6JKP/l/PSg=="],
59
-
60
54
  "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
61
55
 
62
56
  "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
@@ -67,6 +61,32 @@
67
61
 
68
62
  "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
69
63
 
64
+ "@kurkle/color": ["@kurkle/color@0.3.4", "", {}, "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="],
65
+
66
+ "@napi-rs/canvas": ["@napi-rs/canvas@1.0.0", "", { "optionalDependencies": { "@napi-rs/canvas-android-arm64": "1.0.0", "@napi-rs/canvas-darwin-arm64": "1.0.0", "@napi-rs/canvas-darwin-x64": "1.0.0", "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.0", "@napi-rs/canvas-linux-arm64-gnu": "1.0.0", "@napi-rs/canvas-linux-arm64-musl": "1.0.0", "@napi-rs/canvas-linux-riscv64-gnu": "1.0.0", "@napi-rs/canvas-linux-x64-gnu": "1.0.0", "@napi-rs/canvas-linux-x64-musl": "1.0.0", "@napi-rs/canvas-win32-arm64-msvc": "1.0.0", "@napi-rs/canvas-win32-x64-msvc": "1.0.0" } }, "sha512-Jqxcy1XOIqj+lH9sl1GT+il6GR3uQv13vI2mrwubP3uT8Olak2ClDrK2RnxlQKjwv8BRr4b3ug0YR7c6hBX8wg=="],
67
+
68
+ "@napi-rs/canvas-android-arm64": ["@napi-rs/canvas-android-arm64@1.0.0", "", { "os": "android", "cpu": "arm64" }, "sha512-3hNKJObUK7JsCF9aJlVCs1J0/KE/gGfZNeK8MO1ge6bB3aicr5walGme9t9No1f/oyk9GgvdAT/rjSdsx3gbIw=="],
69
+
70
+ "@napi-rs/canvas-darwin-arm64": ["@napi-rs/canvas-darwin-arm64@1.0.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ZIja19/BiGz2puhki+WUYSRriwFeFJ8Mi9eK3hZdSS85w4Y60cuEAJVhMCfKwswQkKkUtrnzdKMBuO7TupvexA=="],
71
+
72
+ "@napi-rs/canvas-darwin-x64": ["@napi-rs/canvas-darwin-x64@1.0.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-hImggWc82jqZVpEsFR9S7PE9OQYjq/H/D7vwCGB6X1jRH+UVBP1+1niJTPBOat1B154T6GKK7/kcFtoWgjgFzQ=="],
73
+
74
+ "@napi-rs/canvas-linux-arm-gnueabihf": ["@napi-rs/canvas-linux-arm-gnueabihf@1.0.0", "", { "os": "linux", "cpu": "arm" }, "sha512-hlJRy6d+kWLKVOG/+1rEvNQVURZ0DxxRPJsLmEWwhwiXZUJc0BF5o9esALHSEP4CoJK4wChRtj3hnyBgVx2oWA=="],
75
+
76
+ "@napi-rs/canvas-linux-arm64-gnu": ["@napi-rs/canvas-linux-arm64-gnu@1.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Hru4T3RXkosRQafcjelv7AUzw9mXqmGYsxnzeDDOWveFCJyEPMSJltvGCM+jfH98seOCbfwm9KyFg6Jm5FhAA=="],
77
+
78
+ "@napi-rs/canvas-linux-arm64-musl": ["@napi-rs/canvas-linux-arm64-musl@1.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-LTUl9jS8WsLSUGaxQZKQkxfluOJRpgvBuxxdM4pYcjib+di8AU4OzQc6+L6SzGMLcKc9H0RAjojRatBhTMqYdg=="],
79
+
80
+ "@napi-rs/canvas-linux-riscv64-gnu": ["@napi-rs/canvas-linux-riscv64-gnu@1.0.0", "", { "os": "linux", "cpu": "none" }, "sha512-Iz931SAZf+WVDzpjk52Q3ffW3zw0YflFwEZMgs036Wfu1kX/LrwT9wGjsuSqyduqefUkl91/vTdAjn8hQu5ezA=="],
81
+
82
+ "@napi-rs/canvas-linux-x64-gnu": ["@napi-rs/canvas-linux-x64-gnu@1.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-pFEQ5eFK4JusgN1K6KkO9DKP/Hi1WMJOkF8Ch03/khTc4bFbCKkCCsJG4YcOMOW9bI4XbT2/eMAWxhO0xaWgPA=="],
83
+
84
+ "@napi-rs/canvas-linux-x64-musl": ["@napi-rs/canvas-linux-x64-musl@1.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-jnvr8NrLHiZ3NCiOKWqDbkI4Ah+QDrqtZ+sddPZBltEb1mQ2coSvCSJYfict+oAwcm0c970oTmVySpjKP/lnaA=="],
85
+
86
+ "@napi-rs/canvas-win32-arm64-msvc": ["@napi-rs/canvas-win32-arm64-msvc@1.0.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-y2j9/Gfd5joqiqxdP/L1smqjQ+uAx3C4N0EC7bDHrnZEEH8ToM/OC5p3uHvtj4Lq591aHj+ArL01UDLNwT5HgQ=="],
87
+
88
+ "@napi-rs/canvas-win32-x64-msvc": ["@napi-rs/canvas-win32-x64-msvc@1.0.0", "", { "os": "win32", "cpu": "x64" }, "sha512-qwdhh9N6Gge/hC4pL9S1tQp0iKwhSl/dYjg7+RGp9k26iRGRi5MqqUyKGOXIWli0zOcuy5Y2wIH/jk2ry6i/jA=="],
89
+
70
90
  "@tailwindcss/node": ["@tailwindcss/node@4.3.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.21.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.0" } }, "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g=="],
71
91
 
72
92
  "@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.0", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.0", "@tailwindcss/oxide-darwin-arm64": "4.3.0", "@tailwindcss/oxide-darwin-x64": "4.3.0", "@tailwindcss/oxide-freebsd-x64": "4.3.0", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", "@tailwindcss/oxide-linux-x64-musl": "4.3.0", "@tailwindcss/oxide-wasm32-wasi": "4.3.0", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" } }, "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg=="],
@@ -107,6 +127,8 @@
107
127
 
108
128
  "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
109
129
 
130
+ "chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="],
131
+
110
132
  "commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
111
133
 
112
134
  "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weasyprint-tsx",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "bin": {
5
5
  "create-weasyprint-tsx": "bun packages/create/cli.ts",
6
6
  "build-weasyprint-tsx": "bun packages/build/src/cli.ts"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasyprint-tsx/build",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "main": "./src/index.ts",
5
5
  "exports": { ".": "./src/index.ts" },
6
6
  "types": "./src/index.ts",
@@ -46,7 +46,7 @@ export async function devMode(output?: string) {
46
46
 
47
47
  WATCH_DIRS.forEach((dir) =>
48
48
  watch(dir, { recursive: true }, async (_, f) => {
49
- process.stdout.write(`file changed ${f}`);
49
+ process.stdout.write(`file changed ${f}\n`);
50
50
  await rebuild();
51
51
  }),
52
52
  );
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasyprint-tsx/create",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "bin": {
5
5
  "create-weasyprint-tsx": "cli.js"
6
6
  },
@@ -114,6 +114,5 @@ See the full API: https://github.com/weasyprint-tsx/weasyprint-tsx/blob/main/pac
114
114
  - **No `@media screen`** — the document is rendered in print media; use `@media print` or no media query
115
115
  - **Page geometry** belongs in `@page` rules, not on `html` or `body`
116
116
  - **All layout** should use CSS that WeasyPrint supports. Flexbox and CSS Grid have partial support — prefer block layout or the `BlockBox`/`Block` components for multi-column content
117
- - **Components are Preact**, not React — use `class` not `className` for raw HTML elements (Preact accepts both, but prefer `class`)
118
117
  - **Images** must be embedded as base64 data URIs or served by the dev server; external URLs may not resolve during build
119
118
  - **Fonts** must be declared in CSS with `@font-face` or imported via Tailwind; Google Fonts CDN links work at build time
@@ -1,7 +1,6 @@
1
+ import { Chart, H1, H2, LI, UL } from "@weasyprint-tsx/ui";
1
2
  import "./index.css";
2
3
 
3
- import { H1, H2, LI, UL } from "@weasyprint-tsx/ui";
4
-
5
4
  export default function Document() {
6
5
  return (
7
6
  <html lang="en">
@@ -13,12 +12,33 @@ export default function Document() {
13
12
  <body>
14
13
  <H1>My Document</H1>
15
14
  <H2>Introduction</H2>
16
- <p>Edit <code>src/index.tsx</code> to start writing your document.</p>
15
+ <p>
16
+ Edit <code>src/index.tsx</code> to start writing your document.
17
+ </p>
17
18
  <UL>
18
- <LI>Use components from <code>@weasyprint-tsx/ui</code></LI>
19
- <LI>Style with Tailwind utility classes or plain CSS in <code>src/index.css</code></LI>
20
- <LI>Run <code>bun run dev</code> for live preview</LI>
19
+ <LI>
20
+ Use components from <code>@weasyprint-tsx/ui</code>
21
+ </LI>
22
+ <LI>
23
+ Style with Tailwind utility classes or plain CSS in{" "}
24
+ <code>src/index.css</code>
25
+ </LI>
26
+ <LI>
27
+ Run <code>bun run dev</code> for live preview
28
+ </LI>
21
29
  </UL>
30
+ <H2>Chart Example</H2>
31
+ <Chart
32
+ config={{
33
+ type: "bar",
34
+ data: {
35
+ labels: ["Jan", "Feb", "Mar"],
36
+ datasets: [{ label: "Sales", data: [12, 8, 21] }],
37
+ },
38
+ }}
39
+ width={600}
40
+ height={300}
41
+ />
22
42
  </body>
23
43
  </html>
24
44
  );
@@ -276,3 +276,77 @@ LaTeX equation rendering via KaTeX.
276
276
  | `displayMode` | `boolean` | `false` | Render as block-level equation |
277
277
  | `aligned` | `boolean` | `false` | Wrap in `\begin{aligned}…\end{aligned}` |
278
278
  | `chemical` | `boolean` | `false` | Wrap in `\ce{…}` for chemical notation |
279
+
280
+ ---
281
+
282
+ ## Chart
283
+
284
+ Renders a [chart.js](https://www.chartjs.org/) chart server-side as a base64-encoded PNG `<img>`.
285
+
286
+ ### `Chart`
287
+
288
+ ```tsx
289
+ import type { ChartConfiguration } from "chart.js";
290
+ import { Chart } from "@weasyprint-tsx/ui";
291
+
292
+ const config: ChartConfiguration = {
293
+ type: "bar",
294
+ data: {
295
+ labels: ["Jan", "Feb", "Mar"],
296
+ datasets: [{ label: "Sales", data: [12, 8, 21] }],
297
+ },
298
+ };
299
+
300
+ <Chart config={config} width={600} height={300} />
301
+ ```
302
+
303
+ | Prop | Type | Default | Description |
304
+ |------|------|---------|-------------|
305
+ | `config` | `ChartConfiguration` | — | chart.js configuration object |
306
+ | `width` | `number` | `800` | Canvas width in pixels |
307
+ | `height` | `number` | `500` | Canvas height in pixels |
308
+ | `...rest` | `Omit<ComponentProps<"img">, "src">` | — | All standard `<img>` attributes except `src` |
309
+
310
+ ---
311
+
312
+ ### `chartFunction`
313
+
314
+ Samples a numeric function into a data array for chart datasets. Produces `sample + 1` values evaluated at `n * step` for `n` in `0..sample`.
315
+
316
+ ```ts
317
+ chartFunction(func, options?)
318
+ ```
319
+
320
+ | Param | Type | Default | Description |
321
+ |-------|------|---------|-------------|
322
+ | `func` | `(n: number) => number` | — | Function to sample |
323
+ | `options.step` | `number` | `1` | Multiplier applied to the index before calling `func` |
324
+ | `options.sample` | `number` | `100` | Number of intervals (yields `sample + 1` points) |
325
+
326
+ ```tsx
327
+ import { Chart, chartFunction } from "@weasyprint-tsx/ui";
328
+
329
+ <Chart config={{
330
+ type: "line",
331
+ data: {
332
+ labels: chartFunction(n => n, { step: 0.1 }),
333
+ datasets: [{ label: "sin(x)", data: chartFunction(Math.sin, { step: 0.1 }) }],
334
+ },
335
+ }} />
336
+ ```
337
+
338
+ ---
339
+
340
+ ### `labelFunction`
341
+
342
+ Same as `chartFunction` but the sampling function may return a `number` or `string`. Use to generate axis labels.
343
+
344
+ ```ts
345
+ labelFunction(func, options?)
346
+ ```
347
+
348
+ | Param | Type | Default | Description |
349
+ |-------|------|---------|-------------|
350
+ | `func` | `(n: number) => number \| string` | — | Function to sample |
351
+ | `options.step` | `number` | `1` | Multiplier applied to the index |
352
+ | `options.sample` | `number` | `100` | Number of intervals (yields `sample + 1` values) |
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@weasyprint-tsx/ui",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "exports": {
5
5
  ".": "./src/index.ts"
6
6
  },
7
7
  "types": "./src/index.ts",
8
8
  "dependencies": {
9
+ "@napi-rs/canvas": "^1.0.0",
10
+ "chart.js": "^4.5.1",
9
11
  "highlight.js": "11.11.1",
10
12
  "katex": "^0.16.47"
11
13
  }
@@ -0,0 +1,54 @@
1
+ import { createCanvas } from "@napi-rs/canvas";
2
+ import type { ChartConfiguration } from "chart.js";
3
+ import { Chart as ChartJS } from "chart.js/auto";
4
+ import { ComponentProps } from "preact";
5
+
6
+ export interface ChartProps extends Omit<ComponentProps<"img">, "src"> {
7
+ config: ChartConfiguration;
8
+ width?: number;
9
+ height?: number;
10
+ }
11
+
12
+ export function Chart({
13
+ config,
14
+ width = 800,
15
+ height = 500,
16
+ ...props
17
+ }: ChartProps) {
18
+ const canvas = createCanvas(width, height);
19
+
20
+ const chart = new ChartJS(canvas as unknown as HTMLCanvasElement, {
21
+ ...config,
22
+ options: {
23
+ ...config.options,
24
+ animation: false,
25
+ responsive: false,
26
+ },
27
+ });
28
+
29
+ const dataUrl = `data:image/png;base64,${canvas.toBuffer("image/png").toString("base64")}`;
30
+ chart.destroy();
31
+
32
+ return <img src={dataUrl} width={width} height={height} {...props} />;
33
+ }
34
+
35
+ type FunctionOptions = {
36
+ step?: number;
37
+ sample?: number;
38
+ };
39
+
40
+ export function chartFunction(
41
+ func: (n: number) => number,
42
+ options?: FunctionOptions,
43
+ ) {
44
+ const { sample = 100, step = 1 } = options ?? {};
45
+ return Array.from({ length: sample + 1 }, (_, n) => func(n * step));
46
+ }
47
+
48
+ export function labelFunction(
49
+ func: (n: number) => number | string,
50
+ options?: FunctionOptions
51
+ ) {
52
+ const { sample = 100, step = 1 } = options ?? {};
53
+ return Array.from({ length: sample + 1 }, (_, n) => func(n * step));
54
+ }
@@ -1,3 +1,5 @@
1
+ export { Chart, chartFunction, labelFunction } from "./Chart";
2
+ export type { ChartProps } from "./Chart";
1
3
  export { Block, BlockBox } from "./BlockBox";
2
4
  export type { BlockBoxProps, BlockProps } from "./BlockBox";
3
5
  export { CodeBlock } from "./CodeBlock";