mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 11:08:12 +00:00
fix contrat,wagon allocation wehn a booking is split
This commit is contained in:
@@ -3,6 +3,10 @@ import Handlebars from 'handlebars';
|
||||
/** One numbered clause of a dynamic article, with optional nested bullets. */
|
||||
export interface RenderedClause {
|
||||
text: string;
|
||||
/** Computed outline number, e.g. "3" or "2.1.4". */
|
||||
number: string;
|
||||
/** Nesting level: 1 = clause, 2 = sub-clause (x.y), 3 = x.y.z, … */
|
||||
depth: number;
|
||||
bullets: string[];
|
||||
}
|
||||
|
||||
@@ -16,10 +20,26 @@ export interface RenderedArticle {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Leading outline token on a clause line: "1.", "2)", "1.1", "1.1.1." …
|
||||
* The token's segment count sets the clause depth; its digits are ignored —
|
||||
* numbering is recomputed sequentially so stale numbers self-heal.
|
||||
* A single-segment token requires its "."/")" ("10 tons…" is prose, "10. x"
|
||||
* is clause ten); multi-segment tokens ("1.1") may omit it. A token may also
|
||||
* end the line — that is an empty clause still being typed in the editor.
|
||||
*/
|
||||
const CLAUSE_NUMBER_RE = /^(?:(\d+(?:\.\d+)+)[.)]?|(\d+)[.)])(?:\s+|$)/;
|
||||
|
||||
/** Deepest supported sub-clause level (1.1.1.1.1.1). */
|
||||
const MAX_CLAUSE_DEPTH = 6;
|
||||
|
||||
/**
|
||||
* Parse a template article body into clauses. Format: one clause per line.
|
||||
* A leading outline number ("2. ", "2.1 ", "2.1.3 ") nests the line as a
|
||||
* sub-clause at that depth — the typed digits are stripped and renumbered
|
||||
* sequentially, so editing order never leaves stale numbers in the document.
|
||||
* Lines prefixed with "- " become bullets nested under the preceding clause.
|
||||
* A body that reduces to a single un-numbered 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 ?? '')
|
||||
@@ -28,20 +48,44 @@ export function parseArticleBody(body: string): Pick<RenderedArticle, 'paragraph
|
||||
.filter((line) => line.length > 0);
|
||||
|
||||
const clauses: RenderedClause[] = [];
|
||||
// counters[i] = current number at depth i+1; truncated when a shallower
|
||||
// clause arrives so deeper numbering restarts at 1.
|
||||
const counters: number[] = [];
|
||||
let sawNumberToken = false;
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('- ')) {
|
||||
const bullet = line.slice(2).trim();
|
||||
if (clauses.length === 0) {
|
||||
clauses.push({ text: bullet, bullets: [] });
|
||||
counters.splice(0, counters.length, 1);
|
||||
clauses.push({ text: bullet, number: '1', depth: 1, bullets: [] });
|
||||
} else {
|
||||
clauses[clauses.length - 1].bullets.push(bullet);
|
||||
}
|
||||
} else {
|
||||
clauses.push({ text: line, bullets: [] });
|
||||
continue;
|
||||
}
|
||||
|
||||
const match = CLAUSE_NUMBER_RE.exec(line);
|
||||
const token = match ? (match[1] ?? match[2]) : null;
|
||||
let depth = token ? Math.min(token.split('.').length, MAX_CLAUSE_DEPTH) : 1;
|
||||
// A sub-clause can only sit directly under an existing parent — "1.1.1"
|
||||
// typed as the first line clamps to whatever level is actually open.
|
||||
depth = Math.min(depth, counters.length + 1);
|
||||
if (match) sawNumberToken = true;
|
||||
|
||||
counters.splice(depth);
|
||||
while (counters.length < depth) counters.push(0);
|
||||
counters[depth - 1] += 1;
|
||||
|
||||
clauses.push({
|
||||
text: match ? line.slice(match[0].length).trim() : line,
|
||||
number: counters.slice(0, depth).join('.'),
|
||||
depth,
|
||||
bullets: [],
|
||||
});
|
||||
}
|
||||
|
||||
if (clauses.length === 1 && clauses[0].bullets.length === 0) {
|
||||
if (clauses.length === 1 && clauses[0].bullets.length === 0 && !sawNumberToken) {
|
||||
return { paragraph: clauses[0].text, clauses: [] };
|
||||
}
|
||||
return { clauses };
|
||||
|
||||
Reference in New Issue
Block a user