@kitsy/pdf 0.0.0-stage → 0.1.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/CHANGELOG.md +22 -0
- package/LICENSE +201 -0
- package/NOTICE +16 -0
- package/README.md +229 -2
- package/THIRD_PARTY_NOTICES.md +48 -0
- package/dist/chunk-2K5X7L5J.js +43 -0
- package/dist/chunk-2K5X7L5J.js.map +1 -0
- package/dist/chunk-4EAYBJ6G.js +362 -0
- package/dist/chunk-4EAYBJ6G.js.map +1 -0
- package/dist/chunk-4LBJTDV5.js +165 -0
- package/dist/chunk-4LBJTDV5.js.map +1 -0
- package/dist/chunk-4USCGC24.js +304 -0
- package/dist/chunk-4USCGC24.js.map +1 -0
- package/dist/chunk-5OIMR74G.js +273 -0
- package/dist/chunk-5OIMR74G.js.map +1 -0
- package/dist/chunk-6NFNAKWA.js +257 -0
- package/dist/chunk-6NFNAKWA.js.map +1 -0
- package/dist/chunk-7MTEMQLL.js +47 -0
- package/dist/chunk-7MTEMQLL.js.map +1 -0
- package/dist/chunk-7V4SWTUK.js +83 -0
- package/dist/chunk-7V4SWTUK.js.map +1 -0
- package/dist/chunk-7XH7MFZ4.js +295 -0
- package/dist/chunk-7XH7MFZ4.js.map +1 -0
- package/dist/chunk-BK3MYSUS.js +61 -0
- package/dist/chunk-BK3MYSUS.js.map +1 -0
- package/dist/chunk-BLHNKR3S.js +35 -0
- package/dist/chunk-BLHNKR3S.js.map +1 -0
- package/dist/chunk-CCJ43SIX.js +342 -0
- package/dist/chunk-CCJ43SIX.js.map +1 -0
- package/dist/chunk-CNEDWATL.js +210 -0
- package/dist/chunk-CNEDWATL.js.map +1 -0
- package/dist/chunk-CYTWDJE2.js +152 -0
- package/dist/chunk-CYTWDJE2.js.map +1 -0
- package/dist/chunk-DKVOICYZ.js +45 -0
- package/dist/chunk-DKVOICYZ.js.map +1 -0
- package/dist/chunk-DPEJU4P6.js +79 -0
- package/dist/chunk-DPEJU4P6.js.map +1 -0
- package/dist/chunk-DQPABZTU.js +22 -0
- package/dist/chunk-DQPABZTU.js.map +1 -0
- package/dist/chunk-EKHEY3LI.js +46 -0
- package/dist/chunk-EKHEY3LI.js.map +1 -0
- package/dist/chunk-G467LFKC.js +191 -0
- package/dist/chunk-G467LFKC.js.map +1 -0
- package/dist/chunk-GLYWSVSB.js +250 -0
- package/dist/chunk-GLYWSVSB.js.map +1 -0
- package/dist/chunk-GXBIMUO7.js +135 -0
- package/dist/chunk-GXBIMUO7.js.map +1 -0
- package/dist/chunk-H6EERRCR.js +180 -0
- package/dist/chunk-H6EERRCR.js.map +1 -0
- package/dist/chunk-HDTM3LXD.js +35 -0
- package/dist/chunk-HDTM3LXD.js.map +1 -0
- package/dist/chunk-IGMX56C3.js +180 -0
- package/dist/chunk-IGMX56C3.js.map +1 -0
- package/dist/chunk-J4IRICCJ.js +74 -0
- package/dist/chunk-J4IRICCJ.js.map +1 -0
- package/dist/chunk-JXKQ7S6W.js +331 -0
- package/dist/chunk-JXKQ7S6W.js.map +1 -0
- package/dist/chunk-KY6DXS6S.js +34 -0
- package/dist/chunk-KY6DXS6S.js.map +1 -0
- package/dist/chunk-NOFGCYGS.js +22 -0
- package/dist/chunk-NOFGCYGS.js.map +1 -0
- package/dist/chunk-OSHUJRKD.js +131 -0
- package/dist/chunk-OSHUJRKD.js.map +1 -0
- package/dist/chunk-PMH7OWPF.js +40 -0
- package/dist/chunk-PMH7OWPF.js.map +1 -0
- package/dist/chunk-PRBKSX3A.js +299 -0
- package/dist/chunk-PRBKSX3A.js.map +1 -0
- package/dist/chunk-SVPUX7AM.js +48 -0
- package/dist/chunk-SVPUX7AM.js.map +1 -0
- package/dist/chunk-TR6HJ4NO.js +659 -0
- package/dist/chunk-TR6HJ4NO.js.map +1 -0
- package/dist/chunk-TV3E4YUF.js +69 -0
- package/dist/chunk-TV3E4YUF.js.map +1 -0
- package/dist/chunk-U2ROTOPF.js +256 -0
- package/dist/chunk-U2ROTOPF.js.map +1 -0
- package/dist/chunk-VCTN77K2.js +112 -0
- package/dist/chunk-VCTN77K2.js.map +1 -0
- package/dist/chunk-WEOPDD3P.js +120 -0
- package/dist/chunk-WEOPDD3P.js.map +1 -0
- package/dist/chunk-ZBZ7OC6I.js +228 -0
- package/dist/chunk-ZBZ7OC6I.js.map +1 -0
- package/dist/config-CJYo46X9.d.ts +19 -0
- package/dist/index.d.ts +487 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/react/certificate-sign.d.ts +5 -0
- package/dist/react/certificate-sign.js +14 -0
- package/dist/react/certificate-sign.js.map +1 -0
- package/dist/react/compress.d.ts +5 -0
- package/dist/react/compress.js +8 -0
- package/dist/react/compress.js.map +1 -0
- package/dist/react/fill-form.d.ts +5 -0
- package/dist/react/fill-form.js +8 -0
- package/dist/react/fill-form.js.map +1 -0
- package/dist/react/images-to-pdf.d.ts +5 -0
- package/dist/react/images-to-pdf.js +7 -0
- package/dist/react/images-to-pdf.js.map +1 -0
- package/dist/react/merge.d.ts +5 -0
- package/dist/react/merge.js +8 -0
- package/dist/react/merge.js.map +1 -0
- package/dist/react/metadata.d.ts +5 -0
- package/dist/react/metadata.js +8 -0
- package/dist/react/metadata.js.map +1 -0
- package/dist/react/organize.d.ts +5 -0
- package/dist/react/organize.js +12 -0
- package/dist/react/organize.js.map +1 -0
- package/dist/react/pdf-to-images.d.ts +5 -0
- package/dist/react/pdf-to-images.js +13 -0
- package/dist/react/pdf-to-images.js.map +1 -0
- package/dist/react/protect.d.ts +5 -0
- package/dist/react/protect.js +8 -0
- package/dist/react/protect.js.map +1 -0
- package/dist/react/sign.d.ts +5 -0
- package/dist/react/sign.js +13 -0
- package/dist/react/sign.js.map +1 -0
- package/dist/react/split.d.ts +5 -0
- package/dist/react/split.js +11 -0
- package/dist/react/split.js.map +1 -0
- package/dist/react/verify-signatures.d.ts +5 -0
- package/dist/react/verify-signatures.js +8 -0
- package/dist/react/verify-signatures.js.map +1 -0
- package/dist/react/watermark.d.ts +5 -0
- package/dist/react/watermark.js +10 -0
- package/dist/react/watermark.js.map +1 -0
- package/dist/react.d.ts +40 -0
- package/dist/react.js +40 -0
- package/dist/react.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/vite.d.ts +5 -0
- package/dist/vite.js +9 -0
- package/dist/vite.js.map +1 -0
- package/package.json +163 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sign/SignatureCreator.tsx","../src/sign/SignPdf.tsx"],"names":["useState","useEffect","jsxs","jsx","Fragment","useRef","placement","byId"],"mappings":"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","file":"chunk-TR6HJ4NO.js","sourcesContent":["import \"@fontsource/dancing-script/400.css\";\nimport \"@fontsource/great-vibes/400.css\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { canvasToBlob } from \"../shared/pdfRender\";\nimport { fieldLabelClass, inputClass, primaryButtonClass, secondaryButtonClass } from \"../shared/ToolLayout\";\nimport { opaqueBounds, whiteToTransparent } from \"./signatureImage\";\n\nconst TABS = [\n { id: \"draw\", label: \"Draw\", icon: \"fa-solid fa-pen-nib\" },\n { id: \"type\", label: \"Type\", icon: \"fa-solid fa-keyboard\" },\n { id: \"upload\", label: \"Upload\", icon: \"fa-solid fa-upload\" },\n];\n\nconst FONTS = [\n { family: \"Dancing Script\", label: \"Handwritten\" },\n { family: \"Great Vibes\", label: \"Elegant\" },\n { family: \"Helvetica, Arial, sans-serif\", label: \"Plain (dates, initials)\" },\n];\n\nconst INKS = [\n { value: \"#0f172a\", label: \"Black\" },\n { value: \"#1d4ed8\", label: \"Blue\" },\n];\n\n/** Crop a canvas to its visible pixels (plus padding) and encode as PNG. */\nasync function trimToPng(canvas, padding = 8) {\n const context = canvas.getContext(\"2d\");\n const { data } = context.getImageData(0, 0, canvas.width, canvas.height);\n const bounds = opaqueBounds(data, canvas.width, canvas.height);\n if (!bounds) return null;\n\n const x = Math.max(0, bounds.x - padding);\n const y = Math.max(0, bounds.y - padding);\n const width = Math.min(canvas.width - x, bounds.width + padding * 2);\n const height = Math.min(canvas.height - y, bounds.height + padding * 2);\n\n const out = document.createElement(\"canvas\");\n out.width = width;\n out.height = height;\n out.getContext(\"2d\").drawImage(canvas, x, y, width, height, 0, 0, width, height);\n const blob = await canvasToBlob(out, \"image/png\");\n return {\n bytes: new Uint8Array(await blob.arrayBuffer()),\n url: URL.createObjectURL(blob),\n aspect: width / height,\n };\n}\n\nfunction DrawPad({ ink, onReady }) {\n const canvasRef = useRef(null);\n const drawing = useRef(false);\n const last = useRef(null);\n const [hasInk, setHasInk] = useState(false);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const ratio = Math.min(3, window.devicePixelRatio || 1);\n canvas.width = canvas.clientWidth * ratio;\n canvas.height = canvas.clientHeight * ratio;\n const context = canvas.getContext(\"2d\");\n context.scale(ratio, ratio);\n context.lineCap = \"round\";\n context.lineJoin = \"round\";\n }, []);\n\n const point = (event) => {\n const rect = canvasRef.current.getBoundingClientRect();\n return { x: event.clientX - rect.left, y: event.clientY - rect.top };\n };\n\n const start = (event) => {\n event.preventDefault();\n canvasRef.current.setPointerCapture(event.pointerId);\n drawing.current = true;\n last.current = point(event);\n };\n\n const moveTo = (event) => {\n if (!drawing.current) return;\n const context = canvasRef.current.getContext(\"2d\");\n const next = point(event);\n // Slightly thinner strokes when moving fast, like a real pen.\n const distance = Math.hypot(next.x - last.current.x, next.y - last.current.y);\n context.strokeStyle = ink;\n context.lineWidth = Math.max(1.6, 3.2 - distance / 18);\n context.beginPath();\n context.moveTo(last.current.x, last.current.y);\n context.lineTo(next.x, next.y);\n context.stroke();\n last.current = next;\n setHasInk(true);\n };\n\n const stop = () => {\n drawing.current = false;\n };\n\n const clear = () => {\n const canvas = canvasRef.current;\n canvas.getContext(\"2d\").clearRect(0, 0, canvas.width, canvas.height);\n setHasInk(false);\n };\n\n return (\n <>\n <canvas\n ref={canvasRef}\n onPointerDown={start}\n onPointerMove={moveTo}\n onPointerUp={stop}\n onPointerCancel={stop}\n aria-label=\"Signature drawing area\"\n className=\"h-40 w-full touch-none rounded-xl border border-dashed border-slate-300 bg-white dark:border-slate-600\"\n />\n <div className=\"mt-3 flex flex-wrap gap-2\">\n <button type=\"button\" onClick={() => onReady(canvasRef.current)} disabled={!hasInk} className={primaryButtonClass}>\n <i className=\"fa-solid fa-check\" />\n Use signature\n </button>\n <button type=\"button\" onClick={clear} disabled={!hasInk} className={secondaryButtonClass}>\n <i className=\"fa-solid fa-eraser\" />\n Clear\n </button>\n </div>\n </>\n );\n}\n\nfunction TypePad({ ink, onReady }) {\n const [text, setText] = useState(\"\");\n const [font, setFont] = useState(FONTS[0].family);\n\n const render = async () => {\n const size = 120;\n const cssFont = `${size}px ${font.includes(\",\") ? font : `\"${font}\"`}`;\n await document.fonts.load(cssFont, text);\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n context.font = cssFont;\n const width = Math.ceil(context.measureText(text).width) + size;\n canvas.width = width;\n canvas.height = Math.ceil(size * 1.8);\n context.font = cssFont;\n context.fillStyle = ink;\n context.textBaseline = \"middle\";\n context.fillText(text, size / 2, canvas.height / 2);\n onReady(canvas);\n };\n\n return (\n <>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className={fieldLabelClass}>\n Your name or text\n <input\n type=\"text\"\n value={text}\n maxLength={60}\n onChange={(event) => setText(event.target.value)}\n placeholder=\"Jane Doe\"\n className={`mt-2 ${inputClass}`}\n />\n </label>\n <label className={fieldLabelClass}>\n Style\n <select value={font} onChange={(event) => setFont(event.target.value)} className={`mt-2 ${inputClass}`}>\n {FONTS.map((option) => (\n <option key={option.family} value={option.family}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n <div\n className=\"mt-3 flex h-24 items-center justify-center overflow-hidden rounded-xl border border-dashed border-slate-300 bg-white px-4 text-4xl dark:border-slate-600\"\n style={{ fontFamily: font.includes(\",\") ? font : `\"${font}\"`, color: ink }}\n >\n {text || <span className=\"text-base text-slate-400\">Preview</span>}\n </div>\n <button type=\"button\" onClick={render} disabled={!text.trim()} className={`mt-3 ${primaryButtonClass}`}>\n <i className=\"fa-solid fa-check\" />\n Use signature\n </button>\n </>\n );\n}\n\nfunction UploadPad({ onReady, onError }) {\n const [removeBackground, setRemoveBackground] = useState(true);\n const inputRef = useRef(null);\n\n const handleFile = async (file) => {\n if (!file) return;\n try {\n const bitmap = await createImageBitmap(file);\n const scale = Math.min(1, 1200 / bitmap.width);\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.round(bitmap.width * scale);\n canvas.height = Math.round(bitmap.height * scale);\n const context = canvas.getContext(\"2d\");\n context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);\n bitmap.close?.();\n if (removeBackground) {\n const image = context.getImageData(0, 0, canvas.width, canvas.height);\n whiteToTransparent(image.data);\n context.putImageData(image, 0, 0);\n }\n onReady(canvas);\n } catch {\n onError(\"That image could not be read. Try a PNG or JPG.\");\n }\n };\n\n return (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp\"\n className=\"hidden\"\n onChange={(event) => {\n handleFile(event.target.files?.[0]);\n event.target.value = \"\";\n }}\n />\n <button type=\"button\" onClick={() => inputRef.current?.click()} className={secondaryButtonClass}>\n <i className=\"fa-solid fa-image\" />\n Choose signature image\n </button>\n <label className=\"mt-3 flex items-center gap-3 text-sm text-slate-700 dark:text-slate-300\">\n <input\n type=\"checkbox\"\n checked={removeBackground}\n onChange={(event) => setRemoveBackground(event.target.checked)}\n className=\"h-4 w-4 accent-[#1F8CFF]\"\n />\n Remove white background (for photos or scans of paper)\n </label>\n </>\n );\n}\n\nexport default function SignatureCreator({ onCreate, onError }) {\n const [tab, setTab] = useState(\"draw\");\n const [ink, setInk] = useState(INKS[0].value);\n\n const finish = async (canvas) => {\n const result = await trimToPng(canvas);\n if (!result) {\n onError(\"The signature is empty.\");\n return;\n }\n onCreate(result);\n };\n\n return (\n <div>\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div role=\"tablist\" className=\"inline-flex rounded-xl border border-slate-200 bg-slate-50 p-1 dark:border-slate-700 dark:bg-slate-900\">\n {TABS.map((option) => (\n <button\n key={option.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === option.id}\n onClick={() => setTab(option.id)}\n className={`inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs font-semibold uppercase tracking-[0.12em] transition ${\n tab === option.id\n ? \"bg-white text-slate-900 shadow-sm dark:bg-slate-800 dark:text-slate-100\"\n : \"text-slate-500 hover:text-slate-800 dark:text-slate-400\"\n }`}\n >\n <i className={option.icon} />\n {option.label}\n </button>\n ))}\n </div>\n {tab !== \"upload\" ? (\n <div className=\"flex items-center gap-2\" aria-label=\"Ink colour\">\n {INKS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => setInk(option.value)}\n aria-label={`${option.label} ink`}\n aria-pressed={ink === option.value}\n className={`h-6 w-6 rounded-full border-2 ${ink === option.value ? \"border-[#1F8CFF]\" : \"border-transparent\"}`}\n style={{ backgroundColor: option.value }}\n />\n ))}\n </div>\n ) : null}\n </div>\n\n <div className=\"mt-4\">\n {tab === \"draw\" ? <DrawPad ink={ink} onReady={finish} /> : null}\n {tab === \"type\" ? <TypePad ink={ink} onReady={finish} /> : null}\n {tab === \"upload\" ? <UploadPad onReady={finish} onError={onError} /> : null}\n </div>\n </div>\n );\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { downloadBlob, formatBytes, toBaseName } from \"../shared/files\";\nimport { canvasToBlob, renderPageToCanvas } from \"../shared/pdfRender\";\nimport {\n BackToPdfTools,\n FileDropzone,\n PdfToolColumns,\n PdfToolPage,\n SelectedPdfCard,\n SideTips,\n StatusBanner,\n cardClass,\n iconButtonClass,\n primaryButtonClass,\n secondaryButtonClass,\n} from \"../shared/ToolLayout\";\nimport { useRenderDocument } from \"../shared/useRenderDocument\";\nimport { useSinglePdf } from \"../shared/useSinglePdf\";\nimport SignatureCreator from \"./SignatureCreator\";\nimport { applySignatures } from \"./signPdfCore\";\n\nconst PREVIEW_WIDTH = 900;\nlet nextId = 0;\n\nconst clamp = (value, min, max) => Math.min(max, Math.max(min, value));\n\nfunction usePagePreview(doc, pageIndex) {\n const [preview, setPreview] = useState(null);\n\n useEffect(() => {\n if (!doc) {\n setPreview(null);\n return undefined;\n }\n let cancelled = false;\n let url = null;\n (async () => {\n const page = await doc.getPage(pageIndex + 1);\n const base = page.getViewport({ scale: 1 });\n const ratio = Math.min(2, window.devicePixelRatio || 1);\n const render = await renderPageToCanvas(doc, pageIndex + 1, {\n scale: (PREVIEW_WIDTH / base.width) * ratio,\n });\n const blob = await canvasToBlob(render.canvas, \"image/jpeg\", 0.85);\n if (cancelled) return;\n url = URL.createObjectURL(blob);\n setPreview({ url, width: render.width, height: render.height });\n })().catch(() => {});\n return () => {\n cancelled = true;\n if (url) URL.revokeObjectURL(url);\n };\n }, [doc, pageIndex]);\n\n return preview;\n}\n\nfunction PlacementBox({ placement, signature, pageAspect, selected, onSelect, onChange, onRemove, containerRef }) {\n const startDrag = (event, mode) => {\n event.preventDefault();\n event.stopPropagation();\n onSelect();\n const rect = containerRef.current.getBoundingClientRect();\n const origin = { x: event.clientX, y: event.clientY, placement };\n\n const handleMove = (moveEvent) => {\n const dx = (moveEvent.clientX - origin.x) / rect.width;\n const dy = (moveEvent.clientY - origin.y) / rect.height;\n const start = origin.placement;\n if (mode === \"move\") {\n onChange({\n x: clamp(start.x + dx, 0, 1 - start.width),\n y: clamp(start.y + dy, 0, 1 - start.height),\n });\n } else {\n // Keep the signature's own aspect ratio while resizing.\n const width = clamp(start.width + dx, 0.04, 1 - start.x);\n const height = (width * pageAspect) / signature.aspect;\n if (start.y + height <= 1) onChange({ width, height });\n }\n };\n const handleUp = () => {\n window.removeEventListener(\"pointermove\", handleMove);\n window.removeEventListener(\"pointerup\", handleUp);\n };\n window.addEventListener(\"pointermove\", handleMove);\n window.addEventListener(\"pointerup\", handleUp);\n };\n\n const nudge = (event) => {\n const step = event.shiftKey ? 0.02 : 0.005;\n const moves = { ArrowLeft: [-step, 0], ArrowRight: [step, 0], ArrowUp: [0, -step], ArrowDown: [0, step] };\n if (event.key === \"Delete\" || event.key === \"Backspace\") {\n event.preventDefault();\n onRemove();\n return;\n }\n const move = moves[event.key];\n if (!move) return;\n event.preventDefault();\n onChange({\n x: clamp(placement.x + move[0], 0, 1 - placement.width),\n y: clamp(placement.y + move[1], 0, 1 - placement.height),\n });\n };\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n aria-label=\"Placed signature. Drag to move, use arrow keys to nudge, Delete to remove.\"\n onPointerDown={(event) => startDrag(event, \"move\")}\n onKeyDown={nudge}\n onFocus={onSelect}\n className={`absolute cursor-move touch-none select-none outline-none ${\n selected ? \"ring-2 ring-[#1F8CFF]\" : \"ring-1 ring-[#1F8CFF]/40 hover:ring-[#1F8CFF]\"\n }`}\n style={{\n left: `${placement.x * 100}%`,\n top: `${placement.y * 100}%`,\n width: `${placement.width * 100}%`,\n height: `${placement.height * 100}%`,\n }}\n >\n <img src={signature.url} alt=\"\" draggable={false} className=\"pointer-events-none h-full w-full\" />\n {selected ? (\n <>\n <button\n type=\"button\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={onRemove}\n aria-label=\"Remove signature\"\n className=\"absolute -right-3 -top-3 inline-flex h-6 w-6 items-center justify-center rounded-full bg-rose-600 text-[10px] text-white shadow\"\n >\n <i className=\"fa-solid fa-xmark\" />\n </button>\n <span\n onPointerDown={(event) => startDrag(event, \"resize\")}\n aria-hidden=\"true\"\n className=\"absolute -bottom-2 -right-2 h-4 w-4 cursor-nwse-resize rounded-sm border-2 border-white bg-[#1F8CFF] shadow\"\n />\n </>\n ) : null}\n </div>\n );\n}\n\nexport default function SignPdf() {\n const [signatures, setSignatures] = useState([]);\n const [placements, setPlacements] = useState([]);\n const [selectedId, setSelectedId] = useState(null);\n const [pageIndex, setPageIndex] = useState(0);\n const [isSaving, setIsSaving] = useState(false);\n const [status, setStatus] = useState({\n tone: \"info\",\n text: \"Add a PDF, create your signature, then place it on the page.\",\n });\n const containerRef = useRef(null);\n const signaturesRef = useRef(signatures);\n signaturesRef.current = signatures;\n\n useEffect(() => {\n document.title = \"Sign PDF | Apps\";\n return () => signaturesRef.current.forEach((signature) => URL.revokeObjectURL(signature.url));\n }, []);\n\n const onError = useCallback((text) => setStatus({ tone: \"error\", text }), []);\n const onLoaded = useCallback(({ file, pageCount }) => {\n setPlacements([]);\n setPageIndex(0);\n setStatus({\n tone: \"success\",\n text: `${file.name} loaded with ${pageCount} page${pageCount === 1 ? \"\" : \"s\"}. Create a signature to place it.`,\n });\n }, []);\n const pdf = useSinglePdf({ onError, onLoaded });\n const { doc, error: renderError } = useRenderDocument(pdf.bytes);\n const preview = usePagePreview(doc, pageIndex);\n const pageAspect = preview ? preview.width / preview.height : 1 / 1.414;\n\n const placeSignature = (signature, onPage = pageIndex) => {\n const width = 0.3;\n const height = Math.min((width * pageAspect) / signature.aspect, 1);\n // Step each new placement up and left so it does not hide an earlier one.\n const step = placements.filter((placement) => placement.pageIndex === onPage).length % 6;\n const placement = {\n id: `place-${++nextId}`,\n signatureId: signature.id,\n pageIndex: onPage,\n x: clamp(0.6 - width / 2 - step * 0.04, 0, 1 - width),\n y: clamp(0.8 - height / 2 - step * 0.08, 0, 1 - height),\n width,\n height,\n };\n setPlacements((current) => [...current, placement]);\n setSelectedId(placement.id);\n };\n\n const addSignature = (created) => {\n const signature = { id: `sig-${++nextId}`, ...created };\n setSignatures((current) => [...current, signature]);\n if (pdf.pageCount) {\n placeSignature(signature);\n setStatus({ tone: \"success\", text: \"Signature placed. Drag it into position, or resize it from the corner.\" });\n }\n };\n\n const updatePlacement = (id, patch) => {\n setPlacements((current) => current.map((placement) => (placement.id === id ? { ...placement, ...patch } : placement)));\n };\n\n const removePlacement = (id) => {\n setPlacements((current) => current.filter((placement) => placement.id !== id));\n setSelectedId(null);\n };\n\n const removeSignature = (id) => {\n setSignatures((current) => {\n const removed = current.find((signature) => signature.id === id);\n if (removed) URL.revokeObjectURL(removed.url);\n return current.filter((signature) => signature.id !== id);\n });\n setPlacements((current) => current.filter((placement) => placement.signatureId !== id));\n };\n\n const clearFile = () => {\n pdf.clear();\n setPlacements([]);\n };\n\n const handleSave = async () => {\n if (!pdf.bytes || !placements.length) return;\n setIsSaving(true);\n setStatus({ tone: \"info\", text: \"Signing your PDF...\" });\n try {\n const byId = new Map(signatures.map((signature) => [signature.id, signature]));\n const bytes = await applySignatures(\n pdf.bytes,\n placements.map((placement) => ({ ...placement, image: byId.get(placement.signatureId).bytes }))\n );\n const blob = new Blob([bytes as BlobPart], { type: \"application/pdf\" });\n downloadBlob(blob, `${toBaseName(pdf.file.name, \"document\")}-signed.pdf`);\n setStatus({\n tone: \"success\",\n text: `Signed with ${placements.length} signature${placements.length === 1 ? \"\" : \"s\"} (${formatBytes(blob.size)}). Your download has started.`,\n });\n } catch (error) {\n setStatus({ tone: \"error\", text: `Signing failed: ${error?.message || \"Please try again.\"}` });\n } finally {\n setIsSaving(false);\n }\n };\n\n const busy = isSaving || pdf.isReading;\n const pagePlacements = placements.filter((placement) => placement.pageIndex === pageIndex);\n const byId = new Map(signatures.map((signature) => [signature.id, signature]));\n\n return (\n <PdfToolPage\n title=\"Sign PDF\"\n description=\"Draw, type, or upload your signature and place it anywhere on the page. Runs in your browser; your document and signature never leave your device.\"\n stats={[\n { value: pdf.pageCount || \"-\", label: \"Pages\" },\n { value: placements.length || \"-\", label: \"Placed\" },\n ]}\n >\n <PdfToolColumns\n main={\n <>\n {pdf.file ? (\n <SelectedPdfCard\n signed={pdf.signed} file={pdf.file} pageCount={pdf.pageCount} onRemove={clearFile} disabled={isSaving} />\n ) : (\n <FileDropzone\n accept=\".pdf,application/pdf\"\n disabled={busy}\n onFiles={pdf.selectFiles}\n title=\"Drag and drop a PDF here\"\n hint=\"or click to browse from your device\"\n />\n )}\n\n {renderError ? <p className=\"mt-3 text-xs text-rose-700 dark:text-rose-300\">{renderError}</p> : null}\n\n {pdf.pageCount ? (\n <div className=\"mt-5\">\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => setPageIndex((index) => Math.max(0, index - 1))}\n disabled={pageIndex === 0}\n className={iconButtonClass}\n aria-label=\"Previous page\"\n >\n <i className=\"fa-solid fa-chevron-left\" />\n </button>\n <span className=\"text-sm text-slate-700 dark:text-slate-300\">\n Page {pageIndex + 1} of {pdf.pageCount}\n </span>\n <button\n type=\"button\"\n onClick={() => setPageIndex((index) => Math.min(pdf.pageCount - 1, index + 1))}\n disabled={pageIndex === pdf.pageCount - 1}\n className={iconButtonClass}\n aria-label=\"Next page\"\n >\n <i className=\"fa-solid fa-chevron-right\" />\n </button>\n </div>\n <span className=\"text-xs text-slate-500 dark:text-slate-400\">\n {pagePlacements.length} on this page\n </span>\n </div>\n\n <div className=\"flex justify-center rounded-2xl bg-slate-100 p-3 dark:bg-slate-800\">\n <div\n ref={containerRef}\n onPointerDown={() => setSelectedId(null)}\n className=\"relative w-full max-w-[720px] bg-white shadow-md\"\n style={{ aspectRatio: preview ? `${preview.width} / ${preview.height}` : \"1 / 1.414\" }}\n >\n {preview ? (\n <img\n src={preview.url}\n alt={`Page ${pageIndex + 1}`}\n draggable={false}\n className=\"pointer-events-none absolute inset-0 h-full w-full select-none\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <i className=\"fa-solid fa-spinner fa-spin text-slate-400\" aria-label=\"Rendering page\" />\n </div>\n )}\n {pagePlacements.map((placement) => (\n <PlacementBox\n key={placement.id}\n placement={placement}\n signature={byId.get(placement.signatureId)}\n pageAspect={pageAspect}\n selected={selectedId === placement.id}\n onSelect={() => setSelectedId(placement.id)}\n onChange={(patch) => updatePlacement(placement.id, patch)}\n onRemove={() => removePlacement(placement.id)}\n containerRef={containerRef}\n />\n ))}\n </div>\n </div>\n </div>\n ) : null}\n\n <StatusBanner status={status} />\n\n <div className=\"mt-5 flex flex-wrap gap-3\">\n <button type=\"button\" onClick={handleSave} disabled={busy || !placements.length} className={primaryButtonClass}>\n <i className={`fa-solid ${isSaving ? \"fa-spinner fa-spin\" : \"fa-signature\"}`} />\n {isSaving ? \"Signing...\" : \"Sign & Download\"}\n </button>\n <BackToPdfTools />\n </div>\n </>\n }\n side={\n <>\n <h2 className=\"text-base font-semibold text-slate-900 dark:text-slate-100\">Your signature</h2>\n <div className=\"mt-4\">\n <SignatureCreator onCreate={addSignature} onError={onError} />\n </div>\n\n {signatures.length ? (\n <ul className=\"mt-5 space-y-2\">\n {signatures.map((signature) => (\n <li key={signature.id} className={`${cardClass} !p-2`}>\n <div className=\"flex h-14 items-center justify-center rounded-lg bg-white\">\n <img src={signature.url} alt=\"Saved signature\" className=\"max-h-full max-w-full\" />\n </div>\n <div className=\"mt-2 flex gap-2\">\n <button\n type=\"button\"\n onClick={() => placeSignature(signature)}\n disabled={!pdf.pageCount}\n className={`flex-1 justify-center ${secondaryButtonClass}`}\n >\n <i className=\"fa-solid fa-plus\" />\n Place\n </button>\n <button\n type=\"button\"\n onClick={() => removeSignature(signature.id)}\n className={iconButtonClass}\n aria-label=\"Delete signature\"\n >\n <i className=\"fa-solid fa-trash\" />\n </button>\n </div>\n </li>\n ))}\n </ul>\n ) : null}\n\n <SideTips\n tips={[\n \"Place the same signature on several pages, or add initials with Type → Plain.\",\n \"Select a signature and press Delete to remove it; arrow keys nudge it.\",\n \"This adds a visible signature image. It is not a certificate-based digital signature.\",\n ]}\n />\n </>\n }\n />\n </PdfToolPage>\n );\n}\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { producerName } from './chunk-DQPABZTU.js';
|
|
2
|
+
import { parsePageSelection, parsePageGroups } from './chunk-BLHNKR3S.js';
|
|
3
|
+
import { loadPdf } from './chunk-EKHEY3LI.js';
|
|
4
|
+
import { PDFDocument } from 'pdf-lib';
|
|
5
|
+
|
|
6
|
+
function rangeLabel(indices) {
|
|
7
|
+
const first = indices[0] + 1;
|
|
8
|
+
const last = indices[indices.length - 1] + 1;
|
|
9
|
+
return indices.length === 1 ? `p${first}` : `p${first}-${last}`;
|
|
10
|
+
}
|
|
11
|
+
function planSplit(pageCount, options) {
|
|
12
|
+
if (pageCount < 1) {
|
|
13
|
+
throw new Error("This PDF has no pages.");
|
|
14
|
+
}
|
|
15
|
+
if (options.mode === "every") {
|
|
16
|
+
const size = Math.floor(Number(options.every));
|
|
17
|
+
if (!Number.isFinite(size) || size < 1) {
|
|
18
|
+
throw new Error("Pages per file must be a whole number of at least 1.");
|
|
19
|
+
}
|
|
20
|
+
const groups = [];
|
|
21
|
+
for (let start = 0; start < pageCount; start += size) {
|
|
22
|
+
groups.push(
|
|
23
|
+
Array.from({ length: Math.min(size, pageCount - start) }, (_, offset) => start + offset)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return groups;
|
|
27
|
+
}
|
|
28
|
+
if (options.mode === "extract") {
|
|
29
|
+
if (!(options.ranges || "").trim()) {
|
|
30
|
+
throw new Error("Enter the pages to extract, e.g. 1-3, 5.");
|
|
31
|
+
}
|
|
32
|
+
return [parsePageSelection(options.ranges, pageCount)];
|
|
33
|
+
}
|
|
34
|
+
if (!(options.ranges || "").trim()) {
|
|
35
|
+
throw new Error("Enter at least one page range, e.g. 1-3, 4-6.");
|
|
36
|
+
}
|
|
37
|
+
return parsePageGroups(options.ranges, pageCount);
|
|
38
|
+
}
|
|
39
|
+
async function splitPdf(bytes, options) {
|
|
40
|
+
const source = await loadPdf(bytes);
|
|
41
|
+
const groups = planSplit(source.getPageCount(), options);
|
|
42
|
+
const baseName = options.baseName || "document";
|
|
43
|
+
const outputs = [];
|
|
44
|
+
for (const indices of groups) {
|
|
45
|
+
const out = await PDFDocument.create();
|
|
46
|
+
const pages = await out.copyPages(source, indices);
|
|
47
|
+
pages.forEach((page) => out.addPage(page));
|
|
48
|
+
const title = source.getTitle();
|
|
49
|
+
if (title) out.setTitle(title);
|
|
50
|
+
out.setProducer(producerName());
|
|
51
|
+
out.setCreationDate(/* @__PURE__ */ new Date());
|
|
52
|
+
outputs.push({
|
|
53
|
+
name: options.mode === "extract" ? `${baseName}-extracted.pdf` : `${baseName}-${rangeLabel(indices)}.pdf`,
|
|
54
|
+
pageIndices: indices,
|
|
55
|
+
bytes: await out.save()
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const seen = /* @__PURE__ */ new Map();
|
|
59
|
+
for (const output of outputs) {
|
|
60
|
+
const count = (seen.get(output.name) || 0) + 1;
|
|
61
|
+
seen.set(output.name, count);
|
|
62
|
+
if (count > 1) output.name = output.name.replace(/\.pdf$/, `-${count}.pdf`);
|
|
63
|
+
}
|
|
64
|
+
return outputs;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { planSplit, splitPdf };
|
|
68
|
+
//# sourceMappingURL=chunk-TV3E4YUF.js.map
|
|
69
|
+
//# sourceMappingURL=chunk-TV3E4YUF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/split/splitPdfCore.ts"],"names":[],"mappings":"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","file":"chunk-TV3E4YUF.js","sourcesContent":["import { PDFDocument } from \"pdf-lib\";\nimport { loadPdf } from \"../shared/files\";\nimport { parsePageGroups, parsePageSelection } from \"../shared/pageRanges\";\nimport { producerName } from \"../config\";\n\nexport type SplitMode = \"ranges\" | \"every\" | \"extract\";\n\nexport type SplitPdfOptions = {\n mode: SplitMode;\n /** 1-based selection. \"ranges\": one file per comma part. \"extract\": one file. */\n ranges?: string;\n /** \"every\": pages per output file. */\n every?: number;\n baseName?: string;\n};\n\nexport type SplitPdfOutput = { name: string; pageIndices: number[]; bytes: Uint8Array };\n\nfunction rangeLabel(indices: number[]) {\n const first = indices[0] + 1;\n const last = indices[indices.length - 1] + 1;\n return indices.length === 1 ? `p${first}` : `p${first}-${last}`;\n}\n\n/** Work out which pages go into which output file, without touching PDF bytes. */\nexport function planSplit(pageCount: number, options: SplitPdfOptions) {\n if (pageCount < 1) {\n throw new Error(\"This PDF has no pages.\");\n }\n\n if (options.mode === \"every\") {\n const size = Math.floor(Number(options.every));\n if (!Number.isFinite(size) || size < 1) {\n throw new Error(\"Pages per file must be a whole number of at least 1.\");\n }\n const groups: number[][] = [];\n for (let start = 0; start < pageCount; start += size) {\n groups.push(\n Array.from({ length: Math.min(size, pageCount - start) }, (_, offset) => start + offset)\n );\n }\n return groups;\n }\n\n if (options.mode === \"extract\") {\n if (!(options.ranges || \"\").trim()) {\n throw new Error(\"Enter the pages to extract, e.g. 1-3, 5.\");\n }\n return [parsePageSelection(options.ranges, pageCount)];\n }\n\n if (!(options.ranges || \"\").trim()) {\n throw new Error(\"Enter at least one page range, e.g. 1-3, 4-6.\");\n }\n return parsePageGroups(options.ranges, pageCount);\n}\n\nexport async function splitPdf(bytes: ArrayBuffer | Uint8Array, options: SplitPdfOptions) {\n const source = await loadPdf(bytes);\n const groups = planSplit(source.getPageCount(), options);\n const baseName = options.baseName || \"document\";\n const outputs: SplitPdfOutput[] = [];\n\n for (const indices of groups) {\n const out = await PDFDocument.create();\n const pages = await out.copyPages(source, indices);\n pages.forEach((page) => out.addPage(page));\n\n const title = source.getTitle();\n if (title) out.setTitle(title);\n out.setProducer(producerName());\n out.setCreationDate(new Date());\n\n outputs.push({\n name:\n options.mode === \"extract\"\n ? `${baseName}-extracted.pdf`\n : `${baseName}-${rangeLabel(indices)}.pdf`,\n pageIndices: indices,\n bytes: await out.save(),\n });\n }\n\n // Ranges like \"1, 1\" would otherwise produce two files with the same name.\n const seen = new Map<string, number>();\n for (const output of outputs) {\n const count = (seen.get(output.name) || 0) + 1;\n seen.set(output.name, count);\n if (count > 1) output.name = output.name.replace(/\\.pdf$/, `-${count}.pdf`);\n }\n\n return outputs;\n}\n"]}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { placementToVisual } from './chunk-SVPUX7AM.js';
|
|
2
|
+
import { describeCertificate, buildCmsSignature, sha256 } from './chunk-5OIMR74G.js';
|
|
3
|
+
import { visualSize, textOrigin } from './chunk-PMH7OWPF.js';
|
|
4
|
+
import { hasDigitalSignatures, signatureFields } from './chunk-7MTEMQLL.js';
|
|
5
|
+
import { loadPdf } from './chunk-EKHEY3LI.js';
|
|
6
|
+
import forge from 'node-forge/lib/forge.js';
|
|
7
|
+
import 'node-forge/lib/asn1.js';
|
|
8
|
+
import 'node-forge/lib/pki.js';
|
|
9
|
+
import 'node-forge/lib/pkcs12.js';
|
|
10
|
+
import { PDFString, PDFHexString, PDFDict, PDFArray, PDFNumber, PDFName, StandardFonts, pushGraphicsState, setStrokingRgbColor, setLineWidth, rectangle, stroke, setFillingRgbColor, beginText, setFontAndSize, moveText, showText, endText, popGraphicsState } from 'pdf-lib';
|
|
11
|
+
|
|
12
|
+
var CertificatePasswordError = class extends Error {
|
|
13
|
+
constructor() {
|
|
14
|
+
super("That password does not open this certificate file.");
|
|
15
|
+
this.name = "CertificatePasswordError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var toBinary = (bytes) => {
|
|
19
|
+
let out = "";
|
|
20
|
+
for (let i = 0; i < bytes.length; i += 32768) {
|
|
21
|
+
out += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
};
|
|
25
|
+
var fromBinary = (text) => Uint8Array.from(text, (char) => char.charCodeAt(0));
|
|
26
|
+
function parseKeepingCertificateBytes(p12Asn1, password) {
|
|
27
|
+
const derByCert = /* @__PURE__ */ new Map();
|
|
28
|
+
const original = forge.pki.certificateFromAsn1;
|
|
29
|
+
forge.pki.certificateFromAsn1 = (asn1, computeHash) => {
|
|
30
|
+
const cert = original(asn1, computeHash);
|
|
31
|
+
derByCert.set(cert, fromBinary(forge.asn1.toDer(asn1).getBytes()));
|
|
32
|
+
return cert;
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
return { p12: forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, password), derByCert };
|
|
36
|
+
} finally {
|
|
37
|
+
forge.pki.certificateFromAsn1 = original;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function readPkcs12(bytes, password) {
|
|
41
|
+
const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
42
|
+
let p12Asn1;
|
|
43
|
+
try {
|
|
44
|
+
p12Asn1 = forge.asn1.fromDer(forge.util.createBuffer(toBinary(data)), false);
|
|
45
|
+
} catch {
|
|
46
|
+
throw new Error("This is not a .pfx / .p12 certificate file.");
|
|
47
|
+
}
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = parseKeepingCertificateBytes(p12Asn1, password);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const message = String(error?.message || "");
|
|
53
|
+
if (/MAC could not be verified|Invalid password|wrong password|decrypt/i.test(message)) {
|
|
54
|
+
throw new CertificatePasswordError();
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Could not read this certificate file (${message || "unknown format"}).`);
|
|
57
|
+
}
|
|
58
|
+
const { p12, derByCert } = parsed;
|
|
59
|
+
const keyBags = [
|
|
60
|
+
...p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag })[forge.pki.oids.pkcs8ShroudedKeyBag] || [],
|
|
61
|
+
...p12.getBags({ bagType: forge.pki.oids.keyBag })[forge.pki.oids.keyBag] || []
|
|
62
|
+
];
|
|
63
|
+
const certBags = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag] || [];
|
|
64
|
+
const key = keyBags.find((bag) => bag.key)?.key;
|
|
65
|
+
if (!key) {
|
|
66
|
+
if (keyBags.length) {
|
|
67
|
+
throw new Error("Only RSA certificates are supported. This file holds a different key type.");
|
|
68
|
+
}
|
|
69
|
+
throw new Error("This file has no private key. Export the certificate together with its private key.");
|
|
70
|
+
}
|
|
71
|
+
const certs = certBags.filter((bag) => bag.cert);
|
|
72
|
+
const leaf = certs.find(
|
|
73
|
+
(bag) => bag.cert.publicKey?.n && bag.cert.publicKey.n.equals(key.n) && bag.cert.publicKey.e.equals(key.e)
|
|
74
|
+
);
|
|
75
|
+
if (!leaf) {
|
|
76
|
+
throw new Error("No certificate in this file matches its private key.");
|
|
77
|
+
}
|
|
78
|
+
const pkcs8 = forge.pki.wrapRsaPrivateKey(forge.pki.privateKeyToAsn1(key));
|
|
79
|
+
return {
|
|
80
|
+
certificate: derByCert.get(leaf.cert),
|
|
81
|
+
chain: certs.filter((bag) => bag !== leaf).map((bag) => derByCert.get(bag.cert)),
|
|
82
|
+
privateKeyPkcs8: fromBinary(forge.asn1.toDer(pkcs8).getBytes())
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
var N = (name) => PDFName.of(name);
|
|
86
|
+
var PLACEHOLDER = 1234567890;
|
|
87
|
+
var latin1 = new TextDecoder("latin1");
|
|
88
|
+
function pad(value) {
|
|
89
|
+
return String(value).padStart(2, "0");
|
|
90
|
+
}
|
|
91
|
+
function displayDate(date) {
|
|
92
|
+
const offset = -date.getTimezoneOffset();
|
|
93
|
+
const sign = offset >= 0 ? "+" : "-";
|
|
94
|
+
const abs = Math.abs(offset);
|
|
95
|
+
return `${date.getFullYear()}.${pad(date.getMonth() + 1)}.${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())} ${sign}${pad(Math.floor(abs / 60))}'${pad(abs % 60)}'`;
|
|
96
|
+
}
|
|
97
|
+
function uniqueFieldName(doc) {
|
|
98
|
+
const taken = new Set(doc.getForm().getFields().map((field) => field.getName()));
|
|
99
|
+
signatureFields(doc).forEach((field) => taken.add(field.name));
|
|
100
|
+
let index = 1;
|
|
101
|
+
while (taken.has(`Signature${index}`)) index += 1;
|
|
102
|
+
return `Signature${index}`;
|
|
103
|
+
}
|
|
104
|
+
function safeText(font, value) {
|
|
105
|
+
return Array.from(value).map((char) => {
|
|
106
|
+
try {
|
|
107
|
+
font.encodeText(char);
|
|
108
|
+
return char;
|
|
109
|
+
} catch {
|
|
110
|
+
return "?";
|
|
111
|
+
}
|
|
112
|
+
}).join("");
|
|
113
|
+
}
|
|
114
|
+
async function appearance(doc, page, box, lines, angle) {
|
|
115
|
+
const font = await doc.embedFont(StandardFonts.Helvetica);
|
|
116
|
+
const { width, height } = box;
|
|
117
|
+
const padding = Math.min(6, width * 0.05, height * 0.08);
|
|
118
|
+
const shown = lines.map((line) => safeText(font, line));
|
|
119
|
+
const widest = Math.max(...shown.map((line) => font.widthOfTextAtSize(line, 10)), 1);
|
|
120
|
+
const size = Math.max(4, Math.min(10, 10 * (width - padding * 2) / widest, (height - padding * 2) / (shown.length * 1.25)));
|
|
121
|
+
const operators = [
|
|
122
|
+
pushGraphicsState(),
|
|
123
|
+
setStrokingRgbColor(0.12, 0.35, 0.75),
|
|
124
|
+
setLineWidth(0.8),
|
|
125
|
+
rectangle(0.4, 0.4, width - 0.8, height - 0.8),
|
|
126
|
+
stroke(),
|
|
127
|
+
setFillingRgbColor(0.06, 0.09, 0.16),
|
|
128
|
+
beginText(),
|
|
129
|
+
setFontAndSize(N("F1"), size),
|
|
130
|
+
moveText(padding, height - padding - size)
|
|
131
|
+
];
|
|
132
|
+
shown.forEach((line, index) => {
|
|
133
|
+
if (index > 0) operators.push(moveText(0, -size * 1.25));
|
|
134
|
+
operators.push(showText(font.encodeText(line)));
|
|
135
|
+
});
|
|
136
|
+
operators.push(endText(), popGraphicsState());
|
|
137
|
+
const radians = angle * Math.PI / 180;
|
|
138
|
+
const cos = Math.round(Math.cos(radians));
|
|
139
|
+
const sin = Math.round(Math.sin(radians));
|
|
140
|
+
const stream = doc.context.formXObject(operators, {
|
|
141
|
+
BBox: [0, 0, width, height],
|
|
142
|
+
// Counter the page's /Rotate so the box reads upright on screen.
|
|
143
|
+
Matrix: [cos, sin, -sin, cos, 0, 0],
|
|
144
|
+
Resources: { Font: { F1: font.ref } }
|
|
145
|
+
});
|
|
146
|
+
return doc.context.register(stream);
|
|
147
|
+
}
|
|
148
|
+
function findPlaceholders(bytes, contentsLength) {
|
|
149
|
+
const text = latin1.decode(bytes);
|
|
150
|
+
const zeros = "0".repeat(contentsLength);
|
|
151
|
+
const contentsStart = text.lastIndexOf(`<${zeros}>`);
|
|
152
|
+
if (contentsStart < 0) throw new Error("Could not prepare the signature (contents placeholder not found).");
|
|
153
|
+
const contentsEnd = contentsStart + contentsLength + 2;
|
|
154
|
+
const pattern = /\/ByteRange\s*\[\s*0\s+1234567890\s+1234567890\s+1234567890\s*\]/g;
|
|
155
|
+
let match;
|
|
156
|
+
let last = null;
|
|
157
|
+
while (match = pattern.exec(text)) last = match;
|
|
158
|
+
if (!last) throw new Error("Could not prepare the signature (byte range placeholder not found).");
|
|
159
|
+
const open = last.index + last[0].indexOf("[");
|
|
160
|
+
const close = last.index + last[0].length - 1;
|
|
161
|
+
return { contentsStart, contentsEnd, byteRangeOpen: open, byteRangeClose: close };
|
|
162
|
+
}
|
|
163
|
+
async function signPdfWithCertificate(bytes, signer, options = {}) {
|
|
164
|
+
const doc = await loadPdf(bytes, { updateMetadata: false });
|
|
165
|
+
if (hasDigitalSignatures(doc)) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
"This PDF is already digitally signed. Adding another signature here would invalidate the existing one."
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
const certificate = describeCertificate(signer.certificate);
|
|
171
|
+
const signingTime = options.signingTime ?? /* @__PURE__ */ new Date();
|
|
172
|
+
const certBytes = signer.certificate.length + (signer.chain || []).reduce((sum, der) => sum + der.length, 0);
|
|
173
|
+
const reserved = certBytes + 8192;
|
|
174
|
+
const signatureDict = doc.context.obj({
|
|
175
|
+
Type: "Sig",
|
|
176
|
+
Filter: "Adobe.PPKLite",
|
|
177
|
+
SubFilter: "ETSI.CAdES.detached",
|
|
178
|
+
ByteRange: [0, PLACEHOLDER, PLACEHOLDER, PLACEHOLDER],
|
|
179
|
+
Contents: PDFHexString.of("0".repeat(reserved * 2)),
|
|
180
|
+
M: PDFString.fromDate(signingTime)
|
|
181
|
+
});
|
|
182
|
+
if (certificate.commonName) signatureDict.set(N("Name"), PDFHexString.fromText(certificate.commonName));
|
|
183
|
+
if (options.reason) signatureDict.set(N("Reason"), PDFHexString.fromText(options.reason));
|
|
184
|
+
if (options.location) signatureDict.set(N("Location"), PDFHexString.fromText(options.location));
|
|
185
|
+
if (options.contactInfo) signatureDict.set(N("ContactInfo"), PDFHexString.fromText(options.contactInfo));
|
|
186
|
+
const signatureRef = doc.context.register(signatureDict);
|
|
187
|
+
const pages = doc.getPages();
|
|
188
|
+
const pageIndex = options.visible ? options.visible.pageIndex : 0;
|
|
189
|
+
const page = pages[pageIndex];
|
|
190
|
+
if (!page) throw new Error(`Page ${pageIndex + 1} does not exist.`);
|
|
191
|
+
let rect = [0, 0, 0, 0];
|
|
192
|
+
let appearanceRef;
|
|
193
|
+
if (options.visible) {
|
|
194
|
+
const { visualWidth, visualHeight } = visualSize(page);
|
|
195
|
+
const box = placementToVisual(options.visible, visualWidth, visualHeight);
|
|
196
|
+
const a = textOrigin(page, box.vx, box.vy);
|
|
197
|
+
const b = textOrigin(page, box.vx + box.width, box.vy + box.height);
|
|
198
|
+
rect = [Math.min(a.x, b.x), Math.min(a.y, b.y), Math.max(a.x, b.x), Math.max(a.y, b.y)];
|
|
199
|
+
const lines = [
|
|
200
|
+
`Digitally signed by ${certificate.commonName || "(no name)"}`,
|
|
201
|
+
`Date: ${displayDate(signingTime)}`,
|
|
202
|
+
...options.reason ? [`Reason: ${options.reason}`] : [],
|
|
203
|
+
...options.location ? [`Location: ${options.location}`] : []
|
|
204
|
+
];
|
|
205
|
+
appearanceRef = await appearance(doc, page, box, lines, a.angle);
|
|
206
|
+
} else {
|
|
207
|
+
appearanceRef = doc.context.register(doc.context.formXObject([], { BBox: [0, 0, 0, 0] }));
|
|
208
|
+
}
|
|
209
|
+
const widget = doc.context.obj({
|
|
210
|
+
Type: "Annot",
|
|
211
|
+
Subtype: "Widget",
|
|
212
|
+
FT: "Sig",
|
|
213
|
+
T: PDFHexString.fromText(uniqueFieldName(doc)),
|
|
214
|
+
V: signatureRef,
|
|
215
|
+
F: 132,
|
|
216
|
+
// Print + Locked
|
|
217
|
+
P: page.ref,
|
|
218
|
+
Rect: rect,
|
|
219
|
+
AP: { N: appearanceRef }
|
|
220
|
+
});
|
|
221
|
+
const widgetRef = doc.context.register(widget);
|
|
222
|
+
page.node.addAnnot(widgetRef);
|
|
223
|
+
let acroForm = doc.catalog.lookup(N("AcroForm"));
|
|
224
|
+
if (!(acroForm instanceof PDFDict)) {
|
|
225
|
+
acroForm = doc.context.obj({ Fields: [] });
|
|
226
|
+
doc.catalog.set(N("AcroForm"), doc.context.register(acroForm));
|
|
227
|
+
}
|
|
228
|
+
const form = acroForm;
|
|
229
|
+
let fields = form.lookup(N("Fields"));
|
|
230
|
+
if (!(fields instanceof PDFArray)) {
|
|
231
|
+
fields = doc.context.obj([]);
|
|
232
|
+
form.set(N("Fields"), fields);
|
|
233
|
+
}
|
|
234
|
+
fields.push(widgetRef);
|
|
235
|
+
form.set(N("SigFlags"), PDFNumber.of(3));
|
|
236
|
+
const prepared = await doc.save({ useObjectStreams: false, updateFieldAppearances: false });
|
|
237
|
+
const { contentsStart, contentsEnd, byteRangeOpen, byteRangeClose } = findPlaceholders(prepared, reserved * 2);
|
|
238
|
+
const byteRange = [0, contentsStart, contentsEnd, prepared.length - contentsEnd];
|
|
239
|
+
const byteRangeText = ` ${byteRange.join(" ")}`.padEnd(byteRangeClose - byteRangeOpen - 1, " ");
|
|
240
|
+
const output = new Uint8Array(prepared);
|
|
241
|
+
output.set(new TextEncoder().encode(byteRangeText), byteRangeOpen + 1);
|
|
242
|
+
const signed = new Uint8Array(contentsStart + (output.length - contentsEnd));
|
|
243
|
+
signed.set(output.subarray(0, contentsStart), 0);
|
|
244
|
+
signed.set(output.subarray(contentsEnd), contentsStart);
|
|
245
|
+
const cms = await buildCmsSignature(await sha256(signed), signer);
|
|
246
|
+
if (cms.length > reserved) {
|
|
247
|
+
throw new Error("The signature is larger than the space reserved for it.");
|
|
248
|
+
}
|
|
249
|
+
const hex = Array.from(cms, (byte) => byte.toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
250
|
+
output.set(new TextEncoder().encode(hex), contentsStart + 1);
|
|
251
|
+
return output;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export { CertificatePasswordError, displayDate, readPkcs12, signPdfWithCertificate };
|
|
255
|
+
//# sourceMappingURL=chunk-U2ROTOPF.js.map
|
|
256
|
+
//# sourceMappingURL=chunk-U2ROTOPF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/certsign/pkcs12.ts","../src/certsign/padesCore.ts"],"names":[],"mappings":"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","file":"chunk-U2ROTOPF.js","sourcesContent":["// Read a .pfx / .p12 certificate file. node-forge is used only to decrypt\n// the container: Windows and many CA exports use legacy PKCS#12 encryption\n// (3DES / RC2 with SHA-1), which WebCrypto cannot decrypt. All signing and\n// verification happens in WebCrypto/pkijs, never in forge.\nimport forge from \"node-forge/lib/forge.js\";\nimport \"node-forge/lib/asn1.js\";\nimport \"node-forge/lib/pki.js\";\nimport \"node-forge/lib/pkcs12.js\";\n\nexport class CertificatePasswordError extends Error {\n constructor() {\n super(\"That password does not open this certificate file.\");\n this.name = \"CertificatePasswordError\";\n }\n}\n\nexport type CertificateIdentity = {\n /** DER of the signer certificate, byte-for-byte as stored in the file. */\n certificate: Uint8Array;\n /** DER of the other certificates in the file (issuers), if any. */\n chain: Uint8Array[];\n /** PKCS#8 DER of the RSA private key, for WebCrypto importKey. */\n privateKeyPkcs8: Uint8Array;\n};\n\nconst toBinary = (bytes: Uint8Array) => {\n let out = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) {\n out += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n }\n return out;\n};\n\nconst fromBinary = (text: string) => Uint8Array.from(text, (char) => char.charCodeAt(0));\n\n/**\n * forge rebuilds parts of a certificate when re-encoding it, which can change\n * its bytes (e.g. an omitted NULL algorithm parameter) and so break the CA's\n * signature on it. Capture each certificate's original ASN.1 while parsing and\n * DER-encode that instead.\n */\nfunction parseKeepingCertificateBytes(p12Asn1, password: string) {\n const derByCert = new Map();\n const original = forge.pki.certificateFromAsn1;\n forge.pki.certificateFromAsn1 = (asn1, computeHash) => {\n const cert = original(asn1, computeHash);\n derByCert.set(cert, fromBinary(forge.asn1.toDer(asn1).getBytes()));\n return cert;\n };\n try {\n return { p12: forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, password), derByCert };\n } finally {\n forge.pki.certificateFromAsn1 = original;\n }\n}\n\nexport function readPkcs12(bytes: ArrayBuffer | Uint8Array, password: string): CertificateIdentity {\n const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n\n let p12Asn1;\n try {\n p12Asn1 = forge.asn1.fromDer(forge.util.createBuffer(toBinary(data)), false);\n } catch {\n throw new Error(\"This is not a .pfx / .p12 certificate file.\");\n }\n\n let parsed;\n try {\n parsed = parseKeepingCertificateBytes(p12Asn1, password);\n } catch (error) {\n const message = String(error?.message || \"\");\n if (/MAC could not be verified|Invalid password|wrong password|decrypt/i.test(message)) {\n throw new CertificatePasswordError();\n }\n throw new Error(`Could not read this certificate file (${message || \"unknown format\"}).`);\n }\n const { p12, derByCert } = parsed;\n\n const keyBags = [\n ...(p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag })[forge.pki.oids.pkcs8ShroudedKeyBag] || []),\n ...(p12.getBags({ bagType: forge.pki.oids.keyBag })[forge.pki.oids.keyBag] || []),\n ];\n const certBags = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag] || [];\n\n const key = keyBags.find((bag) => bag.key)?.key;\n if (!key) {\n if (keyBags.length) {\n throw new Error(\"Only RSA certificates are supported. This file holds a different key type.\");\n }\n throw new Error(\"This file has no private key. Export the certificate together with its private key.\");\n }\n\n const certs = certBags.filter((bag) => bag.cert);\n const leaf = certs.find(\n (bag) => bag.cert.publicKey?.n && bag.cert.publicKey.n.equals(key.n) && bag.cert.publicKey.e.equals(key.e)\n );\n if (!leaf) {\n throw new Error(\"No certificate in this file matches its private key.\");\n }\n\n const pkcs8 = forge.pki.wrapRsaPrivateKey(forge.pki.privateKeyToAsn1(key));\n return {\n certificate: derByCert.get(leaf.cert),\n chain: certs.filter((bag) => bag !== leaf).map((bag) => derByCert.get(bag.cert)),\n privateKeyPkcs8: fromBinary(forge.asn1.toDer(pkcs8).getBytes()),\n };\n}\n","// Sign a PDF with a certificate: PAdES baseline (ETSI.CAdES.detached).\nimport {\n PDFArray,\n PDFDict,\n PDFDocument,\n PDFHexString,\n PDFName,\n PDFNumber,\n PDFRef,\n PDFString,\n StandardFonts,\n beginText,\n endText,\n popGraphicsState,\n pushGraphicsState,\n rectangle,\n setFillingRgbColor,\n setFontAndSize,\n setLineWidth,\n setStrokingRgbColor,\n showText,\n moveText,\n stroke,\n} from \"pdf-lib\";\nimport { loadPdf } from \"../shared/files\";\nimport { textOrigin, visualSize } from \"../shared/pageGeometry\";\nimport { hasDigitalSignatures, signatureFields } from \"../shared/signatureFields\";\nimport { placementToVisual } from \"../sign/signPdfCore\";\nimport { buildCmsSignature, describeCertificate, sha256, type RawSigner } from \"./cms\";\n\nconst N = (name: string) => PDFName.of(name);\nconst PLACEHOLDER = 1234567890;\nconst latin1 = new TextDecoder(\"latin1\");\n\nexport type VisibleSignature = {\n pageIndex: number;\n /** Fractions (0-1) of the visible page, from its top-left corner. */\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\nexport type CertificateSignOptions = {\n reason?: string;\n location?: string;\n contactInfo?: string;\n /** Omit for an invisible signature. */\n visible?: VisibleSignature | null;\n signingTime?: Date;\n};\n\nfunction pad(value: number) {\n return String(value).padStart(2, \"0\");\n}\n\n/** \"2026.11.01 14:05:09 +05'30'\" in the signer's local time. */\nexport function displayDate(date: Date) {\n const offset = -date.getTimezoneOffset();\n const sign = offset >= 0 ? \"+\" : \"-\";\n const abs = Math.abs(offset);\n return (\n `${date.getFullYear()}.${pad(date.getMonth() + 1)}.${pad(date.getDate())} ` +\n `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())} ` +\n `${sign}${pad(Math.floor(abs / 60))}'${pad(abs % 60)}'`\n );\n}\n\nfunction uniqueFieldName(doc: PDFDocument) {\n const taken = new Set(doc.getForm().getFields().map((field) => field.getName()));\n signatureFields(doc).forEach((field) => taken.add(field.name));\n let index = 1;\n while (taken.has(`Signature${index}`)) index += 1;\n return `Signature${index}`;\n}\n\n/** Text the standard Helvetica font can encode; anything else becomes \"?\". */\nfunction safeText(font, value: string) {\n return Array.from(value)\n .map((char) => {\n try {\n font.encodeText(char);\n return char;\n } catch {\n return \"?\";\n }\n })\n .join(\"\");\n}\n\nasync function appearance(doc: PDFDocument, page, box, lines: string[], angle: number) {\n const font = await doc.embedFont(StandardFonts.Helvetica);\n const { width, height } = box;\n const padding = Math.min(6, width * 0.05, height * 0.08);\n const shown = lines.map((line) => safeText(font, line));\n const widest = Math.max(...shown.map((line) => font.widthOfTextAtSize(line, 10)), 1);\n const size = Math.max(4, Math.min(10, (10 * (width - padding * 2)) / widest, (height - padding * 2) / (shown.length * 1.25)));\n\n const operators = [\n pushGraphicsState(),\n setStrokingRgbColor(0.12, 0.35, 0.75),\n setLineWidth(0.8),\n rectangle(0.4, 0.4, width - 0.8, height - 0.8),\n stroke(),\n setFillingRgbColor(0.06, 0.09, 0.16),\n beginText(),\n setFontAndSize(N(\"F1\"), size),\n moveText(padding, height - padding - size),\n ];\n shown.forEach((line, index) => {\n if (index > 0) operators.push(moveText(0, -size * 1.25));\n operators.push(showText(font.encodeText(line)));\n });\n operators.push(endText(), popGraphicsState());\n\n const radians = (angle * Math.PI) / 180;\n const cos = Math.round(Math.cos(radians));\n const sin = Math.round(Math.sin(radians));\n const stream = doc.context.formXObject(operators, {\n BBox: [0, 0, width, height],\n // Counter the page's /Rotate so the box reads upright on screen.\n Matrix: [cos, sin, -sin, cos, 0, 0],\n Resources: { Font: { F1: font.ref } },\n });\n return doc.context.register(stream);\n}\n\nfunction findPlaceholders(bytes: Uint8Array, contentsLength: number) {\n const text = latin1.decode(bytes);\n const zeros = \"0\".repeat(contentsLength);\n const contentsStart = text.lastIndexOf(`<${zeros}>`);\n if (contentsStart < 0) throw new Error(\"Could not prepare the signature (contents placeholder not found).\");\n const contentsEnd = contentsStart + contentsLength + 2;\n\n const pattern = /\\/ByteRange\\s*\\[\\s*0\\s+1234567890\\s+1234567890\\s+1234567890\\s*\\]/g;\n let match;\n let last = null;\n while ((match = pattern.exec(text))) last = match;\n if (!last) throw new Error(\"Could not prepare the signature (byte range placeholder not found).\");\n const open = last.index + last[0].indexOf(\"[\");\n const close = last.index + last[0].length - 1;\n return { contentsStart, contentsEnd, byteRangeOpen: open, byteRangeClose: close };\n}\n\n/**\n * Add a digital signature. Rejects PDFs that are already signed: rewriting\n * the file (as pdf-lib does) would invalidate the existing signature.\n */\nexport async function signPdfWithCertificate(\n bytes: ArrayBuffer | Uint8Array,\n signer: RawSigner,\n options: CertificateSignOptions = {}\n) {\n const doc = await loadPdf(bytes, { updateMetadata: false });\n if (hasDigitalSignatures(doc)) {\n throw new Error(\n \"This PDF is already digitally signed. Adding another signature here would invalidate the existing one.\"\n );\n }\n\n const certificate = describeCertificate(signer.certificate);\n const signingTime = options.signingTime ?? new Date();\n const certBytes = signer.certificate.length + (signer.chain || []).reduce((sum, der) => sum + der.length, 0);\n // Room for the certificates, signature, attributes, and a future timestamp.\n const reserved = certBytes + 8192;\n\n const signatureDict = doc.context.obj({\n Type: \"Sig\",\n Filter: \"Adobe.PPKLite\",\n SubFilter: \"ETSI.CAdES.detached\",\n ByteRange: [0, PLACEHOLDER, PLACEHOLDER, PLACEHOLDER],\n Contents: PDFHexString.of(\"0\".repeat(reserved * 2)),\n M: PDFString.fromDate(signingTime),\n }) as PDFDict;\n if (certificate.commonName) signatureDict.set(N(\"Name\"), PDFHexString.fromText(certificate.commonName));\n if (options.reason) signatureDict.set(N(\"Reason\"), PDFHexString.fromText(options.reason));\n if (options.location) signatureDict.set(N(\"Location\"), PDFHexString.fromText(options.location));\n if (options.contactInfo) signatureDict.set(N(\"ContactInfo\"), PDFHexString.fromText(options.contactInfo));\n const signatureRef = doc.context.register(signatureDict);\n\n const pages = doc.getPages();\n const pageIndex = options.visible ? options.visible.pageIndex : 0;\n const page = pages[pageIndex];\n if (!page) throw new Error(`Page ${pageIndex + 1} does not exist.`);\n\n let rect = [0, 0, 0, 0];\n let appearanceRef: PDFRef;\n if (options.visible) {\n const { visualWidth, visualHeight } = visualSize(page);\n const box = placementToVisual(options.visible, visualWidth, visualHeight);\n const a = textOrigin(page, box.vx, box.vy);\n const b = textOrigin(page, box.vx + box.width, box.vy + box.height);\n rect = [Math.min(a.x, b.x), Math.min(a.y, b.y), Math.max(a.x, b.x), Math.max(a.y, b.y)];\n const lines = [\n `Digitally signed by ${certificate.commonName || \"(no name)\"}`,\n `Date: ${displayDate(signingTime)}`,\n ...(options.reason ? [`Reason: ${options.reason}`] : []),\n ...(options.location ? [`Location: ${options.location}`] : []),\n ];\n appearanceRef = await appearance(doc, page, box, lines, a.angle);\n } else {\n appearanceRef = doc.context.register(doc.context.formXObject([], { BBox: [0, 0, 0, 0] }));\n }\n\n const widget = doc.context.obj({\n Type: \"Annot\",\n Subtype: \"Widget\",\n FT: \"Sig\",\n T: PDFHexString.fromText(uniqueFieldName(doc)),\n V: signatureRef,\n F: 132, // Print + Locked\n P: page.ref,\n Rect: rect,\n AP: { N: appearanceRef },\n });\n const widgetRef = doc.context.register(widget);\n page.node.addAnnot(widgetRef);\n\n let acroForm = doc.catalog.lookup(N(\"AcroForm\"));\n if (!(acroForm instanceof PDFDict)) {\n acroForm = doc.context.obj({ Fields: [] }) as PDFDict;\n doc.catalog.set(N(\"AcroForm\"), doc.context.register(acroForm));\n }\n const form = acroForm as PDFDict;\n let fields = form.lookup(N(\"Fields\"));\n if (!(fields instanceof PDFArray)) {\n fields = doc.context.obj([]);\n form.set(N(\"Fields\"), fields);\n }\n (fields as PDFArray).push(widgetRef);\n form.set(N(\"SigFlags\"), PDFNumber.of(3));\n\n // No object streams: the signature dictionary must stay plain text so its\n // placeholders can be found and filled in place.\n const prepared = await doc.save({ useObjectStreams: false, updateFieldAppearances: false });\n const { contentsStart, contentsEnd, byteRangeOpen, byteRangeClose } = findPlaceholders(prepared, reserved * 2);\n\n const byteRange = [0, contentsStart, contentsEnd, prepared.length - contentsEnd];\n const byteRangeText = ` ${byteRange.join(\" \")}`.padEnd(byteRangeClose - byteRangeOpen - 1, \" \");\n const output = new Uint8Array(prepared);\n output.set(new TextEncoder().encode(byteRangeText), byteRangeOpen + 1);\n\n const signed = new Uint8Array(contentsStart + (output.length - contentsEnd));\n signed.set(output.subarray(0, contentsStart), 0);\n signed.set(output.subarray(contentsEnd), contentsStart);\n const cms = await buildCmsSignature(await sha256(signed), signer);\n if (cms.length > reserved) {\n throw new Error(\"The signature is larger than the space reserved for it.\");\n }\n const hex = Array.from(cms, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\").toUpperCase();\n output.set(new TextEncoder().encode(hex), contentsStart + 1);\n\n return output;\n}\n"]}
|