weasyprint-tsx 0.1.0 → 0.1.2
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.pdf +0 -0
- package/bun.lock +22 -4
- package/package.json +7 -2
- package/packages/build/package.json +1 -1
- package/packages/build/src/build.ts +9 -9
- package/packages/build/src/config.ts +2 -2
- package/packages/build/src/orchestrator.ts +8 -14
- package/packages/build/src/server.ts +4 -5
- package/packages/ui/package.json +6 -2
- package/packages/ui/src/BlockBox.tsx +8 -5
- package/packages/ui/src/CodeBlock.module.css +4 -0
- package/packages/ui/src/CodeBlock.tsx +21 -3
- package/packages/ui/src/DotLine.tsx +1 -1
- package/packages/ui/src/Equation.tsx +53 -4
- package/packages/ui/src/List.tsx +4 -4
- package/packages/ui/src/Page.tsx +1 -1
- package/packages/ui/src/Stack.module.css +9 -0
- package/packages/ui/src/Stack.tsx +24 -0
- package/packages/ui/src/Table.tsx +1 -1
- package/packages/ui/src/Title.module.css +40 -32
- package/packages/ui/src/Titles.tsx +3 -3
- package/packages/ui/src/index.ts +16 -1
- package/src/index.css +7 -2
- package/src/index.tsx +271 -128
- package/testUI/index.css +1 -0
- package/testUI/index.tsx +22 -0
- package/weasyprint-tsx.config.ts +9 -1
package/ReadMe.pdf
CHANGED
|
Binary file
|
package/bun.lock
CHANGED
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
"workspaces": {
|
|
5
5
|
"": {
|
|
6
6
|
"name": "@weasyprint-tsx/build",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@fontsource-variable/public-sans": "^5.2.7",
|
|
9
|
+
},
|
|
7
10
|
},
|
|
8
11
|
"packages/build": {
|
|
9
12
|
"name": "@weasyprint-tsx/build",
|
|
10
|
-
"version": "0.
|
|
13
|
+
"version": "0.1.1",
|
|
11
14
|
"bin": {
|
|
12
15
|
"weasyprint-tsx": "./src/cli.ts",
|
|
13
16
|
},
|
|
@@ -24,14 +27,21 @@
|
|
|
24
27
|
},
|
|
25
28
|
"packages/create": {
|
|
26
29
|
"name": "@weasyprint-tsx/create",
|
|
27
|
-
"version": "0.0
|
|
30
|
+
"version": "0.1.0",
|
|
28
31
|
"bin": {
|
|
29
|
-
"create-weasyprint-tsx": "
|
|
32
|
+
"create-weasyprint-tsx": "cli.js",
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"highlight.js": "11.11.1",
|
|
30
36
|
},
|
|
31
37
|
},
|
|
32
38
|
"packages/ui": {
|
|
33
39
|
"name": "@weasyprint-tsx/ui",
|
|
34
|
-
"version": "0.0
|
|
40
|
+
"version": "0.1.0",
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"highlight.js": "^11.11.1",
|
|
43
|
+
"katex": "^0.16.47",
|
|
44
|
+
},
|
|
35
45
|
},
|
|
36
46
|
},
|
|
37
47
|
"packages": {
|
|
@@ -45,6 +55,8 @@
|
|
|
45
55
|
|
|
46
56
|
"@csstools/utilities": ["@csstools/utilities@3.0.0", "", { "peerDependencies": { "postcss": "^8.4" } }, "sha512-etDqA/4jYvOGBM6yfKCOsEXfH96BKztZdgGmGqKi2xHnDe0ILIBraRspwgYatJH9JsCZ5HCGoCst8w18EKOAdg=="],
|
|
47
57
|
|
|
58
|
+
"@fontsource-variable/public-sans": ["@fontsource-variable/public-sans@5.2.7", "", {}, "sha512-4mvade2J3slKkvwRkS+p8T3szet/0vhWoSnuUJTVU81Uo2pRpSZY/Y8bSLRqpSwzIPxjVmRJ53oq6JKP/l/PSg=="],
|
|
59
|
+
|
|
48
60
|
"@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=="],
|
|
49
61
|
|
|
50
62
|
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
|
@@ -95,14 +107,20 @@
|
|
|
95
107
|
|
|
96
108
|
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
|
97
109
|
|
|
110
|
+
"commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
|
|
111
|
+
|
|
98
112
|
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
99
113
|
|
|
100
114
|
"enhanced-resolve": ["enhanced-resolve@5.24.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ=="],
|
|
101
115
|
|
|
102
116
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
|
103
117
|
|
|
118
|
+
"highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="],
|
|
119
|
+
|
|
104
120
|
"jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
|
|
105
121
|
|
|
122
|
+
"katex": ["katex@0.16.47", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg=="],
|
|
123
|
+
|
|
106
124
|
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
|
107
125
|
|
|
108
126
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "weasyprint-tsx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"bin": {
|
|
5
|
+
"create-weasyprint-tsx": "bun packages/create/cli.ts",
|
|
6
|
+
"build-weasyprint-tsx": "bun packages/build/src/cli.ts"
|
|
7
|
+
},
|
|
4
8
|
"scripts": {
|
|
5
9
|
"dev": "bun packages/build/src/cli.ts --watch",
|
|
6
|
-
"init"
|
|
10
|
+
"init": "bun packages/create/cli.ts",
|
|
11
|
+
"build": "bun packages/build/src/cli.ts"
|
|
7
12
|
},
|
|
8
13
|
"workspaces": [
|
|
9
14
|
"packages/*"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { DConfig } from "./config";
|
|
1
|
+
import tailwindcss from "@tailwindcss/postcss";
|
|
3
2
|
import { BunPlugin } from "bun";
|
|
3
|
+
import { join } from "path";
|
|
4
4
|
import postcss from "postcss";
|
|
5
5
|
import customProperties from "postcss-custom-properties";
|
|
6
|
-
import tailwindcss from "@tailwindcss/postcss";
|
|
7
|
-
import { injectDevScript } from "./server";
|
|
8
6
|
import { h } from "preact";
|
|
9
7
|
import { renderToStaticMarkup } from "preact-render-to-string";
|
|
8
|
+
import { DConfig } from "./config";
|
|
9
|
+
import { DEV_SCRIPT } from "./server";
|
|
10
10
|
|
|
11
11
|
const tailwindPlugin: BunPlugin = {
|
|
12
12
|
name: "tailwind-postcss",
|
|
@@ -49,17 +49,17 @@ export async function buildHTML(cfg: DConfig, dev: boolean = false) {
|
|
|
49
49
|
join(BUILD_DIR, `index.js?t=${performance.now()}`)
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
await Bun.write(BUILD_PATH, html);
|
|
52
|
+
let html = "<!DOCTYPE html>" + renderToStaticMarkup(h(Document, {}));
|
|
55
53
|
|
|
56
54
|
if (dev) {
|
|
57
|
-
|
|
55
|
+
html = html.replace("</html>", `${DEV_SCRIPT}</html>`);
|
|
58
56
|
}
|
|
57
|
+
await Bun.write(BUILD_PATH, html);
|
|
59
58
|
process.stdout.write(
|
|
60
59
|
`Bun HTML build -- ${(performance.now() - t0).toFixed(2)}ms\n`,
|
|
61
60
|
);
|
|
62
|
-
|
|
61
|
+
const css = await Bun.file(join(BUILD_DIR, "index.css")).text();
|
|
62
|
+
return Bun.hash(html + css);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function buildArgs(cfg: DConfig): string[] {
|
|
@@ -24,7 +24,7 @@ export interface Config {
|
|
|
24
24
|
};
|
|
25
25
|
dev?: {
|
|
26
26
|
port?: number;
|
|
27
|
-
watch?: string;
|
|
27
|
+
watch?: string[];
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -44,7 +44,7 @@ const defaultConfig = {
|
|
|
44
44
|
},
|
|
45
45
|
dev: {
|
|
46
46
|
port: 3000,
|
|
47
|
-
watch: "src",
|
|
47
|
+
watch: ["src"],
|
|
48
48
|
},
|
|
49
49
|
} satisfies Config;
|
|
50
50
|
|
|
@@ -1,28 +1,20 @@
|
|
|
1
1
|
import { watch } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
2
3
|
import { buildHTML, buildPDF } from "./build";
|
|
3
4
|
import { loadConfig } from "./config";
|
|
4
5
|
import { bumpPing, startServer } from "./server";
|
|
5
|
-
import { join } from "path";
|
|
6
6
|
|
|
7
7
|
export async function buildOnce(output?: string) {
|
|
8
8
|
const cfg = await loadConfig();
|
|
9
9
|
if (output) cfg.io.output = output;
|
|
10
|
-
let t0 = performance.now();
|
|
11
10
|
|
|
12
11
|
await buildHTML(cfg);
|
|
13
|
-
process.stdout.write(
|
|
14
|
-
`Bun HTML build -- ${(performance.now() - t0).toFixed(2)} ms`,
|
|
15
|
-
);
|
|
16
12
|
await buildPDF(cfg);
|
|
17
|
-
t0 = performance.now();
|
|
18
|
-
process.stdout.write(
|
|
19
|
-
`Weasyprint PDF build -- ${(performance.now() - t0).toFixed(2)} ms → ${cfg.io.output}`,
|
|
20
|
-
);
|
|
21
13
|
}
|
|
22
14
|
|
|
23
15
|
export async function devMode(output?: string) {
|
|
24
16
|
const cfg = await loadConfig();
|
|
25
|
-
const
|
|
17
|
+
const WATCH_DIRS = cfg.dev.watch.map((p) => join(process.cwd(), p));
|
|
26
18
|
|
|
27
19
|
if (output) cfg.io.output = cfg.io.output ?? output;
|
|
28
20
|
process.stdout.write(`Dev: http://localhost:${cfg.dev.port}`);
|
|
@@ -52,10 +44,12 @@ export async function devMode(output?: string) {
|
|
|
52
44
|
|
|
53
45
|
startServer(cfg.dev.port, cfg.io.buildDir);
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
WATCH_DIRS.forEach((dir) =>
|
|
48
|
+
watch(dir, { recursive: true }, async (_, f) => {
|
|
49
|
+
process.stdout.write(`file changed ${f}`);
|
|
50
|
+
await rebuild();
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
59
53
|
|
|
60
54
|
await Bun.sleep(Infinity);
|
|
61
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from "path";
|
|
2
2
|
|
|
3
|
-
const DEV_SCRIPT = `<script>var _t=null;setInterval(function(){fetch('/__dev_ping').then(function(r){return r.text();}).then(function(s){if(_t!==null&&s!==_t)location.reload();_t=s;}).catch(function(){});},
|
|
3
|
+
export const DEV_SCRIPT = `<script>var _t=null;setInterval(function(){fetch('/__dev_ping').then(function(r){return r.text();}).then(function(s){if(_t!==null&&s!==_t)location.reload();_t=s;}).catch(function(){});},1000);</script>`;
|
|
4
4
|
|
|
5
5
|
let pingCounter = 0;
|
|
6
6
|
|
|
@@ -19,8 +19,9 @@ export function startServer(port: number, buildDir: string): void {
|
|
|
19
19
|
headers: { "Cache-Control": "no-store" },
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const pathname = url.pathname === "/" ? "/index.html" : url.pathname;
|
|
23
|
+
if (pathname == "/favicon.ico") return new Response(null);
|
|
24
|
+
const file = Bun.file(join(process.cwd(), buildDir, pathname));
|
|
24
25
|
return new Response(file);
|
|
25
26
|
},
|
|
26
27
|
});
|
|
@@ -29,8 +30,6 @@ export function startServer(port: number, buildDir: string): void {
|
|
|
29
30
|
export async function injectDevScript(htmlPath: string): Promise<void> {
|
|
30
31
|
let html = await Bun.file(htmlPath).text();
|
|
31
32
|
if (!html.includes("/__dev_ping")) {
|
|
32
|
-
html = html.replace("</html>", `${DEV_SCRIPT}</html>`);
|
|
33
33
|
await Bun.write(htmlPath, html);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
|
package/packages/ui/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasyprint-tsx/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": "./src/index.ts"
|
|
6
6
|
},
|
|
7
|
-
"types": "./src/index.ts"
|
|
7
|
+
"types": "./src/index.ts",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"highlight.js": "11.11.1",
|
|
10
|
+
"katex": "^0.16.47"
|
|
11
|
+
}
|
|
8
12
|
}
|
|
@@ -2,7 +2,7 @@ import { ComponentProps, toChildArray, VNode } from "preact";
|
|
|
2
2
|
import styles from "./BlockBox.module.css";
|
|
3
3
|
import { joinClasses, mergeStyle } from "./utils";
|
|
4
4
|
|
|
5
|
-
interface BlockBoxProps extends ComponentProps<"div"> {
|
|
5
|
+
export interface BlockBoxProps extends ComponentProps<"div"> {
|
|
6
6
|
children: VNode<BlockProps>[] | VNode<BlockProps>;
|
|
7
7
|
gap?: string;
|
|
8
8
|
basis?: number;
|
|
@@ -10,14 +10,14 @@ interface BlockBoxProps extends ComponentProps<"div"> {
|
|
|
10
10
|
align?: "middle" | "top" | "bottom";
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
interface BlockProps extends ComponentProps<"div"> {
|
|
13
|
+
export interface BlockProps extends ComponentProps<"div"> {
|
|
14
14
|
ratio?: number;
|
|
15
15
|
centered?: boolean;
|
|
16
16
|
align?: "middle" | "top" | "bottom";
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function Block(
|
|
20
|
-
return
|
|
19
|
+
export function Block({ children }: BlockProps) {
|
|
20
|
+
return children;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function BlockBox({
|
|
@@ -40,7 +40,10 @@ export function BlockBox({
|
|
|
40
40
|
const child = blockList.map(
|
|
41
41
|
({ props: { style, ratio = 1, className, centered, align, ...props } }) => (
|
|
42
42
|
<div
|
|
43
|
-
style={mergeStyle(style, {
|
|
43
|
+
style={mergeStyle(style, {
|
|
44
|
+
"--ratio": ratio,
|
|
45
|
+
"--block-box-align": align,
|
|
46
|
+
})}
|
|
44
47
|
className={joinClasses(
|
|
45
48
|
className,
|
|
46
49
|
styles.block,
|
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
import hljs from "highlight.js";
|
|
2
2
|
import "highlight.js/styles/atom-one-dark.css";
|
|
3
3
|
import { ComponentProps } from "preact";
|
|
4
|
+
import styles from "./CodeBlock.module.css";
|
|
5
|
+
import { joinClasses, mergeStyle } from "./utils";
|
|
4
6
|
|
|
5
|
-
interface CodeBlockProps extends Omit<ComponentProps<"code">, "children"> {
|
|
7
|
+
export interface CodeBlockProps extends Omit<ComponentProps<"code">, "children"> {
|
|
6
8
|
language: string;
|
|
7
9
|
code: string;
|
|
10
|
+
bgColor?: string;
|
|
11
|
+
color?: string;
|
|
12
|
+
|
|
8
13
|
}
|
|
9
14
|
|
|
10
|
-
export function CodeBlock({
|
|
15
|
+
export function CodeBlock({
|
|
16
|
+
code,
|
|
17
|
+
language,
|
|
18
|
+
bgColor,
|
|
19
|
+
color,
|
|
20
|
+
style,
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}: CodeBlockProps) {
|
|
11
24
|
const codeBlock = hljs.highlight(code, { language: language });
|
|
25
|
+
const css = mergeStyle(style, {
|
|
26
|
+
"--codeblock-bg": bgColor,
|
|
27
|
+
"--color-color" : color,
|
|
28
|
+
breakInside: "avoid",
|
|
29
|
+
});
|
|
12
30
|
return (
|
|
13
|
-
<pre style={{
|
|
31
|
+
<pre style={css} className={joinClasses(className, styles.pre)}>
|
|
14
32
|
<code {...props} dangerouslySetInnerHTML={{ __html: codeBlock.value }} />
|
|
15
33
|
</pre>
|
|
16
34
|
);
|
|
@@ -2,7 +2,7 @@ import { ComponentProps } from "preact";
|
|
|
2
2
|
import styles from "./DotLine.module.css";
|
|
3
3
|
import { joinClasses, mergeStyle } from "./utils";
|
|
4
4
|
|
|
5
|
-
interface DotLineProps extends ComponentProps<"span"> {
|
|
5
|
+
export interface DotLineProps extends ComponentProps<"span"> {
|
|
6
6
|
num?: number;
|
|
7
7
|
width?: number | string;
|
|
8
8
|
inline?: boolean;
|
|
@@ -5,11 +5,12 @@ import { ComponentProps } from "preact";
|
|
|
5
5
|
import styles from "./Equation.module.css";
|
|
6
6
|
import { joinClasses } from "./utils";
|
|
7
7
|
|
|
8
|
-
interface EquationProps extends Omit<ComponentProps<"span">, "children"> {
|
|
8
|
+
export interface EquationProps extends Omit<ComponentProps<"span">, "children"> {
|
|
9
9
|
tex: string;
|
|
10
10
|
displayMode?: boolean;
|
|
11
11
|
aligned?: boolean;
|
|
12
12
|
chemical?: boolean;
|
|
13
|
+
numberFormat?: boolean;
|
|
13
14
|
}
|
|
14
15
|
export function Equation({
|
|
15
16
|
tex,
|
|
@@ -17,15 +18,16 @@ export function Equation({
|
|
|
17
18
|
className = "",
|
|
18
19
|
aligned = false,
|
|
19
20
|
chemical = false,
|
|
21
|
+
numberFormat = true,
|
|
20
22
|
...props
|
|
21
23
|
}: EquationProps) {
|
|
24
|
+
const numberFormated = numberFormat ? formatNumber(tex) : tex;
|
|
22
25
|
const alignedCode = aligned
|
|
23
26
|
? `\\begin{aligned}
|
|
24
|
-
${
|
|
27
|
+
${numberFormated}
|
|
25
28
|
\\end{aligned}`
|
|
26
|
-
:
|
|
29
|
+
: numberFormated;
|
|
27
30
|
const chemCode = chemical ? `\\ce{${alignedCode}}` : alignedCode;
|
|
28
|
-
|
|
29
31
|
return (
|
|
30
32
|
<span
|
|
31
33
|
dangerouslySetInnerHTML={{
|
|
@@ -36,3 +38,50 @@ ${tex}
|
|
|
36
38
|
/>
|
|
37
39
|
);
|
|
38
40
|
}
|
|
41
|
+
|
|
42
|
+
export interface SymbolProps {
|
|
43
|
+
children?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function symbolFactory(
|
|
47
|
+
fn: (txt?: string, children?: string) => string | undefined,
|
|
48
|
+
txt?: string,
|
|
49
|
+
init?: string,
|
|
50
|
+
) {
|
|
51
|
+
return function ({ children = init }: SymbolProps) {
|
|
52
|
+
return <Equation tex={fn(txt, children) ?? ""} />;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function underscriptFactory(txt: string, init?: string) {
|
|
57
|
+
return symbolFactory(
|
|
58
|
+
(txt, children) => (children ? `${txt}_{${children}}` : `${txt}`),
|
|
59
|
+
txt,
|
|
60
|
+
init,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function functionFactory(txt: string, init: string = "x") {
|
|
65
|
+
return symbolFactory(
|
|
66
|
+
(txt, children) => (children ? `${txt}(${children})` : `${txt}`),
|
|
67
|
+
txt,
|
|
68
|
+
init,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function formatNumber(tex: string | undefined) {
|
|
73
|
+
if (!tex) return "";
|
|
74
|
+
return tex.replace(/\d+(?:\.\d+)?/g, (match) => {
|
|
75
|
+
const [intPart, decPart] = match.split(".");
|
|
76
|
+
const formattedInt = intPart.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1\\,");
|
|
77
|
+
if (decPart === undefined) return formattedInt;
|
|
78
|
+
const formattedDec = decPart.replace(/(\d{3})(?=\d)/g, "$1\\,");
|
|
79
|
+
return `${formattedInt},${formattedDec}\\:`;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function Eq(props: SymbolProps) {
|
|
84
|
+
return symbolFactory((_, children) => {
|
|
85
|
+
return formatNumber(children);
|
|
86
|
+
})(props);
|
|
87
|
+
}
|
package/packages/ui/src/List.tsx
CHANGED
|
@@ -9,24 +9,24 @@ export type CounterType =
|
|
|
9
9
|
| "lower-roman"
|
|
10
10
|
| "upper-roman";
|
|
11
11
|
|
|
12
|
-
interface ListItemProps extends ComponentProps<"div"> {
|
|
12
|
+
export interface ListItemProps extends ComponentProps<"div"> {
|
|
13
13
|
count?: number;
|
|
14
14
|
marker?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
interface ListProps extends ComponentProps<"div"> {
|
|
17
|
+
export interface ListProps extends ComponentProps<"div"> {
|
|
18
18
|
pre?: ComponentChildren;
|
|
19
19
|
gap?: string | number;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
interface OLProps extends ListProps {
|
|
22
|
+
export interface OLProps extends ListProps {
|
|
23
23
|
start?: number;
|
|
24
24
|
counterType?: CounterType;
|
|
25
25
|
markerPre?: string;
|
|
26
26
|
markerPost?: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
interface ULProps extends ListProps {
|
|
29
|
+
export interface ULProps extends ListProps {
|
|
30
30
|
marker?: string;
|
|
31
31
|
}
|
|
32
32
|
|
package/packages/ui/src/Page.tsx
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ComponentProps } from "preact";
|
|
2
|
+
import styles from "./Stack.module.css";
|
|
3
|
+
import { joinClasses, mergeStyle } from "./utils";
|
|
4
|
+
|
|
5
|
+
export interface StackProps extends ComponentProps<"div"> {
|
|
6
|
+
gap?: number | string;
|
|
7
|
+
align?: "left" | "right";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Stack({ gap, align, className, style, ...props }: StackProps) {
|
|
11
|
+
const css = mergeStyle(style, {
|
|
12
|
+
"--stack-gap": gap,
|
|
13
|
+
"--stack-ml": align === "left" ? undefined : "auto",
|
|
14
|
+
"--stack-mr": align === "right" ? undefined : "auto",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
style={css}
|
|
20
|
+
className={joinClasses(className, styles.stack)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -22,7 +22,7 @@ export function Entry(_props: TableEntryProps): null {
|
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
interface TableProps extends ComponentProps<"table"> {
|
|
25
|
+
export interface TableProps extends ComponentProps<"table"> {
|
|
26
26
|
orientation?: "col" | "row";
|
|
27
27
|
contentClass?: string;
|
|
28
28
|
headerClass?: string;
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
.
|
|
3
|
-
.
|
|
4
|
-
.
|
|
5
|
-
.
|
|
6
|
-
.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
float: left;
|
|
10
|
-
clear: left;
|
|
11
|
-
}
|
|
12
|
-
&[data-marker]::before {
|
|
13
|
-
content: attr(data-marker);
|
|
14
|
-
}
|
|
1
|
+
.h1::before,
|
|
2
|
+
.h2::before,
|
|
3
|
+
.h3::before,
|
|
4
|
+
.h4::before,
|
|
5
|
+
.h5::before,
|
|
6
|
+
.h6::before {
|
|
7
|
+
float: left;
|
|
8
|
+
clear: left;
|
|
15
9
|
}
|
|
16
10
|
|
|
11
|
+
.h1[data-marker]::before,
|
|
12
|
+
.h2[data-marker]::before,
|
|
13
|
+
.h3[data-marker]::before,
|
|
14
|
+
.h4[data-marker]::before,
|
|
15
|
+
.h5[data-marker]::before,
|
|
16
|
+
.h6[data-marker]::before {
|
|
17
|
+
content: attr(data-marker);
|
|
18
|
+
}
|
|
17
19
|
|
|
18
20
|
.h1 {
|
|
19
21
|
color: var(--h1-color, inherit);
|
|
20
22
|
font-size: var(--h1-fontsize, inherit);
|
|
21
23
|
counter-reset: count-h2 count-h3 count-h4 count-h5 count-h6;
|
|
22
24
|
counter-increment: count-h1;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:where(.h1)::before {
|
|
28
|
+
content: counter(count-h1, upper-roman) ". ";
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
.h2 {
|
|
@@ -30,9 +33,10 @@
|
|
|
30
33
|
font-size: var(--h2-fontsize, inherit);
|
|
31
34
|
counter-reset: count-h3 count-h4 count-h5 count-h6;
|
|
32
35
|
counter-increment: count-h2;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:where(.h2)::before {
|
|
39
|
+
content: counter(count-h2, decimal) ". ";
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
.h3 {
|
|
@@ -40,9 +44,10 @@
|
|
|
40
44
|
font-size: var(--h3-fontsize, inherit);
|
|
41
45
|
counter-reset: count-h4 count-h5 count-h6;
|
|
42
46
|
counter-increment: count-h3;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:where(.h3)::before {
|
|
50
|
+
content: counter(count-h3, upper-alpha) ". ";
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
.h4 {
|
|
@@ -50,9 +55,10 @@
|
|
|
50
55
|
font-size: var(--h4-fontsize, inherit);
|
|
51
56
|
counter-reset: count-h5 count-h6;
|
|
52
57
|
counter-increment: count-h4;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:where(.h4)::before {
|
|
61
|
+
content: counter(count-h4, decimal) ". ";
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
.h5 {
|
|
@@ -60,16 +66,18 @@
|
|
|
60
66
|
font-size: var(--h5-fontsize, inherit);
|
|
61
67
|
counter-reset: count-h6;
|
|
62
68
|
counter-increment: count-h5;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
:where(.h5)::before {
|
|
72
|
+
content: counter(count-h5, lower-alpha) ". ";
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
.h6 {
|
|
69
76
|
color: var(--h6-color, inherit);
|
|
70
77
|
font-size: var(--h6-fontsize, inherit);
|
|
71
78
|
counter-increment: count-h6;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:where(.h6)::before {
|
|
82
|
+
content: counter(count-h6, lower-roman) ". ";
|
|
75
83
|
}
|
|
@@ -2,9 +2,9 @@ import { ComponentProps, ComponentType } from "preact";
|
|
|
2
2
|
import styles from "./Title.module.css";
|
|
3
3
|
import { joinClasses, mergeStyle } from "./utils";
|
|
4
4
|
|
|
5
|
-
type Htype = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
5
|
+
export type Htype = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
6
6
|
|
|
7
|
-
type Hprops<h extends Htype> = ComponentProps<h> & {
|
|
7
|
+
export type Hprops<h extends Htype> = ComponentProps<h> & {
|
|
8
8
|
marker?: string;
|
|
9
9
|
color?: string;
|
|
10
10
|
fontSize?: string;
|
|
@@ -73,7 +73,7 @@ export function H6({ className = "", marker, color, fontSize, style, ...props }:
|
|
|
73
73
|
|
|
74
74
|
const TAG_MAP = { h1: H1, h2: H2, h3: H3, h4: H4, h5: H5, h6: H6 };
|
|
75
75
|
|
|
76
|
-
type TitleProps<h extends Htype> = Hprops<h> & { type: h };
|
|
76
|
+
export type TitleProps<h extends Htype> = Hprops<h> & { type: h };
|
|
77
77
|
export function Title<h extends Htype>({ type, ...props }: TitleProps<h>) {
|
|
78
78
|
const Tag = TAG_MAP[type] as ComponentType<Hprops<h>>;
|
|
79
79
|
return <Tag {...(props as Hprops<h>)} />;
|
package/packages/ui/src/index.ts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
export { Block, BlockBox } from "./BlockBox";
|
|
2
|
+
export type { BlockBoxProps, BlockProps } from "./BlockBox";
|
|
2
3
|
export { CodeBlock } from "./CodeBlock";
|
|
4
|
+
export type { CodeBlockProps } from "./CodeBlock";
|
|
3
5
|
export { DotLine } from "./DotLine";
|
|
4
|
-
export {
|
|
6
|
+
export type { DotLineProps } from "./DotLine";
|
|
7
|
+
export {
|
|
8
|
+
Eq, Equation,
|
|
9
|
+
functionFactory, symbolFactory,
|
|
10
|
+
underscriptFactory
|
|
11
|
+
} from "./Equation";
|
|
12
|
+
export type { EquationProps, SymbolProps } from "./Equation";
|
|
5
13
|
export { LI, OL, UL } from "./List";
|
|
14
|
+
export type { CounterType, ListItemProps, ListProps, OLProps, ULProps } from "./List";
|
|
6
15
|
export { Page, PageBreak } from "./Page";
|
|
16
|
+
export type { PageProps } from "./Page";
|
|
17
|
+
export { Stack } from "./Stack";
|
|
18
|
+
export type { StackProps } from "./Stack";
|
|
7
19
|
export { Entry, Table } from "./Table";
|
|
20
|
+
export type { TableEntryProps, TableProps } from "./Table";
|
|
8
21
|
export { H1, H2, H3, H4, H5, H6, ResetCounter, Title } from "./Titles";
|
|
22
|
+
export type { Hprops, Htype, TitleProps } from "./Titles";
|
|
23
|
+
export * from "./utils";
|
|
9
24
|
|
package/src/index.css
CHANGED
|
@@ -19,16 +19,21 @@ body {
|
|
|
19
19
|
font-size: 10pt;
|
|
20
20
|
line-height: 1.75;
|
|
21
21
|
font-family: system-ui, sans-serif;
|
|
22
|
+
font-family: "Public Sans Variable", sans-serif;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
h1,
|
|
25
|
+
h1,
|
|
26
|
+
h2,
|
|
27
|
+
h3 {
|
|
25
28
|
line-height: 1.2;
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
|
|
32
|
+
|
|
28
33
|
code {
|
|
29
34
|
font-family: ui-monospace, monospace;
|
|
30
35
|
font-size: 0.88em;
|
|
31
|
-
background: #
|
|
36
|
+
background: #4490dd;
|
|
32
37
|
padding: 0.1em 0.3em;
|
|
33
38
|
border-radius: 3px;
|
|
34
39
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
H1, H2, H3,
|
|
3
|
-
Page, PageBreak,
|
|
4
|
-
UL, OL, LI,
|
|
5
|
-
Table, Entry,
|
|
6
|
-
BlockBox, Block,
|
|
7
2
|
CodeBlock,
|
|
8
3
|
DotLine,
|
|
4
|
+
Entry,
|
|
5
|
+
H1,
|
|
6
|
+
H2,
|
|
7
|
+
H3,
|
|
8
|
+
LI,
|
|
9
|
+
OL,
|
|
10
|
+
PageBreak,
|
|
11
|
+
Stack,
|
|
12
|
+
Table,
|
|
13
|
+
UL,
|
|
9
14
|
} from "@weasyprint-tsx/ui";
|
|
10
15
|
import "./index.css";
|
|
11
16
|
|
|
@@ -56,148 +61,286 @@ export default function Document() {
|
|
|
56
61
|
<link rel="stylesheet" href="index.css" />
|
|
57
62
|
</head>
|
|
58
63
|
<body>
|
|
59
|
-
|
|
60
64
|
{/* ── Cover ── */}
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<BlockBox gap="1cm">
|
|
72
|
-
<Block ratio={1}>
|
|
73
|
-
<H3 color="#1e40af">Requirements</H3>
|
|
74
|
-
<UL>
|
|
75
|
-
<LI>Bun ≥ 1.0</LI>
|
|
76
|
-
<LI>WeasyPrint (pip install weasyprint)</LI>
|
|
77
|
-
</UL>
|
|
78
|
-
</Block>
|
|
79
|
-
<Block ratio={1}>
|
|
80
|
-
<H3 color="#1e40af">Quick start</H3>
|
|
81
|
-
<OL>
|
|
82
|
-
<LI>bunx create-weasyprint-tsx my-doc</LI>
|
|
83
|
-
<LI>cd my-doc && bun install</LI>
|
|
84
|
-
<LI>bun run dev</LI>
|
|
85
|
-
</OL>
|
|
86
|
-
</Block>
|
|
87
|
-
</BlockBox>
|
|
88
|
-
</Page>
|
|
65
|
+
<div style={{ marginBottom: "1.5cm" }}>
|
|
66
|
+
<H1 fontSize="28pt" color="#1e40af">
|
|
67
|
+
weasyprint-tsx
|
|
68
|
+
</H1>
|
|
69
|
+
<p style={{ fontSize: "13pt", color: "#475569", marginTop: "0.3cm" }}>
|
|
70
|
+
Write PDFs in TSX — Bun bundles your Preact components into HTML,
|
|
71
|
+
WeasyPrint renders them as PDF.
|
|
72
|
+
</p>
|
|
73
|
+
<DotLine width="100%" color="#cbd5e1" />
|
|
74
|
+
</div>
|
|
89
75
|
|
|
76
|
+
<Stack gap="1cm">
|
|
77
|
+
<div className="w-1/2">
|
|
78
|
+
<H3 color="#1e40af">Requirements</H3>
|
|
79
|
+
<UL>
|
|
80
|
+
<LI>Bun ≥ 1.0</LI>
|
|
81
|
+
<LI>WeasyPrint (pip install weasyprint)</LI>
|
|
82
|
+
</UL>
|
|
83
|
+
</div>
|
|
84
|
+
<div className="w-1/2">
|
|
85
|
+
<H3 color="#1e40af">
|
|
86
|
+
Quick start
|
|
87
|
+
</H3>
|
|
88
|
+
<OL>
|
|
89
|
+
<LI>bunx create-weasyprint-tsx my-doc</LI>
|
|
90
|
+
<LI>cd my-doc && bun install</LI>
|
|
91
|
+
<LI>bun run dev</LI>
|
|
92
|
+
</OL>
|
|
93
|
+
</div>
|
|
94
|
+
</Stack>
|
|
90
95
|
<PageBreak />
|
|
91
96
|
|
|
92
97
|
{/* ── Getting Started ── */}
|
|
93
|
-
<
|
|
94
|
-
<H2 color="#1e40af">Getting Started</H2>
|
|
98
|
+
<H2 color="#1e40af">Getting Started</H2>
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
<p>
|
|
101
|
+
The <code>create-weasyprint-tsx</code> scaffolder generates a
|
|
102
|
+
ready-to-use project. After installation, two scripts are available:
|
|
103
|
+
</p>
|
|
100
104
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
<Table
|
|
106
|
+
orientation="col"
|
|
107
|
+
headerBg="#1e40af"
|
|
108
|
+
headerFontSize="9pt"
|
|
109
|
+
cellFontSize="9pt"
|
|
110
|
+
borderColor="#e2e8f0"
|
|
111
|
+
>
|
|
112
|
+
<Entry content={["Script", "Effect"]} />
|
|
113
|
+
<Entry
|
|
114
|
+
content={[
|
|
115
|
+
"bun run dev",
|
|
116
|
+
"Watch src/, rebuild on change, serve preview at localhost:3000",
|
|
117
|
+
]}
|
|
118
|
+
/>
|
|
119
|
+
<Entry content={["bun run build", "Build once, write output.pdf"]} />
|
|
120
|
+
</Table>
|
|
106
121
|
|
|
107
|
-
|
|
108
|
-
|
|
122
|
+
<H3>Project structure</H3>
|
|
123
|
+
<CodeBlock
|
|
124
|
+
language="plaintext"
|
|
125
|
+
code={`my-doc/
|
|
109
126
|
├── src/
|
|
110
127
|
│ ├── index.tsx # Document root — export a default Preact component
|
|
111
128
|
│ └── index.css # Styles — must start with @import "tailwindcss"
|
|
112
129
|
├── weasyprint-tsx.config.ts
|
|
113
|
-
└── package.json`}
|
|
114
|
-
|
|
115
|
-
<H3>Entry point</H3>
|
|
116
|
-
<p>
|
|
117
|
-
<code>src/index.tsx</code> must export a default component that renders a
|
|
118
|
-
complete HTML document. WeasyPrint receives the full HTML string.
|
|
119
|
-
</p>
|
|
120
|
-
<CodeBlock language="tsx" code={indexCode} />
|
|
121
|
-
</Page>
|
|
130
|
+
└── package.json`}
|
|
131
|
+
/>
|
|
122
132
|
|
|
123
|
-
<
|
|
133
|
+
<H3>Entry point</H3>
|
|
134
|
+
<p>
|
|
135
|
+
<code>src/index.tsx</code> must export a default component that
|
|
136
|
+
renders a complete HTML document. WeasyPrint receives the full HTML
|
|
137
|
+
string.
|
|
138
|
+
</p>
|
|
139
|
+
<CodeBlock language="tsx" code={indexCode} />
|
|
124
140
|
|
|
125
141
|
{/* ── Configuration ── */}
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<CodeBlock language="typescript" code={configCode} />
|
|
133
|
-
|
|
134
|
-
<H3>All config fields</H3>
|
|
135
|
-
|
|
136
|
-
<Table orientation="col" headerBg="#334155" headerFontSize="8.5pt" cellFontSize="8.5pt" borderColor="#e2e8f0">
|
|
137
|
-
<Entry content={["Field", "Default", "Description"]} />
|
|
138
|
-
<Entry content={["io.input", "src/index.tsx", "TSX entry point"]} />
|
|
139
|
-
<Entry content={["io.output", "output.pdf", "Output PDF path"]} />
|
|
140
|
-
<Entry content={["io.buildDir", ".build", "Intermediate HTML directory"]} />
|
|
141
|
-
<Entry content={["io.media_type", "print", "CSS media type"]} />
|
|
142
|
-
<Entry content={["weasyprint.path", "weasyprint", "Path to WeasyPrint binary"]} />
|
|
143
|
-
<Entry content={["weasyprint.dpi", "—", "Output resolution"]} />
|
|
144
|
-
<Entry content={["weasyprint.optimize_images", "—", "Compress images in output"]} />
|
|
145
|
-
<Entry content={["weasyprint.pdf_forms", "—", "Enable PDF form fields"]} />
|
|
146
|
-
<Entry content={["weasyprint.pdf_variant", "—", "pdf/a-1b, pdf/ua-1, …"]} />
|
|
147
|
-
<Entry content={["weasyprint.full_fonts", "—", "Embed full font files"]} />
|
|
148
|
-
<Entry content={["weasyprint.cache", "—", "Font/image cache folder"]} />
|
|
149
|
-
<Entry content={["dev.port", "3000", "Dev server port"]} />
|
|
150
|
-
<Entry content={["dev.watch", "src", "Directory to watch"]} />
|
|
151
|
-
<Entry content={["pdf.stylesheets", "[]", "Extra CSS files via --stylesheet"]} />
|
|
152
|
-
</Table>
|
|
153
|
-
</Page>
|
|
142
|
+
<H2 color="#1e40af">Configuration</H2>
|
|
143
|
+
<p>
|
|
144
|
+
Create <code>weasyprint-tsx.config.ts</code> at the project root to
|
|
145
|
+
override any default:
|
|
146
|
+
</p>
|
|
147
|
+
<CodeBlock language="typescript" code={configCode} />
|
|
154
148
|
|
|
155
|
-
<
|
|
149
|
+
<H3>All config fields</H3>
|
|
150
|
+
|
|
151
|
+
<Table
|
|
152
|
+
orientation="col"
|
|
153
|
+
headerBg="#334155"
|
|
154
|
+
headerFontSize="8.5pt"
|
|
155
|
+
cellFontSize="8.5pt"
|
|
156
|
+
borderColor="#e2e8f0"
|
|
157
|
+
>
|
|
158
|
+
<Entry content={["Field", "Default", "Description"]} />
|
|
159
|
+
<Entry content={["io.input", "src/index.tsx", "TSX entry point"]} />
|
|
160
|
+
<Entry content={["io.output", "output.pdf", "Output PDF path"]} />
|
|
161
|
+
<Entry
|
|
162
|
+
content={["io.buildDir", ".build", "Intermediate HTML directory"]}
|
|
163
|
+
/>
|
|
164
|
+
<Entry content={["io.media_type", "print", "CSS media type"]} />
|
|
165
|
+
<Entry
|
|
166
|
+
content={[
|
|
167
|
+
"weasyprint.path",
|
|
168
|
+
"weasyprint",
|
|
169
|
+
"Path to WeasyPrint binary",
|
|
170
|
+
]}
|
|
171
|
+
/>
|
|
172
|
+
<Entry content={["weasyprint.dpi", "—", "Output resolution"]} />
|
|
173
|
+
<Entry
|
|
174
|
+
content={[
|
|
175
|
+
"weasyprint.optimize_images",
|
|
176
|
+
"—",
|
|
177
|
+
"Compress images in output",
|
|
178
|
+
]}
|
|
179
|
+
/>
|
|
180
|
+
<Entry
|
|
181
|
+
content={["weasyprint.pdf_forms", "—", "Enable PDF form fields"]}
|
|
182
|
+
/>
|
|
183
|
+
<Entry
|
|
184
|
+
content={["weasyprint.pdf_variant", "—", "pdf/a-1b, pdf/ua-1, …"]}
|
|
185
|
+
/>
|
|
186
|
+
<Entry
|
|
187
|
+
content={["weasyprint.full_fonts", "—", "Embed full font files"]}
|
|
188
|
+
/>
|
|
189
|
+
<Entry
|
|
190
|
+
content={["weasyprint.cache", "—", "Font/image cache folder"]}
|
|
191
|
+
/>
|
|
192
|
+
<Entry content={["dev.port", "3000", "Dev server port"]} />
|
|
193
|
+
<Entry content={["dev.watch", "src", "Directory to watch"]} />
|
|
194
|
+
<Entry
|
|
195
|
+
content={[
|
|
196
|
+
"pdf.stylesheets",
|
|
197
|
+
"[]",
|
|
198
|
+
"Extra CSS files via --stylesheet",
|
|
199
|
+
]}
|
|
200
|
+
/>
|
|
201
|
+
</Table>
|
|
156
202
|
|
|
157
203
|
{/* ── UI Components ── */}
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
</
|
|
204
|
+
<H2 color="#1e40af">UI Components</H2>
|
|
205
|
+
<p>
|
|
206
|
+
<code>@weasyprint-tsx/ui</code> provides print-optimized Preact
|
|
207
|
+
components. Import everything from the package root:
|
|
208
|
+
</p>
|
|
209
|
+
<CodeBlock
|
|
210
|
+
language="ts"
|
|
211
|
+
code={`import { H1, H2, Page, PageBreak, UL, OL, LI, Table, Entry, BlockBox, Block, DotLine, CodeBlock, Equation } from "@weasyprint-tsx/ui";`}
|
|
212
|
+
/>
|
|
213
|
+
|
|
214
|
+
<H3>Page & Layout</H3>
|
|
215
|
+
<Table
|
|
216
|
+
orientation="row"
|
|
217
|
+
headerBg="#f1f5f9"
|
|
218
|
+
borderColor="#e2e8f0"
|
|
219
|
+
headerFontSize="8.5pt"
|
|
220
|
+
cellFontSize="8.5pt"
|
|
221
|
+
>
|
|
222
|
+
<Entry
|
|
223
|
+
content={[
|
|
224
|
+
"Page",
|
|
225
|
+
"Wraps a page section (<section>). Accepts page?: string for named page rules.",
|
|
226
|
+
]}
|
|
227
|
+
/>
|
|
228
|
+
<Entry
|
|
229
|
+
content={["PageBreak", "Inserts a CSS page break. No props."]}
|
|
230
|
+
/>
|
|
231
|
+
<Entry
|
|
232
|
+
content={[
|
|
233
|
+
"BlockBox",
|
|
234
|
+
"Multi-column flex container. Props: gap, basis, centered, align.",
|
|
235
|
+
]}
|
|
236
|
+
/>
|
|
237
|
+
<Entry
|
|
238
|
+
content={[
|
|
239
|
+
"Block",
|
|
240
|
+
"Column inside BlockBox. Props: ratio, centered, align.",
|
|
241
|
+
]}
|
|
242
|
+
/>
|
|
243
|
+
</Table>
|
|
244
|
+
|
|
245
|
+
<H3>Headings</H3>
|
|
246
|
+
<Table
|
|
247
|
+
orientation="row"
|
|
248
|
+
headerBg="#f1f5f9"
|
|
249
|
+
borderColor="#e2e8f0"
|
|
250
|
+
headerFontSize="8.5pt"
|
|
251
|
+
cellFontSize="8.5pt"
|
|
252
|
+
>
|
|
253
|
+
<Entry
|
|
254
|
+
content={[
|
|
255
|
+
"H1 – H6",
|
|
256
|
+
"Render h1–h6. Props: marker (data-marker for CSS counters), color, fontSize.",
|
|
257
|
+
]}
|
|
258
|
+
/>
|
|
259
|
+
<Entry
|
|
260
|
+
content={[
|
|
261
|
+
"ResetCounter",
|
|
262
|
+
"Hidden div that resets CSS counters. Use at the top of numbered sections.",
|
|
263
|
+
]}
|
|
264
|
+
/>
|
|
265
|
+
</Table>
|
|
266
|
+
|
|
267
|
+
<H3>Lists</H3>
|
|
268
|
+
<Table
|
|
269
|
+
orientation="row"
|
|
270
|
+
headerBg="#f1f5f9"
|
|
271
|
+
borderColor="#e2e8f0"
|
|
272
|
+
headerFontSize="8.5pt"
|
|
273
|
+
cellFontSize="8.5pt"
|
|
274
|
+
>
|
|
275
|
+
<Entry
|
|
276
|
+
content={[
|
|
277
|
+
"UL",
|
|
278
|
+
"Unordered list. Props: marker (bullet char), gap, pre.",
|
|
279
|
+
]}
|
|
280
|
+
/>
|
|
281
|
+
<Entry
|
|
282
|
+
content={[
|
|
283
|
+
"OL",
|
|
284
|
+
"Ordered list. Props: start, counterType (decimal/lower-alpha/upper-roman/…), markerPre, markerPost, gap, pre.",
|
|
285
|
+
]}
|
|
286
|
+
/>
|
|
287
|
+
<Entry
|
|
288
|
+
content={[
|
|
289
|
+
"LI",
|
|
290
|
+
"List item. Props: marker (override bullet), count (override counter).",
|
|
291
|
+
]}
|
|
292
|
+
/>
|
|
293
|
+
</Table>
|
|
294
|
+
|
|
295
|
+
<H3>Table</H3>
|
|
296
|
+
<Table
|
|
297
|
+
orientation="row"
|
|
298
|
+
headerBg="#f1f5f9"
|
|
299
|
+
borderColor="#e2e8f0"
|
|
300
|
+
headerFontSize="8.5pt"
|
|
301
|
+
cellFontSize="8.5pt"
|
|
302
|
+
>
|
|
303
|
+
<Entry
|
|
304
|
+
content={[
|
|
305
|
+
"Table",
|
|
306
|
+
`orientation "col" (default): first Entry is the header row. orientation "row": first cell of each Entry is the row header. Also: headerBg, cellBg, borderWidth, borderColor, headerFontSize, cellFontSize.`,
|
|
307
|
+
]}
|
|
308
|
+
/>
|
|
309
|
+
<Entry
|
|
310
|
+
content={[
|
|
311
|
+
"Entry",
|
|
312
|
+
"Data row/column. content: ComponentChild[] holds cell values. Accepts per-entry overrides: headerBg, cellBg.",
|
|
313
|
+
]}
|
|
314
|
+
/>
|
|
315
|
+
</Table>
|
|
200
316
|
|
|
317
|
+
<H3>Inline elements</H3>
|
|
318
|
+
<Table
|
|
319
|
+
orientation="row"
|
|
320
|
+
headerBg="#f1f5f9"
|
|
321
|
+
borderColor="#e2e8f0"
|
|
322
|
+
headerFontSize="8.5pt"
|
|
323
|
+
cellFontSize="8.5pt"
|
|
324
|
+
>
|
|
325
|
+
<Entry
|
|
326
|
+
content={[
|
|
327
|
+
"DotLine",
|
|
328
|
+
"Repeating dot fill line. Props: num, width, inline, color, lineHeight.",
|
|
329
|
+
]}
|
|
330
|
+
/>
|
|
331
|
+
<Entry
|
|
332
|
+
content={[
|
|
333
|
+
"CodeBlock",
|
|
334
|
+
"Syntax-highlighted code (highlight.js). Props: language, code.",
|
|
335
|
+
]}
|
|
336
|
+
/>
|
|
337
|
+
<Entry
|
|
338
|
+
content={[
|
|
339
|
+
"Equation",
|
|
340
|
+
"LaTeX via KaTeX. Props: tex, displayMode, aligned, chemical.",
|
|
341
|
+
]}
|
|
342
|
+
/>
|
|
343
|
+
</Table>
|
|
201
344
|
</body>
|
|
202
345
|
</html>
|
|
203
346
|
);
|
package/testUI/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
package/testUI/index.tsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Eq, Equation, functionFactory } from "@weasyprint-tsx/ui";
|
|
2
|
+
import "./index.css";
|
|
3
|
+
|
|
4
|
+
const S = functionFactory("S" , "x")
|
|
5
|
+
|
|
6
|
+
export default function Document() {
|
|
7
|
+
return (
|
|
8
|
+
<html>
|
|
9
|
+
<head>
|
|
10
|
+
<meta charset="UTF-8" />
|
|
11
|
+
<title>weasyprint-tsx</title>
|
|
12
|
+
<link rel="stylesheet" href="index.css" />
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<Equation tex="C_m = 50000.0000000000000000001 g/L"></Equation>
|
|
16
|
+
<Eq>151545312313513.13543545345343 a151515131 .13513513</Eq>
|
|
17
|
+
<S/>
|
|
18
|
+
<S>g</S>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
);
|
|
22
|
+
}
|
package/weasyprint-tsx.config.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { Config } from "./packages/build/src/config";
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
|
+
// io: {
|
|
5
|
+
// output: "ReadMe.pdf",
|
|
6
|
+
// },
|
|
7
|
+
|
|
4
8
|
io: {
|
|
5
|
-
output: "
|
|
9
|
+
output: "TestUI.pdf",
|
|
10
|
+
input: "testUI/index.tsx",
|
|
11
|
+
},
|
|
12
|
+
dev: {
|
|
13
|
+
watch: ["packages/ui/", "testUI"],
|
|
6
14
|
},
|
|
7
15
|
} satisfies Config;
|