From 197f13a83e8ed533710f9c042159494f0421c70e Mon Sep 17 00:00:00 2001 From: Duncan Murphy <97642890+WiDuMu@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:29:11 -0600 Subject: [PATCH 1/4] header outlines --- package.json | 4 ++-- src/index.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6f776fb..0e2eb07 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ ], "devDependencies": { "@types/mdast": "^4.0.4", - "@types/pdfkit": "^0.13.4", + "@types/pdfkit": "^0.17.4", "mdast": "^3.0.0", "pdfkit": "^0.15.0", "remark-parse": "^11.0.0", @@ -36,7 +36,7 @@ }, "peerDependencies": { "mdast": ">= 3.0.0 < 4.0.0", - "pdfkit": ">= 0.12.0 < 0.16.0" + "pdfkit": "^0.17.2" }, "optionalDependencies": { "mdast": "^3.0.0" diff --git a/src/index.ts b/src/index.ts index 5a162d6..cf44ca7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,8 @@ export interface PdfkitMarkdownSettings { headerGapBefore: (depth: number) => number; /** Function to determine gap size after a header by depth */ headerGapAfter: (depth: number) => number; + /** Add outlines (bookmarks) based on the header */ + displayHeaderOutlines: boolean; /** Throw error on unsupported markdown feature, otherwise silently ignored */ throwOnUnsupported: boolean; } @@ -58,6 +60,7 @@ export class MarkdownRenderer { headerFontSize: (h) => 20 - h * 1.5, headerGapBefore: () => 12, headerGapAfter: () => 8, + displayHeaderOutlines: true, fontSize: 10, throwOnUnsupported: false, }; @@ -74,10 +77,12 @@ export class MarkdownRenderer { render(tree: MDAST.Root) { this.doc.fontSize(this.settings.fontSize); this.updateFont(); + this.outlineStack = [ this.doc.outline ]; for (const c of tree.children) this.handleChild(c); } + private outlineStack: PDFKit.PDFOutline[] = []; private listIndent = 0; private bold = false; private italic = false; @@ -182,6 +187,13 @@ export class MarkdownRenderer { } private handleHeading(heading: MDAST.Heading) { + if (this.settings.displayHeaderOutlines) { + const text = heading.children.find(child => child.type == "text")?.value; + if (text) { + this.outlineStack.splice(heading.depth); + this.outlineStack.push(this.outlineStack[this.outlineStack.length - 1].addItem(text, { expanded: true })); + } + } this.doc.y += this.settings.headerGapBefore(heading.depth); this.doc.font(this.settings.headerFontName(heading.depth)); this.doc.fontSize(this.settings.headerFontSize(heading.depth)); From 4875b15c67907a0920cb9289bf36bdcde6c281a4 Mon Sep 17 00:00:00 2001 From: Duncan Murphy <97642890+WiDuMu@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:05:35 -0600 Subject: [PATCH 2/4] comment --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index cf44ca7..c6c559f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -82,6 +82,7 @@ export class MarkdownRenderer { for (const c of tree.children) this.handleChild(c); } + /** Used to keep track of the context for bookmark purposes */ private outlineStack: PDFKit.PDFOutline[] = []; private listIndent = 0; private bold = false; From f9ae569538994faa8cf35af58d15d25e0d2ba5d5 Mon Sep 17 00:00:00 2001 From: Duncan Murphy <97642890+WiDuMu@users.noreply.github.com> Date: Fri, 9 Jan 2026 19:20:31 -0600 Subject: [PATCH 3/4] revert pdfkit version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e2eb07..0b7c50a 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ }, "peerDependencies": { "mdast": ">= 3.0.0 < 4.0.0", - "pdfkit": "^0.17.2" + "pdfkit": ">= 0.12.0 < 0.16.0" }, "optionalDependencies": { "mdast": "^3.0.0" From 9dd9fb873a2dbdb241690e95656181ea3a517dba Mon Sep 17 00:00:00 2001 From: Duncan Murphy <97642890+WiDuMu@users.noreply.github.com> Date: Fri, 9 Jan 2026 19:31:26 -0600 Subject: [PATCH 4/4] add progamatic filtering of outlines --- src/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 7ce152c..d86a26a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,8 +36,8 @@ export interface PdfkitMarkdownSettings { headerGapBefore: (depth: number) => number; /** Function to determine gap size after a header by depth */ headerGapAfter: (depth: number) => number; - /** Add outlines (bookmarks) based on the header */ - displayHeaderOutlines: boolean; + /** Add outlines (bookmarks) based on the header depth */ + headerOutlines: (depth:number) => boolean; /** Throw error on unsupported markdown feature, otherwise silently ignored */ throwOnUnsupported: boolean; } @@ -60,7 +60,7 @@ export class MarkdownRenderer { headerFontSize: (h) => 20 - h * 1.5, headerGapBefore: () => 12, headerGapAfter: () => 8, - displayHeaderOutlines: true, + headerOutlines: () => true, fontSize: 10, throwOnUnsupported: false, }; @@ -185,7 +185,7 @@ export class MarkdownRenderer { } private handleHeading(heading: MDAST.Heading) { - if (this.settings.displayHeaderOutlines) { + if (this.settings.headerOutlines(heading.depth)) { const text = heading.children.find(child => child.type == "text")?.value; if (text) { this.outlineStack.splice(heading.depth);