@voyant-travel/utils 0.109.0 → 0.110.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/pdf-renderer.d.ts +3 -0
- package/dist/pdf-renderer.js +10 -2
- package/dist/pdf-renderer.js.map +1 -1
- package/package.json +3 -2
package/dist/pdf-renderer.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { PDFDocument } from "pdf-lib";
|
|
1
2
|
export type PdfContentFormat = "text" | "html" | "markdown" | "lexical_json";
|
|
2
3
|
export interface RenderPdfDocumentInput {
|
|
3
4
|
title?: string | null;
|
|
4
5
|
content: string;
|
|
5
6
|
format?: PdfContentFormat;
|
|
6
7
|
metadataLines?: string[];
|
|
8
|
+
fontBytes?: Uint8Array;
|
|
9
|
+
fontkit?: Parameters<PDFDocument["registerFontkit"]>[0];
|
|
7
10
|
}
|
|
8
11
|
export declare function renderPdfDocument(input: RenderPdfDocumentInput): Promise<Uint8Array>;
|
package/dist/pdf-renderer.js
CHANGED
|
@@ -80,8 +80,16 @@ function wrapLine(text, width, measure) {
|
|
|
80
80
|
}
|
|
81
81
|
export async function renderPdfDocument(input) {
|
|
82
82
|
const pdfDoc = await PDFDocument.create();
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
if (input.fontBytes) {
|
|
84
|
+
if (!input.fontkit) {
|
|
85
|
+
throw new Error("Custom PDF font bytes require an explicit fontkit runtime.");
|
|
86
|
+
}
|
|
87
|
+
pdfDoc.registerFontkit(input.fontkit);
|
|
88
|
+
}
|
|
89
|
+
const font = input.fontBytes
|
|
90
|
+
? await pdfDoc.embedFont(input.fontBytes)
|
|
91
|
+
: await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
92
|
+
const bold = input.fontBytes ? font : await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
|
85
93
|
const PAGE_WIDTH = 595.28;
|
|
86
94
|
const PAGE_HEIGHT = 841.89;
|
|
87
95
|
const MARGIN = 48;
|
package/dist/pdf-renderer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-renderer.js","sourceRoot":"","sources":["../src/pdf-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import { PDFDocument, rgb, StandardFonts } from \"pdf-lib\"\n\nexport type PdfContentFormat = \"text\" | \"html\" | \"markdown\" | \"lexical_json\"\n\nexport interface RenderPdfDocumentInput {\n title?: string | null\n content: string\n format?: PdfContentFormat\n metadataLines?: string[]\n}\n\nfunction decodeEntities(input: string) {\n return input\n .replace(/ /gi, \" \")\n .replace(/&/gi, \"&\")\n .replace(/</gi, \"<\")\n .replace(/>/gi, \">\")\n .replace(/"/gi, '\"')\n .replace(/'/gi, \"'\")\n}\n\nfunction stripHtml(input: string) {\n return decodeEntities(\n input\n .replace(/<\\/(p|div|section|article|h[1-6]|li|tr)>/gi, \"\\n\")\n .replace(/<br\\s*\\/?>/gi, \"\\n\")\n .replace(/<[^>]+>/g, \" \")\n .replace(/[ \\t]+\\n/g, \"\\n\"),\n )\n}\n\nfunction stripMarkdown(input: string) {\n return input\n .replace(/^#{1,6}\\s*/gm, \"\")\n .replace(/[*_~`>#-]+/g, \" \")\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n}\n\nfunction extractLexicalText(input: string) {\n try {\n const root = JSON.parse(input)\n const parts: string[] = []\n const visit = (node: unknown) => {\n if (!node || typeof node !== \"object\") return\n if (\"text\" in node && typeof node.text === \"string\") {\n parts.push(node.text)\n }\n if (\"children\" in node && Array.isArray(node.children)) {\n for (const child of node.children) visit(child)\n if ((node as { type?: string }).type === \"paragraph\") {\n parts.push(\"\\n\")\n }\n }\n }\n visit(root)\n return parts.join(\" \")\n } catch {\n return input\n }\n}\n\nfunction normalizePdfText(input: string, format: PdfContentFormat) {\n const text =\n format === \"html\"\n ? stripHtml(input)\n : format === \"markdown\"\n ? stripMarkdown(input)\n : format === \"lexical_json\"\n ? extractLexicalText(input)\n : input\n\n return text\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .replace(/[ \\t]{2,}/g, \" \")\n .trim()\n}\n\nfunction wrapLine(text: string, width: number, measure: (value: string) => number) {\n const words = text.split(/\\s+/).filter(Boolean)\n const lines: string[] = []\n let current = \"\"\n\n for (const word of words) {\n const next = current ? `${current} ${word}` : word\n if (measure(next) <= width || !current) {\n current = next\n } else {\n lines.push(current)\n current = word\n }\n }\n\n if (current) lines.push(current)\n return lines.length > 0 ? lines : [\"\"]\n}\n\nexport async function renderPdfDocument(input: RenderPdfDocumentInput): Promise<Uint8Array> {\n const pdfDoc = await PDFDocument.create()\n const font = await pdfDoc.embedFont(StandardFonts.Helvetica)\n const bold = await pdfDoc.embedFont(StandardFonts.HelveticaBold)\n\n const PAGE_WIDTH = 595.28\n const PAGE_HEIGHT = 841.89\n const MARGIN = 48\n const TITLE_SIZE = 18\n const BODY_SIZE = 10\n const LINE_HEIGHT = 14\n const bodyWidth = PAGE_WIDTH - MARGIN * 2\n const measure = (value: string) => font.widthOfTextAtSize(value, BODY_SIZE)\n\n let page = pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT])\n let y = PAGE_HEIGHT - MARGIN\n\n const ensureSpace = (needed: number) => {\n if (y - needed < MARGIN) {\n page = pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT])\n y = PAGE_HEIGHT - MARGIN\n }\n }\n\n const drawLine = (text: string, options?: { bold?: boolean; size?: number }) => {\n const size = options?.size ?? BODY_SIZE\n ensureSpace(LINE_HEIGHT)\n page.drawText(text, {\n x: MARGIN,\n y,\n size,\n font: options?.bold ? bold : font,\n color: rgb(0.12, 0.12, 0.12),\n })\n y -= LINE_HEIGHT\n }\n\n const title = input.title?.trim()\n if (title) {\n drawLine(title, { bold: true, size: TITLE_SIZE })\n y -= 6\n }\n\n for (const meta of input.metadataLines ?? []) {\n const trimmed = meta.trim()\n if (!trimmed) continue\n for (const line of wrapLine(trimmed, bodyWidth, measure)) {\n drawLine(line)\n }\n }\n\n if ((input.metadataLines?.length ?? 0) > 0) {\n y -= 6\n }\n\n const normalized = normalizePdfText(input.content, input.format ?? \"text\")\n for (const paragraph of normalized.split(/\\n{2,}/)) {\n const lines = paragraph.split(\"\\n\").flatMap((line) => wrapLine(line, bodyWidth, measure))\n for (const line of lines) {\n drawLine(line)\n }\n y -= 4\n }\n\n return pdfDoc.save()\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pdf-renderer.js","sourceRoot":"","sources":["../src/pdf-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import { PDFDocument, rgb, StandardFonts } from \"pdf-lib\"\n\nexport type PdfContentFormat = \"text\" | \"html\" | \"markdown\" | \"lexical_json\"\n\nexport interface RenderPdfDocumentInput {\n title?: string | null\n content: string\n format?: PdfContentFormat\n metadataLines?: string[]\n fontBytes?: Uint8Array\n fontkit?: Parameters<PDFDocument[\"registerFontkit\"]>[0]\n}\n\nfunction decodeEntities(input: string) {\n return input\n .replace(/ /gi, \" \")\n .replace(/&/gi, \"&\")\n .replace(/</gi, \"<\")\n .replace(/>/gi, \">\")\n .replace(/"/gi, '\"')\n .replace(/'/gi, \"'\")\n}\n\nfunction stripHtml(input: string) {\n return decodeEntities(\n input\n .replace(/<\\/(p|div|section|article|h[1-6]|li|tr)>/gi, \"\\n\")\n .replace(/<br\\s*\\/?>/gi, \"\\n\")\n .replace(/<[^>]+>/g, \" \")\n .replace(/[ \\t]+\\n/g, \"\\n\"),\n )\n}\n\nfunction stripMarkdown(input: string) {\n return input\n .replace(/^#{1,6}\\s*/gm, \"\")\n .replace(/[*_~`>#-]+/g, \" \")\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n}\n\nfunction extractLexicalText(input: string) {\n try {\n const root = JSON.parse(input)\n const parts: string[] = []\n const visit = (node: unknown) => {\n if (!node || typeof node !== \"object\") return\n if (\"text\" in node && typeof node.text === \"string\") {\n parts.push(node.text)\n }\n if (\"children\" in node && Array.isArray(node.children)) {\n for (const child of node.children) visit(child)\n if ((node as { type?: string }).type === \"paragraph\") {\n parts.push(\"\\n\")\n }\n }\n }\n visit(root)\n return parts.join(\" \")\n } catch {\n return input\n }\n}\n\nfunction normalizePdfText(input: string, format: PdfContentFormat) {\n const text =\n format === \"html\"\n ? stripHtml(input)\n : format === \"markdown\"\n ? stripMarkdown(input)\n : format === \"lexical_json\"\n ? extractLexicalText(input)\n : input\n\n return text\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .replace(/[ \\t]{2,}/g, \" \")\n .trim()\n}\n\nfunction wrapLine(text: string, width: number, measure: (value: string) => number) {\n const words = text.split(/\\s+/).filter(Boolean)\n const lines: string[] = []\n let current = \"\"\n\n for (const word of words) {\n const next = current ? `${current} ${word}` : word\n if (measure(next) <= width || !current) {\n current = next\n } else {\n lines.push(current)\n current = word\n }\n }\n\n if (current) lines.push(current)\n return lines.length > 0 ? lines : [\"\"]\n}\n\nexport async function renderPdfDocument(input: RenderPdfDocumentInput): Promise<Uint8Array> {\n const pdfDoc = await PDFDocument.create()\n if (input.fontBytes) {\n if (!input.fontkit) {\n throw new Error(\"Custom PDF font bytes require an explicit fontkit runtime.\")\n }\n pdfDoc.registerFontkit(input.fontkit)\n }\n const font = input.fontBytes\n ? await pdfDoc.embedFont(input.fontBytes)\n : await pdfDoc.embedFont(StandardFonts.Helvetica)\n const bold = input.fontBytes ? font : await pdfDoc.embedFont(StandardFonts.HelveticaBold)\n\n const PAGE_WIDTH = 595.28\n const PAGE_HEIGHT = 841.89\n const MARGIN = 48\n const TITLE_SIZE = 18\n const BODY_SIZE = 10\n const LINE_HEIGHT = 14\n const bodyWidth = PAGE_WIDTH - MARGIN * 2\n const measure = (value: string) => font.widthOfTextAtSize(value, BODY_SIZE)\n\n let page = pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT])\n let y = PAGE_HEIGHT - MARGIN\n\n const ensureSpace = (needed: number) => {\n if (y - needed < MARGIN) {\n page = pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT])\n y = PAGE_HEIGHT - MARGIN\n }\n }\n\n const drawLine = (text: string, options?: { bold?: boolean; size?: number }) => {\n const size = options?.size ?? BODY_SIZE\n ensureSpace(LINE_HEIGHT)\n page.drawText(text, {\n x: MARGIN,\n y,\n size,\n font: options?.bold ? bold : font,\n color: rgb(0.12, 0.12, 0.12),\n })\n y -= LINE_HEIGHT\n }\n\n const title = input.title?.trim()\n if (title) {\n drawLine(title, { bold: true, size: TITLE_SIZE })\n y -= 6\n }\n\n for (const meta of input.metadataLines ?? []) {\n const trimmed = meta.trim()\n if (!trimmed) continue\n for (const line of wrapLine(trimmed, bodyWidth, measure)) {\n drawLine(line)\n }\n }\n\n if ((input.metadataLines?.length ?? 0) > 0) {\n y -= 6\n }\n\n const normalized = normalizePdfText(input.content, input.format ?? \"text\")\n for (const paragraph of normalized.split(/\\n{2,}/)) {\n const lines = paragraph.split(\"\\n\").flatMap((line) => wrapLine(line, bodyWidth, measure))\n for (const line of lines) {\n drawLine(line)\n }\n y -= 4\n }\n\n return pdfDoc.save()\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyant-travel/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.110.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -118,11 +118,12 @@
|
|
|
118
118
|
"dist"
|
|
119
119
|
],
|
|
120
120
|
"dependencies": {
|
|
121
|
+
"@pdf-lib/fontkit": "^1.1.1",
|
|
121
122
|
"drizzle-orm": "^0.45.2",
|
|
122
123
|
"pdf-lib": "^1.17.1",
|
|
123
124
|
"zod": "^4.4.3",
|
|
124
125
|
"@voyant-travel/templating": "^0.104.2",
|
|
125
|
-
"@voyant-travel/types": "^0.109.
|
|
126
|
+
"@voyant-travel/types": "^0.109.9"
|
|
126
127
|
},
|
|
127
128
|
"optionalDependencies": {
|
|
128
129
|
"@upstash/redis": "^1.35.6"
|