From cbb5e21d66921611c45e17b1dc096560c2005c73 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 May 2026 09:49:49 +0000
Subject: [PATCH 01/10] feat: add PDF export for chart snapshots
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/09b0dcd6-021e-4da8-b93b-7abd34639d4e
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
README.md | 2 +-
package-lock.json | 4 +-
package.json | 2 +-
src/App.tsx | 28 ++++++++--
src/lib/exportSvg.ts | 123 ++++++++++++++++++++++++++++++++++++++++---
5 files changed, 144 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index 132d204..8f2d65b 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ It reads local Engine DJ SQLite databases and Traktor `collection.nml` files dir
- Playlist transition summaries derived from playlist ordering
- Sparse / missing region surfacing
- Mock dataset mode for first-run exploration
-- PNG export for both charts
+- PNG and PDF export for both charts
- GitHub Pages-ready static deployment
## Local development
diff --git a/package-lock.json b/package-lock.json
index 3f4f696..799efce 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "keybpmmap",
- "version": "0.13.0",
+ "version": "0.14.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "keybpmmap",
- "version": "0.13.0",
+ "version": "0.14.0",
"dependencies": {
"d3": "^7.9.0",
"fast-xml-parser": "^5.8.0",
diff --git a/package.json b/package.json
index 0f04ec1..41fc058 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "keybpmmap",
"private": true,
- "version": "0.1.0",
+ "version": "0.14.0",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src/App.tsx b/src/App.tsx
index 676a07d..08e53e9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -13,7 +13,7 @@ import {
summarizeTracks,
} from './lib/analysis'
import { CAMELOT_KEYS, formatKey, type KeyRepresentation } from './lib/camelot'
-import { downloadSvgAsPng } from './lib/exportSvg'
+import { downloadSvgAsPdf, downloadSvgAsPng } from './lib/exportSvg'
import { loadLibraryFromFile } from './lib/libraryLoader'
import { createMockLibrary } from './lib/mockData'
import {
@@ -772,11 +772,17 @@ function App() {
const exportChart = async (
svgElement: SVGSVGElement | null,
fileName: string,
+ format: 'png' | 'pdf',
) => {
if (!svgElement) {
return
}
+ if (format === 'pdf') {
+ await downloadSvgAsPdf(svgElement, fileName)
+ return
+ }
+
await downloadSvgAsPng(svgElement, fileName)
}
@@ -875,7 +881,7 @@ function App() {
Reads Traktor collection.nml files and their backups locally in the browser.
Reads Rekordbox XML exports locally in the browser.
Understands Engine DJ, Traktor, and Rekordbox playlist relationships.
- Exports both charts as PNG snapshots.
+ Exports both charts as PNG and PDF snapshots.
Find my music and socials:
@@ -1575,10 +1581,17 @@ function App() {
+
exportChart(heatmapRef.current, 'keybpmmap-heatmap.png')}
+ onClick={() => exportChart(heatmapRef.current, 'keybpmmap-heatmap.png', 'png')}
>
Export PNG
+
{
+ const { canvas, url } = await renderSvgToCanvas(svgElement)
+
+ try {
+ const downloadUrl = canvas.toDataURL('image/png')
+ triggerDownload(downloadUrl, fileName)
+ } finally {
+ URL.revokeObjectURL(url)
+ }
+}
+
+export async function downloadSvgAsPdf(
+ svgElement: SVGSVGElement,
+ fileName: string,
+): Promise {
+ const { canvas, url } = await renderSvgToCanvas(svgElement)
+ let downloadUrl: string | null = null
+
+ try {
+ const jpegDataUrl = canvas.toDataURL('image/jpeg', 0.95)
+ const pdfData = createPdfFromJpegDataUrl(jpegDataUrl, canvas.width, canvas.height)
+ const pdfBlob = new Blob([pdfData], { type: 'application/pdf' })
+ downloadUrl = URL.createObjectURL(pdfBlob)
+ triggerDownload(downloadUrl, fileName)
+ } finally {
+ if (downloadUrl) {
+ URL.revokeObjectURL(downloadUrl)
+ }
+ URL.revokeObjectURL(url)
+ }
+}
+
+async function renderSvgToCanvas(
+ svgElement: SVGSVGElement,
+): Promise<{ canvas: HTMLCanvasElement; url: string }> {
const clonedSvg = svgElement.cloneNode(true) as SVGSVGElement
inlineTextStyles(svgElement, clonedSvg)
const serializer = new XMLSerializer()
const source = serializer.serializeToString(clonedSvg)
const blob = new Blob([source], { type: 'image/svg+xml;charset=utf-8' })
const url = URL.createObjectURL(blob)
-
try {
const image = await loadImage(url)
const viewBox = svgElement.viewBox.baseVal
@@ -27,13 +60,10 @@ export async function downloadSvgAsPng(
context.fillRect(0, 0, width, height)
context.drawImage(image, 0, 0, width, height)
- const downloadUrl = canvas.toDataURL('image/png')
- const anchor = document.createElement('a')
- anchor.href = downloadUrl
- anchor.download = fileName
- anchor.click()
- } finally {
+ return { canvas, url }
+ } catch (error) {
URL.revokeObjectURL(url)
+ throw error
}
}
@@ -77,3 +107,82 @@ function loadImage(src: string): Promise {
image.src = src
})
}
+
+function triggerDownload(href: string, fileName: string): void {
+ const anchor = document.createElement('a')
+ anchor.href = href
+ anchor.download = fileName
+ anchor.click()
+}
+
+function createPdfFromJpegDataUrl(dataUrl: string, width: number, height: number): Uint8Array {
+ const base64Data = dataUrl.split(',')[1]
+
+ if (!base64Data) {
+ throw new Error('Unable to encode chart image for PDF export.')
+ }
+
+ const jpegBinary = atob(base64Data)
+ const jpegBytes = new Uint8Array(jpegBinary.length)
+
+ for (let byteIndex = 0; byteIndex < jpegBinary.length; byteIndex += 1) {
+ jpegBytes[byteIndex] = jpegBinary.charCodeAt(byteIndex)
+ }
+
+ const objects: Uint8Array[] = []
+ const offsets: number[] = [0]
+ const encoder = new TextEncoder()
+
+ const pageWidth = Math.max(1, Math.round(width))
+ const pageHeight = Math.max(1, Math.round(height))
+ const imageObject = encoder.encode(
+ `4 0 obj\n<< /Type /XObject /Subtype /Image /Width ${pageWidth} /Height ${pageHeight} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ${jpegBytes.length} >>\nstream\n`,
+ )
+ const imageObjectEnd = encoder.encode('\nendstream\nendobj\n')
+ const contentStream = encoder.encode(`q\n${pageWidth} 0 0 ${pageHeight} 0 0 cm\n/Im0 Do\nQ\n`)
+ const contentObject = encoder.encode(`5 0 obj\n<< /Length ${contentStream.length} >>\nstream\n`)
+ const contentObjectEnd = encoder.encode('endstream\nendobj\n')
+
+ objects.push(encoder.encode('1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n'))
+ objects.push(encoder.encode('2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n'))
+ objects.push(
+ encoder.encode(
+ `3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${pageWidth} ${pageHeight}] /Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>\nendobj\n`,
+ ),
+ )
+ objects.push(concatUint8Arrays([imageObject, jpegBytes, imageObjectEnd]))
+ objects.push(concatUint8Arrays([contentObject, contentStream, contentObjectEnd]))
+
+ let currentOffset = encoder.encode('%PDF-1.4\n').length
+ for (const objectData of objects) {
+ offsets.push(currentOffset)
+ currentOffset += objectData.length
+ }
+
+ const xrefStart = currentOffset
+ const xrefHeader = encoder.encode(`xref\n0 ${objects.length + 1}\n`)
+ const xrefRows = offsets
+ .map((offset, index) =>
+ index === 0 ? '0000000000 65535 f \n' : `${offset.toString().padStart(10, '0')} 00000 n \n`,
+ )
+ .join('')
+ const xrefData = encoder.encode(xrefRows)
+ const trailer = encoder.encode(
+ `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\nstartxref\n${xrefStart}\n%%EOF`,
+ )
+
+ return concatUint8Arrays([encoder.encode('%PDF-1.4\n'), ...objects, xrefHeader, xrefData, trailer])
+}
+
+function concatUint8Arrays(chunks: Uint8Array[]): Uint8Array {
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
+ const output = new Uint8Array(totalLength)
+ let offset = 0
+
+ for (const chunk of chunks) {
+ output.set(chunk, offset)
+ offset += chunk.length
+ }
+
+ return output
+}
From 51e09eaaf85ce13ccc72350d7bab0e5eaede0a5a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 May 2026 09:50:33 +0000
Subject: [PATCH 02/10] fix: resolve typed array blob compatibility in pdf
export
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/09b0dcd6-021e-4da8-b93b-7abd34639d4e
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
src/lib/exportSvg.ts | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/lib/exportSvg.ts b/src/lib/exportSvg.ts
index 8a8d300..eb3d87c 100644
--- a/src/lib/exportSvg.ts
+++ b/src/lib/exportSvg.ts
@@ -115,7 +115,11 @@ function triggerDownload(href: string, fileName: string): void {
anchor.click()
}
-function createPdfFromJpegDataUrl(dataUrl: string, width: number, height: number): Uint8Array {
+function createPdfFromJpegDataUrl(
+ dataUrl: string,
+ width: number,
+ height: number,
+): Uint8Array {
const base64Data = dataUrl.split(',')[1]
if (!base64Data) {
@@ -129,7 +133,7 @@ function createPdfFromJpegDataUrl(dataUrl: string, width: number, height: number
jpegBytes[byteIndex] = jpegBinary.charCodeAt(byteIndex)
}
- const objects: Uint8Array[] = []
+ const objects: Uint8Array[] = []
const offsets: number[] = [0]
const encoder = new TextEncoder()
@@ -174,7 +178,7 @@ function createPdfFromJpegDataUrl(dataUrl: string, width: number, height: number
return concatUint8Arrays([encoder.encode('%PDF-1.4\n'), ...objects, xrefHeader, xrefData, trailer])
}
-function concatUint8Arrays(chunks: Uint8Array[]): Uint8Array {
+function concatUint8Arrays(chunks: Uint8Array[]): Uint8Array {
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
const output = new Uint8Array(totalLength)
let offset = 0
From 453f59fd47794d38845bfe9be3374ace178523fd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 May 2026 09:51:55 +0000
Subject: [PATCH 03/10] chore: set package version to 0.2.0
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/09b0dcd6-021e-4da8-b93b-7abd34639d4e
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
package-lock.json | 4 ++--
package.json | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 799efce..ef0b3e3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "keybpmmap",
- "version": "0.14.0",
+ "version": "0.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "keybpmmap",
- "version": "0.14.0",
+ "version": "0.2.0",
"dependencies": {
"d3": "^7.9.0",
"fast-xml-parser": "^5.8.0",
diff --git a/package.json b/package.json
index 41fc058..0955a06 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "keybpmmap",
"private": true,
- "version": "0.14.0",
+ "version": "0.2.0",
"type": "module",
"scripts": {
"dev": "vite",
From de595d3c0896168ee2d3a3e18233cef3470757be Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 May 2026 09:52:37 +0000
Subject: [PATCH 04/10] chore: align package version to 0.14.0
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/09b0dcd6-021e-4da8-b93b-7abd34639d4e
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
package-lock.json | 4 ++--
package.json | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index ef0b3e3..799efce 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "keybpmmap",
- "version": "0.2.0",
+ "version": "0.14.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "keybpmmap",
- "version": "0.2.0",
+ "version": "0.14.0",
"dependencies": {
"d3": "^7.9.0",
"fast-xml-parser": "^5.8.0",
diff --git a/package.json b/package.json
index 0955a06..41fc058 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "keybpmmap",
"private": true,
- "version": "0.2.0",
+ "version": "0.14.0",
"type": "module",
"scripts": {
"dev": "vite",
From 16805512150902b553217205a1748a04f8cd11da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 26 May 2026 02:52:20 +0000
Subject: [PATCH 05/10] fix: export svg charts as vector pdfs
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/3f07c599-905c-4258-abf7-addf6dc6595d
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
package-lock.json | 280 ++++++++++++++++++++++++++++++++++++++++++-
package.json | 4 +-
src/lib/exportSvg.ts | 124 ++++++-------------
3 files changed, 320 insertions(+), 88 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 799efce..1845efe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,9 +10,11 @@
"dependencies": {
"d3": "^7.9.0",
"fast-xml-parser": "^5.8.0",
+ "jspdf": "^4.2.1",
"react": "^19.2.6",
"react-dom": "^19.2.6",
- "sql.js": "^1.14.1"
+ "sql.js": "^1.14.1",
+ "svg2pdf.js": "^2.7.0"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
@@ -225,6 +227,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
+ "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/template": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
@@ -1221,6 +1232,19 @@
"undici-types": "~7.16.0"
}
},
+ "node_modules/@types/pako": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
+ "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/raf": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
+ "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@types/react": {
"version": "19.2.15",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz",
@@ -1252,6 +1276,13 @@
"@types/node": "*"
}
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.59.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz",
@@ -1694,6 +1725,16 @@
"node": "18 || 20 || >=22"
}
},
+ "node_modules/base64-arraybuffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+ "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/baseline-browser-mapping": {
"version": "2.10.31",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz",
@@ -1775,6 +1816,26 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/canvg": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
+ "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@types/raf": "^3.4.0",
+ "core-js": "^3.8.3",
+ "raf": "^3.4.1",
+ "regenerator-runtime": "^0.13.7",
+ "rgbcolor": "^1.0.1",
+ "stackblur-canvas": "^2.0.0",
+ "svg-pathdata": "^6.0.3"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/chai": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
@@ -1801,6 +1862,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/core-js": {
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz",
+ "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -1816,6 +1889,28 @@
"node": ">= 8"
}
},
+ "node_modules/css-line-break": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
+ "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "utrie": "^1.0.2"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -2268,6 +2363,16 @@
"node": ">=8"
}
},
+ "node_modules/dompurify": {
+ "version": "3.4.5",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.5.tgz",
+ "integrity": "sha512-OrwIBKsdNSVEeubdJ1HBv/wNENRM9ytAVCv7YXt//A3vPdVMNuACRqK9mXCGCBW2ln7BT/A4X0jXHo2Gu89miA==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optional": true,
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.360",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.360.tgz",
@@ -2528,6 +2633,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-png": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
+ "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/pako": "^2.0.3",
+ "iobuffer": "^5.3.2",
+ "pako": "^2.1.0"
+ }
+ },
"node_modules/fast-xml-builder": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
@@ -2584,6 +2700,12 @@
}
}
},
+ "node_modules/fflate": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
+ "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
+ "license": "MIT"
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -2635,6 +2757,12 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/font-family-papandreou": {
+ "version": "0.2.0-patch2",
+ "resolved": "https://registry.npmjs.org/font-family-papandreou/-/font-family-papandreou-0.2.0-patch2.tgz",
+ "integrity": "sha512-l/YiRdBSH/eWv6OF3sLGkwErL+n0MqCICi9mppTZBOCL5vixWGDqCYvRcuxB2h7RGCTzaTKOHT2caHvCXQPRlw==",
+ "license": "MIT"
+ },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -2703,6 +2831,20 @@
"hermes-estree": "0.25.1"
}
},
+ "node_modules/html2canvas": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
+ "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "css-line-break": "^2.1.0",
+ "text-segmentation": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -2744,6 +2886,12 @@
"node": ">=12"
}
},
+ "node_modules/iobuffer": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
+ "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
+ "license": "MIT"
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2828,6 +2976,23 @@
"node": ">=6"
}
},
+ "node_modules/jspdf": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz",
+ "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.6",
+ "fast-png": "^6.2.0",
+ "fflate": "^0.8.1"
+ },
+ "optionalDependencies": {
+ "canvg": "^3.0.11",
+ "core-js": "^3.6.0",
+ "dompurify": "^3.3.1",
+ "html2canvas": "^1.0.0-rc.5"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -3266,6 +3431,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/pako": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
+ "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
+ "license": "(MIT AND Zlib)"
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -3308,6 +3479,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -3377,6 +3555,16 @@
"node": ">=6"
}
},
+ "node_modules/raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "performance-now": "^2.1.0"
+ }
+ },
"node_modules/react": {
"version": "19.2.6",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
@@ -3398,6 +3586,23 @@
"react": "^19.2.6"
}
},
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/rgbcolor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
+ "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+ "license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.8.15"
+ }
+ },
"node_modules/robust-predicates": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz",
@@ -3506,6 +3711,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/specificity": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz",
+ "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==",
+ "license": "MIT",
+ "bin": {
+ "specificity": "bin/specificity"
+ }
+ },
"node_modules/sql.js": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.1.tgz",
@@ -3519,6 +3733,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/stackblur-canvas": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
+ "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.14"
+ }
+ },
"node_modules/std-env": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz",
@@ -3538,6 +3762,50 @@
],
"license": "MIT"
},
+ "node_modules/svg-pathdata": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+ "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/svg2pdf.js": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/svg2pdf.js/-/svg2pdf.js-2.7.0.tgz",
+ "integrity": "sha512-nXK4Wx28H0KtOktanm5nsphl1KMEoLNMelAT/776qxPAj9DshwYcqgdpKuBnY1nrcYOriQFHVQLE4tIag+aDJA==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "font-family-papandreou": "^0.2.0-patch1",
+ "specificity": "^0.4.1",
+ "svgpath": "^2.3.0"
+ },
+ "peerDependencies": {
+ "jspdf": "^4.0.0 || ^3.0.0 || ^2.0.0"
+ }
+ },
+ "node_modules/svgpath": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.6.0.tgz",
+ "integrity": "sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/fontello/svg2ttf?sponsor=1"
+ }
+ },
+ "node_modules/text-segmentation": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
+ "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "utrie": "^1.0.2"
+ }
+ },
"node_modules/tinybench": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
@@ -3702,6 +3970,16 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/utrie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
+ "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "base64-arraybuffer": "^1.0.2"
+ }
+ },
"node_modules/vite": {
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz",
diff --git a/package.json b/package.json
index 41fc058..d4a432b 100644
--- a/package.json
+++ b/package.json
@@ -13,9 +13,11 @@
"dependencies": {
"d3": "^7.9.0",
"fast-xml-parser": "^5.8.0",
+ "jspdf": "^4.2.1",
"react": "^19.2.6",
"react-dom": "^19.2.6",
- "sql.js": "^1.14.1"
+ "sql.js": "^1.14.1",
+ "svg2pdf.js": "^2.7.0"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
diff --git a/src/lib/exportSvg.ts b/src/lib/exportSvg.ts
index eb3d87c..7898910 100644
--- a/src/lib/exportSvg.ts
+++ b/src/lib/exportSvg.ts
@@ -1,3 +1,6 @@
+import { jsPDF } from 'jspdf'
+import 'svg2pdf.js'
+
export async function downloadSvgAsPng(
svgElement: SVGSVGElement,
fileName: string,
@@ -16,37 +19,40 @@ export async function downloadSvgAsPdf(
svgElement: SVGSVGElement,
fileName: string,
): Promise {
- const { canvas, url } = await renderSvgToCanvas(svgElement)
+ const { clonedSvg, width, height } = cloneSvgForExport(svgElement)
let downloadUrl: string | null = null
try {
- const jpegDataUrl = canvas.toDataURL('image/jpeg', 0.95)
- const pdfData = createPdfFromJpegDataUrl(jpegDataUrl, canvas.width, canvas.height)
- const pdfBlob = new Blob([pdfData], { type: 'application/pdf' })
+ const pdf = new jsPDF({
+ compress: true,
+ format: [width, height],
+ orientation: width > height ? 'landscape' : 'portrait',
+ unit: 'pt',
+ })
+
+ await pdf.svg(clonedSvg, { height, width, x: 0, y: 0 })
+
+ const pdfBuffer = pdf.output('arraybuffer')
+ const pdfBlob = new Blob([pdfBuffer], { type: 'application/pdf' })
downloadUrl = URL.createObjectURL(pdfBlob)
triggerDownload(downloadUrl, fileName)
} finally {
if (downloadUrl) {
URL.revokeObjectURL(downloadUrl)
}
- URL.revokeObjectURL(url)
}
}
async function renderSvgToCanvas(
svgElement: SVGSVGElement,
): Promise<{ canvas: HTMLCanvasElement; url: string }> {
- const clonedSvg = svgElement.cloneNode(true) as SVGSVGElement
- inlineTextStyles(svgElement, clonedSvg)
+ const { clonedSvg, height, width } = cloneSvgForExport(svgElement)
const serializer = new XMLSerializer()
const source = serializer.serializeToString(clonedSvg)
const blob = new Blob([source], { type: 'image/svg+xml;charset=utf-8' })
const url = URL.createObjectURL(blob)
try {
const image = await loadImage(url)
- const viewBox = svgElement.viewBox.baseVal
- const width = viewBox.width || svgElement.clientWidth || 1200
- const height = viewBox.height || svgElement.clientHeight || 800
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
@@ -67,6 +73,28 @@ async function renderSvgToCanvas(
}
}
+function cloneSvgForExport(
+ svgElement: SVGSVGElement,
+): { clonedSvg: SVGSVGElement; height: number; width: number } {
+ const clonedSvg = svgElement.cloneNode(true) as SVGSVGElement
+ const { height, width } = getSvgExportDimensions(svgElement)
+
+ clonedSvg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
+ clonedSvg.setAttribute('width', width.toString())
+ clonedSvg.setAttribute('height', height.toString())
+ inlineTextStyles(svgElement, clonedSvg)
+
+ return { clonedSvg, height, width }
+}
+
+function getSvgExportDimensions(svgElement: SVGSVGElement): { height: number; width: number } {
+ const viewBox = svgElement.viewBox.baseVal
+ const width = Math.max(1, Math.round(viewBox.width || svgElement.clientWidth || 1200))
+ const height = Math.max(1, Math.round(viewBox.height || svgElement.clientHeight || 800))
+
+ return { height, width }
+}
+
function inlineTextStyles(sourceSvg: SVGSVGElement, targetSvg: SVGSVGElement): void {
const sourceTextNodes = sourceSvg.querySelectorAll('text')
const targetTextNodes = targetSvg.querySelectorAll('text')
@@ -114,79 +142,3 @@ function triggerDownload(href: string, fileName: string): void {
anchor.download = fileName
anchor.click()
}
-
-function createPdfFromJpegDataUrl(
- dataUrl: string,
- width: number,
- height: number,
-): Uint8Array {
- const base64Data = dataUrl.split(',')[1]
-
- if (!base64Data) {
- throw new Error('Unable to encode chart image for PDF export.')
- }
-
- const jpegBinary = atob(base64Data)
- const jpegBytes = new Uint8Array(jpegBinary.length)
-
- for (let byteIndex = 0; byteIndex < jpegBinary.length; byteIndex += 1) {
- jpegBytes[byteIndex] = jpegBinary.charCodeAt(byteIndex)
- }
-
- const objects: Uint8Array[] = []
- const offsets: number[] = [0]
- const encoder = new TextEncoder()
-
- const pageWidth = Math.max(1, Math.round(width))
- const pageHeight = Math.max(1, Math.round(height))
- const imageObject = encoder.encode(
- `4 0 obj\n<< /Type /XObject /Subtype /Image /Width ${pageWidth} /Height ${pageHeight} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ${jpegBytes.length} >>\nstream\n`,
- )
- const imageObjectEnd = encoder.encode('\nendstream\nendobj\n')
- const contentStream = encoder.encode(`q\n${pageWidth} 0 0 ${pageHeight} 0 0 cm\n/Im0 Do\nQ\n`)
- const contentObject = encoder.encode(`5 0 obj\n<< /Length ${contentStream.length} >>\nstream\n`)
- const contentObjectEnd = encoder.encode('endstream\nendobj\n')
-
- objects.push(encoder.encode('1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n'))
- objects.push(encoder.encode('2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n'))
- objects.push(
- encoder.encode(
- `3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${pageWidth} ${pageHeight}] /Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>\nendobj\n`,
- ),
- )
- objects.push(concatUint8Arrays([imageObject, jpegBytes, imageObjectEnd]))
- objects.push(concatUint8Arrays([contentObject, contentStream, contentObjectEnd]))
-
- let currentOffset = encoder.encode('%PDF-1.4\n').length
- for (const objectData of objects) {
- offsets.push(currentOffset)
- currentOffset += objectData.length
- }
-
- const xrefStart = currentOffset
- const xrefHeader = encoder.encode(`xref\n0 ${objects.length + 1}\n`)
- const xrefRows = offsets
- .map((offset, index) =>
- index === 0 ? '0000000000 65535 f \n' : `${offset.toString().padStart(10, '0')} 00000 n \n`,
- )
- .join('')
- const xrefData = encoder.encode(xrefRows)
- const trailer = encoder.encode(
- `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\nstartxref\n${xrefStart}\n%%EOF`,
- )
-
- return concatUint8Arrays([encoder.encode('%PDF-1.4\n'), ...objects, xrefHeader, xrefData, trailer])
-}
-
-function concatUint8Arrays(chunks: Uint8Array[]): Uint8Array {
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
- const output = new Uint8Array(totalLength)
- let offset = 0
-
- for (const chunk of chunks) {
- output.set(chunk, offset)
- offset += chunk.length
- }
-
- return output
-}
From 07583d5cc61d3a39c1bffda74a1a2f9f5ef85626 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 26 May 2026 02:53:33 +0000
Subject: [PATCH 06/10] chore: bump version to 0.15.0
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/3f07c599-905c-4258-abf7-addf6dc6595d
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
package-lock.json | 4 ++--
package.json | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 1845efe..f1e150c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "keybpmmap",
- "version": "0.14.0",
+ "version": "0.15.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "keybpmmap",
- "version": "0.14.0",
+ "version": "0.15.0",
"dependencies": {
"d3": "^7.9.0",
"fast-xml-parser": "^5.8.0",
diff --git a/package.json b/package.json
index d4a432b..2bb357b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "keybpmmap",
"private": true,
- "version": "0.14.0",
+ "version": "0.15.0",
"type": "module",
"scripts": {
"dev": "vite",
From 39af9a683c9fdbf70b0b01ba17ad0317e79e5538 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 26 May 2026 09:08:52 +0000
Subject: [PATCH 07/10] fix: preserve legend scale in exported pdfs
Agent-Logs-Url: https://github.com/samsta/KeyBpmMap/sessions/efd0cbb5-7232-466f-bce1-0868308f4de1
Co-authored-by: samsta <3915450+samsta@users.noreply.github.com>
---
docs/screenshots/vector-pdf-legend-scale.png | Bin 0 -> 394622 bytes
src/components/HeatmapChart.tsx | 25 ++++++++++++-------
src/components/PolarDensityChart.tsx | 25 ++++++++++++-------
3 files changed, 32 insertions(+), 18 deletions(-)
create mode 100644 docs/screenshots/vector-pdf-legend-scale.png
diff --git a/docs/screenshots/vector-pdf-legend-scale.png b/docs/screenshots/vector-pdf-legend-scale.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2537ebab5e7b54cdfddf7953741bb961f516399
GIT binary patch
literal 394622
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