PageSourceSearch

https://worklazy.net/assets/PdfComparePage-DehEcqj6.js

js worklazy.net collected 2026-10-02 02:02:34 UTC 31,821 bytes, 4 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/xlsxReport-KXqIRBuw.js","assets/exceljs.min-ksWazBY2.js","assets/_commonjsHelpers-Cpj98o6Y.js","assets/_commonjs-dynamic-modules-TDtrdbi3.js","assets/zipArchive-DWl4_AoV.js","assets/zip-fs-wasm-BHw0rJt3.js","assets/index-YleZ7k9F.js","assets/index--ZVOYC6-.css","assets/fileNameSafety-DS2JH4w4.js","assets/index-BtdMvux8.js"])))=>i.map(i=>d[i]);
2var Ne=Object.defineProperty;var De=(t,e,r)=>e in t?Ne(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var N=(t,e,r)=>De(t,typeof e!="symbol"?e+"":e,r);import{_ as U,u as Ee,r as w,t as te,j as a,w as Se,x as ke,U as A,a4 as G,B as D,l as re,ac as Ae,q as Z,s as ce,o as ae,D as Fe,G as Te}from"./index-YleZ7k9F.js";import{openOwnedPdfDocument as Me}from"./pdfPreview-ByQkeT0W.js";import{w as X,a as Re}from"./pdfRenderLifecycle-Dv40KurT.js";import{f as Oe}from"./featureMessages-DAnFod9h.js";import{A as _e}from"./arrow-left-right-D-jk69YP.js";import{S as Ie}from"./square-C9ragkM0.js";import{P as Le}from"./play-G_kbWtNv.js";import"./zipArchive-DWl4_AoV.js";import"./zip-fs-wasm-BHw0rJt3.js";import"./fileNameSafety-DS2JH4w4.js";class j extends Error{constructor(r){super(r);N(this,"code");this.code=r,this.name="PdfCompareError"}}function p(t){if(t!=null&&t.aborted)throw new DOMException("Aborted","AbortError")}function Ue(t,e){return Array.from({length:Math.max(t,e)},(r,n)=>({before:n<t?n:null,after:n<e?n:null}))}function ue(t,e,r){const n={before:new Set,after:new Set};if(!t.length)throw new j("invalid-mapping");for(const o of t){if(o.before===null&&o.after===null)throw new j("invalid-mapping");for(const i of["before","after"]){const s=o[i],l=i==="before"?e:r;if(s!==null){if(!Number.isInteger(s)||s<0||s>=l||n[i].has(s))throw new j("invalid-mapping");n[i].add(s)}}}return t.map(o=>({...o}))}function ze(t){return{text:t.map(e=>e.str+(e.hasEOL?`
3`:"")).join(""),available:t.some(e=>e.str.length>0)}}function $e(t,e){const r=Math.max((t==null?void 0:t.width)??0,(e==null?void 0:e.width)??0),n=Math.max((t==null?void 0:t.height)??0,(e==null?void 0:e.height)??0);if(!(r>0&&n>0&&Number.isFinite(r)&&Number.isFinite(n)))throw new j("render-failed");const o=Math.min(1,4096/r,4096/n,Math.sqrt(4096**2/(r*n)));return{width:Math.min(4096,Math.ceil(r*o)),height:Math.min(4096,Math.ceil(n*o)),beforeWidth:t?Math.min(4096,Math.ceil(t.width*o)):0,beforeHeight:t?Math.min(4096,Math.ceil(t.height*o)):0,afterWidth:e?Math.min(4096,Math.ceil(e.width*o)):0,afterHeight:e?Math.min(4096,Math.ceil(e.height*o)):0,scaleFactor:o,dpi:96*o,reducedResolution:o<1,pageSizeChanged:!!t&&!!e&&(t.width!==e.width||t.height!==e.height)}}function pe(t,e){return{mapping:{...t},status:"unknown",beforeTextAvailable:!1,afterTextAvailable:!1,beforeText:"",afterText:"",textComparison:"unavailable",segments:[],visualComparison:"unknown",pixelCount:null,pixelRatio:null,threshold:e,geometry:null,warnings:["extraction-limit"]}}function z(t,e="read-failed"){if(t instanceof j)return t.code;if(t instanceof Error){if(t.name==="PasswordException"||t.message===Oe("en","pdf.messages.pdfPreview.thisPdfIsPasswordProtectedTryAgainWith"))return"password";if(t.name==="InvalidPDFException")return"invalid-pdf"}return e}async function $(t,e){p(e);let r;try{r=await X(t.arrayBuffer(),e)}catch(c){throw p(e),new j(z(c))}if(p(e),!new TextDecoder("latin1").decode(r.slice(0,1024)).includes("%PDF-"))throw new j("invalid-pdf");let n;try{n=await Me(r,"en",e)}catch(c){throw p(e),new j(z(c))}let o,i=!1;const s=()=>(e.removeEventListener("abort",l),o??(o=n.loadingTask.destroy())),l=()=>{i||s().catch(()=>{})};return e.addEventListener("abort",l,{once:!0}),e.aborted&&(await s(),p(e)),{document:n.document,deferAbortUntilRenderSettles(){i=!0},close:s}}async function ne(t,e,r,n=!1){p(r);const o=await X(t.document.getPage(e+1),r);try{p(r);const i=await X(o.getTextContent(),r);p(r);const s=i.items.filter(u=>"str"in u),l=ze(s),c=n?s.map(u=>({str:u.str,hasEOL:u.hasEOL,transform:[...u.transform],width:u.width,height:u.height,pageIndex:e})):[];return{page:o,text:l,selectedItems:c}}catch(i){throw o.cleanup(),i}}async function ie(t,e,r){p(r);const n=document.createElement("canvas");n.width=e.width,n.height=e.height;try{const o=n.getContext("2d",{willReadFrequently:!0});if(!o)throw new j("render-failed");o.fillStyle="#fff",o.fillRect(0,0,n.width,n.height);const i=t.getViewport({scale:96/72*e.scaleFactor}),s=t.render({canvas:n,canvasContext:o,viewport:i,background:"rgb(255,255,255)",annotationMode:1});return await Re(s,t,{signal:r,cleanupOnCancel:!1}),p(r),n}catch(o){throw n.width=n.height=0,o}}function Ve(t,e,r,n,o=!1,i){return p(n),new Promise((s,l)=>{const c=new Worker(new URL("/assets/pdf-compare.worker-DUi39olV.js",import.meta.url),{type:"module"}),u=()=>{n.removeEventListener("abort",m),c.terminate()},m=()=>{u(),l(new DOMException("Aborted","AbortError"))};n.addEventListener("abort",m,{once:!0}),c.onerror=()=>{u(),l(new j("render-failed"))},c.onmessage=h=>{u(),n.aborted?l(new DOMException("Aborted","AbortError")):h.data.error?l(new j("render-failed")):s(h.data)};try{p(n);const h=t.getContext("2d").getImageData(0,0,t.width,t.height).data,f=e.getContext("2d").getImageData(0,0,e.width,e.height).data;c.postMessage({before:h,after:f,threshold:r,overlay:o,beforeText:i==null?void 0:i.before,afterText:i==null?void 0:i.after},[h.buffer,f.buffer])}catch(h){u(),l(h)}})}function T(t){t&&(t.width=t.height=0)}async function fe(t,e,r,n,o,i){let s,l,c,u,m=null,h=!1;try{r.before!==null&&(s=await ne(t,r.before,n,i)),p(n),r.after!==null&&(l=await ne(e,r.after,n,i)),p(n);const f=$e((s==null?void 0:s.page.getViewport({scale:96/72}))??null,(l==null?void 0:l.page.getViewport({scale:96/72}))??null);t.deferAbortUntilRenderSettles(),e.deferAbortUntilRenderSettles(),s&&(c=await ie(s.page,f,n)),p(n),l&&(u=await ie(l.page,f,n)),p(n);const b={...pe(r,o),geometry:f,beforeText:(s==null?void 0:s.text.text)??"",afterText:(l==null?void 0:l.text.text)??"",beforeTextAvailable:(s==null?void 0:s.text.available)??!1,afterTextAvailable:(l==null?void 0:l.text.available)??!1};if(f.reducedResolution&&b.warnings.push("reduced-resolution"),c&&u){const E=s.text.available&&l.text.available?{before:s.text.text,after:l.text.text}:void 0,k=await Ve(c,u,o,n,i,E);if(p(n),b.pixelCount=k.count,b.pixelRatio=k.ratio,b.visualComparison=k.count?"different-pixels":"equal-pixels",E&&(b.segments=k.segments,b.textComparison=E.before===E.after?"equal-extracted-text":"different-extracted-text"),i&&k.diff){m=document.createElement("canvas"),m.width=f.width,m.height=f.height;const y=m.getContext("2d");if(!y)throw new j("render-failed");y.putImageData(new ImageData(k.diff,f.width,f.height),0,0)}}else b.visualComparison=c?"deleted":"added";p(n),b.status="complete";const C=i?{before:c??null,after:u??null,overlay:m,beforeItems:(s==null?void 0:s.selectedItems)??[],afterItems:(l==null?void 0:l.selectedItems)??[],geometry:f,release(){T(this.before),T(this.after),T(this.overlay),this.before=this.after=this.overlay=null,this.beforeItems.length=this.afterItems.length=0}}:void 0;return h=i,{page:b,preview:C}}finally{s==null||s.page.cleanup(),l==null||l.page.cleanup(),h||(T(c),T(u),T(m))}}async function qe(t,e){const{signal:r,onProgress:n}=e,o=e.threshold??16;if(![0,16,32].includes(o)||new Set(t.map(s=>s.id)).size!==t.length)throw new j("invalid-mapping");const i={runId:e.runId??0,pairs:[],canceled:!1};for(const[s,l]of t.entries()){const c={id:l.id,beforeName:l.before.name,afterName:l.after.name,beforePageCount:0,afterPageCount:0,mappingSource:l.mapping?"manual":"page-number",status:"complete",pages:[],partial:!1};i.pairs.push(c);let u,m;try{p(r),u=await $(l.before,r),p(r),m=await $(l.after,r),p(r),c.beforePageCount=u.document.numPages,c.afterPageCount=m.document.numPages;const h=ue(l.mapping??Ue(c.beforePageCount,c.afterPageCount),c.beforePageCount,c.afterPageCount);c.pages=h.map(f=>pe(f,o)),n==null||n({pairIndex:s,pairCount:t.length,completedPages:0,totalPages:h.length});for(const[f,b]of h.entries())try{p(r);const{page:C}=await fe(u,m,b,r,o,!1);await new Promise(E=>setTimeout(E,0)),p(r),c.pages[f]=C,n==null||n({pairIndex:s,pairCount:t.length,completedPages:f+1,totalPages:h.length})}catch(C){throw c.pages[f].status=r.aborted?"canceled":"unknown",r.aborted||(c.pages[f].error=z(C,"render-failed")),C}}catch(h){c.status=r.aborted?"canceled":"failed",r.aborted||(c.error=z(h)),c.partial=c.pages.some(f=>f.status==="complete"),r.aborted&&(i.canceled=!0)}finally{await Promise.allSettled([u==null?void 0:u.close(),m==null?void 0:m.close()])}}return i}async function Be(t,e,r,n){let o,i;try{o=await $(t.before,n),p(n),i=await $(t.after,n),p(n),ue([e],o.document.numPages,i.document.numPages);const{preview:s}=await fe(o,i,e,n,r,!0);return n.aborted&&(s.release(),p(n)),s}finally{await Promise.allSettled([o==null?void 0:o.close(),i==null?void 0:i.close()])}}class We{constructor(){N(this,"generation",0);N(this,"controller");N(this,"previewController");N(this,"preview");N(this,"tail",Promise.resolve());N(this,"previewTail",Promise.resolve());N(this,"disposed",!1);N(this,"result",null)}invalidate(){var e;this.generation++,(e=this.controller)==null||e.abort(),this.clearPreview(),this.result=null}cancel(){var e;(e=this.controller)==null||e.abort(),this.clearPreview()}clearPreview(){var e,r;(e=this.previewController)==null||e.abort(),(r=this.preview)==null||r.release(),this.preview=void 0}
3async run(e,r=16,n){if(this.disposed)throw new DOMException("Disposed","AbortError");this.invalidate();const o=this.generation,i=this.controller=new AbortController,s=e.map(m=>{var h;return{...m,mapping:(h=m.mapping)==null?void 0:h.map(f=>({...f}))}}),l=this.tail,c=this.previewTail,u=(async()=>{await Promise.allSettled([l,c]);const m=await qe(s,{threshold:r,signal:i.signal,runId:o,onProgress:h=>{!i.signal.aborted&&this.generation===o&&!this.disposed&&(n==null||n(h))}});return this.generation!==o||this.disposed?null:(this.result=m,m)})();return this.tail=u,u}async select(e,r,n=16){if(this.disposed)throw new DOMException("Disposed","AbortError");this.clearPreview();const o=this.previewController=new AbortController,i=this.previewTail,s=this.tail,l=(async()=>{await Promise.allSettled([i,s]),p(o.signal);const c=await Be(e,{...r},n,o.signal);if(o.signal.aborted||this.disposed)throw c.release(),p(o.signal),new DOMException("Disposed","AbortError");return this.preview=c,c})();return this.previewTail=l,l}async dispose(){this.disposed=!0,this.invalidate(),await Promise.allSettled([this.tail,this.previewTail])}}const He={en:{sheet:"PDF comparison",empty:"Summary",warning:"Extracted text can differ from the original. Pixel comparison does not establish document identity.",headers:["Before file","After file","Before page","After page","Mapping source","Pair status","Page status","Before text available","After text available","Text comparison","Extracted text diff","Visual comparison","Pixel count","Pixel ratio","DPI","Scale factor","Threshold","Size changed","Before dimensions","After dimensions","Warning","Partial","Error"]},ko:{sheet:"PDF 비교",empty:"요약",warning:"추출된 텍스트는 원문과 다를 수 있습니다. 픽셀 비교는 문서의 동일성을 보장하지 않습니다.",headers:["변경 전 파일","변경 후 파일","변경 전 쪽","변경 후 쪽","쪽 대응","파일쌍 상태","쪽 상태","변경 전 텍스트 있음","변경 후 텍스트 있음","추출 텍스트 비교","추출 텍스트 변경","시각 비교","차이 픽셀 수","차이 비율","DPI","배율","임계값","쪽 크기 변경","변경 전 크기","변경 후 크기","주의","부분 결과","오류"]}},Ge={"page-number":["쪽 번호로 대응","Match by page number"],manual:["수동 대응","Manual mapping"],complete:["완료","Complete"],failed:["실패","Failed"],canceled:["취소됨","Canceled"],unknown:["미확인","Unknown"],"equal-extracted-text":["추출된 텍스트에서 차이 없음","No difference in extracted text"],"different-extracted-text":["추출된 텍스트에 차이 있음","Difference in extracted text"],unavailable:["비교할 텍스트 없음","No text to compare"],"equal-pixels":["설정된 렌더링에서 픽셀 차이 없음","No pixel difference at the selected rendering settings"],"different-pixels":["픽셀 차이 있음","Pixel difference"],added:["추가","Added"],deleted:["삭제","Deleted"],password:["잠금 없는 PDF 사본이 필요합니다","Use an unlocked PDF copy"],"invalid-pdf":["PDF를 읽을 수 없습니다","Cannot read this PDF"],"read-failed":["파일 읽기에 실패했습니다","File could not be read"],"render-failed":["쪽 비교에 실패했습니다","Page comparison failed"],"invalid-mapping":["쪽 대응을 확인하세요","Check page mapping"]};function Ze(t,e){const r=He[e],n=i=>{var s;return((s=Ge[i])==null?void 0:s[e==="ko"?0:1])??i},o=t.pages.map(i=>{const s=i.geometry;return[t.beforeName,t.afterName,i.mapping.before===null?"":i.mapping.before+1,i.mapping.after===null?"":i.mapping.after+1,n(t.mappingSource),n(t.status),n(i.status),i.beforeTextAvailable,i.afterTextAvailable,n(i.textComparison),i.segments.filter(l=>l.type!=="equal").map(l=>`${l.type==="deleted"?"−":"+"} ${l.text}`).join(`
4`),n(i.visualComparison),i.pixelCount??"",i.pixelRatio??"",(s==null?void 0:s.dpi)??"",(s==null?void 0:s.scaleFactor)??"",i.threshold,(s==null?void 0:s.pageSizeChanged)??"",s?`${s.beforeWidth}×${s.beforeHeight}`:"",s?`${s.afterWidth}×${s.afterHeight}`:"",r.warning+(s!=null&&s.reducedResolution?e==="ko"?" 비교 해상도를 낮췄습니다.":" Comparison resolution was reduced.":""),t.partial,i.error?n(i.error):""]});return o.length||o.push([t.beforeName,t.afterName,"","",n(t.mappingSource),n(t.status),r.empty,"","","","","","","","","","","","","",r.warning,t.partial,t.error?n(t.error):""]),{sheets:[{name:r.sheet,headers:r.headers,rows:o}]}}async function se(t,e,r){p(r);const[{writeXlsxReport:n},{createSafeFileName:o}]=await Promise.all([U(()=>import("./xlsxReport-KXqIRBuw.js"),__vite__mapDeps([0,1,2,3])),U(()=>import("./fileNameSafety-DS2JH4w4.js"),[])]);p(r);const i=await n(Ze(t,e));return p(r),{blob:new Blob([new Uint8Array(i)],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}),fileName:o(`${t.beforeName.replace(/\.pdf$/i,"")}-${t.afterName.replace(/\.pdf$/i,"")}-comparison.xlsx`)}}async function Xe(t,e,r){if(p(r),!t.length)throw new Error("No comparison results");if(t.length===1)return se(t[0],e,r);const[{writeZipArchive:n,createSafeZipArchiveSources:o},{BlobWriter:i}]=await Promise.all([U(()=>import("./zipArchive-DWl4_AoV.js"),__vite__mapDeps([4,5,6,7,8])),U(()=>import("./index-BtdMvux8.js"),__vite__mapDeps([9,5,6,7]))]);p(r);const s=[];for(const c of t)s.push(await se(c,e,r)),p(r);const l=await n(o(s),new i("application/zip"),r);
4return p(r),{blob:l,fileName:"pdf-comparison-reports.zip"}}const Je={ko:{eyebrow:"PDF 비교",title:"PDF 파일 비교",description:"수정 전후 PDF를 쌍으로 놓고 페이지별 화면과 추출 텍스트 차이를 확인합니다.",files:"PDF 쌍 선택",filesDesc:"각 쌍의 수정 전·후 파일을 선택하세요. 파일은 브라우저 안에서만 처리됩니다.",before:"수정 전 PDF",after:"수정 후 PDF",hint:"PDF 파일 1개",add:"비교 쌍 추가",remove:"쌍 삭제",swap:"좌우 교체",settings:"비교 설정",threshold:"픽셀 민감도",mapping:"쪽 번호로 대응",run:"비교 시작",rerun:"다시 비교",cancel:"비교 취소",running:"페이지를 비교하고 있습니다.",results:"비교 결과",changedOnly:"변경 페이지만 보기",all:"모든 페이지",side:"좌우 보기",overlay:"차이 겹쳐 보기",opacity:"겹침 불투명도",report:"보고서 다운로드",select:"페이지 선택",page:"{{n}}번째 대응",added:"추가",deleted:"삭제",changed:"변경",sameVisual:"렌더 픽셀 차이 없음",sameText:"추출된 텍스트에서 차이 없음",noText:"비교할 텍스트 없음",unknown:"확인되지 않음",canceled:"취소됨",failed:"비교 실패",partial:"완료된 페이지를 포함한 부분 결과입니다.",limit:"추출 텍스트의 읽기 순서와 글자는 PDF 내부 정보에 따라 실제 화면과 다를 수 있습니다. 화면 비교와 텍스트 비교 결과를 각각 확인하세요.",renderLimit:"화면 비교는 같은 렌더 설정의 픽셀 차이이며 문서 내용의 동일성을 뜻하지 않습니다.",reduced:"큰 페이지를 낮은 해상도로 비교했습니다.",size:"페이지 크기 변경",dpi:"실제 {{dpi}} DPI · 배율 {{scale}}",manual:"수동 대응",none:"없음",apply:"대응 적용 후 재실행",needFiles:"각 쌍에 수정 전·후 PDF를 선택하세요.",password:"암호가 없는 PDF 사본을 선택하세요.",invalid:"PDF 파일을 읽을 수 없습니다. 파일이 손상되지 않았는지 확인하세요.",renderError:"페이지 화면을 비교하지 못했습니다.",mappingError:"페이지 대응을 확인하세요. 각 페이지는 한 번만 사용할 수 있습니다.",exportError:"보고서를 만들지 못했습니다. 다시 시도하세요.",empty:"조건에 맞는 페이지가 없습니다."},en:{eyebrow:"PDF comparison",title:"Compare PDF files",description:"Place before and after PDFs in pairs, then inspect visual and extracted-text differences page by page.",files:"Choose PDF pairs",filesDesc:"Choose one before and one after file for each pair. Files stay in your browser.",before:"Before PDF",after:"After PDF",hint:"One PDF file",add:"Add comparison pair",remove:"Remove pair",swap:"Swap sides",settings:"Comparison settings",threshold:"Pixel sensitivity",mapping:"Match by page number",run:"Start comparison",rerun:"Compare again",cancel:"Cancel comparison",running:"Comparing pages.",results:"Comparison results",changedOnly:"Changed pages only",all:"All pages",side:"Side by side",overlay:"Difference overlay",opacity:"Overlay opacity",report:"Download report",select:"Select page",page:"Pair {{n}}",added:"Added",deleted:"Deleted",changed:"Changed",sameVisual:"No rendered pixel difference",sameText:"No difference in extracted text",noText:"No text to compare",unknown:"Unknown",canceled:"Canceled",failed:"Comparison failed",partial:"This is a partial result containing completed pages.",limit:"Extracted text order and characters can differ from the visible PDF because they follow the PDF's internal data. Check visual and text results separately.",renderLimit:"Visual comparison reports pixel differences under the same render settings and does not establish document equivalence.",reduced:"A large page was compared at reduced resolution.",size:"Page size changed",dpi:"Actual {{dpi}} DPI · scale {{scale}}",manual:"Manual matching",none:"None",apply:"Apply mapping and compare again",needFiles:"
4Choose a before and after PDF for every pair.",password:"Choose an unlocked copy of the PDF.",invalid:"The PDF could not be read. Check that the file is not damaged.",renderError:"The page could not be rendered for comparison.",mappingError:"Check the page mapping. Each page can be used only once.",exportError:"The report could not be created. Try again.",empty:"No pages match this filter."}};function ft(){var ee;const t=Ee(),e=Je[t],r=w.useRef(null);w.useEffect(()=>{const d=new We;return r.current=d,()=>{d.dispose(),r.current===d&&(r.current=null)}},[]);const[n,o]=w.useState(()=>[{id:te(),before:null,after:null}]),[i,s]=w.useState(16),[l,c]=w.useState(null),[u,m]=w.useState(!1),[h,f]=w.useState(0),[b,C]=w.useState(),[E,k]=w.useState(!1),[y,J]=w.useState(null),[xe,V]=w.useState(null),[ge,R]=w.useState("idle"),[q,we]=w.useState("side"),[K,be]=w.useState(.55),F=w.useRef(null),S=w.useRef(0),O=w.useRef(new Map),B=()=>{var d;(d=F.current)==null||d.abort(),F.current=null;for(const[g,x]of O.current)clearTimeout(x),URL.revokeObjectURL(g);O.current.clear()};w.useEffect(()=>()=>{var d;S.current++,B(),(d=r.current)==null||d.dispose()},[]);const M=()=>{var d;S.current++,B(),(d=r.current)==null||d.invalidate(),c(null),J(null),V(null),R("idle"),C(void 0),m(!1)},_=(d,g)=>{M(),o(x=>x.map((P,v)=>v===d?{...P,...g}:P))},ve=()=>{M(),o(d=>[...d,{id:te(),before:null,after:null}])},W=w.useMemo(()=>n.flatMap(d=>d.before&&d.after?[{id:d.id,before:d.before,after:d.after,mapping:d.mapping}]:[]),[n]),ye=async()=>{if(W.length!==n.length){C(e.needFiles);return}M();const d=S.current;m(!0),f(1);try{const g=await r.current.run(W,i,x=>{d===S.current&&f(Math.max(1,Math.round((x.pairIndex+(x.totalPages?x.completedPages/x.totalPages:0))/x.pairCount*100)))});g&&d===S.current&&(c(g),f(100))}catch(g){d===S.current&&!(g instanceof DOMException&&g.name==="AbortError")&&C(e.invalid)}finally{d===S.current&&m(!1)}},Pe=()=>{var d;return(d=r.current)==null?void 0:d.cancel()},Q=async(d,g)=>{var P;J({pair:d,page:g}),V(null),R("loading");const x=(P=l==null?void 0:l.pairs[d])==null?void 0:P.pages[g];if(x)try{const v=await r.current.select(W[d],x.mapping,i);V(v),R("idle")}catch(v){v instanceof DOMException&&v.name==="AbortError"||R("error")}},je=async()=>{var P;if(!l||u||((P=r.current)==null?void 0:P.result)!==l)return;B();const d=new AbortController;F.current=d;const g=S.current,x=()=>!d.signal.aborted&&F.current===d&&g===S.current;try{const v=await Xe(l.pairs,t,d.signal);if(!x())return;const I=URL.createObjectURL(v.blob),Ce=setTimeout(()=>{URL.revokeObjectURL(I),O.current.delete(I)},15e3);O.current.set(I,Ce);const H=document.createElement("a");H.href=I,H.download=v.fileName,H.click()}catch(v){x()&&!(v instanceof DOMException&&v.name==="AbortError")&&C(e.exportError)}finally{F.current===d&&(F.current=null)}},Y=y?(ee=l==null?void 0:l.pairs[y.pair])==null?void 0:ee.pages[y.page]:void 0;return a.jsxs(Se,{toolId:"pdf-compare",children:[a.jsx(ke,{eyebrow:e.eyebrow,title:e.title,description:e.description}),a.jsx(A,{className:"mb-4",kind:"warning",children:e.limit}),a.jsxs(G,{title:e.files,description:e.filesDesc,step:1,children:[a.jsx("div",{className:"space-y-4",children:n.map((d,g)=>a.jsxs("div",{className:"rounded-3xl border border-border p-4","data-testid":"pdf-pair",children:[a.jsxs("div",{className:"mb-3 flex flex-wrap items-center justify-between gap-2",children:[a.jsx("strong",{children:e.page.replace("{{n}}",String(g+1))}),a.jsxs("div",{className:"flex gap-2",children:[a.jsxs(D,{type:"button",variant:"outline",className:"min-h-11",onClick:()=>_(g,{before:d.after,after:d.before,mapping:void 0}),children:[a.jsx(_e,{size:16}),e.swap]}),n.length>1?a.jsx(D,{type:"button",variant:"ghost",className:"min-h-11",onClick:()=>{M(),o(x=>x.filter((P,v)=>v!==g))},children:e.remove}):null]})]}),a.jsxs("div",{className:"grid gap-4 min-[1000px]:grid-cols-2",children:[a.jsx(re,{label:e.before,hint:e.hint,accept:"application/pdf,.pdf",files:d.before?[d.before]:[],onFiles:x=>_(g,{before:x[0]??null,mapping:void 0}),accent:"violet",disabled:u}),a.jsx(re,{label:e.after,hint:e.hint,accept:"application/pdf,.pdf",files:d.after?[d.after]:[],onFiles:x=>_(g,{after:x[0]??null,mapping:void 0}),accent:"violet",disabled:u})]})]},d.id))}),a.jsxs(D,{type:"button",variant:"outline",className:"mt-4 min-h-11",disabled:u,onClick:ve,children:[a.jsx(Ae,{size:17}),e.add]})]}),a.jsxs(G,{title:e.settings,step:2,children:[a.jsxs("div",{className:"grid gap-4 min-[621px]:grid-cols-2",children:[a.jsxs(Z,{children:[e.threshold,a.jsxs(ce,{value:i,disabled:u,onChange:d=>{M(),s(Number(d.target.value))},children:[a.jsx("option",{value:"0",children:"0"}),a.jsx("option",{value:"16",children:"16"}),a.jsx("option",{value:"32",children:"32"})]})]}),a.jsxs(Z,{children:[e.mapping,a.jsx("div",{className:"flex h-10 items-center rounded-xl border border-input px-3 text-sm",children:e.mapping})]})]}),a.jsx("div",{className:"mt-5 flex gap-3",children:u?a.jsxs(D,{className:"min-h-12 flex-1",variant:"destructive",onClick:Pe,children:[a.jsx(Ie,{size:17}),e.cancel]}):a.jsxs(D,{className:"min-h-12 flex-1",onClick:()=>void ye(),children:[a.jsx(Le,{size:17}),l?e.rerun:e.run]})}),u?a.jsxs("div",{className:"mt-4",role:"status","aria-live":"polite",children:[a.jsxs("div",{className:"mb-1 flex justify-between text-sm",children:[a.jsx("span",{children:e.running}),a.jsxs("b",{children:[h,"%"]})]}),a.jsx("div",{className:"h-2 overflow-hidden rounded-full bg-muted",children:a.jsx("div",{className:"h-full bg-primary",style:{width:`${h}%`}})})]}):null,b?a.jsx(A,{className:"mt-4",kind:"error",role:"alert",children:b}):null]}),l?a.jsxs(G,{title:e.results,step:3,children:[a.jsxs("div",{className:"mb-4 flex flex-wrap gap-3",children:[a.jsx(ae,{value:E?"changed":"all",label:e.changedOnly,options:[{value:"all",label:e.all},{value:"changed",label:e.changedOnly}],onChange:d=>k(d==="changed")}),a.jsxs(D,{type:"button",className:"min-h-11",onClick:()=>void je(),children:[a.jsx(Fe,{size:17}),e.report]})]}),l.canceled?a.jsx(A,{kind:"warning",children:e.partial}):null,a.jsx("div",{className:"mb-5 space-y-3",children:l.pairs.map((d,g)=>d.status==="failed"?null:a.jsx(Ye,{pair:d,c:e,onApply:x=>_(g,{mapping:x})},d.id))}),a.jsxs("div",{className:"mt-4 grid gap-5 min-[821px]:grid-cols-[280px_minmax(0,1fr)]",children:[a.jsx("nav",{className:"max-h-[620px] space-y-3 overflow-auto","aria-label":e.select,children:l.pairs.map((d,g)=>a.jsxs("div",{children:[a.jsxs("strong",{className:"mb-2 block truncate",children:[d.beforeName," ↔ ",d.afterName]}),d.status==="failed"?a.jsx(A,{kind:"error",children:tt(d.error,e)}):d.pages.map((x,P)=>{const v=me(x);return E&&!v?null:a.jsxs(D,{type:"button",variant:(y==null?void 0:y.pair)===g&&y.page===P?"default":"outline",className:"mb-2 h-auto min-h-11 w-full justify-start whitespace-normal text-left",onClick:()=>void Q(g,P),children:[et(x.mapping)," · ",he(x,e)]},P)}
4)]},d.id))}),a.jsx("div",{children:Y?a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"mb-3 flex flex-wrap gap-3",children:[a.jsx(ae,{value:q,label:e.select,options:[{value:"side",label:e.side},{value:"overlay",label:e.overlay}],onChange:we}),q==="overlay"?a.jsxs(Z,{className:"min-w-48",children:[e.opacity,a.jsx("input",{type:"range",min:"0",max:"1",step:".05",value:K,onChange:d=>be(Number(d.target.value))})]}):null]}),a.jsx(Ke,{preview:xe,view:q,opacity:K,status:ge,onRetry:()=>y&&Q(y.pair,y.page),c:e}),a.jsx(Qe,{page:Y,c:e})]}):a.jsxs("p",{className:"rounded-3xl border border-dashed p-8 text-center text-muted-foreground",children:[e.select," "]})})]})]}):null,a.jsxs(A,{kind:"warning",children:[e.renderLimit," ",t==="ko"?"시각 비교는 현재 브라우저의 표시 결과를 비교합니다. 화면 배율, 기기와 글꼴 환경에 따라 차이율이 달라질 수 있습니다.":"Visual comparison uses the rendering in your current browser. Pixel differences can vary with display scaling, devices and available fonts."]}),a.jsx(Te,{slug:"pdfCompare"})]})}function Ke({preview:t,view:e,opacity:r,status:n,onRetry:o,c:i}){return n==="error"?a.jsxs("div",{className:"flex min-h-48 flex-col items-center justify-center gap-4 roun
4ded-3xl border border-destructive/20 bg-destructive/5 text-destructive p-6 text-center",children:[a.jsx("p",{children:i.renderError}),a.jsx(D,{type:"button",variant:"outline",onClick:o,children:"다시 시도"})]}):t?a.jsx("div",{className:e==="side"?"grid gap-3 sm:grid-cols-2":"relative mx-auto w-fit max-w-full overflow-auto rounded-2xl border bg-white",children:e==="side"?a.jsxs(a.Fragment,{children:[a.jsx(L,{canvas:t.before}),a.jsx(L,{canvas:t.after})]}):a.jsxs(a.Fragment,{children:[a.jsx(L,{canvas:t.before}),a.jsx("div",{className:"pointer-events-none absolute inset-0",style:{opacity:r},children:a.jsx(L,{canvas:t.overlay})})]})}):a.jsx("div",{className:"min-h-48 animate-pulse rounded-3xl bg-muted",role:"status"})}function L({canvas:t}){const e=w.useRef(null);return w.useEffect(()=>{const r=e.current;return t&&r&&(r.replaceChildren(t),t.style.maxWidth="100%",t.style.height="auto"),()=>{r&&(t==null?void 0:t.parentElement)===r&&r.removeChild(t)}},[t]),a.jsx("div",{ref:e,className:"min-w-0 overflow-auto rounded-2xl border bg-white"})}function Qe({page:t,c:e}){var r,n;return a.jsxs("div",{className:"mt-4 space-y-3",children:[a.jsxs("div",{className:"flex flex-wrap gap-2 text-sm",children:[a.jsx("span",{className:"rounded-full bg-muted px-3 py-1",children:he(t,e)}),(r=t.geometry)!=null&&r.pageSizeChanged?a.jsx("span",{className:"rounded-full bg-amber-500/10 px-3 py-1 text-amber-800 dark:text-amber-300",children:e.size}):null,t.geometry?a.jsx("span",{className:"rounded-full bg-muted px-3 py-1",children:e.dpi.replace("{{dpi}}",String(Math.round(t.geometry.dpi))).replace("{{scale}}",t.geometry.scaleFactor.toFixed(2))}):null]}),(n=t.geometry)!=null&&n.reducedResolution?a.jsx(A,{kind:"warning",children:e.reduced}
4):null,a.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[a.jsx(oe,{title:e.before,text:t.beforeText,available:t.beforeTextAvailable,c:e}),a.jsx(oe,{title:e.after,text:t.afterText,available:t.afterTextAvailable,c:e})]}),t.textComparison==="different-extracted-text"?a.jsx("div",{className:"rounded-2xl border p-4 whitespace-pre-wrap",children:t.segments.map((o,i)=>a.jsx("span",{className:o.type==="added"?"bg-green-200 text-green-950 dark:bg-green-900 dark:text-green-100":o.type==="deleted"?"bg-red-200 text-red-950 line-through dark:bg-red-900 dark:text-red-100":"",children:o.text},i))}):null]})}function oe({title:t,text:e,available:r,c:n}){return a.jsxs("section",{className:"min-w-0 rounded-2xl border p-4",children:[a.jsx("strong",{children:t}),a.jsx("pre",{className:"mt-2 max-h-64 overflow-auto whitespace-pre-wrap break-words text-sm",children:r?e:n.noText})]})}function Ye({pair:t,c:e,onApply:r}){const[n,o]=w.useState(!1),[i,s]=w.useState(()=>t.pages.map(c=>({...c.mapping}))),l=de(i,"before")||de(i,"after")||i.some(c=>c.before===null&&c.after===null);return a.jsxs("section",{className:"rounded-2xl border p-3",children:[a.jsxs(D,{type:"button",variant:"ghost",className:"min-h-11 w-full justify-between","aria-expanded":n,onClick:()=>o(c=>!c),children:[a.jsxs("span",{className:"truncate",children:[t.beforeName," ↔ ",t.afterName]}),a.jsx("span",{children:e.manual})]}),n?a.jsxs("div",{className:"mt-3 space-y-2",children:[i.map((c,u)=>a.jsxs("div",{className:"grid grid-cols-[1fr_auto_1fr] items-center gap-2",children:[a.jsx(le,{label:e.before,count:t.beforePageCount,value:c.before,none:e.none,onChange:m=>s(h=>h.map((f,b)=>b===u?{...f,before:m}:f))}),a.jsx("span",{"aria-hidden":"true",children:"↔"}),a.jsx(le,{label:e.after,count:t.afterPageCount,value:c.after,none:e.none,onChange:m=>s(h=>h.map((f,b)=>b===u?{...f,after:m}:f))})]},u)),l?a.jsx(A,{kind:"error",children:e.mappingError}):null,a.jsx(D,{type:"button",className:"min-h-11 w-full",disabled:l,onClick:()=>r(i),children:e.apply})]}):null]})}function le({label:t,count:e,value:r,none:n,onChange:o}){return a.jsxs(ce,{"aria-label":t,value:r===null?"":String(r),onChange:i=>o(i.target.value===""?null:Number(i.target.value)),children:[a.jsx("option",{value:"",children:n}),Array.from({length:e},(i,s)=>a.jsx("option",{value:s,children:s+1},s))]})}function de(t,e){const r=t.map(n=>n[e]).filter(n=>n!==null);return new Set(r).size!==r.length}function me(t){var e;return t.status!=="complete"||t.visualComparison!=="equal-pixels"||t.textComparison!=="equal-extracted-text"||!!((e=t.geometry)!=null&&e.pageSizeChanged)}function et(t){return`${t.before===null?"—":t.before+1} ↔ ${t.after===null?"—":t.after+1}`}function he(t,e){return t.status==="canceled"?e.canceled:t.status!=="complete"?e.unknown:t.visualComparison==="added"?e.added:t.visualComparison==="deleted"?e.deleted:t.textComparison==="unavailable"?t.visualComparison==="equal-pixels"?`${e.sameVisual} · ${e.noText}`:e.changed:me(t)?e.changed:`${e.sameVisual} · ${e.sameText}`}function tt(t,e){return t==="password"?e.password:t==="invalid-mapping"?e.mappingError:t==="render-failed"?e.renderError:e.invalid}export{ft as PdfComparePage};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.