訂判斷及所需輸入
本例明訂奇數頁是正面。前節到第三頁,下一節須正面開始,所以生成程序明確加空白第四頁,NEWSECTION 在第五。若把空白頁一律刪掉,就違題內正反頁規則。
| 情況 | 輸入 JSON |
|---|---|
| 原例測試 | {"priorPages":3,"frontRequired":true} |
跑所附比較
真正 PDF 抽字核總頁數、空白頁及新節標記。這是明確生成頁次規則,未驗實體雙面設備,也不靠未測的指定面拆頁屬性。
| 路徑 | 輸出 JSON |
|---|---|
| 錯誤路徑 | {"newSectionPage":4,"blankPages":[],"pageCount":4} |
| 所需路徑 | {"newSectionPage":5,"blankPages":[4],"pageCount":5} |
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {pathToFileURL} from 'node:url';
const htmlEscape=s=>String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
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.frontRequired!=='boolean'||![2,3].includes(i.priorPages))return {held:true};
const blank=corrected&&i.frontRequired&&i.priorPages%2===1?'<section class="prior"></section>':'';
const html=printStyle+'<style>.prior{height:80mm;break-after:page}.next{break-before:page}</style>'+Array.from({length:i.priorPages},(_,n)=>'<section class="prior">PRIOR'+(n+1)+'</section>').join('')+blank+'<section class="next">NEWSECTION</section>';
const out=await pdfObservation(html);return {newSectionPage:out.pages.findIndex(p=>p.some(x=>x.text==='NEWSECTION'))+1,blankPages:out.pages.map((p,n)=>p.length?null:n+1).filter(n=>n!==null),pageCount:out.pageCount};
};
const cases=[{"input":{"priorPages":3,"frontRequired":true},"corrected":false,"expected":{"newSectionPage":4,"blankPages":[],"pageCount":4}},{"input":{"priorPages":3,"frontRequired":true},"corrected":true,"expected":{"newSectionPage":5,"blankPages":[4],"pageCount":5}},{"input":{"priorPages":2,"frontRequired":true},"corrected":true,"expected":{"newSectionPage":3,"blankPages":[],"pageCount":3}},{"input":{"priorPages":3,"frontRequired":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);}
按邊界依據作判斷
前節在第二頁完,第三頁已符合,不需空白。正面要求未訂便暫停。
- 核正面頁次規則
- 生成所需空白頁
- 核新節及空白位置
不能用此假設頁次推實體打印機的面次規則。
| 條件 | 輸入 JSON | 預期輸出 JSON |
|---|---|---|
| 前節在背面頁完 | {"priorPages":2,"frontRequired":true} | {"newSectionPage":3,"blankPages":[],"pageCount":3} |
| 正面要求未訂 | {"priorPages":3,"frontRequired":null} | {"held":true} |
原例第四頁空白,是錯誤嗎?
查看參考答案
不是,要靠它讓新節由第五頁這個下個正面開始,PDF 共五頁。