From 40c2ecc065d2dd7e70c79ec3c62f56c3b79deb2d Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:02:51 +0000 Subject: [PATCH 1/5] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/lib/docx-pleading.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/docx-pleading.ts b/src/lib/docx-pleading.ts index e9030aa..cd8cf66 100644 --- a/src/lib/docx-pleading.ts +++ b/src/lib/docx-pleading.ts @@ -13,6 +13,7 @@ import { BorderStyle, Footer, LevelFormat, + PageNumber, } from "docx"; import pkg from "file-saver"; const { saveAs } = pkg; @@ -33,6 +34,9 @@ export interface PleadingInput { bodyHtml?: string; // rich HTML body body?: string; // legacy plain text fallback footnotes?: PleadingFootnote[]; + footerLeft?: string; + footerCenter?: string; + footerRight?: string; // user text prepended to "Page X of Y" } const FONT = "Bookman Old Style"; From eee182b0e5ca476d1d0aeee060a444c25bfb326a Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:02:58 +0000 Subject: [PATCH 2/5] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/lib/docx-pleading.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/docx-pleading.ts b/src/lib/docx-pleading.ts index cd8cf66..32725fe 100644 --- a/src/lib/docx-pleading.ts +++ b/src/lib/docx-pleading.ts @@ -301,7 +301,7 @@ export function buildPleadingDoc(input: PleadingInput): Document { }, footers: { default: new Footer({ - children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [run("")] })], + children: [buildFooterTable(input.footerLeft, input.footerCenter, input.footerRight)], }), }, children: [ From 59ea9c7d1f86a7c55443536e5965b07b0dc73b0e Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:03:10 +0000 Subject: [PATCH 3/5] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/lib/docx-pleading.ts | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/lib/docx-pleading.ts b/src/lib/docx-pleading.ts index 32725fe..e994a14 100644 --- a/src/lib/docx-pleading.ts +++ b/src/lib/docx-pleading.ts @@ -183,6 +183,54 @@ function htmlToParagraphs(html: string): Paragraph[] { return out; } +function footerCell(width: number, align: (typeof AlignmentType)[keyof typeof AlignmentType], children: TextRun[]) { + return new TableCell({ + width: { size: width, type: WidthType.DXA }, + borders: noBorder, + margins: { top: 40, bottom: 40, left: 60, right: 60 }, + children: [ + new Paragraph({ + alignment: align, + children: children.length ? children : [run("")], + }), + ], + }); +} + +function buildFooterTable(left?: string, center?: string, right?: string): Table { + const total = 9360; + const col = Math.floor(total / 3); + const cols = [col, col, total - 2 * col]; + + const leftRuns: TextRun[] = left ? [run(left, { size: 20 })] : []; + const centerRuns: TextRun[] = center ? [run(center, { size: 20 })] : []; + + // Right column: optional user text + always "Page X of Y" + const rightRuns: TextRun[] = []; + if (right && right.trim()) { + rightRuns.push(run(`${right} `, { size: 20 })); + } + rightRuns.push(run("Page ", { size: 20 })); + rightRuns.push(new TextRun({ children: [PageNumber.CURRENT], font: FONT, size: 20 })); + rightRuns.push(run(" of ", { size: 20 })); + rightRuns.push(new TextRun({ children: [PageNumber.TOTAL_PAGES], font: FONT, size: 20 })); + + return new Table({ + width: { size: total, type: WidthType.DXA }, + columnWidths: cols, + borders: noBorder, + rows: [ + new TableRow({ + children: [ + footerCell(cols[0], AlignmentType.LEFT, leftRuns), + footerCell(cols[1], AlignmentType.CENTER, centerRuns), + footerCell(cols[2], AlignmentType.RIGHT, rightRuns), + ], + }), + ], + }); +} + export function buildPleadingDoc(input: PleadingInput): Document { const headerLine1 = `IN THE ${input.courtType} COURT OF THE ${input.circuit} JUDICIAL CIRCUIT,`; const headerLine2 = `IN AND FOR ${input.county.toUpperCase()} COUNTY, FLORIDA`; From f1a2718a20da9a06755ca577beb0ed61c808ac72 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:03:25 +0000 Subject: [PATCH 4/5] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/documents.pleading.new.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/routes/documents.pleading.new.tsx b/src/routes/documents.pleading.new.tsx index 8daf654..3a56b0b 100644 --- a/src/routes/documents.pleading.new.tsx +++ b/src/routes/documents.pleading.new.tsx @@ -35,6 +35,9 @@ function PleadingNewPage() { const [title, setTitle] = useState(""); const [bodyHtml, setBodyHtml] = useState("
"); const [footnotes, setFootnotes] = useState
+ Three columns. The right column always ends with Page X of Y.
+