Import aus Monorepo (frischer Start)
All checks were successful
Build & Deploy / deploy (push) Successful in 10s
All checks were successful
Build & Deploy / deploy (push) Successful in 10s
This commit is contained in:
146
src/lib/page-layout.js
Normal file
146
src/lib/page-layout.js
Normal file
@@ -0,0 +1,146 @@
|
||||
const PX_PER_MM = 3.78; // 96dpi
|
||||
const FONT_SIZE_PX = 26;
|
||||
|
||||
// ── Formate: Defaults (Fallback) + datengetriebener Cache ───────────────────
|
||||
// Die Werte kommen zentral aus Directus (Collection render_formats) und werden
|
||||
// im Speicher gehalten (stündlich / manuell aufgefrischt via applyRenderFormats).
|
||||
// Ist Directus nicht erreichbar oder ein Format nicht hinterlegt, greifen die
|
||||
// eingebauten Defaults – die Generierung läuft also immer.
|
||||
const DEFAULT_LINE_LIMITS = { a4: 27, a6p: 14, a6l: 11 };
|
||||
const DEFAULT_FORMAT_LAYOUTS = {
|
||||
a4: { marginTopMm: 25, marginLeftMm: 20, lineHeightFactor: 1.35 },
|
||||
a6p: { marginTopMm: 8, marginLeftMm: 8, lineHeightFactor: 1.3 },
|
||||
a6l: { marginTopMm: 8, marginLeftMm: 8, marginRightMm: 14, lineHeightFactor: 1.2 },
|
||||
din_lang: { marginTopMm: 50, marginLeftMm: 10, lineHeightFactor: 1.2 },
|
||||
c6: { marginTopMm: 60, marginLeftMm: 10, lineHeightFactor: 1.2 },
|
||||
};
|
||||
const DEFAULT_PAGE_FORMATS = {
|
||||
a4: { widthMm: 210, heightMm: 297 },
|
||||
a6p: { widthMm: 105, heightMm: 148 },
|
||||
a6l: { widthMm: 148, heightMm: 105 },
|
||||
din_lang: { widthMm: 220, heightMm: 110 },
|
||||
c6: { widthMm: 162, heightMm: 114 },
|
||||
};
|
||||
|
||||
// Live-Cache (wird von applyRenderFormats ersetzt). Start = Defaults.
|
||||
let LINE_LIMITS = { ...DEFAULT_LINE_LIMITS };
|
||||
let FORMAT_LAYOUTS = { ...DEFAULT_FORMAT_LAYOUTS };
|
||||
let PAGE_FORMATS = { ...DEFAULT_PAGE_FORMATS };
|
||||
|
||||
/**
|
||||
* Übernimmt Format-Definitionen aus Directus (render_formats) in den Cache.
|
||||
* Baut immer auf den Defaults auf, damit Teilangaben nichts kaputt machen.
|
||||
* rows: [{ key, page_width_mm, page_height_mm, margin_top_mm, margin_left_mm,
|
||||
* margin_right_mm, line_height_factor, line_limit }]
|
||||
*/
|
||||
function applyRenderFormats(rows) {
|
||||
const pf = { ...DEFAULT_PAGE_FORMATS };
|
||||
const fl = { ...DEFAULT_FORMAT_LAYOUTS };
|
||||
const ll = { ...DEFAULT_LINE_LIMITS };
|
||||
for (const r of Array.isArray(rows) ? rows : []) {
|
||||
const k = String(r.key || '').toLowerCase();
|
||||
if (!k) continue;
|
||||
if (r.page_width_mm && r.page_height_mm) {
|
||||
pf[k] = { widthMm: Number(r.page_width_mm), heightMm: Number(r.page_height_mm) };
|
||||
}
|
||||
const alt = fl[k] || {};
|
||||
const layout = {
|
||||
marginTopMm: Number(r.margin_top_mm ?? alt.marginTopMm ?? 25),
|
||||
marginLeftMm: Number(r.margin_left_mm ?? alt.marginLeftMm ?? 20),
|
||||
lineHeightFactor: Number(r.line_height_factor ?? alt.lineHeightFactor ?? 1.35),
|
||||
};
|
||||
const mr = r.margin_right_mm ?? alt.marginRightMm;
|
||||
if (mr != null && mr !== '') layout.marginRightMm = Number(mr);
|
||||
fl[k] = layout;
|
||||
if (r.line_limit != null && r.line_limit !== '') ll[k] = Number(r.line_limit);
|
||||
}
|
||||
PAGE_FORMATS = pf;
|
||||
FORMAT_LAYOUTS = fl;
|
||||
LINE_LIMITS = ll;
|
||||
signaledMisses.clear();
|
||||
}
|
||||
|
||||
// mm in Pixel umrechnen
|
||||
function mmToPx(mm) {
|
||||
return mm * PX_PER_MM;
|
||||
}
|
||||
|
||||
// ── Refresh bei unbekanntem Format ──────────────────────────────────────────
|
||||
// Wird ein Format angefragt, das (noch) nicht im Cache liegt, meldet page-layout
|
||||
// das einmalig an einen Handler (den der Server auf refreshRenderFormats setzt).
|
||||
// So werden neu in Directus angelegte Formate sofort nachgeladen, ohne die
|
||||
// stündliche Aktualisierung abzuwarten. Für DIESEN Aufruf greift noch der
|
||||
// Default – der nächste Aufruf hat das Format.
|
||||
let missHandler = null;
|
||||
const signaledMisses = new Set();
|
||||
function setFormatMissHandler(fn) { missHandler = fn; }
|
||||
function signalMiss(key) {
|
||||
const k = String(key || '').toLowerCase();
|
||||
if (!missHandler || !k || signaledMisses.has(k)) return;
|
||||
signaledMisses.add(k);
|
||||
try { missHandler(k); } catch { /* egal */ }
|
||||
}
|
||||
|
||||
// Layout für Format holen
|
||||
function getLayoutForFormat(format) {
|
||||
const normalizedFormat = String(format).toLowerCase();
|
||||
const layoutConfig = FORMAT_LAYOUTS[normalizedFormat];
|
||||
if (!layoutConfig) signalMiss(normalizedFormat);
|
||||
|
||||
if (!layoutConfig) {
|
||||
// Fallback auf a4
|
||||
return {
|
||||
marginTopPx: mmToPx(FORMAT_LAYOUTS.a4.marginTopMm),
|
||||
marginLeftPx: mmToPx(FORMAT_LAYOUTS.a4.marginLeftMm),
|
||||
lineHeightPx: FONT_SIZE_PX * FORMAT_LAYOUTS.a4.lineHeightFactor,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
marginTopPx: mmToPx(layoutConfig.marginTopMm),
|
||||
marginLeftPx: mmToPx(layoutConfig.marginLeftMm),
|
||||
marginRightPx: layoutConfig.marginRightMm ? mmToPx(layoutConfig.marginRightMm) : null,
|
||||
lineHeightPx: FONT_SIZE_PX * layoutConfig.lineHeightFactor,
|
||||
};
|
||||
}
|
||||
|
||||
// Seiten-Dimensionen holen
|
||||
function getPageDimensions(format) {
|
||||
const normalizedFormat = String(format).toLowerCase();
|
||||
if (!PAGE_FORMATS[normalizedFormat]) signalMiss(normalizedFormat);
|
||||
const dimensions = PAGE_FORMATS[normalizedFormat] || PAGE_FORMATS.a4;
|
||||
|
||||
return {
|
||||
widthMm: dimensions.widthMm,
|
||||
heightMm: dimensions.heightMm,
|
||||
widthPx: mmToPx(dimensions.widthMm),
|
||||
heightPx: mmToPx(dimensions.heightMm),
|
||||
};
|
||||
}
|
||||
|
||||
// XML Escaping
|
||||
function escapeXml(str) {
|
||||
return String(str)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
// Zeilenlimit für Format holen
|
||||
function getLineLimit(format) {
|
||||
const normalizedFormat = String(format).toLowerCase();
|
||||
if (!LINE_LIMITS[normalizedFormat]) signalMiss(normalizedFormat);
|
||||
return LINE_LIMITS[normalizedFormat] || LINE_LIMITS.a4;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
PX_PER_MM,
|
||||
FONT_SIZE_PX,
|
||||
mmToPx,
|
||||
getLayoutForFormat,
|
||||
getPageDimensions,
|
||||
getLineLimit,
|
||||
escapeXml,
|
||||
applyRenderFormats,
|
||||
setFormatMissHandler,
|
||||
};
|
||||
Reference in New Issue
Block a user