pdf-smith 0.1.0 → 0.3.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.
package/dist/server.cjs CHANGED
@@ -31,10 +31,39 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
33
  // src/export.ts
34
+ function discoverDocuments(root) {
35
+ const pdfsDir = import_node_path.default.join(root, "pdfs");
36
+ if (!import_node_fs.default.existsSync(pdfsDir)) return [];
37
+ const entries = import_node_fs.default.readdirSync(pdfsDir, { withFileTypes: true });
38
+ const documents = [];
39
+ for (const entry of entries) {
40
+ if (!entry.isDirectory()) continue;
41
+ const pagesDir = import_node_path.default.join(pdfsDir, entry.name, "pages");
42
+ if (!import_node_fs.default.existsSync(pagesDir)) continue;
43
+ const configPath = import_node_path.default.join(pdfsDir, entry.name, "config.ts");
44
+ documents.push({
45
+ slug: entry.name,
46
+ configPath: import_node_fs.default.existsSync(configPath) ? configPath : null
47
+ });
48
+ }
49
+ return documents;
50
+ }
34
51
  async function exportPDF(options) {
35
- const { root, output, pageNumbers, pages } = options;
36
- const outputPath = import_node_path.default.resolve(root, output ?? "./output.pdf");
37
- import_node_fs.default.mkdirSync(import_node_path.default.dirname(outputPath), { recursive: true });
52
+ const { root, document: documentSlug, output } = options;
53
+ const outputDir = import_node_path.default.resolve(root, output ?? "output");
54
+ let documents = discoverDocuments(root);
55
+ if (documentSlug) {
56
+ documents = documents.filter((d) => d.slug === documentSlug);
57
+ if (documents.length === 0) {
58
+ throw new Error(
59
+ `Document "${documentSlug}" not found. Check that pdfs/${documentSlug}/pages/ exists.`
60
+ );
61
+ }
62
+ }
63
+ if (documents.length === 0) {
64
+ throw new Error("No documents found. Create at least one document in pdfs/<name>/pages/.");
65
+ }
66
+ import_node_fs.default.mkdirSync(outputDir, { recursive: true });
38
67
  let playwright;
39
68
  try {
40
69
  playwright = await import("playwright");
@@ -44,33 +73,49 @@ async function exportPDF(options) {
44
73
  );
45
74
  }
46
75
  const { startPreview: startPreview2 } = await Promise.resolve().then(() => (init_server(), server_exports));
47
- const server = await startPreview2({ root, port: 0, pages, open: false });
76
+ const server = await startPreview2({ root, port: 0, open: false });
77
+ const vite = server._vite;
48
78
  const browser = await playwright.chromium.launch({ headless: true });
79
+ const outputs = [];
49
80
  try {
50
- const page = await browser.newPage();
51
- await page.goto(server.url, { waitUntil: "networkidle" });
52
- await page.waitForSelector("[data-pdf-smith-page]", { timeout: 3e4 });
53
- const margin = { top: "0", bottom: "0", left: "0", right: "0" };
54
- const pdfOptions = {
55
- path: outputPath,
56
- preferCSSPageSize: true,
57
- printBackground: true,
58
- margin
59
- };
60
- if (pageNumbers?.enabled) {
61
- pdfOptions.displayHeaderFooter = true;
62
- pdfOptions.headerTemplate = "<span></span>";
63
- pdfOptions.footerTemplate = pageNumbers.template ?? '<div style="font-size:10px;text-align:center;width:100%;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>';
64
- margin.bottom = "40px";
81
+ for (const doc of documents) {
82
+ let config;
83
+ if (doc.configPath && vite) {
84
+ try {
85
+ const configModule = await vite.ssrLoadModule(doc.configPath);
86
+ config = configModule.default;
87
+ } catch {
88
+ }
89
+ }
90
+ const filename = config?.output ?? `${doc.slug}.pdf`;
91
+ const outputPath = import_node_path.default.resolve(outputDir, filename);
92
+ const page = await browser.newPage();
93
+ await page.goto(`${server.url}/${doc.slug}`, { waitUntil: "networkidle" });
94
+ await page.waitForSelector("[data-pdf-smith-page]", { timeout: 3e4 });
95
+ const margin = { top: "0", bottom: "0", left: "0", right: "0" };
96
+ const pdfOptions = {
97
+ path: outputPath,
98
+ preferCSSPageSize: true,
99
+ printBackground: true,
100
+ margin
101
+ };
102
+ if (config?.pageNumbers?.enabled) {
103
+ pdfOptions.displayHeaderFooter = true;
104
+ pdfOptions.headerTemplate = "<span></span>";
105
+ pdfOptions.footerTemplate = config.pageNumbers.template ?? '<div style="font-size:10px;text-align:center;width:100%;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>';
106
+ margin.bottom = "40px";
107
+ }
108
+ await page.pdf(pdfOptions);
109
+ await page.close();
110
+ outputs.push({ document: doc.slug, outputPath });
65
111
  }
66
- await page.pdf(pdfOptions);
67
112
  } finally {
68
113
  await browser.close().catch(() => {
69
114
  });
70
115
  await server.close().catch(() => {
71
116
  });
72
117
  }
73
- return { outputPath };
118
+ return { outputs };
74
119
  }
75
120
  var import_node_fs, import_node_path;
76
121
  var init_export = __esm({
@@ -86,13 +131,90 @@ var preview_plugin_exports = {};
86
131
  __export(preview_plugin_exports, {
87
132
  pdfSmithPreviewPlugin: () => pdfSmithPreviewPlugin
88
133
  });
89
- function pdfSmithPreviewPlugin({ pkgSrcDir, pagesGlob }) {
134
+ async function handleExportRequest(server, slug, res) {
135
+ const root = server.config.root;
136
+ const pagesDir = import_node_path2.default.join(root, "pdfs", slug, "pages");
137
+ if (!import_node_fs2.default.existsSync(pagesDir)) {
138
+ res.statusCode = 404;
139
+ res.setHeader("Content-Type", "application/json");
140
+ res.end(JSON.stringify({ error: `Document "${slug}" not found` }));
141
+ return;
142
+ }
143
+ let config;
144
+ const configPath = import_node_path2.default.join(root, "pdfs", slug, "config.ts");
145
+ if (import_node_fs2.default.existsSync(configPath)) {
146
+ try {
147
+ const configModule = await server.ssrLoadModule(configPath);
148
+ config = configModule.default;
149
+ } catch {
150
+ }
151
+ }
152
+ let playwright;
153
+ try {
154
+ playwright = await import("playwright");
155
+ } catch {
156
+ res.statusCode = 500;
157
+ res.setHeader("Content-Type", "application/json");
158
+ res.end(
159
+ JSON.stringify({
160
+ error: "Playwright is required for PDF export. Install it with: npm install -D playwright && npx playwright install chromium"
161
+ })
162
+ );
163
+ return;
164
+ }
165
+ let browser;
166
+ try {
167
+ const address = server.httpServer?.address();
168
+ const port = address?.port;
169
+ if (!port) throw new Error("Could not determine server port");
170
+ browser = await playwright.chromium.launch({ headless: true });
171
+ const page = await browser.newPage();
172
+ await page.goto(`http://localhost:${port}/${slug}`, { waitUntil: "networkidle" });
173
+ await page.waitForSelector("[data-pdf-smith-page]", { timeout: 3e4 });
174
+ const margin = { top: "0", bottom: "0", left: "0", right: "0" };
175
+ const pdfOptions = {
176
+ preferCSSPageSize: true,
177
+ printBackground: true,
178
+ margin
179
+ };
180
+ if (config?.pageNumbers?.enabled) {
181
+ pdfOptions.displayHeaderFooter = true;
182
+ pdfOptions.headerTemplate = "<span></span>";
183
+ pdfOptions.footerTemplate = config.pageNumbers.template ?? '<div style="font-size:10px;text-align:center;width:100%;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>';
184
+ margin.bottom = "40px";
185
+ }
186
+ const buffer = await page.pdf(pdfOptions);
187
+ await page.close();
188
+ const filename = config?.output ?? `${slug}.pdf`;
189
+ res.statusCode = 200;
190
+ res.setHeader("Content-Type", "application/pdf");
191
+ res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
192
+ res.end(buffer);
193
+ } catch (err) {
194
+ if (!res.headersSent) {
195
+ res.statusCode = 500;
196
+ res.setHeader("Content-Type", "application/json");
197
+ res.end(JSON.stringify({ error: err instanceof Error ? err.message : "PDF export failed" }));
198
+ }
199
+ } finally {
200
+ await browser?.close().catch(() => {
201
+ });
202
+ }
203
+ }
204
+ function pdfSmithPreviewPlugin({ pkgSrcDir }) {
90
205
  return {
91
206
  name: "pdf-smith-preview",
92
207
  configureServer(server) {
208
+ server.middlewares.use((req, res, next) => {
209
+ if (req.method !== "POST") return next();
210
+ const match = req.url?.match(/^\/api\/export\/([^/]+)$/);
211
+ if (!match) return next();
212
+ void handleExportRequest(server, match[1], res);
213
+ });
93
214
  return () => {
94
215
  server.middlewares.use((req, res, next) => {
95
- if (req.url !== "/" && req.url !== "/index.html") {
216
+ const url = req.url ?? "";
217
+ if (url.includes(".") || url.startsWith("/@") || url.startsWith("/node_modules/")) {
96
218
  next();
97
219
  return;
98
220
  }
@@ -110,18 +232,35 @@ window.__vite_plugin_react_preamble_installed__ = true
110
232
  <meta charset="UTF-8" />
111
233
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
112
234
  <title>pdf-smith Preview</title>
235
+ <link rel="preconnect" href="https://fonts.googleapis.com">
236
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
237
+ <link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT,WONK@0,9..144,100..900,0..100,0..1&family=Inter:opsz,wght@14..32,100..900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
113
238
  <style>
239
+ *, *::before, *::after { box-sizing: border-box; }
240
+ body {
241
+ margin: 0;
242
+ font-family: 'Inter', system-ui, sans-serif;
243
+ -webkit-font-smoothing: antialiased;
244
+ }
245
+ .pdf-smith-search::placeholder { color: #78716C; }
114
246
  @media print {
115
247
  [data-pdf-smith-nav] { display: none !important; }
248
+ [data-pdf-smith-toolbar] { display: none !important; }
249
+ [data-pdf-smith-minimap] { display: none !important; }
116
250
  [data-pdf-smith-container] {
117
251
  margin-left: 0 !important;
118
252
  padding: 0 !important;
253
+ padding-top: 0 !important;
119
254
  background: none !important;
120
255
  }
121
- [data-pdf-smith-container] > [data-pdf-smith-document] > div {
256
+ [data-pdf-smith-container] > div {
257
+ padding: 0 !important;
258
+ gap: 0 !important;
259
+ }
260
+ [data-pdf-smith-document] > div {
122
261
  margin-bottom: 0 !important;
123
262
  }
124
- [data-pdf-smith-container] > [data-pdf-smith-document] > div > div:first-child {
263
+ [data-pdf-smith-document] > div > div:first-child {
125
264
  display: none !important;
126
265
  }
127
266
  }
@@ -139,36 +278,57 @@ window.__vite_plugin_react_preamble_installed__ = true
139
278
  };
140
279
  },
141
280
  resolveId(id) {
142
- if (id === VIRTUAL_PAGES_ID) {
143
- return RESOLVED_VIRTUAL_PAGES_ID;
281
+ if (id === VIRTUAL_DOCUMENTS_ID) {
282
+ return RESOLVED_VIRTUAL_DOCUMENTS_ID;
144
283
  }
145
284
  },
146
285
  load(id) {
147
- if (id === RESOLVED_VIRTUAL_PAGES_ID) {
286
+ if (id === RESOLVED_VIRTUAL_DOCUMENTS_ID) {
148
287
  return `
149
- const modules = import.meta.glob('${pagesGlob}', { eager: true });
288
+ const pageModules = import.meta.glob('/pdfs/*/pages/**/*.tsx', { eager: true });
289
+ const configModules = import.meta.glob('/pdfs/*/config.ts', { eager: true });
290
+
291
+ export function getDocuments() {
292
+ const documents = {};
293
+
294
+ for (const [path, mod] of Object.entries(pageModules)) {
295
+ const match = path.match(/^\\/pdfs\\/([^/]+)\\/pages\\/(.+)\\.[^.]+$/);
296
+ if (!match) continue;
297
+ const [, slug, pageName] = match;
298
+ if (!documents[slug]) {
299
+ documents[slug] = { slug, pages: {}, config: undefined };
300
+ }
301
+ documents[slug].pages[pageName] = mod.default;
302
+ }
150
303
 
151
- export function getPages() {
152
- const pages = {};
153
- for (const [path, mod] of Object.entries(modules)) {
154
- const name = path
155
- .replace(/^\\/pages\\//, '')
156
- .replace(/\\.[^.]+$/, '');
157
- pages[name] = mod.default;
158
- }
159
- return pages;
304
+ for (const [path, mod] of Object.entries(configModules)) {
305
+ const match = path.match(/^\\/pdfs\\/([^/]+)\\/config\\.ts$/);
306
+ if (!match) continue;
307
+ const slug = match[1];
308
+ if (documents[slug]) {
309
+ documents[slug].config = mod.default;
310
+ }
311
+ }
312
+
313
+ return documents;
314
+ }
315
+
316
+ export function getDocumentSlugs() {
317
+ return Object.keys(getDocuments());
160
318
  }
161
319
  `;
162
320
  }
163
321
  }
164
322
  };
165
323
  }
166
- var VIRTUAL_PAGES_ID, RESOLVED_VIRTUAL_PAGES_ID;
324
+ var import_node_fs2, import_node_path2, VIRTUAL_DOCUMENTS_ID, RESOLVED_VIRTUAL_DOCUMENTS_ID;
167
325
  var init_preview_plugin = __esm({
168
326
  "src/preview/preview-plugin.ts"() {
169
327
  "use strict";
170
- VIRTUAL_PAGES_ID = "virtual:pdf-smith-pages";
171
- RESOLVED_VIRTUAL_PAGES_ID = `\0${VIRTUAL_PAGES_ID}`;
328
+ import_node_fs2 = __toESM(require("fs"), 1);
329
+ import_node_path2 = __toESM(require("path"), 1);
330
+ VIRTUAL_DOCUMENTS_ID = "virtual:pdf-smith-documents";
331
+ RESOLVED_VIRTUAL_DOCUMENTS_ID = `\0${VIRTUAL_DOCUMENTS_ID}`;
172
332
  }
173
333
  });
174
334
 
@@ -180,14 +340,14 @@ __export(server_exports, {
180
340
  });
181
341
  module.exports = __toCommonJS(server_exports);
182
342
  async function startPreview(options) {
183
- const { root, port = 3e3, pages = "/pages/**/*.tsx", open = false } = options;
343
+ const { root, port = 3e3, open = false } = options;
184
344
  const { createServer } = await import("vite");
185
345
  const react = (await import("@vitejs/plugin-react")).default;
186
346
  const tailwindcss = (await import("@tailwindcss/vite")).default;
187
347
  const { pdfSmithPreviewPlugin: pdfSmithPreviewPlugin2 } = await Promise.resolve().then(() => (init_preview_plugin(), preview_plugin_exports));
188
- const currentDir = import_node_path2.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
189
- const pkgRoot = import_node_path2.default.resolve(currentDir, "..");
190
- const pkgSrcDir = import_node_path2.default.resolve(pkgRoot, "src");
348
+ const currentDir = import_node_path3.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
349
+ const pkgRoot = import_node_path3.default.resolve(currentDir, "..");
350
+ const pkgSrcDir = import_node_path3.default.resolve(pkgRoot, "src");
191
351
  const server = await createServer({
192
352
  configFile: false,
193
353
  appType: "custom",
@@ -202,11 +362,11 @@ async function startPreview(options) {
202
362
  },
203
363
  resolve: {
204
364
  alias: {
205
- "pdf-smith": import_node_path2.default.resolve(pkgSrcDir, "index.ts")
365
+ "pdf-smith": import_node_path3.default.resolve(pkgSrcDir, "index.ts")
206
366
  },
207
367
  dedupe: ["react", "react-dom"]
208
368
  },
209
- plugins: [react(), tailwindcss(), pdfSmithPreviewPlugin2({ pkgSrcDir, pagesGlob: pages })],
369
+ plugins: [react(), tailwindcss(), pdfSmithPreviewPlugin2({ pkgSrcDir })],
210
370
  optimizeDeps: {
211
371
  include: ["react", "react-dom", "react-dom/client", "react/jsx-runtime"]
212
372
  }
@@ -218,7 +378,7 @@ async function startPreview(options) {
218
378
  const address = server.httpServer?.address();
219
379
  const resolvedPort = address?.port ?? port;
220
380
  const url = `http://localhost:${resolvedPort}`;
221
- return {
381
+ const previewServer = {
222
382
  close: async () => {
223
383
  const httpServer = server.httpServer;
224
384
  httpServer?.closeAllConnections?.();
@@ -227,11 +387,16 @@ async function startPreview(options) {
227
387
  port: resolvedPort,
228
388
  url
229
389
  };
390
+ Object.defineProperty(previewServer, "_vite", {
391
+ value: server,
392
+ enumerable: false
393
+ });
394
+ return previewServer;
230
395
  }
231
- var import_node_path2, import_node_url, import_meta;
396
+ var import_node_path3, import_node_url, import_meta;
232
397
  var init_server = __esm({
233
398
  "src/server.ts"() {
234
- import_node_path2 = __toESM(require("path"), 1);
399
+ import_node_path3 = __toESM(require("path"), 1);
235
400
  import_node_url = require("url");
236
401
  init_export();
237
402
  import_meta = {};
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/export.ts","../src/preview/preview-plugin.ts","../src/server.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport type { ExportOptions, ExportResult } from './export-types';\n\nexport async function exportPDF(options: ExportOptions): Promise<ExportResult> {\n const { root, output, pageNumbers, pages } = options;\n const outputPath = path.resolve(root, output ?? './output.pdf');\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n\n let playwright: typeof import('playwright');\n try {\n playwright = await import('playwright');\n } catch {\n throw new Error(\n 'Playwright is required for PDF export. Install it with: npm install -D playwright && npx playwright install chromium',\n );\n }\n\n const { startPreview } = await import('./server');\n const server = await startPreview({ root, port: 0, pages, open: false });\n\n const browser = await playwright.chromium.launch({ headless: true });\n try {\n const page = await browser.newPage();\n await page.goto(server.url, { waitUntil: 'networkidle' });\n await page.waitForSelector('[data-pdf-smith-page]', { timeout: 30_000 });\n\n const margin = { top: '0', bottom: '0', left: '0', right: '0' };\n\n const pdfOptions: Parameters<typeof page.pdf>[0] = {\n path: outputPath,\n preferCSSPageSize: true,\n printBackground: true,\n margin,\n };\n\n if (pageNumbers?.enabled) {\n pdfOptions.displayHeaderFooter = true;\n pdfOptions.headerTemplate = '<span></span>';\n pdfOptions.footerTemplate =\n pageNumbers.template ??\n '<div style=\"font-size:10px;text-align:center;width:100%;\"><span class=\"pageNumber\"></span> / <span class=\"totalPages\"></span></div>';\n margin.bottom = '40px';\n }\n\n await page.pdf(pdfOptions);\n } finally {\n await browser.close().catch(() => {});\n await server.close().catch(() => {});\n }\n\n return { outputPath };\n}\n","import type { Plugin } from 'vite';\n\nconst VIRTUAL_PAGES_ID = 'virtual:pdf-smith-pages';\nconst RESOLVED_VIRTUAL_PAGES_ID = `\\0${VIRTUAL_PAGES_ID}`;\n\ninterface PreviewPluginOptions {\n pkgSrcDir: string;\n pagesGlob: string;\n}\n\nexport function pdfSmithPreviewPlugin({ pkgSrcDir, pagesGlob }: PreviewPluginOptions): Plugin {\n return {\n name: 'pdf-smith-preview',\n\n configureServer(server) {\n return () => {\n server.middlewares.use((req, res, next) => {\n if (req.url !== '/' && req.url !== '/index.html') {\n next();\n return;\n }\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <script type=\"module\">\nimport RefreshRuntime from \"/@react-refresh\"\nRefreshRuntime.injectIntoGlobalHook(window)\nwindow.$RefreshReg$ = () => {}\nwindow.$RefreshSig$ = () => (type) => type\nwindow.__vite_plugin_react_preamble_installed__ = true\n</script>\n <script type=\"module\" src=\"/@vite/client\"></script>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>pdf-smith Preview</title>\n <style>\n @media print {\n [data-pdf-smith-nav] { display: none !important; }\n [data-pdf-smith-container] {\n margin-left: 0 !important;\n padding: 0 !important;\n background: none !important;\n }\n [data-pdf-smith-container] > [data-pdf-smith-document] > div {\n margin-bottom: 0 !important;\n }\n [data-pdf-smith-container] > [data-pdf-smith-document] > div > div:first-child {\n display: none !important;\n }\n }\n </style>\n</head>\n<body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/@fs/${pkgSrcDir}/preview/entry.tsx\"></script>\n</body>\n</html>`;\n\n res.setHeader('Content-Type', 'text/html');\n res.statusCode = 200;\n res.end(html);\n });\n };\n },\n\n resolveId(id) {\n if (id === VIRTUAL_PAGES_ID) {\n return RESOLVED_VIRTUAL_PAGES_ID;\n }\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_PAGES_ID) {\n return `\nconst modules = import.meta.glob('${pagesGlob}', { eager: true });\n\nexport function getPages() {\n const pages = {};\n for (const [path, mod] of Object.entries(modules)) {\n const name = path\n .replace(/^\\\\/pages\\\\//, '')\n .replace(/\\\\.[^.]+$/, '');\n pages[name] = mod.default;\n }\n return pages;\n}\n`;\n }\n },\n };\n}\n","import type { AddressInfo } from 'node:net';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { PreviewOptions, PreviewServer } from './preview/types';\n\nexport { exportPDF } from './export';\nexport type { ExportOptions, ExportResult } from './export-types';\nexport type { PreviewOptions, PreviewServer } from './preview/types';\n\nexport async function startPreview(options: PreviewOptions): Promise<PreviewServer> {\n const { root, port = 3000, pages = '/pages/**/*.tsx', open = false } = options;\n\n const { createServer } = await import('vite');\n const react = (await import('@vitejs/plugin-react')).default;\n const tailwindcss = (await import('@tailwindcss/vite')).default;\n const { pdfSmithPreviewPlugin } = await import('./preview/preview-plugin');\n\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const pkgRoot = path.resolve(currentDir, '..');\n const pkgSrcDir = path.resolve(pkgRoot, 'src');\n\n const server = await createServer({\n configFile: false,\n appType: 'custom',\n root,\n server: {\n port,\n strictPort: port !== 0,\n open,\n fs: {\n allow: [root, pkgSrcDir, pkgRoot],\n },\n },\n resolve: {\n alias: {\n 'pdf-smith': path.resolve(pkgSrcDir, 'index.ts'),\n },\n dedupe: ['react', 'react-dom'],\n },\n plugins: [react(), tailwindcss(), pdfSmithPreviewPlugin({ pkgSrcDir, pagesGlob: pages })],\n optimizeDeps: {\n include: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime'],\n },\n });\n\n await server.listen();\n\n if (port !== 0) {\n server.printUrls();\n }\n\n const address = server.httpServer?.address() as AddressInfo | null;\n const resolvedPort = address?.port ?? port;\n const url = `http://localhost:${resolvedPort}`;\n\n return {\n close: async () => {\n const httpServer = server.httpServer as { closeAllConnections?: () => void } | null;\n httpServer?.closeAllConnections?.();\n await server.close();\n },\n port: resolvedPort,\n url,\n };\n}\n"],"mappings":"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","names":["path","fs","startPreview","pdfSmithPreviewPlugin","path","import_node_path"]}
1
+ {"version":3,"sources":["../src/export.ts","../src/preview/preview-plugin.ts","../src/server.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport type { DocumentConfig } from './config';\nimport type { ExportOptions, ExportResult } from './export-types';\n\ninterface DiscoveredDocument {\n slug: string;\n configPath: string | null;\n}\n\nfunction discoverDocuments(root: string): DiscoveredDocument[] {\n const pdfsDir = path.join(root, 'pdfs');\n if (!fs.existsSync(pdfsDir)) return [];\n\n const entries = fs.readdirSync(pdfsDir, { withFileTypes: true });\n const documents: DiscoveredDocument[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const pagesDir = path.join(pdfsDir, entry.name, 'pages');\n if (!fs.existsSync(pagesDir)) continue;\n\n const configPath = path.join(pdfsDir, entry.name, 'config.ts');\n documents.push({\n slug: entry.name,\n configPath: fs.existsSync(configPath) ? configPath : null,\n });\n }\n\n return documents;\n}\n\nexport async function exportPDF(options: ExportOptions): Promise<ExportResult> {\n const { root, document: documentSlug, output } = options;\n const outputDir = path.resolve(root, output ?? 'output');\n\n let documents = discoverDocuments(root);\n\n if (documentSlug) {\n documents = documents.filter((d) => d.slug === documentSlug);\n if (documents.length === 0) {\n throw new Error(\n `Document \"${documentSlug}\" not found. Check that pdfs/${documentSlug}/pages/ exists.`,\n );\n }\n }\n\n if (documents.length === 0) {\n throw new Error('No documents found. Create at least one document in pdfs/<name>/pages/.');\n }\n\n fs.mkdirSync(outputDir, { recursive: true });\n\n let playwright: typeof import('playwright');\n try {\n playwright = await import('playwright');\n } catch {\n throw new Error(\n 'Playwright is required for PDF export. Install it with: npm install -D playwright && npx playwright install chromium',\n );\n }\n\n const { startPreview } = await import('./server');\n const server = await startPreview({ root, port: 0, open: false });\n\n const vite = (\n server as unknown as {\n _vite: { ssrLoadModule: (id: string) => Promise<{ default?: DocumentConfig }> };\n }\n )._vite;\n\n const browser = await playwright.chromium.launch({ headless: true });\n const outputs: ExportResult['outputs'] = [];\n\n try {\n for (const doc of documents) {\n let config: DocumentConfig | undefined;\n if (doc.configPath && vite) {\n try {\n const configModule = await vite.ssrLoadModule(doc.configPath);\n config = configModule.default;\n } catch {\n // Config loading failed, proceed without it\n }\n }\n\n const filename = config?.output ?? `${doc.slug}.pdf`;\n const outputPath = path.resolve(outputDir, filename);\n\n const page = await browser.newPage();\n await page.goto(`${server.url}/${doc.slug}`, { waitUntil: 'networkidle' });\n await page.waitForSelector('[data-pdf-smith-page]', { timeout: 30_000 });\n\n const margin = { top: '0', bottom: '0', left: '0', right: '0' };\n\n const pdfOptions: Parameters<typeof page.pdf>[0] = {\n path: outputPath,\n preferCSSPageSize: true,\n printBackground: true,\n margin,\n };\n\n if (config?.pageNumbers?.enabled) {\n pdfOptions.displayHeaderFooter = true;\n pdfOptions.headerTemplate = '<span></span>';\n pdfOptions.footerTemplate =\n config.pageNumbers.template ??\n '<div style=\"font-size:10px;text-align:center;width:100%;\"><span class=\"pageNumber\"></span> / <span class=\"totalPages\"></span></div>';\n margin.bottom = '40px';\n }\n\n await page.pdf(pdfOptions);\n await page.close();\n\n outputs.push({ document: doc.slug, outputPath });\n }\n } finally {\n await browser.close().catch(() => {});\n await server.close().catch(() => {});\n }\n\n return { outputs };\n}\n","import fs from 'node:fs';\nimport type { AddressInfo } from 'node:net';\nimport path from 'node:path';\nimport type { Plugin } from 'vite';\nimport type { DocumentConfig } from '../config';\n\nconst VIRTUAL_DOCUMENTS_ID = 'virtual:pdf-smith-documents';\nconst RESOLVED_VIRTUAL_DOCUMENTS_ID = `\\0${VIRTUAL_DOCUMENTS_ID}`;\n\ninterface PreviewPluginOptions {\n pkgSrcDir: string;\n}\n\nasync function handleExportRequest(\n server: import('vite').ViteDevServer,\n slug: string,\n res: import('node:http').ServerResponse,\n) {\n const root = server.config.root;\n const pagesDir = path.join(root, 'pdfs', slug, 'pages');\n\n if (!fs.existsSync(pagesDir)) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: `Document \"${slug}\" not found` }));\n return;\n }\n\n let config: DocumentConfig | undefined;\n const configPath = path.join(root, 'pdfs', slug, 'config.ts');\n if (fs.existsSync(configPath)) {\n try {\n const configModule = await server.ssrLoadModule(configPath);\n config = configModule.default;\n } catch {\n // Config loading failed, proceed without it\n }\n }\n\n let playwright: typeof import('playwright');\n try {\n playwright = await import('playwright');\n } catch {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(\n JSON.stringify({\n error:\n 'Playwright is required for PDF export. Install it with: npm install -D playwright && npx playwright install chromium',\n }),\n );\n return;\n }\n\n let browser: import('playwright').Browser | undefined;\n try {\n const address = server.httpServer?.address() as AddressInfo | null;\n const port = address?.port;\n if (!port) throw new Error('Could not determine server port');\n\n browser = await playwright.chromium.launch({ headless: true });\n const page = await browser.newPage();\n await page.goto(`http://localhost:${port}/${slug}`, { waitUntil: 'networkidle' });\n await page.waitForSelector('[data-pdf-smith-page]', { timeout: 30_000 });\n\n const margin = { top: '0', bottom: '0', left: '0', right: '0' };\n const pdfOptions: Parameters<typeof page.pdf>[0] = {\n preferCSSPageSize: true,\n printBackground: true,\n margin,\n };\n\n if (config?.pageNumbers?.enabled) {\n pdfOptions.displayHeaderFooter = true;\n pdfOptions.headerTemplate = '<span></span>';\n pdfOptions.footerTemplate =\n config.pageNumbers.template ??\n '<div style=\"font-size:10px;text-align:center;width:100%;\"><span class=\"pageNumber\"></span> / <span class=\"totalPages\"></span></div>';\n margin.bottom = '40px';\n }\n\n const buffer = await page.pdf(pdfOptions);\n await page.close();\n\n const filename = config?.output ?? `${slug}.pdf`;\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/pdf');\n res.setHeader('Content-Disposition', `attachment; filename=\"${filename}\"`);\n res.end(buffer);\n } catch (err) {\n if (!res.headersSent) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: err instanceof Error ? err.message : 'PDF export failed' }));\n }\n } finally {\n await browser?.close().catch(() => {});\n }\n}\n\nexport function pdfSmithPreviewPlugin({ pkgSrcDir }: PreviewPluginOptions): Plugin {\n return {\n name: 'pdf-smith-preview',\n\n configureServer(server) {\n // Pre-middleware: Export API runs before Vite internals.\n // Must be a sync function — async middleware returns a Promise that\n // Connect ignores, so the pipeline can advance to the catch-all\n // before the async work finishes.\n server.middlewares.use((req, res, next) => {\n if (req.method !== 'POST') return next();\n const match = req.url?.match(/^\\/api\\/export\\/([^/]+)$/);\n if (!match) return next();\n void handleExportRequest(server, match[1], res);\n });\n\n // Post-middleware: catch-all HTML handler (after Vite internals)\n return () => {\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? '';\n\n // Skip file requests, Vite internals, and node_modules\n if (url.includes('.') || url.startsWith('/@') || url.startsWith('/node_modules/')) {\n next();\n return;\n }\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <script type=\"module\">\nimport RefreshRuntime from \"/@react-refresh\"\nRefreshRuntime.injectIntoGlobalHook(window)\nwindow.$RefreshReg$ = () => {}\nwindow.$RefreshSig$ = () => (type) => type\nwindow.__vite_plugin_react_preamble_installed__ = true\n</script>\n <script type=\"module\" src=\"/@vite/client\"></script>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>pdf-smith Preview</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT,WONK@0,9..144,100..900,0..100,0..1&family=Inter:opsz,wght@14..32,100..900&family=JetBrains+Mono:wght@400;500;600&display=swap\" rel=\"stylesheet\">\n <style>\n *, *::before, *::after { box-sizing: border-box; }\n body {\n margin: 0;\n font-family: 'Inter', system-ui, sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n .pdf-smith-search::placeholder { color: #78716C; }\n @media print {\n [data-pdf-smith-nav] { display: none !important; }\n [data-pdf-smith-toolbar] { display: none !important; }\n [data-pdf-smith-minimap] { display: none !important; }\n [data-pdf-smith-container] {\n margin-left: 0 !important;\n padding: 0 !important;\n padding-top: 0 !important;\n background: none !important;\n }\n [data-pdf-smith-container] > div {\n padding: 0 !important;\n gap: 0 !important;\n }\n [data-pdf-smith-document] > div {\n margin-bottom: 0 !important;\n }\n [data-pdf-smith-document] > div > div:first-child {\n display: none !important;\n }\n }\n </style>\n</head>\n<body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/@fs/${pkgSrcDir}/preview/entry.tsx\"></script>\n</body>\n</html>`;\n\n res.setHeader('Content-Type', 'text/html');\n res.statusCode = 200;\n res.end(html);\n });\n };\n },\n\n resolveId(id) {\n if (id === VIRTUAL_DOCUMENTS_ID) {\n return RESOLVED_VIRTUAL_DOCUMENTS_ID;\n }\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_DOCUMENTS_ID) {\n return `\nconst pageModules = import.meta.glob('/pdfs/*/pages/**/*.tsx', { eager: true });\nconst configModules = import.meta.glob('/pdfs/*/config.ts', { eager: true });\n\nexport function getDocuments() {\n const documents = {};\n\n for (const [path, mod] of Object.entries(pageModules)) {\n const match = path.match(/^\\\\/pdfs\\\\/([^/]+)\\\\/pages\\\\/(.+)\\\\.[^.]+$/);\n if (!match) continue;\n const [, slug, pageName] = match;\n if (!documents[slug]) {\n documents[slug] = { slug, pages: {}, config: undefined };\n }\n documents[slug].pages[pageName] = mod.default;\n }\n\n for (const [path, mod] of Object.entries(configModules)) {\n const match = path.match(/^\\\\/pdfs\\\\/([^/]+)\\\\/config\\\\.ts$/);\n if (!match) continue;\n const slug = match[1];\n if (documents[slug]) {\n documents[slug].config = mod.default;\n }\n }\n\n return documents;\n}\n\nexport function getDocumentSlugs() {\n return Object.keys(getDocuments());\n}\n`;\n }\n },\n };\n}\n","import type { AddressInfo } from 'node:net';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { PreviewOptions, PreviewServer } from './preview/types';\n\nexport { exportPDF } from './export';\nexport type { ExportOptions, ExportResult } from './export-types';\nexport type { PreviewOptions, PreviewServer } from './preview/types';\n\nexport async function startPreview(options: PreviewOptions): Promise<PreviewServer> {\n const { root, port = 3000, open = false } = options;\n\n const { createServer } = await import('vite');\n const react = (await import('@vitejs/plugin-react')).default;\n const tailwindcss = (await import('@tailwindcss/vite')).default;\n const { pdfSmithPreviewPlugin } = await import('./preview/preview-plugin');\n\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const pkgRoot = path.resolve(currentDir, '..');\n const pkgSrcDir = path.resolve(pkgRoot, 'src');\n\n const server = await createServer({\n configFile: false,\n appType: 'custom',\n root,\n server: {\n port,\n strictPort: port !== 0,\n open,\n fs: {\n allow: [root, pkgSrcDir, pkgRoot],\n },\n },\n resolve: {\n alias: {\n 'pdf-smith': path.resolve(pkgSrcDir, 'index.ts'),\n },\n dedupe: ['react', 'react-dom'],\n },\n plugins: [react(), tailwindcss(), pdfSmithPreviewPlugin({ pkgSrcDir })],\n optimizeDeps: {\n include: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime'],\n },\n });\n\n await server.listen();\n\n if (port !== 0) {\n server.printUrls();\n }\n\n const address = server.httpServer?.address() as AddressInfo | null;\n const resolvedPort = address?.port ?? port;\n const url = `http://localhost:${resolvedPort}`;\n\n const previewServer: PreviewServer = {\n close: async () => {\n const httpServer = server.httpServer as { closeAllConnections?: () => void } | null;\n httpServer?.closeAllConnections?.();\n await server.close();\n },\n port: resolvedPort,\n url,\n };\n\n Object.defineProperty(previewServer, '_vite', {\n value: server,\n enumerable: false,\n });\n\n return previewServer;\n}\n"],"mappings":"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","names":["path","fs","startPreview","path","fs","import_node_fs","import_node_path","pdfSmithPreviewPlugin","path","import_node_path"]}
package/dist/server.d.cts CHANGED
@@ -3,7 +3,6 @@ interface PreviewOptions {
3
3
  root: string;
4
4
  /** Dev server port (default: 3000) */
5
5
  port?: number;
6
- pages?: string;
7
6
  /** Auto-open browser (default: false) */
8
7
  open?: boolean;
9
8
  }
@@ -15,15 +14,14 @@ interface PreviewServer {
15
14
 
16
15
  interface ExportOptions {
17
16
  root: string;
17
+ document?: string;
18
18
  output?: string;
19
- pageNumbers?: {
20
- enabled: boolean;
21
- template?: string;
22
- };
23
- pages?: string;
24
19
  }
25
20
  interface ExportResult {
26
- outputPath: string;
21
+ outputs: Array<{
22
+ document: string;
23
+ outputPath: string;
24
+ }>;
27
25
  }
28
26
 
29
27
  declare function exportPDF(options: ExportOptions): Promise<ExportResult>;
package/dist/server.d.ts CHANGED
@@ -3,7 +3,6 @@ interface PreviewOptions {
3
3
  root: string;
4
4
  /** Dev server port (default: 3000) */
5
5
  port?: number;
6
- pages?: string;
7
6
  /** Auto-open browser (default: false) */
8
7
  open?: boolean;
9
8
  }
@@ -15,15 +14,14 @@ interface PreviewServer {
15
14
 
16
15
  interface ExportOptions {
17
16
  root: string;
17
+ document?: string;
18
18
  output?: string;
19
- pageNumbers?: {
20
- enabled: boolean;
21
- template?: string;
22
- };
23
- pages?: string;
24
19
  }
25
20
  interface ExportResult {
26
- outputPath: string;
21
+ outputs: Array<{
22
+ document: string;
23
+ outputPath: string;
24
+ }>;
27
25
  }
28
26
 
29
27
  declare function exportPDF(options: ExportOptions): Promise<ExportResult>;