Add GitHub workflow for PDF generation using Playwright

Create a workflow that generates a DIN A4 PDF of the print version
of index.html and stores it as an artifact. Uses Playwright with
Chromium to load the page, wait for QR codes to render, and
generate the PDF.
This commit is contained in:
Claude 2025-11-23 16:34:11 +00:00
parent 9b596b5506
commit f58462df32
No known key found for this signature in database
3 changed files with 90 additions and 0 deletions

37
.github/workflows/generate-pdf.yml vendored Normal file
View file

@ -0,0 +1,37 @@
name: Generate PDF Labels
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:
jobs:
generate-pdf:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install
- name: Install Playwright Chromium
run: npx playwright install chromium
- name: Generate PDF
run: npm run generate-pdf
- name: Upload PDF artifact
uses: actions/upload-artifact@v4
with:
name: asn-labels-pdf
path: asn-labels.pdf
retention-days: 30

12
package.json Normal file
View file

@ -0,0 +1,12 @@
{
"name": "asn-qr-code-label-generator",
"version": "1.0.0",
"description": "QR code label generator for Paperless-ngx Archive Serial Numbers",
"private": true,
"scripts": {
"generate-pdf": "node scripts/generate-pdf.js"
},
"devDependencies": {
"playwright": "^1.49.0"
}
}

41
scripts/generate-pdf.js Normal file
View file

@ -0,0 +1,41 @@
const { chromium } = require('playwright');
const path = require('path');
async function generatePDF() {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// Load the local HTML file
const htmlPath = path.join(__dirname, '..', 'index.html');
await page.goto(`file://${htmlPath}`);
// Wait for AlpineJS to initialize and generate labels
await page.waitForFunction(() => {
const labels = document.querySelectorAll('ol li');
return labels.length === 189; // 7 columns x 27 rows
});
// Wait for all QR code images to load
await page.waitForFunction(() => {
const images = document.querySelectorAll('ol li img');
return Array.from(images).every(img => img.complete && img.naturalHeight > 0);
}, { timeout: 60000 });
// Generate PDF with A4 format and print media
await page.pdf({
path: 'asn-labels.pdf',
format: 'A4',
printBackground: true,
margin: { top: 0, right: 0, bottom: 0, left: 0 }
});
console.log('PDF generated successfully: asn-labels.pdf');
await browser.close();
}
generatePDF().catch(err => {
console.error('Error generating PDF:', err);
process.exit(1);
});