mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 07:10:57 +00:00
make a contrat template
This commit is contained in:
63
apps/edr-freight-api/src/contracts/contract-article.util.ts
Normal file
63
apps/edr-freight-api/src/contracts/contract-article.util.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import Handlebars from 'handlebars';
|
||||
|
||||
/** One numbered clause of a dynamic article, with optional nested bullets. */
|
||||
export interface RenderedClause {
|
||||
text: string;
|
||||
bullets: string[];
|
||||
}
|
||||
|
||||
/** A dynamic article ready for the Handlebars template. */
|
||||
export interface RenderedArticle {
|
||||
number: number;
|
||||
title: string;
|
||||
/** Set (instead of clauses) when the body is a single plain paragraph. */
|
||||
paragraph?: string;
|
||||
clauses: RenderedClause[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a template article body into clauses. Format: one clause per line;
|
||||
* lines prefixed with "- " become bullets nested under the preceding clause.
|
||||
* A body that reduces to a single clause without bullets renders as a plain
|
||||
* paragraph rather than a numbered list of one.
|
||||
*/
|
||||
export function parseArticleBody(body: string): Pick<RenderedArticle, 'paragraph' | 'clauses'> {
|
||||
const lines = (body ?? '')
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0);
|
||||
|
||||
const clauses: RenderedClause[] = [];
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('- ')) {
|
||||
const bullet = line.slice(2).trim();
|
||||
if (clauses.length === 0) {
|
||||
clauses.push({ text: bullet, bullets: [] });
|
||||
} else {
|
||||
clauses[clauses.length - 1].bullets.push(bullet);
|
||||
}
|
||||
} else {
|
||||
clauses.push({ text: line, bullets: [] });
|
||||
}
|
||||
}
|
||||
|
||||
if (clauses.length === 1 && clauses[0].bullets.length === 0) {
|
||||
return { paragraph: clauses[0].text, clauses: [] };
|
||||
}
|
||||
return { clauses };
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate Handlebars placeholders ({{client.companyName}}, {{contractDate}},
|
||||
* …) inside admin-authored template text against the contract view model.
|
||||
* Malformed placeholders must never break document generation — fall back to
|
||||
* the raw text.
|
||||
*/
|
||||
export function interpolateTemplateText(text: string, context: unknown): string {
|
||||
if (!text || !text.includes('{{')) return text ?? '';
|
||||
try {
|
||||
return Handlebars.compile(text)(context);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user