Skip to content

Commit aca99d7

Browse files
committed
feat(pdf): drop node+puppeteer deps
1 parent cd51e69 commit aca99d7

49 files changed

Lines changed: 1015 additions & 743 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
build/
22
**/build/
3+
**/node_modules/
34
.git/
45
.github/
56
.run/

.github/actions/setup-environment/action.yml

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,11 @@ runs:
2929
- name: Setup Gradle
3030
uses: gradle/actions/setup-gradle@v3
3131

32-
- name: Setup Node.js
33-
uses: actions/setup-node@v4
34-
3532
- name: Setup Chrome
3633
uses: browser-actions/setup-chrome@v1
3734
id: setup-chrome
3835

39-
- name: Set Puppeteer's executable path
40-
run: |
41-
echo "PUPPETEER_EXECUTABLE_PATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> $GITHUB_ENV
42-
shell: bash
43-
44-
- name: Set npm environment variables
45-
run: |
46-
mkdir -p $HOME/.npm-global/lib
47-
echo "QD_NPM_PREFIX=$HOME/.npm-global/lib" >> $GITHUB_ENV
48-
echo "NODE_PATH=$HOME/.npm-global/lib/node_modules" >> $GITHUB_ENV
49-
shell: bash
50-
51-
- name: Install Puppeteer
36+
- name: Set browser path
5237
run: |
53-
export PUPPETEER_SKIP_DOWNLOAD=true
54-
npm install puppeteer --prefix ${{ env.QD_NPM_PREFIX }}
38+
echo "QD_CHROME_PATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> $GITHUB_ENV
5539
shell: bash

.github/workflows/docker-image-test.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ jobs:
2222
steps:
2323
- uses: actions/checkout@v4
2424

25+
- name: Check Chrome version pin is in sync
26+
run: |
27+
VERSION=$(cat quarkdown-html-pdf/scripts/chrome-version.txt)
28+
if ! grep -q "HEADLESS_SHELL_VERSION=$VERSION" Dockerfile; then
29+
echo "ERROR: Dockerfile HEADLESS_SHELL_VERSION is out of sync with quarkdown-html-pdf/scripts/chrome-version.txt ($VERSION)"
30+
exit 1
31+
fi
32+
2533
- name: Build Docker image
2634
run: docker build -t quarkdown:test .
2735

.github/workflows/generate-pdf.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: PDF generation via Puppeteer
1+
name: PDF generation
22

33
on:
44
push:
@@ -18,10 +18,6 @@ jobs:
1818
steps:
1919
- uses: iamgio/quarkdown/.github/actions/setup-environment@main
2020

21-
- name: Setup Chrome
22-
uses: browser-actions/setup-chrome@v1.7.3
23-
id: setup-chrome
24-
2521
- name: Build distribution
2622
uses: burrunan/gradle-cache-action@v3
2723
with:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,5 @@ nb-configuration.xml
111111
.claude/*
112112
!.claude/skills/
113113
*.log
114-
**/_test/
114+
**/_test/
115+
docs/superpowers/

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ The new `callouts` argument of the `.code` function attaches numbered markers to
2121

2222
### Changed
2323

24+
#### PDF export without Node.js [ecosystem breaking change]
25+
26+
Exporting to PDF no longer requires Node.js, npm, and Puppeteer. Quarkdown now communicates directly with a Chromium-family browser, which makes PDF generation faster to start and much simpler to set up.
27+
28+
Package manager installations download a headless Chrome shell automatically. If you installed Quarkdown manually, download it from the [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/) page, or point Quarkdown to an existing Chromium-family installation with the new `--chrome-path` option or the `QD_CHROME_PATH` environment variable.
29+
30+
> Migration note: the `--node-path` and `--npm-path` options, along with the `QD_NPM_PREFIX` and `NODE_PATH` environment variables, are no longer used. `quarkdown doctor env` now reports the browser's status.
31+
2432
#### Reflectionless function calls
2533

2634
Calling a native function no longer involves JVM reflection, improving performance (the official wiki now compiles 10% faster) on function-heavy documents and opening the door to future optimizations.

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This is the Quarkdown project. Quarkdown is a:
55
- Typesetting system, as an alternative to LaTeX, with high-quality typography and layout customization
66
- Compiler, parser and renderer to:
77
- HTML
8-
- PDF (via Puppeteer)
8+
- PDF (via a headless Chromium browser)
99
- Plain text
1010
- CLI tool
1111

@@ -294,7 +294,7 @@ After the Kotlin extension renders the Quarkdown AST to HTML elements,
294294
the front-end TypeScript code takes care of interactivity and dynamic features,
295295
while SCSS files handle styling and layout.
296296

297-
Additionally, Puppeteer is used to generate PDF output from the HTML rendering.
297+
Additionally, a Chromium-family browser (`chrome-headless-shell`), driven from the JVM over the Chrome DevTools Protocol, is used to generate PDF output from the HTML rendering.
298298
This lives in the separate, JVM-only [quarkdown-html-pdf](quarkdown-html-pdf) module,
299299
which decorates the HTML post-renderer and relies on the webserver, located in [quarkdown-server](quarkdown-server).
300300

@@ -333,7 +333,7 @@ A layout or color theme can ship sibling assets (e.g. fonts) that travel with it
333333

334334
## Server
335335

336-
[quarkdown-server](quarkdown-server) is a Ktor-based web server that serves the HTML rendering and allows PDF generation via Puppeteer. The `/preview/<path>` endpoint, used in combination with the CLI's `--preview` and `--watch` options, serves the HTML through a double iframe buffer, allowing for live preview during editing.
336+
[quarkdown-server](quarkdown-server) is a Ktor-based web server that serves the HTML rendering and allows PDF generation via a headless Chromium browser. The `/preview/<path>` endpoint, used in combination with the CLI's `--preview` and `--watch` options, serves the HTML through a double iframe buffer, allowing for live preview during editing.
337337

338338
## Testing
339339

Dockerfile

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Version of the headless browser bundle used for PDF export.
2+
# To keep in sync with quarkdown-html-pdf/scripts/chrome-version.txt, the version shared with the installers.
3+
ARG HEADLESS_SHELL_VERSION=151.0.7922.109
4+
15
# Build stage via Gradle
26
FROM gradle:8.14.3-jdk17 AS builder
37

@@ -25,13 +29,20 @@ WORKDIR build/distributions
2529
RUN unzip quarkdown.zip && rm quarkdown.zip
2630

2731
# Run stage
28-
FROM ghcr.io/puppeteer/puppeteer:24.15.0 AS runner
32+
FROM docker.io/chromedp/headless-shell:${HEADLESS_SHELL_VERSION} AS runner
33+
34+
RUN apt-get update \
35+
&& apt-get install -y --no-install-recommends \
36+
ca-certificates fontconfig fonts-liberation \
37+
&& apt-get clean \
38+
&& rm -rf /var/lib/apt/lists/*
39+
40+
RUN useradd -m quarkdown
41+
USER quarkdown
2942

30-
ENV QD_NPM_PREFIX="/home/pptruser" \
31-
NODE_PATH="/home/pptruser/node_modules" \
32-
PUPPETEER_CACHE_DIR="/home/pptruser/.cache/puppeteer"
43+
ENV QD_CHROME_PATH="/headless-shell/headless-shell" \
44+
QD_NO_SANDBOX="true"
3345

34-
USER pptruser
3546
WORKDIR /app
3647
COPY --from=builder /app/build/distributions/quarkdown quarkdown
3748
ENV PATH="/app/quarkdown/bin:${PATH}"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ curl -fsSL https://raw.githubusercontent.com/quarkdown-labs/get-quarkdown/refs/h
287287
```
288288

289289
Root privileges let the script install Quarkdown into `/opt/quarkdown` and its wrapper script into `/usr/local/bin/quarkdown`.
290-
If missing, Node.js will be installed automatically using the system's package manager.
290+
The browser required for PDF export is installed automatically.
291291

292292
For more installation options, check out [get-quarkdown](https://github.com/quarkdown-labs/get-quarkdown).
293293

@@ -324,7 +324,7 @@ or build it with `gradlew installDist`.
324324
Optionally, adding `<install_dir>/bin` to your `PATH` allows you easier access Quarkdown.
325325

326326
Requirements:
327-
- (Only for PDF export) Node.js, npm, Puppeteer. See [*PDF export*](https://quarkdown.com/wiki/pdf-export) for details.
327+
- (Only for PDF export) A Chromium-family browser, such as `chrome-headless-shell`. See [*PDF export*](https://quarkdown.com/wiki/pdf-export) for details.
328328

329329
</details>
330330

build.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,16 @@ distributions.main {
413413
}
414414
includeEmptyDirs = false
415415
}
416+
// Browser installation scripts, invoked by package managers and installers.
417+
into("scripts") {
418+
from(project(":quarkdown-html-pdf").file("scripts")) {
419+
include("*.sh", "*.ps1")
420+
filePermissions { unix("rwxr-xr-x") }
421+
}
422+
from(project(":quarkdown-html-pdf").file("scripts")) {
423+
include("chrome-version.txt")
424+
}
425+
}
416426
}
417427
}
418428

0 commit comments

Comments
 (0)