From 8850620931e3782002599711ca15472bb1a804f2 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Sun, 27 Sep 2026 11:50:27 +0530 Subject: [PATCH] fix(opd): accurately calculate top margin delta from template @page and fix named header/footer preservation --- app/Controllers/Opd.php | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/app/Controllers/Opd.php b/app/Controllers/Opd.php index e2c8a9b..118af28 100644 --- a/app/Controllers/Opd.php +++ b/app/Controllers/Opd.php @@ -2408,7 +2408,7 @@ class Opd extends BaseController } $resolvedPaperWidthMm = $format === 'LETTER' ? 215.9 : ($format === 'A5' ? 148.0 : ($format === 'CUSTOM' ? (float) $customWidthMm : 210.0)); - $html = $this->applyOpdLongContentPaginationGuard($html, min(12.0, max(5.0, (float) $marginTop)), $resolvedPaperWidthMm); + $html = $this->applyOpdLongContentPaginationGuard($html, (float) $marginTop, $resolvedPaperWidthMm); $html = mpdf_normalize_font_weight_css($html); if ($rawHeaderHtml !== '') { @@ -4742,8 +4742,18 @@ class Opd extends BaseController $widthMm = max(30.0, min($paperWidthMm - $leftMm, $dim['width'])); $rightMarginMm = max(0.0, $paperWidthMm - $leftMm - $widthMm); - // Top clearance spacer height on Page 1 (letterhead offset minus page top margin) - $spacerHeightMm = max(0.0, $dim['top'] - $pageMarginTopMm); + // Check existing @page margin-top in document + $existingPageTopMm = 0.0; + if (preg_match_all('/@page\s*\{[^}]*?margin-top\s*:\s*([0-9\.]+)\s*(mm|cm|px|in|pt)?/i', $html, $allTm, PREG_SET_ORDER)) { + $lastTm = end($allTm); + $existingPageTopMm = $convertMm((float) $lastTm[1], $lastTm[2] ?? 'mm', 297.0); + } + if ($existingPageTopMm <= 0.0 && $pageMarginTopMm > 0.0) { + $existingPageTopMm = $pageMarginTopMm; + } + + // Top clearance spacer height on Page 1 (only the delta needed to reach the template's target top) + $spacerHeightMm = max(0.0, $dim['top'] - $existingPageTopMm); // In-place update margin-left and margin-right in any existing @page blocks if (preg_match('/@page\s*\{/i', $html)) { @@ -4765,15 +4775,17 @@ class Opd extends BaseController // Insert top clearance spacer right before .RxPlace so Page 1 reserves space for letterhead, // but subsequent pages start cleanly at the top of the continuation sheet - $topSpacer = '
 
'; - $html = preg_replace('/()/i', $topSpacer . "\n$1", $html, 1); + if ($spacerHeightMm > 0.5) { + $topSpacer = '
 
'; + $html = preg_replace('/()/i', $topSpacer . "\n$1", $html, 1); + } // Preserve existing named header/footer references if present in the document $extraPageRules = ''; - if (preg_match('/header\s*:\s*([^;\}]+)/i', $html, $hm)) { + if (preg_match('/(?