跳至內容
Astera Technology

加好頁尾後,才核真正總頁數

頁尾總數要跟最終生成的排版。

下載完整個案資料及參考答案 ↓

訂判斷及所需輸入

固定內文在每頁可用八十毫米時共兩頁。留所需頁尾空間後,可用高變七十,最終 PDF 成三頁。照用早前總數二就出現 Page 3 of 2,更正須跟最後頁數。

已填本地測試工作表
情況輸入 JSON
原例測試{"footerRequired":true}
下載可編輯 CSV ↓

跑所附比較

瀏覽器生成最終 PDF,抽字逐頁核頁尾,不用估計內文頁數代替排版後結果。CSS 頁計數只在此引擎實測,未承諾所有呈現器一致。

錯誤及所需輸出
路徑輸出 JSON
錯誤路徑{"pageCount":3,"footers":["Page 1 of 2","Page 2 of 2","Page 3 of 2"]}
所需路徑{"pageCount":3,"footers":["Page 1 of 3","Page 2 of 3","Page 3 of 3"]}
下載可編輯 CSV ↓
Node24.14.1 程序;須 Playwright1.63 Chromium 及 PDF.js6.4.299
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {pathToFileURL} from 'node:url';
const htmlEscape=s=>String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
async function withPage(action,options={}){
  const require=createRequire(import.meta.url);const {chromium}=require('playwright');
  const browser=await chromium.launch({headless:true});
  try{const context=await browser.newContext(options);const page=await context.newPage();
    const requests=[];await page.route('**/*',route=>{requests.push(route.request().url());return route.abort();});
    return await action(page,context,requests);
  }finally{await browser.close();}
}
async function pdfObservation(html){
  const bytes=await withPage(async page=>{await page.setContent(html);return page.pdf({preferCSSPageSize:true,printBackground:true});});
  const require=createRequire(import.meta.url);
  const {getDocument}=await import(pathToFileURL(require.resolve('pdfjs-dist/legacy/build/pdf.mjs')).href);
  const loadingTask=getDocument({data:Uint8Array.from(bytes),useSystemFonts:true,disableFontFace:true});
  try{const document=await loadingTask.promise;const pages=[];for(let n=1;n<=document.numPages;n++){
    const page=await document.getPage(n);const content=await page.getTextContent();
    pages.push(content.items.filter(x=>typeof x.str==='string'&&x.str).map(x=>({text:x.str,x:x.transform[4],y:x.transform[5]})));
  }return {pageCount:document.numPages,pages};}finally{await loadingTask.destroy();}
}
const printStyle='<style>@page{size:100mm 100mm;margin:10mm}body{margin:0;font:10px Arial}p{margin:0}</style>';

const run=async function run(i,corrected=true){
    if(typeof i.footerRequired!=='boolean')return {held:true};
    const footer=i.footerRequired?'@page{margin-bottom:20mm;@bottom-center{content:"Page " counter(page) " of " '+(corrected?'counter(pages)':'"2"')+';font:10px Arial}}':'';
    const html=printStyle+'<style>'+footer+'.body{height:160mm}.line{height:10mm;line-height:10mm}</style><div class="body">'+Array.from({length:16},(_,n)=>'<p class="line">LINE'+(n+1)+'</p>').join('')+'</div>';
    const out=await pdfObservation(html);return {pageCount:out.pageCount,footers:out.pages.map(p=>p.map(x=>x.text).find(s=>s.startsWith('Page '))??null)};
  };
const cases=[{"input":{"footerRequired":true},"corrected":false,"expected":{"pageCount":3,"footers":["Page 1 of 2","Page 2 of 2","Page 3 of 2"]}},{"input":{"footerRequired":true},"corrected":true,"expected":{"pageCount":3,"footers":["Page 1 of 3","Page 2 of 3","Page 3 of 3"]}},{"input":{"footerRequired":false},"corrected":true,"expected":{"pageCount":2,"footers":[null,null]}},{"input":{"footerRequired":null},"corrected":true,"expected":{"held":true}}];
for(const test of cases){const actual=await run(test.input,test.corrected);assert.deepEqual(actual,test.expected);console.log(actual);}
下載可執行例子 ↓

按邊界依據作判斷

沒有該頁尾空間要求,內文仍兩頁且無頁尾;要求未知便先停。

  1. 先留所需頁尾空間
  2. 生成最後排版
  3. 逐頁核總頁數

不能把未加頁尾前的頁數帶到最終文件。

可編輯邊界輸入及結果
條件輸入 JSON預期輸出 JSON
內文毋須留頁尾位{"footerRequired":false}{"pageCount":2,"footers":[null,null]}
頁尾要求未知{"footerRequired":null}{"held":true}
下載可編輯 CSV ↓

原例最後三個頁尾應寫甚麼?

查看參考答案

依次 Page 1 of 3、Page 2 of 3、Page 3 of 3,都是同一份最終三頁檔案。

例子檔案

相關資源