Phase 1 / commit 12 of 14 — strips out the 571-line tiptap-to-pdfme
serializer and every code path that depended on it. TipTap document
templates remain as Documenso-template seed bodies; the CRM no longer
renders them to PDF in-app.
Deleted:
src/lib/pdf/tiptap-to-pdfme.ts (571 LOC)
src/lib/pdf/templates/eoi-standard-inapp.ts (337 LOC)
src/app/api/v1/admin/templates/preview/route.ts
src/app/api/v1/document-templates/[id]/generate/route.ts
src/app/api/v1/document-templates/[id]/generate-and-send/route.ts
src/lib/services/document-templates.ts:generateFromTemplate (~140 LOC)
src/lib/services/document-templates.ts:generateAndSend (~40 LOC)
src/lib/validators/document-templates.ts:generateAndSendSchema
src/lib/validators/document-templates.ts:previewAdminTemplateSchema
tests/unit/tiptap-serializer.test.ts (old bridge tests)
Preserved as src/lib/pdf/tiptap-validation.ts (~70 LOC):
- validateTipTapDocument() — still used to reject unsupported nodes
on save in the admin template editor
- TEMPLATE_VARIABLES — drives the merge-token picker in the
admin template form + preview UI
generateAndSign() now throws a clear ValidationError when a non-EOI
template tries the in-app pathway. Use a Documenso template, or wait
for the deferred AcroForm-fill admin-upload feature.
seed-data.ts: "Standard EOI (in-app)" template row now seeds with stub
bodyHtml + small MERGE_FIELDS array; the deleted HTML helper was never
actually rendered (in-app EOI is pdf-lib AcroForm fill on the source
PDF — generateEoiPdfFromTemplate, unchanged).
After this commit, pdfme has zero callers left. Commit 14 drops the
deps and the generate.ts shim.
1298/1298 vitest green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
2.5 KiB
TypeScript
72 lines
2.5 KiB
TypeScript
/**
|
|
* TipTap content validation helpers shared by the admin template editor
|
|
* and the document-template service. Surfaces unsupported node types so
|
|
* the admin gets a clear validation error before saving, and exports the
|
|
* `TEMPLATE_VARIABLES` catalog so the editor can offer token suggestions.
|
|
*
|
|
* Note: this file was the remaining sliver of the legacy 571-line
|
|
* `tiptap-to-pdfme.ts` bridge. The pdfme rendering path it once fed has
|
|
* been removed (see the PDF stack overhaul spec); only the validation +
|
|
* variable catalog survive because they're still useful for the
|
|
* Documenso-template-body editor UX.
|
|
*/
|
|
|
|
export interface TipTapMark {
|
|
type: string;
|
|
attrs?: Record<string, unknown>;
|
|
}
|
|
|
|
export interface TipTapNode {
|
|
type: string;
|
|
content?: TipTapNode[];
|
|
text?: string;
|
|
marks?: TipTapMark[];
|
|
attrs?: Record<string, unknown>;
|
|
}
|
|
|
|
const UNSUPPORTED_NODES = new Set([
|
|
'blockquote',
|
|
'codeBlock',
|
|
'horizontalRule',
|
|
'taskList',
|
|
'taskItem',
|
|
]);
|
|
|
|
export const TEMPLATE_VARIABLES: Array<{ key: string; label: string; example: string }> = [
|
|
{ key: 'client.name', label: 'Client Full Name', example: 'John Smith' },
|
|
{ key: 'client.company', label: 'Company Name', example: 'Smith Holdings' },
|
|
{ key: 'client.email', label: 'Client Email', example: 'john@smithholdings.com' },
|
|
{ key: 'client.phone', label: 'Client Phone', example: '+61 400 000 000' },
|
|
{ key: 'interest.stage', label: 'Pipeline Stage', example: 'Signed EOI/NDA' },
|
|
{ key: 'interest.berthNumber', label: 'Berth Number (from interest)', example: 'A23' },
|
|
{ key: 'berth.mooring_number', label: 'Berth Number', example: 'A23' },
|
|
{ key: 'berth.price', label: 'Berth Price', example: '$45,000' },
|
|
{ key: 'berth.tenure_type', label: 'Tenure Type', example: 'Freehold' },
|
|
{ key: 'port.name', label: 'Port Name', example: 'Port Nimara' },
|
|
{ key: 'port.currency', label: 'Port Currency', example: 'AUD' },
|
|
{ key: 'date.today', label: "Today's Date", example: '2026-03-15' },
|
|
{ key: 'date.year', label: 'Current Year', example: '2026' },
|
|
];
|
|
|
|
/**
|
|
* Recursively walks a TipTap node tree and collects any unsupported node types.
|
|
* Returns an array of unsupported type names found, or empty array if valid.
|
|
*/
|
|
export function validateTipTapDocument(doc: TipTapNode): string[] {
|
|
const found = new Set<string>();
|
|
|
|
function walk(node: TipTapNode): void {
|
|
if (UNSUPPORTED_NODES.has(node.type)) {
|
|
found.add(node.type);
|
|
}
|
|
if (node.content) {
|
|
for (const child of node.content) {
|
|
walk(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
walk(doc);
|
|
return Array.from(found);
|
|
}
|