@flowselections/layout-maker 1.36.7 → 1.45.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/AfleverbriefBuilderPage.d.ts +10 -0
- package/dist-lib/components/AfleverbriefBuilderPage.d.ts.map +1 -0
- package/dist-lib/components/AfleverbriefBuilderPage.js +101 -0
- package/dist-lib/components/BlokOntwerperPage.d.ts.map +1 -1
- package/dist-lib/components/BlokOntwerperPage.js +8 -3
- package/dist-lib/components/ComputersLijst.d.ts.map +1 -1
- package/dist-lib/components/ComputersLijst.js +1 -1
- package/dist-lib/components/FustKolomVolgorde.d.ts +11 -0
- package/dist-lib/components/FustKolomVolgorde.d.ts.map +1 -0
- package/dist-lib/components/FustKolomVolgorde.js +52 -0
- package/dist-lib/components/LayoutsPage.d.ts.map +1 -1
- package/dist-lib/components/LayoutsPage.js +10 -9
- package/dist-lib/components/PaginaDocument.d.ts +4 -1
- package/dist-lib/components/PaginaDocument.d.ts.map +1 -1
- package/dist-lib/components/PaginaDocument.js +10 -5
- package/dist-lib/components/PakbonBuilderPage.d.ts.map +1 -1
- package/dist-lib/components/PakbonBuilderPage.js +34 -14
- package/dist-lib/components/PakbonPreview.d.ts +4 -2
- package/dist-lib/components/PakbonPreview.d.ts.map +1 -1
- package/dist-lib/components/PakbonPreview.js +74 -24
- package/dist-lib/components/PakbonSectiesPanel.d.ts +5 -3
- package/dist-lib/components/PakbonSectiesPanel.d.ts.map +1 -1
- package/dist-lib/components/PakbonSectiesPanel.js +8 -5
- package/dist-lib/components/PdfMapToestemmingBanner.d.ts +2 -1
- package/dist-lib/components/PdfMapToestemmingBanner.d.ts.map +1 -1
- package/dist-lib/components/PdfMapToestemmingBanner.js +73 -14
- package/dist-lib/components/PdfVoorbeeld.d.ts +20 -0
- package/dist-lib/components/PdfVoorbeeld.d.ts.map +1 -0
- package/dist-lib/components/PdfVoorbeeld.js +95 -0
- package/dist-lib/components/PrintProgrammaUitleg.d.ts.map +1 -1
- package/dist-lib/components/PrintProgrammaUitleg.js +1 -1
- package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
- package/dist-lib/components/PrintQueuePage.js +81 -43
- package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
- package/dist-lib/components/PrintplekDetailPage.js +2 -2
- package/dist-lib/components/PrintplekWizard.d.ts.map +1 -1
- package/dist-lib/components/PrintplekWizard.js +6 -2
- package/dist-lib/components/ProductiebonBuilderPage.d.ts.map +1 -1
- package/dist-lib/components/ProductiebonBuilderPage.js +13 -7
- package/dist-lib/index.d.ts +16 -6
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +11 -5
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +3585 -1267
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +3585 -1267
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/moduleClient.d.ts +25898 -0
- package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/moduleClient.js +29 -0
- package/dist-lib/integrations/supabase/types.d.ts +3607 -1265
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/aiLayout.functions.d.ts +3585 -1267
- package/dist-lib/lib/aiLayout.functions.d.ts.map +1 -1
- package/dist-lib/lib/code128.d.ts +5 -0
- package/dist-lib/lib/code128.d.ts.map +1 -0
- package/dist-lib/lib/code128.js +51 -0
- package/dist-lib/lib/documentVoorbeeld.functions.d.ts +23 -0
- package/dist-lib/lib/documentVoorbeeld.functions.d.ts.map +1 -0
- package/dist-lib/lib/documentVoorbeeld.functions.js +37 -0
- package/dist-lib/lib/fontMetrics.d.ts +15 -0
- package/dist-lib/lib/fontMetrics.d.ts.map +1 -0
- package/dist-lib/lib/fontMetrics.js +118 -0
- package/dist-lib/lib/htmlNaarPdf.server.d.ts +2 -2
- package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlNaarPdf.server.js +2 -1
- package/dist-lib/lib/htmlPdf.server.d.ts +11 -0
- package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlPdf.server.js +170 -9
- package/dist-lib/lib/layoutPreview.d.ts.map +1 -1
- package/dist-lib/lib/layoutPreview.js +6 -3
- package/dist-lib/lib/orderData.server.d.ts.map +1 -1
- package/dist-lib/lib/orderData.server.js +49 -16
- package/dist-lib/lib/pakbonBarcodeVerzoek.d.ts +39 -0
- package/dist-lib/lib/pakbonBarcodeVerzoek.d.ts.map +1 -0
- package/dist-lib/lib/pakbonBarcodeVerzoek.js +80 -0
- package/dist-lib/lib/pakbonBuilder.d.ts +90 -5
- package/dist-lib/lib/pakbonBuilder.d.ts.map +1 -1
- package/dist-lib/lib/pakbonBuilder.js +455 -58
- package/dist-lib/lib/pakbonContent.d.ts +41 -0
- package/dist-lib/lib/pakbonContent.d.ts.map +1 -0
- package/dist-lib/lib/pakbonContent.js +668 -0
- package/dist-lib/lib/pakbonDocument.d.ts +199 -0
- package/dist-lib/lib/pakbonDocument.d.ts.map +1 -0
- package/dist-lib/lib/pakbonDocument.js +735 -0
- package/dist-lib/lib/pakbonHtml.d.ts +21 -2
- package/dist-lib/lib/pakbonHtml.d.ts.map +1 -1
- package/dist-lib/lib/pakbonHtml.js +144 -36
- package/dist-lib/lib/pakbonPresentation.d.ts +8 -0
- package/dist-lib/lib/pakbonPresentation.d.ts.map +1 -0
- package/dist-lib/lib/pakbonPresentation.js +31 -0
- package/dist-lib/lib/pakbonScan.d.ts +44 -0
- package/dist-lib/lib/pakbonScan.d.ts.map +1 -0
- package/dist-lib/lib/pakbonScan.js +87 -0
- package/dist-lib/lib/pdfJobSaver.d.ts +10 -6
- package/dist-lib/lib/pdfJobSaver.d.ts.map +1 -1
- package/dist-lib/lib/pdfJobSaver.js +302 -99
- package/dist-lib/lib/pdfMap.d.ts +37 -2
- package/dist-lib/lib/pdfMap.d.ts.map +1 -1
- package/dist-lib/lib/pdfMap.js +120 -7
- package/dist-lib/lib/pdfOpslagStatus.d.ts +23 -0
- package/dist-lib/lib/pdfOpslagStatus.d.ts.map +1 -0
- package/dist-lib/lib/pdfOpslagStatus.js +74 -0
- package/dist-lib/lib/printApi.d.ts +31 -0
- package/dist-lib/lib/printApi.d.ts.map +1 -1
- package/dist-lib/lib/printApi.js +62 -1
- package/dist-lib/lib/printQueue.server.d.ts +13 -0
- package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/printQueue.server.js +673 -96
- package/dist-lib/lib/printService.functions.d.ts +11840 -2568
- package/dist-lib/lib/printService.functions.d.ts.map +1 -1
- package/dist-lib/lib/profielHtml.d.ts.map +1 -1
- package/dist-lib/lib/profielHtml.js +8 -1
- package/dist-lib/lib/supabaseClient.d.ts +1 -3
- package/dist-lib/lib/supabaseClient.d.ts.map +1 -1
- package/dist-lib/lib/supabaseClient.js +4 -8
- package/dist-lib/lib/useDocumentData.d.ts +8 -0
- package/dist-lib/lib/useDocumentData.d.ts.map +1 -1
- package/dist-lib/lib/useDocumentData.js +1 -1
- package/dist-lib/lib/voorbeeldPrint.d.ts +3 -0
- package/dist-lib/lib/voorbeeldPrint.d.ts.map +1 -1
- package/dist-lib/lib/voorbeeldPrint.js +65 -17
- package/package.json +9 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code128.d.ts","sourceRoot":"","sources":["../../src/lib/code128.ts"],"names":[],"mappings":"AAkBA,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBjD;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQrD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Code 128 subset B — compacte, scanbare barcode voor printdocumenten.
|
|
3
|
+
// ============================================================================
|
|
4
|
+
const PATRONEN = [
|
|
5
|
+
"212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212", "221213",
|
|
6
|
+
"221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221", "223211", "221132",
|
|
7
|
+
"221231", "213212", "223112", "312131", "311222", "321122", "321221", "312212", "322112", "322211",
|
|
8
|
+
"212123", "212321", "232121", "111323", "131123", "131321", "112313", "132113", "132311", "211313",
|
|
9
|
+
"231113", "231311", "112133", "112331", "132131", "113123", "113321", "133121", "313121", "211331",
|
|
10
|
+
"231131", "213113", "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111",
|
|
11
|
+
"314111", "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
|
|
12
|
+
"112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111",
|
|
13
|
+
"111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141",
|
|
14
|
+
"214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311", "113141",
|
|
15
|
+
"114131", "311141", "411131", "211412", "211214", "211232", "2331112",
|
|
16
|
+
];
|
|
17
|
+
/** Geeft de zwart/wit modules van Code 128 subset B terug. */
|
|
18
|
+
export function code128Bars(value) {
|
|
19
|
+
const tekst = String(value ?? "");
|
|
20
|
+
if (!tekst)
|
|
21
|
+
return "";
|
|
22
|
+
const codes = Array.from(tekst, (teken) => {
|
|
23
|
+
const code = teken.charCodeAt(0);
|
|
24
|
+
return code >= 32 && code <= 126 ? code - 32 : "?".charCodeAt(0) - 32;
|
|
25
|
+
});
|
|
26
|
+
const checksum = codes.reduce((som, code, index) => som + code * (index + 1), 104) % 103;
|
|
27
|
+
const symbolen = [104, ...codes, checksum, 106];
|
|
28
|
+
return symbolen
|
|
29
|
+
.map((symbool) => {
|
|
30
|
+
const patroon = PATRONEN[symbool] ?? PATRONEN[0];
|
|
31
|
+
let zwart = true;
|
|
32
|
+
return Array.from(patroon, (breedte) => {
|
|
33
|
+
const modules = Number(breedte);
|
|
34
|
+
const resultaat = (zwart ? "1" : "0").repeat(modules);
|
|
35
|
+
zwart = !zwart;
|
|
36
|
+
return resultaat;
|
|
37
|
+
}).join("");
|
|
38
|
+
})
|
|
39
|
+
.join("");
|
|
40
|
+
}
|
|
41
|
+
/** Browserweergave van de barcode zonder externe barcodebibliotheek. */
|
|
42
|
+
export function code128BarsHtml(value) {
|
|
43
|
+
const bars = code128Bars(value);
|
|
44
|
+
if (!bars)
|
|
45
|
+
return "";
|
|
46
|
+
const modules = bars.length;
|
|
47
|
+
return bars
|
|
48
|
+
.split("")
|
|
49
|
+
.map((bar) => `<span style="display:block;flex:0 0 ${100 / modules}%;height:100%;background:${bar === "1" ? "#111827" : "transparent"}"></span>`)
|
|
50
|
+
.join("");
|
|
51
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface VoorbeeldPdfInvoer {
|
|
2
|
+
html: string;
|
|
3
|
+
breedteMm: number;
|
|
4
|
+
hoogteMm: number;
|
|
5
|
+
margeMm: number;
|
|
6
|
+
paginanummers?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Rendert print-HTML met exact dezelfde servercode als de printwachtrij, zodat
|
|
10
|
+
* het voorbeeld in de editor letterlijk de PDF is die straks wordt geprint.
|
|
11
|
+
* Er wordt niets opgeslagen en geen printopdracht aangemaakt.
|
|
12
|
+
*/
|
|
13
|
+
export declare const maakVoorbeeldPdf: import("@tanstack/start-client-core").RequiredFetcher<undefined, (invoer: VoorbeeldPdfInvoer) => {
|
|
14
|
+
html: string;
|
|
15
|
+
breedteMm: number;
|
|
16
|
+
hoogteMm: number;
|
|
17
|
+
margeMm: number;
|
|
18
|
+
paginanummers: boolean | undefined;
|
|
19
|
+
}, Promise<{
|
|
20
|
+
pdfBase64: string;
|
|
21
|
+
bytes: number;
|
|
22
|
+
}>>;
|
|
23
|
+
//# sourceMappingURL=documentVoorbeeld.functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentVoorbeeld.functions.d.ts","sourceRoot":"","sources":["../../src/lib/documentVoorbeeld.functions.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,4EACF,kBAAkB;;;;;;;;;GA2BzC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
2
|
+
/**
|
|
3
|
+
* Rendert print-HTML met exact dezelfde servercode als de printwachtrij, zodat
|
|
4
|
+
* het voorbeeld in de editor letterlijk de PDF is die straks wordt geprint.
|
|
5
|
+
* Er wordt niets opgeslagen en geen printopdracht aangemaakt.
|
|
6
|
+
*/
|
|
7
|
+
export const maakVoorbeeldPdf = createServerFn({ method: "POST" })
|
|
8
|
+
.inputValidator((invoer) => {
|
|
9
|
+
const html = String(invoer?.html ?? "");
|
|
10
|
+
if (!html.trim())
|
|
11
|
+
throw new Error("Voorbeeld kan niet worden gemaakt: geen HTML aangeleverd.");
|
|
12
|
+
// Pakbonnen met ingesloten logo's/barcodes (data-URI's) worden snel groot;
|
|
13
|
+
// de grens is er alleen om echt onwerkbare invoer te weren.
|
|
14
|
+
if (html.length > 40000000)
|
|
15
|
+
throw new Error("Voorbeeld te groot om te renderen.");
|
|
16
|
+
const breedteMm = Number(invoer?.breedteMm);
|
|
17
|
+
const hoogteMm = Number(invoer?.hoogteMm);
|
|
18
|
+
const margeMm = Number(invoer?.margeMm);
|
|
19
|
+
if (!Number.isFinite(breedteMm) || breedteMm <= 0 || !Number.isFinite(hoogteMm) || hoogteMm <= 0) {
|
|
20
|
+
throw new Error("Voorbeeld kan niet worden gemaakt: papierformaat ontbreekt.");
|
|
21
|
+
}
|
|
22
|
+
if (!Number.isFinite(margeMm) || margeMm < 0 || margeMm * 2 >= Math.min(breedteMm, hoogteMm)) {
|
|
23
|
+
throw new Error("Voorbeeld kan niet worden gemaakt: de ingestelde paginamarge is ongeldig.");
|
|
24
|
+
}
|
|
25
|
+
return { html, breedteMm, hoogteMm, margeMm, paginanummers: invoer?.paginanummers };
|
|
26
|
+
})
|
|
27
|
+
.handler(async ({ data }) => {
|
|
28
|
+
const { htmlNaarPdfBytes, bytesNaarBase64 } = await import("./htmlPdf.server.js");
|
|
29
|
+
const bytes = await htmlNaarPdfBytes({
|
|
30
|
+
html: data.html,
|
|
31
|
+
breedteMm: data.breedteMm,
|
|
32
|
+
hoogteMm: data.hoogteMm,
|
|
33
|
+
margeMm: data.margeMm,
|
|
34
|
+
...(typeof data.paginanummers === "boolean" ? { paginanummers: data.paginanummers } : {}),
|
|
35
|
+
});
|
|
36
|
+
return { pdfBase64: bytesNaarBase64(bytes), bytes: bytes.length };
|
|
37
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Breedte van tekst in punten bij een gegeven fontgrootte. */
|
|
2
|
+
export declare function tekstBreedtePt(tekst: string, groottePt: number, vet?: boolean): number;
|
|
3
|
+
/** Verhouding regelhoogte / fontgrootte; overal identiek. */
|
|
4
|
+
export declare const REGELHOOGTE_FACTOR = 1.25;
|
|
5
|
+
/** Regelhoogte in punten. */
|
|
6
|
+
export declare function regelHoogtePt(groottePt: number): number;
|
|
7
|
+
/**
|
|
8
|
+
* Breekt tekst af op woordgrenzen binnen een maximale breedte. Woorden die
|
|
9
|
+
* zelf te lang zijn worden hard afgebroken (net als overflow-wrap: anywhere).
|
|
10
|
+
* De uitkomst is de definitieve regelverdeling: renderers wrappen nooit zelf.
|
|
11
|
+
*/
|
|
12
|
+
export declare function breekAf(tekst: string, maxBreedtePt: number, groottePt: number, vet?: boolean): string[];
|
|
13
|
+
/** Kort tekst af tot één regel met beletselteken. */
|
|
14
|
+
export declare function kortAf(tekst: string, maxBreedtePt: number, groottePt: number, vet?: boolean): string;
|
|
15
|
+
//# sourceMappingURL=fontMetrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fontMetrics.d.ts","sourceRoot":"","sources":["../../src/lib/fontMetrics.ts"],"names":[],"mappings":"AA+CA,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,MAAM,CAKpF;AAED,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,6BAA6B;AAC7B,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,MAAM,EAAE,CA2CrG;AAED,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,MAAM,CAMlG"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/fontMetrics.ts — centrale fontmetriek voor de pakbon-layoutengine.
|
|
3
|
+
// ----------------------------------------------------------------------------
|
|
4
|
+
// Zowel het live voorbeeld (browser) als de PDF-motor (server) meten tekst met
|
|
5
|
+
// EXACT deze tabellen. Daardoor breekt tekst overal op dezelfde plek af en
|
|
6
|
+
// staan kolommen overal even breed. De waarden zijn de glyph-breedtes van
|
|
7
|
+
// Helvetica / Helvetica-Bold in duizendsten van de fontgrootte (WinAnsi,
|
|
8
|
+
// tekencodes 32 t/m 255) — precies wat de PDF-renderer gebruikt.
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/** Eerste tekencode in de tabellen. */
|
|
11
|
+
const EERSTE = 32;
|
|
12
|
+
const HELVETICA = [
|
|
13
|
+
278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556,
|
|
14
|
+
556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778,
|
|
15
|
+
667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556,
|
|
16
|
+
556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 0,
|
|
17
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
18
|
+
0, 0, 0, 0, 0, 0, 0, 0, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333,
|
|
19
|
+
400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722,
|
|
20
|
+
667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611,
|
|
21
|
+
556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584,
|
|
22
|
+
611, 556, 556, 556, 556, 500, 556, 500,
|
|
23
|
+
];
|
|
24
|
+
const HELVETICA_BOLD = [
|
|
25
|
+
278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556,
|
|
26
|
+
556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778,
|
|
27
|
+
667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611,
|
|
28
|
+
611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 0,
|
|
29
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
30
|
+
0, 0, 0, 0, 0, 0, 0, 0, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333,
|
|
31
|
+
400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722,
|
|
32
|
+
667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611,
|
|
33
|
+
556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584,
|
|
34
|
+
611, 611, 611, 611, 611, 556, 611, 556,
|
|
35
|
+
];
|
|
36
|
+
const ONBEKEND = 556; // breedte van "?" als terugval
|
|
37
|
+
function glyphBreedte(code, vet) {
|
|
38
|
+
const tabel = vet ? HELVETICA_BOLD : HELVETICA;
|
|
39
|
+
const w = tabel[code - EERSTE];
|
|
40
|
+
return typeof w === "number" && w > 0 ? w : ONBEKEND;
|
|
41
|
+
}
|
|
42
|
+
/** Breedte van tekst in punten bij een gegeven fontgrootte. */
|
|
43
|
+
export function tekstBreedtePt(tekst, groottePt, vet = false) {
|
|
44
|
+
let som = 0;
|
|
45
|
+
const s = String(tekst ?? "");
|
|
46
|
+
for (let i = 0; i < s.length; i++)
|
|
47
|
+
som += glyphBreedte(s.charCodeAt(i), vet);
|
|
48
|
+
return (som / 1000) * groottePt;
|
|
49
|
+
}
|
|
50
|
+
/** Verhouding regelhoogte / fontgrootte; overal identiek. */
|
|
51
|
+
export const REGELHOOGTE_FACTOR = 1.25;
|
|
52
|
+
/** Regelhoogte in punten. */
|
|
53
|
+
export function regelHoogtePt(groottePt) {
|
|
54
|
+
return groottePt * REGELHOOGTE_FACTOR;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Breekt tekst af op woordgrenzen binnen een maximale breedte. Woorden die
|
|
58
|
+
* zelf te lang zijn worden hard afgebroken (net als overflow-wrap: anywhere).
|
|
59
|
+
* De uitkomst is de definitieve regelverdeling: renderers wrappen nooit zelf.
|
|
60
|
+
*/
|
|
61
|
+
export function breekAf(tekst, maxBreedtePt, groottePt, vet = false) {
|
|
62
|
+
const bron = String(tekst ?? "").replace(/\s+/g, " ").trim();
|
|
63
|
+
if (!bron)
|
|
64
|
+
return [""];
|
|
65
|
+
if (maxBreedtePt <= 0)
|
|
66
|
+
return [bron];
|
|
67
|
+
const regels = [];
|
|
68
|
+
let huidig = "";
|
|
69
|
+
const duwHard = (woord) => {
|
|
70
|
+
let rest = woord;
|
|
71
|
+
while (rest.length) {
|
|
72
|
+
let n = rest.length;
|
|
73
|
+
while (n > 1 && tekstBreedtePt(rest.slice(0, n), groottePt, vet) > maxBreedtePt)
|
|
74
|
+
n--;
|
|
75
|
+
regels.push(rest.slice(0, n));
|
|
76
|
+
rest = rest.slice(n);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
for (const woord of bron.split(" ")) {
|
|
80
|
+
const kandidaat = huidig ? `${huidig} ${woord}` : woord;
|
|
81
|
+
if (tekstBreedtePt(kandidaat, groottePt, vet) <= maxBreedtePt) {
|
|
82
|
+
huidig = kandidaat;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (huidig) {
|
|
86
|
+
regels.push(huidig);
|
|
87
|
+
huidig = "";
|
|
88
|
+
}
|
|
89
|
+
if (tekstBreedtePt(woord, groottePt, vet) <= maxBreedtePt)
|
|
90
|
+
huidig = woord;
|
|
91
|
+
else {
|
|
92
|
+
const stukken = [];
|
|
93
|
+
let rest = woord;
|
|
94
|
+
while (rest.length) {
|
|
95
|
+
let n = rest.length;
|
|
96
|
+
while (n > 1 && tekstBreedtePt(rest.slice(0, n), groottePt, vet) > maxBreedtePt)
|
|
97
|
+
n--;
|
|
98
|
+
stukken.push(rest.slice(0, n));
|
|
99
|
+
rest = rest.slice(n);
|
|
100
|
+
}
|
|
101
|
+
huidig = stukken.pop() ?? "";
|
|
102
|
+
regels.push(...stukken);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (huidig)
|
|
106
|
+
regels.push(huidig);
|
|
107
|
+
return regels.length ? regels : [""];
|
|
108
|
+
}
|
|
109
|
+
/** Kort tekst af tot één regel met beletselteken. */
|
|
110
|
+
export function kortAf(tekst, maxBreedtePt, groottePt, vet = false) {
|
|
111
|
+
const s = String(tekst ?? "");
|
|
112
|
+
if (tekstBreedtePt(s, groottePt, vet) <= maxBreedtePt)
|
|
113
|
+
return s;
|
|
114
|
+
let n = s.length;
|
|
115
|
+
while (n > 1 && tekstBreedtePt(`${s.slice(0, n)}…`, groottePt, vet) > maxBreedtePt)
|
|
116
|
+
n--;
|
|
117
|
+
return `${s.slice(0, n)}…`;
|
|
118
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare class PdfRenderFout extends Error {
|
|
2
|
-
code: "niet_ingesteld" | "mislukt";
|
|
3
|
-
constructor(code: "niet_ingesteld" | "mislukt", boodschap: string);
|
|
2
|
+
code: "niet_ingesteld" | "mislukt" | "afwijking";
|
|
3
|
+
constructor(code: "niet_ingesteld" | "mislukt" | "afwijking", boodschap: string);
|
|
4
4
|
}
|
|
5
5
|
export interface PdfOpties {
|
|
6
6
|
html: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlNaarPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlNaarPdf.server.ts"],"names":[],"mappings":"AAQA,qBAAa,aAAc,SAAQ,KAAK;IAE7B,IAAI,EAAE,gBAAgB,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"htmlNaarPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlNaarPdf.server.ts"],"names":[],"mappings":"AAQA,qBAAa,aAAc,SAAQ,KAAK;IAE7B,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW;gBAAhD,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW,EACvD,SAAS,EAAE,MAAM;CAKpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,4DAA4D;AAC5D,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB1E"}
|
|
@@ -29,6 +29,7 @@ export async function htmlNaarPdfServer(opties) {
|
|
|
29
29
|
return bytesNaarBase64(bytes);
|
|
30
30
|
}
|
|
31
31
|
catch (e) {
|
|
32
|
-
|
|
32
|
+
const melding = e instanceof Error ? e.message : "PDF maken mislukte.";
|
|
33
|
+
throw new PdfRenderFout(melding.startsWith("Afdrukafwijking gevonden:") ? "afwijking" : "mislukt", melding.startsWith("Afdrukafwijking gevonden:") ? melding : `PDF maken mislukte: ${melding}`);
|
|
33
34
|
}
|
|
34
35
|
}
|
|
@@ -41,6 +41,17 @@ export interface DocumentPdfOpties {
|
|
|
41
41
|
/** Voettekst met paginanummers ("Pagina 1 van 3"). */
|
|
42
42
|
paginanummers?: boolean;
|
|
43
43
|
}
|
|
44
|
+
export interface PdfRenderDiagnostiek {
|
|
45
|
+
geldig: boolean;
|
|
46
|
+
fouten: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Bewaakt constructies die de eigen PDF-motor niet hetzelfde kan uitleggen als
|
|
50
|
+
* een browser. @page is toegestaan: papier en marge komen uit de canonieke
|
|
51
|
+
* DocumentPdfOpties. Andere at-rules en complexe selectors worden geweigerd in
|
|
52
|
+
* plaats van stilletjes genegeerd.
|
|
53
|
+
*/
|
|
54
|
+
export declare function controleerPdfOpmaak(html: string): PdfRenderDiagnostiek;
|
|
44
55
|
/** Zet print-HTML om naar een PDF en levert die als base64 (zonder prefix). */
|
|
45
56
|
export declare function htmlNaarPdfBytes(opties: DocumentPdfOpties): Promise<Uint8Array>;
|
|
46
57
|
export declare function bytesNaarBase64(bytes: Uint8Array): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlPdf.server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"htmlPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlPdf.server.ts"],"names":[],"mappings":"AAYA,OAAO,EAOL,KAAK,GAAG,EACT,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,EAAE,oBAAoB,CAAC;AAIpC,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAuC/C;AAUD,UAAU,SAAS;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AACD,UAAU,QAAQ;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AA2BD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAgClD;AAqBD,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAiBlE;AAKD,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAypCD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA8BtE;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6ErF;AA0BD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQzD"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// rijen naast elkaar, tabellen met vaste kolombreedtes, kaders, lijnen,
|
|
9
9
|
// afbeeldingen, barcodes en QR-vlakken.
|
|
10
10
|
// ============================================================================
|
|
11
|
+
import { code128Bars } from "./code128.js";
|
|
11
12
|
import { PDFDocument, StandardFonts, rgb, } from "pdf-lib";
|
|
12
13
|
export const MM = 2.834645669291339; // punten per millimeter
|
|
13
14
|
const LEEG = new Set(["img", "br", "hr", "col", "meta", "link", "input"]);
|
|
@@ -524,6 +525,16 @@ async function meetHoogte(ctx, n, vak, s) {
|
|
|
524
525
|
await tekenKinderen(meetCtx, { tag: "div", attrs: {}, kinderen: [n] }, vak, s);
|
|
525
526
|
});
|
|
526
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Meet uitsluitend de inhoud van een blok. Het blok zelf meemeten telt padding
|
|
530
|
+
* en marges dubbel; dan valt een achtergrondvlak zichtbaar te ver door.
|
|
531
|
+
*/
|
|
532
|
+
async function meetInhoud(ctx, n, vak, s) {
|
|
533
|
+
const meetCtx = { ...ctx, meten: true };
|
|
534
|
+
return ctx.tk.meet(async () => {
|
|
535
|
+
await tekenKinderen(meetCtx, n, vak, s);
|
|
536
|
+
});
|
|
537
|
+
}
|
|
527
538
|
function rijenVan(tabel) {
|
|
528
539
|
const rijen = [];
|
|
529
540
|
const loop = (k) => {
|
|
@@ -561,6 +572,25 @@ async function tekenBlok(ctx, n, vak, ouderStijl) {
|
|
|
561
572
|
const s = stijlVan(n, ouderStijl);
|
|
562
573
|
const st = eig(n);
|
|
563
574
|
const cl = klassen(n);
|
|
575
|
+
const barcode = eigenBarcodeWaarde(n);
|
|
576
|
+
if (barcode) {
|
|
577
|
+
const balkNode = zoekDirecteBarcodeNode(n);
|
|
578
|
+
const h = lengte(balkNode ? eig(balkNode)["height"] : st["height"]) ?? 15 * MM;
|
|
579
|
+
const onderschrift = heeft(n, "barcode") ? plattTekst(n).trim() : "";
|
|
580
|
+
const onderschriftStijl = { ...s, grootte: Math.min(s.grootte, 7), uitlijning: "center" };
|
|
581
|
+
const tekstHoogte = onderschrift ? regelHoogte(onderschriftStijl) : 0;
|
|
582
|
+
const barcodeBreedte = Math.min(45 * MM, vak.breedte);
|
|
583
|
+
const barcodeX = vak.x + Math.max(0, (vak.breedte - barcodeBreedte) / 2);
|
|
584
|
+
tk.zorgVoor(h + tekstHoogte + 1 * MM);
|
|
585
|
+
tekenBarcode(tk, barcode, barcodeX, barcodeBreedte, h);
|
|
586
|
+
tk.y -= h;
|
|
587
|
+
if (onderschrift) {
|
|
588
|
+
tk.y -= tekstHoogte;
|
|
589
|
+
tekenRegel(tk, onderschrift, vak.x, vak.breedte, tk.y + onderschriftStijl.grootte * 0.25, onderschriftStijl);
|
|
590
|
+
}
|
|
591
|
+
tk.y -= 1 * MM;
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
564
594
|
if (n.tag === "#tekst") {
|
|
565
595
|
const regels = breekAf(tk, n.tekst ?? "", s, vak.breedte);
|
|
566
596
|
for (const r of regels) {
|
|
@@ -686,7 +716,7 @@ async function tekenBlok(ctx, n, vak, ouderStijl) {
|
|
|
686
716
|
const heelHouden = cl.includes("heelhouden") || /avoid/.test(st["break-inside"] ?? st["page-break-inside"] ?? "");
|
|
687
717
|
const binnenVak = { x: vak.x + padding, breedte: vak.breedte - padding * 2 };
|
|
688
718
|
if (!ctx.meten && (heelHouden || achtergrond)) {
|
|
689
|
-
const nodig = (await
|
|
719
|
+
const nodig = (await meetInhoud(ctx, n, binnenVak, s)) + padding * 2;
|
|
690
720
|
if (heelHouden && nodig > tk.ruimte && nodig < tk.hoogte - tk.marge * 2) {
|
|
691
721
|
tk.nieuwePagina();
|
|
692
722
|
}
|
|
@@ -807,7 +837,18 @@ async function tekenTabel(ctx, tabel, vak, s) {
|
|
|
807
837
|
const cellen = rij.kinderen.filter((c) => c.tag === "td" || c.tag === "th");
|
|
808
838
|
const celBreedte = (i) => Math.max(4, (breedtes[i] ?? 20) - padX * 2);
|
|
809
839
|
const celTekst = cellen.map((c) => plattTekst(c));
|
|
810
|
-
|
|
840
|
+
// Eén verkleiningsfactor voor de hele rij: losse cellen die elk hun eigen
|
|
841
|
+
// maat kiezen leveren een rommelige, ongelijke kop- en gegevensregel op.
|
|
842
|
+
const ruwStijl = cellen.map((c) => stijlVan(c, s));
|
|
843
|
+
const factor = cellen.reduce((laagste, _c, i) => {
|
|
844
|
+
const basis = ruwStijl[i];
|
|
845
|
+
const passend = passendeStijl(tk, celTekst[i], basis, celBreedte(i));
|
|
846
|
+
return Math.min(laagste, passend.grootte / basis.grootte);
|
|
847
|
+
}, 1);
|
|
848
|
+
const cellenStijl = ruwStijl.map((st) => ({
|
|
849
|
+
...st,
|
|
850
|
+
grootte: Math.round(st.grootte * factor * 10) / 10,
|
|
851
|
+
}));
|
|
811
852
|
const teksten = cellen.map((_, i) => breekAf(tk, celTekst[i], cellenStijl[i], celBreedte(i)));
|
|
812
853
|
const hoogte = Math.max(regelHoogte(s), ...teksten.map((t, i) => Math.max(1, t.length) * regelHoogte(cellenStijl[i] ?? s))) + padY * 2;
|
|
813
854
|
if (hoogte > tk.ruimte) {
|
|
@@ -886,6 +927,17 @@ async function tekenAbsoluut(ctx, n, s) {
|
|
|
886
927
|
const hoogte = lengte(st["height"]) ?? regelHoogte(eigen);
|
|
887
928
|
const yBoven = tk.hoogte - top;
|
|
888
929
|
const yOnder = yBoven - hoogte;
|
|
930
|
+
const barcode = eigenBarcodeWaarde(n);
|
|
931
|
+
if (barcode) {
|
|
932
|
+
const barcodeHoogte = Math.max(5 * MM, hoogte * 0.72);
|
|
933
|
+
tekenBarcode(tk, barcode, x, breedte, barcodeHoogte, yBoven);
|
|
934
|
+
const onderschrift = plattTekst(n).trim();
|
|
935
|
+
if (onderschrift) {
|
|
936
|
+
const kleinStijl = { ...eigen, grootte: Math.min(eigen.grootte, 7), uitlijning: "center" };
|
|
937
|
+
tekenRegel(tk, onderschrift, x, breedte, yOnder + 1, kleinStijl);
|
|
938
|
+
}
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
889
941
|
const gradientKind = zoekGradient(n);
|
|
890
942
|
if (gradientKind) {
|
|
891
943
|
const gebied = gradientKind === "streepjes" ? hoogte * 0.72 : Math.min(breedte, hoogte);
|
|
@@ -1005,6 +1057,62 @@ async function tekenAbsoluut(ctx, n, s) {
|
|
|
1005
1057
|
tekenRegel(tk, r, x + padding, breedte - padding * 2, y + eigen.grootte * 0.25, eigen);
|
|
1006
1058
|
}
|
|
1007
1059
|
}
|
|
1060
|
+
/** Tekent de waarde-encoded Code 128 subset B barcode. */
|
|
1061
|
+
function tekenBarcode(tk, waarde, x, breedte, hoogte, yBoven) {
|
|
1062
|
+
const patroon = code128Bars(waarde);
|
|
1063
|
+
if (!patroon)
|
|
1064
|
+
return;
|
|
1065
|
+
const boven = yBoven ?? tk.y;
|
|
1066
|
+
const y = boven - hoogte;
|
|
1067
|
+
let start = 0;
|
|
1068
|
+
let zwart = patroon[0] === "1";
|
|
1069
|
+
for (let i = 1; i <= patroon.length; i += 1) {
|
|
1070
|
+
const huidig = patroon[i] === "1";
|
|
1071
|
+
if (i === patroon.length || huidig !== zwart) {
|
|
1072
|
+
if (zwart) {
|
|
1073
|
+
tk.pagina.drawRectangle({
|
|
1074
|
+
x: x + (start / patroon.length) * breedte,
|
|
1075
|
+
y,
|
|
1076
|
+
width: ((i - start) / patroon.length) * breedte,
|
|
1077
|
+
height: hoogte,
|
|
1078
|
+
color: DONKER,
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
start = i;
|
|
1082
|
+
zwart = huidig;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
/** Leest alleen expliciet door de renderer aangeleverde barcodewaarden. */
|
|
1087
|
+
function zoekBarcodeWaarde(n) {
|
|
1088
|
+
const waarde = String(n.attrs["data-barcode"] ?? "").trim();
|
|
1089
|
+
if (waarde)
|
|
1090
|
+
return waarde;
|
|
1091
|
+
for (const k of n.kinderen) {
|
|
1092
|
+
const diep = zoekBarcodeWaarde(k);
|
|
1093
|
+
if (diep)
|
|
1094
|
+
return diep;
|
|
1095
|
+
}
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
/** Barcode alleen wanneer dit element zelf de barcode of barcodecontainer is. */
|
|
1099
|
+
function eigenBarcodeWaarde(n) {
|
|
1100
|
+
const eigen = String(n.attrs["data-barcode"] ?? "").trim();
|
|
1101
|
+
if (eigen)
|
|
1102
|
+
return eigen;
|
|
1103
|
+
if (!heeft(n, "barcode"))
|
|
1104
|
+
return null;
|
|
1105
|
+
return zoekBarcodeWaarde(n);
|
|
1106
|
+
}
|
|
1107
|
+
function zoekDirecteBarcodeNode(n) {
|
|
1108
|
+
if (String(n.attrs["data-barcode"] ?? "").trim())
|
|
1109
|
+
return n;
|
|
1110
|
+
for (const kind of n.kinderen) {
|
|
1111
|
+
if (String(kind.attrs["data-barcode"] ?? "").trim())
|
|
1112
|
+
return kind;
|
|
1113
|
+
}
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1008
1116
|
/** Zoekt een streepjes- of blokjespatroon (barcode/QR) in de knoop of kinderen. */
|
|
1009
1117
|
function zoekGradient(n) {
|
|
1010
1118
|
const css = `${eig(n)["background"] ?? ""} ${eig(n)["background-image"] ?? ""}`;
|
|
@@ -1049,8 +1157,6 @@ async function tekenKinderen(ctx, n, vak, s) {
|
|
|
1049
1157
|
(/grid/.test(display) && kolommen.trim().split(/\s+/).length === 2);
|
|
1050
1158
|
const rijModus = /flex/.test(display) ||
|
|
1051
1159
|
cl.includes("kv") ||
|
|
1052
|
-
cl.includes("karkop") ||
|
|
1053
|
-
cl.includes("laagkop") ||
|
|
1054
1160
|
cl.includes("meta") ||
|
|
1055
1161
|
cl.includes("totalen") ||
|
|
1056
1162
|
cl.includes("regelrij");
|
|
@@ -1088,8 +1194,7 @@ async function tekenKinderen(ctx, n, vak, s) {
|
|
|
1088
1194
|
const spreiden = stukken.length > 1 &&
|
|
1089
1195
|
(verdeel === "space-between" ||
|
|
1090
1196
|
verdeel === "space-around" ||
|
|
1091
|
-
((!verdeel || verdeel === "normal") &&
|
|
1092
|
-
(cl.includes("kv") || cl.includes("karkop") || cl.includes("laagkop"))));
|
|
1197
|
+
((!verdeel || verdeel === "normal") && cl.includes("kv")));
|
|
1093
1198
|
const rechtsUit = verdeel === "flex-end" || verdeel === "right" || verdeel === "end";
|
|
1094
1199
|
if (spreiden) {
|
|
1095
1200
|
let x = vak.x;
|
|
@@ -1195,11 +1300,64 @@ async function laadAfbeeldingen(pdf, wortel) {
|
|
|
1195
1300
|
}));
|
|
1196
1301
|
return { beelden, fouten };
|
|
1197
1302
|
}
|
|
1303
|
+
/**
|
|
1304
|
+
* Bewaakt constructies die de eigen PDF-motor niet hetzelfde kan uitleggen als
|
|
1305
|
+
* een browser. @page is toegestaan: papier en marge komen uit de canonieke
|
|
1306
|
+
* DocumentPdfOpties. Andere at-rules en complexe selectors worden geweigerd in
|
|
1307
|
+
* plaats van stilletjes genegeerd.
|
|
1308
|
+
*/
|
|
1309
|
+
export function controleerPdfOpmaak(html) {
|
|
1310
|
+
const css = leesStylesheets(html).replace(/\/\*[\s\S]*?\*\//g, "");
|
|
1311
|
+
const fouten = new Set();
|
|
1312
|
+
for (const match of css.matchAll(/@([\w-]+)/g)) {
|
|
1313
|
+
const naam = String(match[1] ?? "").toLowerCase();
|
|
1314
|
+
if (naam !== "page")
|
|
1315
|
+
fouten.add(`CSS-regel @${naam} wordt niet ondersteund door de afdrukmotor.`);
|
|
1316
|
+
}
|
|
1317
|
+
let i = 0;
|
|
1318
|
+
while (i < css.length) {
|
|
1319
|
+
const open = css.indexOf("{", i);
|
|
1320
|
+
if (open < 0)
|
|
1321
|
+
break;
|
|
1322
|
+
const kop = css.slice(i, open).trim();
|
|
1323
|
+
let diepte = 0;
|
|
1324
|
+
let einde = open;
|
|
1325
|
+
for (; einde < css.length; einde += 1) {
|
|
1326
|
+
if (css[einde] === "{")
|
|
1327
|
+
diepte += 1;
|
|
1328
|
+
else if (css[einde] === "}") {
|
|
1329
|
+
diepte -= 1;
|
|
1330
|
+
if (!diepte)
|
|
1331
|
+
break;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
i = einde + 1;
|
|
1335
|
+
if (!kop || kop.startsWith("@"))
|
|
1336
|
+
continue;
|
|
1337
|
+
for (const selector of kop.split(",")) {
|
|
1338
|
+
if (!leesSelector(selector)) {
|
|
1339
|
+
fouten.add(`CSS-selector '${selector.trim()}' wordt niet ondersteund door de afdrukmotor.`);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
return { geldig: fouten.size === 0, fouten: [...fouten] };
|
|
1344
|
+
}
|
|
1198
1345
|
/** Zet print-HTML om naar een PDF en levert die als base64 (zonder prefix). */
|
|
1199
1346
|
export async function htmlNaarPdfBytes(opties) {
|
|
1200
1347
|
const bMm = Number(opties.breedteMm ?? 210);
|
|
1201
1348
|
const hMm = Number(opties.hoogteMm ?? 297);
|
|
1202
|
-
const
|
|
1349
|
+
const margeMm = Number(opties.margeMm ?? 10);
|
|
1350
|
+
if (!Number.isFinite(bMm) || !Number.isFinite(hMm) || bMm <= 0 || hMm <= 0) {
|
|
1351
|
+
throw new Error("Het papierformaat is ongeldig.");
|
|
1352
|
+
}
|
|
1353
|
+
if (!Number.isFinite(margeMm) || margeMm < 0 || margeMm * 2 >= Math.min(bMm, hMm)) {
|
|
1354
|
+
throw new Error("De paginamarge is ongeldig.");
|
|
1355
|
+
}
|
|
1356
|
+
const diagnostiek = controleerPdfOpmaak(opties.html);
|
|
1357
|
+
if (!diagnostiek.geldig) {
|
|
1358
|
+
throw new Error(`Afdrukafwijking gevonden: ${diagnostiek.fouten.join(" ")}`);
|
|
1359
|
+
}
|
|
1360
|
+
const marge = margeMm * MM;
|
|
1203
1361
|
const breedte = (opties.landschap ? Math.max(bMm, hMm) : Math.min(bMm, hMm)) * MM;
|
|
1204
1362
|
const hoogte = (opties.landschap ? Math.min(bMm, hMm) : Math.max(bMm, hMm)) * MM;
|
|
1205
1363
|
const pdf = await PDFDocument.create();
|
|
@@ -1210,6 +1368,9 @@ export async function htmlNaarPdfBytes(opties) {
|
|
|
1210
1368
|
// het document er hetzelfde uitziet als in het voorbeeld op het scherm.
|
|
1211
1369
|
stempelCss(wortel, ontleedCss(leesStylesheets(opties.html)));
|
|
1212
1370
|
const { beelden: afbeeldingen, fouten: beeldFouten } = await laadAfbeeldingen(pdf, wortel);
|
|
1371
|
+
if (beeldFouten.size) {
|
|
1372
|
+
throw new Error(`Afdrukafwijking gevonden: ${[...beeldFouten.values()].join(" ")}`);
|
|
1373
|
+
}
|
|
1213
1374
|
const basis = basisGrootte(opties.html);
|
|
1214
1375
|
const tk = new Tekenaar(pdf, breedte, hoogte, marge, normaal, vet);
|
|
1215
1376
|
const ctx = { tk, afbeeldingen, beeldFouten };
|
|
@@ -1234,8 +1395,8 @@ export async function htmlNaarPdfBytes(opties) {
|
|
|
1234
1395
|
}
|
|
1235
1396
|
// De layout bepaalt of paginanummers meegaan; zonder voorkeur alleen bij
|
|
1236
1397
|
// meerdere pagina's.
|
|
1237
|
-
const
|
|
1238
|
-
const nummers = opties.paginanummers ?? (
|
|
1398
|
+
const meta = /name=["']pdf-paginanummers["']\s+content=["'](ja|nee)["']/i.exec(opties.html)?.[1];
|
|
1399
|
+
const nummers = opties.paginanummers ?? (meta ? meta === "ja" : tk.paginas.length > 1);
|
|
1239
1400
|
if (nummers) {
|
|
1240
1401
|
tk.paginas.forEach((p, i) => {
|
|
1241
1402
|
const t = `Pagina ${i + 1} van ${tk.paginas.length}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layoutPreview.d.ts","sourceRoot":"","sources":["../../src/lib/layoutPreview.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"layoutPreview.d.ts","sourceRoot":"","sources":["../../src/lib/layoutPreview.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEvE,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIzD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAE5E;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAuB5F;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;GAI5B,CAAC;AA4FF,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,kBAAkB,EAAE,EAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAaR"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// src/lib/layoutPreview.ts — voorbeeldgegevens, veldvervanging en print-HTML
|
|
3
3
|
// ============================================================================
|
|
4
4
|
import { alleVelden } from "./fieldRegistry.js";
|
|
5
|
+
import { code128BarsHtml } from "./code128.js";
|
|
5
6
|
export function voorbeeldContext() {
|
|
6
7
|
const ctx = {};
|
|
7
8
|
for (const v of alleVelden())
|
|
@@ -79,9 +80,11 @@ function elementHtml(el, ctx) {
|
|
|
79
80
|
case "cirkel":
|
|
80
81
|
return `<div style="${base};border-radius:50%;border:${s.randbreedte || 0.3}mm solid ${s.randkleur ?? "#111827"}"></div>`;
|
|
81
82
|
case "barcode":
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
<div style="
|
|
83
|
+
return inhoud
|
|
84
|
+
? `<div style="${base};display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:monospace">
|
|
85
|
+
<div class="barcode-bars" data-barcode="${esc(inhoud)}" style="width:100%;height:70%;display:flex;background:#fff">${code128BarsHtml(inhoud)}</div>
|
|
86
|
+
<div style="font-size:7pt">${esc(inhoud)}</div></div>`
|
|
87
|
+
: "";
|
|
85
88
|
case "qrcode":
|
|
86
89
|
return `<div style="${base};background:repeating-conic-gradient(#111 0% 25%, #fff 0% 50%) 0 0/22% 22%"></div>`;
|
|
87
90
|
case "logo":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orderData.server.d.ts","sourceRoot":"","sources":["../../src/lib/orderData.server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE/B,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAwBtD,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAKvD;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG;IACrD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAgCA;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG;IAC7C,KAAK,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAMA;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,OAAO,EACX,MAAM,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC7E,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"orderData.server.d.ts","sourceRoot":"","sources":["../../src/lib/orderData.server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE/B,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAwBtD,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAKvD;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG;IACrD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAgCA;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG;IAC7C,KAAK,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAMA;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,OAAO,EACX,MAAM,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC7E,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CA8ZrB;AA+DD;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAGhG"}
|