mineru-layout-viewer 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -145,12 +145,8 @@ var STYLES = `
|
|
|
145
145
|
}
|
|
146
146
|
.split { flex: 1; display: grid; grid-template-columns: 1fr 1fr; min-height: 0; overflow: hidden; }
|
|
147
147
|
.pane { overflow: auto; padding: 10px; }
|
|
148
|
-
.pane-left { border-right: 1px solid #e5e5e5; }
|
|
149
|
-
.pane-right { background: #
|
|
150
|
-
@media (prefers-color-scheme: dark) {
|
|
151
|
-
.pane-left { border-color: #333; }
|
|
152
|
-
.pane-right { background: #1e1e1e; }
|
|
153
|
-
}
|
|
148
|
+
.pane-left { border-right: 1px solid #e5e5e5; background: #fff; }
|
|
149
|
+
.pane-right { background: #fff; }
|
|
154
150
|
.pdf-page { position: relative; margin: 0 auto 12px; border: 1px solid #e5e5e5; border-radius: 4px; overflow: hidden; }
|
|
155
151
|
.pdf-page img { display: block; width: 100%; }
|
|
156
152
|
.pdf-page .page-num { position: absolute; bottom: 2px; right: 4px; font-size: 9px; color: #999; background: rgba(255,255,255,.85); padding: 1px 4px; border-radius: 3px; }
|
|
@@ -272,7 +268,14 @@ var MineruLayoutViewer = class extends HTMLElement {
|
|
|
272
268
|
if (!this.shadowRoot) return;
|
|
273
269
|
this.shadowRoot.innerHTML = `<style>${STYLES}</style>
|
|
274
270
|
<div class="toolbar">
|
|
275
|
-
<span id="stat"></span
|
|
271
|
+
<span id="stat"></span>
|
|
272
|
+
<span style="flex:1"></span>
|
|
273
|
+
<a href="https://www.npmjs.com/package/mineru-layout-viewer" target="_blank" title="npm" style="color:inherit;display:flex;align-items:center;opacity:.5;transition:opacity .15s" onmouseenter="this.style.opacity='1'" onmouseleave="this.style.opacity='.5'">
|
|
274
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v1.336h-1.336v1.336h-2.668V8.667h5.334v5.331z"/></svg>
|
|
275
|
+
</a>
|
|
276
|
+
<a href="https://github.com/rand777gg/mineru-layout-viewer" target="_blank" title="GitHub" style="color:inherit;display:flex;align-items:center;opacity:.5;transition:opacity .15s;margin-left:4px" onmouseenter="this.style.opacity='1'" onmouseleave="this.style.opacity='.5'">
|
|
277
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
|
|
278
|
+
</a>
|
|
276
279
|
</div>
|
|
277
280
|
<div class="split">
|
|
278
281
|
<div class="pane pane-left" id="pdfPane"><slot name="loading">\u52A0\u8F7D PDF + layout.json \u4EE5\u5F00\u59CB</slot></div>
|
|
@@ -397,7 +400,9 @@ var MineruLayoutViewer = class extends HTMLElement {
|
|
|
397
400
|
const s = RENDER_SCALE * (pw / page.w);
|
|
398
401
|
overlays.forEach((ov) => {
|
|
399
402
|
const el2 = ov;
|
|
400
|
-
|
|
403
|
+
const dx = Math.abs(parseFloat(el2.style.left) - sec.bbox[0] * s);
|
|
404
|
+
const dy = Math.abs(parseFloat(el2.style.top) - sec.bbox[1] * s);
|
|
405
|
+
if (dx < 2 && dy < 2) {
|
|
401
406
|
el2.classList.add("active");
|
|
402
407
|
el2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
403
408
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/parse-blocks.ts", "../src/match-markdown.ts", "../src/mineru-viewer.ts"],
|
|
4
|
-
"sourcesContent": ["// \u2500\u2500 Block types \u2500\u2500\n\nexport interface PdfBlock {\n page_idx: number\n bbox: [number, number, number, number]\n text?: string\n type?: string\n}\n\nexport interface MdSection {\n text: string\n page: number\n bbox: [number, number, number, number] | null\n}\n\n// \u2500\u2500 Text extraction from layout.json / middle.json span structure \u2500\u2500\n\nexport function extractSpanText(block: Record<string, unknown>): string {\n const lines = block.lines as Array<Record<string, unknown>> | undefined\n if (!lines) return (block.text as string) || ''\n const texts: string[] = []\n for (const line of lines) {\n const spans = line.spans as Array<Record<string, unknown>> | undefined\n if (spans) {\n for (const span of spans) {\n if (span.content) texts.push(String(span.content))\n }\n }\n }\n return texts.join(' ') || (block.text as string) || ''\n}\n\n// \u2500\u2500 Block parser (supports layout.json, middle.json, content_list.json) \u2500\u2500\n\nexport function parseBlocks(jsonStr: string): PdfBlock[] {\n const result: PdfBlock[] = []\n try {\n const data = JSON.parse(jsonStr)\n\n // layout.json / middle.json: { pdf_info: [{ preproc_blocks, ... }, ...] }\n if (data.pdf_info && Array.isArray(data.pdf_info)) {\n const walkLayout = (items: Record<string, unknown>[], pageIdx: number) => {\n for (const item of items) {\n if (!item.bbox) continue\n const childBlocks = item.blocks as Record<string, unknown>[] | undefined\n if (childBlocks && childBlocks.length > 0) {\n walkLayout(childBlocks, pageIdx)\n } else {\n result.push({\n page_idx: pageIdx,\n bbox: item.bbox as [number, number, number, number],\n text: extractSpanText(item) || undefined,\n type: item.type as string | undefined,\n })\n }\n }\n }\n for (let i = 0; i < data.pdf_info.length; i++) {\n const page = data.pdf_info[i] as Record<string, unknown>\n const blocks = (page.preproc_blocks || page.para_blocks || []) as Record<string, unknown>[]\n walkLayout(blocks, i)\n }\n return result\n }\n\n // content_list.json: [{ page_idx, bbox, text, type, children?, blocks? }, ...]\n if (!Array.isArray(data)) return result\n const walk = (items: Record<string, unknown>[]) => {\n for (const item of items) {\n const idx = (item.page_idx ?? item.page_index) as number | undefined\n if (idx !== undefined && item.bbox) {\n result.push({\n page_idx: idx,\n bbox: item.bbox as [number, number, number, number],\n text: (item.text as string) || undefined,\n type: (item.category || item.type) as string | undefined,\n })\n }\n if (Array.isArray(item.children)) walk(item.children as Record<string, unknown>[])\n if (Array.isArray(item.blocks)) walk(item.blocks as Record<string, unknown>[])\n }\n }\n walk(data)\n } catch { /* ignore parse errors */ }\n return result\n}\n", "import type { PdfBlock, MdSection } from './parse-blocks.js'\n\n// \u2500\u2500 Text normalization \u2500\u2500\n\nexport function normalize(s: string): string {\n return s\n .replace(/[#*\\s\\n\\r\\t`~|>\\\\[\\]()]+/g, ' ')\n .replace(/\\s{2,}/g, ' ')\n .trim()\n .toLowerCase()\n}\n\n// \u2500\u2500 LCS-based similarity (longest common substring) \u2500\u2500\n\nexport function lcsSimilarity(a: string, b: string): number {\n const shorter = a.length < b.length ? a : b\n const longer = a.length < b.length ? b : a\n if (shorter.length === 0) return 0\n\n let maxLen = 0\n const window = Math.min(shorter.length, 30)\n for (let i = 0; i < shorter.length; i++) {\n if (shorter.length - i <= maxLen) break\n for (let len = window; len > maxLen; len--) {\n const sub = shorter.substring(i, i + len)\n if (sub.length < 4) continue\n if (longer.includes(sub)) {\n maxLen = sub.length\n break\n }\n }\n }\n return maxLen / Math.max(shorter.length, 1)\n}\n\n// \u2500\u2500 Match markdown paragraphs to PDF blocks \u2500\u2500\n\nexport function matchMarkdownToPdf(\n markdown: string,\n blocks: PdfBlock[],\n): MdSection[] {\n // Split by line breaks \u2014 layout.json / middle.json blocks are line-level\n const paragraphs = markdown.split(/\\n+/).filter((p) => p.trim())\n const textBlocks = blocks.filter(\n (b) => b.text && b.text.trim().length > 1,\n )\n\n if (textBlocks.length === 0) {\n return paragraphs.map((p) => ({ text: p, page: 1, bbox: null }))\n }\n\n return paragraphs.map((para) => {\n const norm = normalize(para)\n if (norm.length < 4) {\n return { text: para, page: textBlocks[0].page_idx + 1, bbox: textBlocks[0].bbox }\n }\n\n let best: PdfBlock | null = null\n let bestScore = 0\n\n // First pass: skip table internals\n const topBlocks = textBlocks.filter(\n (b) => b.type !== 'table-body' && b.type !== 'table-row',\n )\n for (const b of topBlocks) {\n const s = lcsSimilarity(norm, normalize(b.text!))\n if (s > bestScore) {\n bestScore = s\n best = b\n }\n }\n\n // Fallback: include table blocks\n if (bestScore < 0.2) {\n for (const b of textBlocks) {\n const s = lcsSimilarity(norm, normalize(b.text!))\n if (s > bestScore) {\n bestScore = s\n best = b\n }\n }\n }\n\n // If nothing matches well, estimate by paragraph position\n if (!best || bestScore < 0.1) {\n const ratio =\n paragraphs.indexOf(para) / Math.max(paragraphs.length, 1)\n const estPage = Math.floor(\n ratio *\n (blocks.length > 0\n ? Math.max(...blocks.map((b) => b.page_idx)) + 1\n : 1),\n )\n return { text: para, page: estPage + 1, bbox: null }\n }\n\n return { text: para, page: best.page_idx + 1, bbox: best.bbox }\n })\n}\n", "import { parseBlocks } from './parse-blocks.js'\nimport { matchMarkdownToPdf } from './match-markdown.js'\nimport type { PdfBlock, MdSection } from './parse-blocks.js'\nimport { normalize, lcsSimilarity } from './match-markdown.js'\n\n// We load pdf.js worker from CDN \u2014 consumer can override via window.PDFJS_WORKER_SRC\ndeclare const pdfjsLib: typeof import('pdfjs-dist')\n\nconst RENDER_SCALE = 2.0\n\nconst STYLES = `\n:host { display: flex; flex-direction: column; height: 100%; font-family: system-ui, sans-serif; color-scheme: light dark; }\n.toolbar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-bottom: 1px solid #e5e5e5; font-size: 12px; color: #888; flex-shrink: 0; flex-wrap: wrap; }\n.toolbar .sep { color: #ddd; }\n.toolbar .ok { color: #16a34a; }\n.toolbar .warn { color: #f59e0b; }\n@media (prefers-color-scheme: dark) {\n .toolbar { border-color: #333; }\n .toolbar .sep { color: #555; }\n}\n.split { flex: 1; display: grid; grid-template-columns: 1fr 1fr; min-height: 0; overflow: hidden; }\n.pane { overflow: auto; padding: 10px; }\n.pane-left { border-right: 1px solid #e5e5e5; }\n.pane-right { background: #f9f9f9; }\n@media (prefers-color-scheme: dark) {\n .pane-left { border-color: #333; }\n .pane-right { background: #1e1e1e; }\n}\n.pdf-page { position: relative; margin: 0 auto 12px; border: 1px solid #e5e5e5; border-radius: 4px; overflow: hidden; }\n.pdf-page img { display: block; width: 100%; }\n.pdf-page .page-num { position: absolute; bottom: 2px; right: 4px; font-size: 9px; color: #999; background: rgba(255,255,255,.85); padding: 1px 4px; border-radius: 3px; }\n@media (prefers-color-scheme: dark) { .pdf-page { border-color: #333; } .pdf-page .page-num { background: rgba(0,0,0,.7); } }\n.block-overlay { position: absolute; border: 1px solid transparent; cursor: pointer; transition: all .15s; }\n.block-overlay:hover { border-color: #f59e0b; background: rgba(245,158,11,.12); }\n.block-overlay.active { border-color: #3b82f6 !important; background: rgba(59,130,246,.2) !important; z-index: 10; box-shadow: 0 0 0 1px #3b82f6; }\n.md-line { display: block; cursor: pointer; padding: 2px 8px; border-radius: 4px; border-left: 2px solid transparent; font-size: 13px; line-height: 1.5; font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace; white-space: pre-wrap; word-break: break-all; }\n.md-line.match { border-left-color: rgba(245,158,11,.4); }\n.md-line.match:hover { background: rgba(245,158,11,.08); }\n.md-line.no-match { color: #999; opacity: .6; }\n.md-line.active { background: rgba(59,130,246,.1); border-left-color: #3b82f6; box-shadow: inset 0 0 0 1px rgba(59,130,246,.3); }\n@media (prefers-color-scheme: dark) { .md-line.active { background: rgba(59,130,246,.15); } }\n.md-line .badge { font-size: 10px; color: #999; margin-left: 6px; }\n`\n\nexport class MineruLayoutViewer extends HTMLElement {\n private blocks: PdfBlock[] = []\n private sections: MdSection[] = []\n private pages: { p: number; w: number; h: number; src: string }[] = []\n private activeIdx: number | null = null\n private pdfUrl: string | null = null\n private layoutData: string | null = null\n private markdownText: string | null = null\n\n static observedAttributes = ['pdf', 'layout', 'markdown']\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.setupResize()\n }\n\n attributeChangedCallback(name: string, _old: string | null, newVal: string | null) {\n if (name === 'pdf' && newVal) {\n this.pdfUrl = newVal\n this.loadPdf(newVal)\n }\n if (name === 'layout' && newVal) {\n this.loadLayout(newVal)\n }\n if (name === 'markdown' && newVal) {\n this.markdownText = newVal\n this.rebuild()\n }\n }\n\n // \u2500\u2500 Public API \u2500\u2500\n\n set pdf(value: string) { this.setAttribute('pdf', value) }\n get pdf(): string { return this.getAttribute('pdf') || '' }\n\n set layout(value: string) { this.setAttribute('layout', value) }\n get layout(): string { return this.getAttribute('layout') || '' }\n\n set markdown(value: string) { this.setAttribute('markdown', value) }\n get markdown(): string { return this.getAttribute('markdown') || '' }\n\n /** Programmatic API: load layout JSON directly */\n async loadLayoutFromJson(data: Record<string, unknown> | string) {\n const jsonStr = typeof data === 'string' ? data : JSON.stringify(data)\n this.layoutData = jsonStr\n if (this.pdfUrl) this.rebuild()\n }\n\n /** Programmatic API: load markdown text directly */\n async loadMarkdown(text: string) {\n this.markdownText = text\n if (this.layoutData) this.rebuild()\n }\n\n /** Programmatic API: load PDF + layout from a MinerU zip Blob */\n async loadZip(zipBlob: Blob) {\n const JSZip = (window as any).JSZip || await import('jszip').then(m => m.default)\n const zip = await JSZip.loadAsync(zipBlob)\n let jsonStr = ''\n\n for (const name of ['layout.json', 'middle.json']) {\n const f = zip.file(name); if (f) { jsonStr = await f.async('text'); break }\n }\n if (!jsonStr) {\n for (const name of Object.keys(zip.files)) {\n if (name.endsWith('_layout.json') || name.endsWith('_middle.json')) {\n jsonStr = await zip.file(name)!.async('text'); break\n }\n }\n }\n if (!jsonStr) {\n for (const name of Object.keys(zip.files)) {\n if (name.endsWith('_content_list.json')) {\n jsonStr = await zip.file(name)!.async('text'); break\n }\n }\n }\n\n const mdFile = zip.file('full.md')\n if (mdFile) this.markdownText = await mdFile.async('text')\n\n this.layoutData = jsonStr\n\n // Find PDF\n for (const name of Object.keys(zip.files)) {\n if (name.endsWith('_origin.pdf')) {\n const blob = await zip.file(name)!.async('blob')\n this.pdfUrl = URL.createObjectURL(blob)\n break\n }\n }\n\n if (this.layoutData) this.rebuild()\n else throw new Error('zip \u7F3A\u5C11 layout.json \u6216 middle.json')\n }\n\n // \u2500\u2500 Internal \u2500\u2500\n\n private render() {\n if (!this.shadowRoot) return\n this.shadowRoot.innerHTML = `<style>${STYLES}</style>\n <div class=\"toolbar\">\n <span id=\"stat\"></span><span class=\"flex-1\" style=\"flex:1\"></span>\n </div>\n <div class=\"split\">\n <div class=\"pane pane-left\" id=\"pdfPane\"><slot name=\"loading\">\u52A0\u8F7D PDF + layout.json \u4EE5\u5F00\u59CB</slot></div>\n <div class=\"pane pane-right\" id=\"mdPane\"></div>\n </div>`\n }\n\n private setupResize() {\n const ro = new ResizeObserver(() => this.buildPdfOverlays())\n const pane = this.shadowRoot?.getElementById('pdfPane')\n if (pane) ro.observe(pane)\n }\n\n private async loadPdf(url: string) {\n this.pdfUrl = url\n if (this.layoutData || this.markdownText) await this.rebuild()\n }\n\n private async loadLayout(url: string) {\n const res = await fetch(url)\n this.layoutData = await res.text()\n if (this.pdfUrl) await this.rebuild()\n }\n\n private async rebuild() {\n if (!this.layoutData) return\n this.blocks = parseBlocks(this.layoutData)\n const md = this.markdownText || this.blocks.map(b => b.text || '').filter(Boolean).join('\\n')\n this.sections = matchMarkdownToPdf(md, this.blocks)\n if (this.pdfUrl) await this.renderPdfPages()\n this.buildUI()\n }\n\n private async renderPdfPages() {\n if (!this.pdfUrl) return\n const pdf = await pdfjsLib.getDocument(this.pdfUrl).promise\n this.pages = []\n for (let i = 1; i <= pdf.numPages; i++) {\n const page = await pdf.getPage(i)\n const vp = page.getViewport({ scale: RENDER_SCALE })\n const cvs = document.createElement('canvas')\n cvs.width = vp.width; cvs.height = vp.height\n await page.render({ canvasContext: cvs.getContext('2d')!, viewport: vp }).promise\n this.pages.push({ p: i, w: vp.width, h: vp.height, src: cvs.toDataURL() })\n page.cleanup()\n }\n pdf.destroy()\n }\n\n private buildUI() {\n const shadow = this.shadowRoot!\n const matched = this.sections.filter(s => s.bbox).length\n shadow.getElementById('stat')!.innerHTML =\n `${this.pages.length} \u9875 | ${this.sections.length} \u884C | <span class=\"${matched > 0 ? 'ok' : 'warn'}\">\u5339\u914D ${matched}</span> | ${this.blocks.length} \u5757`\n this.buildPdfOverlays()\n this.buildMarkdown()\n }\n\n private buildPdfOverlays() {\n const pane = this.shadowRoot!.getElementById('pdfPane')!\n pane.innerHTML = ''\n const containerW = pane.clientWidth - 20\n if (containerW <= 0 || this.pages.length === 0) return\n\n for (const rp of this.pages) {\n const cssW = containerW\n const cssH = rp.h * (containerW / rp.w)\n const pageBlocks = this.blocks.filter(b => b.page_idx === rp.p - 1)\n const pageScale = containerW / rp.w\n const s = RENDER_SCALE * pageScale\n\n const wrapper = document.createElement('div')\n wrapper.className = 'pdf-page'\n wrapper.style.width = cssW + 'px'; wrapper.style.height = cssH + 'px'\n wrapper.dataset.page = String(rp.p)\n\n const img = document.createElement('img'); img.src = rp.src\n wrapper.appendChild(img)\n const label = document.createElement('span'); label.className = 'page-num'; label.textContent = String(rp.p)\n wrapper.appendChild(label)\n\n for (const b of pageBlocks) {\n const [x0, y0, x1, y1] = b.bbox\n const ov = document.createElement('div'); ov.className = 'block-overlay'\n ov.style.left = (x0 * s) + 'px'; ov.style.top = (y0 * s) + 'px'\n ov.style.width = Math.max((x1 - x0) * s, 2) + 'px'\n ov.style.height = Math.max((y1 - y0) * s, 2) + 'px'\n ov.title = (b.text || '').slice(0, 120)\n ov.addEventListener('click', () => this.onBlockClick(b, ov))\n wrapper.appendChild(ov)\n }\n pane.appendChild(wrapper)\n }\n }\n\n private buildMarkdown() {\n const pane = this.shadowRoot!.getElementById('mdPane')!\n pane.innerHTML = ''\n for (let i = 0; i < this.sections.length; i++) {\n const sec = this.sections[i]\n const el = document.createElement('span')\n el.className = 'md-line' + (sec.bbox ? ' match' : ' no-match')\n el.dataset.idx = String(i)\n el.textContent = sec.text\n if (sec.bbox) { const b = document.createElement('span'); b.className = 'badge'; b.textContent = `p${sec.page}`; el.appendChild(b) }\n el.addEventListener('click', () => this.onMdClick(sec, i, el))\n pane.appendChild(el)\n }\n }\n\n private onMdClick(sec: MdSection, idx: number, el: HTMLElement) {\n const shadow = this.shadowRoot!\n shadow.querySelectorAll('.md-line.active').forEach(e => e.classList.remove('active'))\n shadow.querySelectorAll('.block-overlay.active').forEach(e => e.classList.remove('active'))\n el.classList.add('active'); this.activeIdx = idx\n if (sec.bbox) {\n const pageEl = shadow.querySelector(`.pdf-page[data-page=\"${sec.page}\"]`) as HTMLElement | null\n if (pageEl) pageEl.scrollIntoView({ behavior: 'smooth', block: 'start' })\n const overlays = shadow.querySelectorAll(`.pdf-page[data-page=\"${sec.page}\"] .block-overlay`)\n const page = this.pages[sec.page - 1]\n if (page) {\n const pw = shadow.getElementById('pdfPane')!.clientWidth - 20\n const s = RENDER_SCALE * (pw / page.w)\n overlays.forEach(ov => {\n const el2 = ov as HTMLElement\n if (Math.abs(parseFloat(el2.style.left) - sec.bbox![0] * s) < 4) {\n el2.classList.add('active'); el2.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n })\n }\n }\n }\n\n private onBlockClick(block: PdfBlock, ov: HTMLElement) {\n const shadow = this.shadowRoot!\n shadow.querySelectorAll('.md-line.active').forEach(e => e.classList.remove('active'))\n shadow.querySelectorAll('.block-overlay.active').forEach(e => e.classList.remove('active'))\n ov.classList.add('active')\n const blockNorm = normalize(block.text || '')\n let bestIdx = -1, bestSim = 0\n for (let i = 0; i < this.sections.length; i++) {\n if (!this.sections[i].bbox) continue\n const sim = lcsSimilarity(blockNorm, normalize(this.sections[i].text))\n if (sim > bestSim && sim > 0.05) { bestSim = sim; bestIdx = i }\n }\n if (bestIdx >= 0) {\n this.activeIdx = bestIdx\n const el = shadow.querySelector(`[data-idx=\"${bestIdx}\"]`) as HTMLElement | null\n if (el) { el.classList.add('active'); el.scrollIntoView({ behavior: 'smooth', block: 'center' }) }\n }\n }\n}\n\nif (typeof customElements !== 'undefined' && !customElements.get('mineru-layout-viewer')) {\n customElements.define('mineru-layout-viewer', MineruLayoutViewer)\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// \u2500\u2500 Block types \u2500\u2500\n\nexport interface PdfBlock {\n page_idx: number\n bbox: [number, number, number, number]\n text?: string\n type?: string\n}\n\nexport interface MdSection {\n text: string\n page: number\n bbox: [number, number, number, number] | null\n}\n\n// \u2500\u2500 Text extraction from layout.json / middle.json span structure \u2500\u2500\n\nexport function extractSpanText(block: Record<string, unknown>): string {\n const lines = block.lines as Array<Record<string, unknown>> | undefined\n if (!lines) return (block.text as string) || ''\n const texts: string[] = []\n for (const line of lines) {\n const spans = line.spans as Array<Record<string, unknown>> | undefined\n if (spans) {\n for (const span of spans) {\n if (span.content) texts.push(String(span.content))\n }\n }\n }\n return texts.join(' ') || (block.text as string) || ''\n}\n\n// \u2500\u2500 Block parser (supports layout.json, middle.json, content_list.json) \u2500\u2500\n\nexport function parseBlocks(jsonStr: string): PdfBlock[] {\n const result: PdfBlock[] = []\n try {\n const data = JSON.parse(jsonStr)\n\n // layout.json / middle.json: { pdf_info: [{ preproc_blocks, ... }, ...] }\n if (data.pdf_info && Array.isArray(data.pdf_info)) {\n const walkLayout = (items: Record<string, unknown>[], pageIdx: number) => {\n for (const item of items) {\n if (!item.bbox) continue\n const childBlocks = item.blocks as Record<string, unknown>[] | undefined\n if (childBlocks && childBlocks.length > 0) {\n walkLayout(childBlocks, pageIdx)\n } else {\n result.push({\n page_idx: pageIdx,\n bbox: item.bbox as [number, number, number, number],\n text: extractSpanText(item) || undefined,\n type: item.type as string | undefined,\n })\n }\n }\n }\n for (let i = 0; i < data.pdf_info.length; i++) {\n const page = data.pdf_info[i] as Record<string, unknown>\n const blocks = (page.preproc_blocks || page.para_blocks || []) as Record<string, unknown>[]\n walkLayout(blocks, i)\n }\n return result\n }\n\n // content_list.json: [{ page_idx, bbox, text, type, children?, blocks? }, ...]\n if (!Array.isArray(data)) return result\n const walk = (items: Record<string, unknown>[]) => {\n for (const item of items) {\n const idx = (item.page_idx ?? item.page_index) as number | undefined\n if (idx !== undefined && item.bbox) {\n result.push({\n page_idx: idx,\n bbox: item.bbox as [number, number, number, number],\n text: (item.text as string) || undefined,\n type: (item.category || item.type) as string | undefined,\n })\n }\n if (Array.isArray(item.children)) walk(item.children as Record<string, unknown>[])\n if (Array.isArray(item.blocks)) walk(item.blocks as Record<string, unknown>[])\n }\n }\n walk(data)\n } catch { /* ignore parse errors */ }\n return result\n}\n", "import type { PdfBlock, MdSection } from './parse-blocks.js'\n\n// \u2500\u2500 Text normalization \u2500\u2500\n\nexport function normalize(s: string): string {\n return s\n .replace(/[#*\\s\\n\\r\\t`~|>\\\\[\\]()]+/g, ' ')\n .replace(/\\s{2,}/g, ' ')\n .trim()\n .toLowerCase()\n}\n\n// \u2500\u2500 LCS-based similarity (longest common substring) \u2500\u2500\n\nexport function lcsSimilarity(a: string, b: string): number {\n const shorter = a.length < b.length ? a : b\n const longer = a.length < b.length ? b : a\n if (shorter.length === 0) return 0\n\n let maxLen = 0\n const window = Math.min(shorter.length, 30)\n for (let i = 0; i < shorter.length; i++) {\n if (shorter.length - i <= maxLen) break\n for (let len = window; len > maxLen; len--) {\n const sub = shorter.substring(i, i + len)\n if (sub.length < 4) continue\n if (longer.includes(sub)) {\n maxLen = sub.length\n break\n }\n }\n }\n return maxLen / Math.max(shorter.length, 1)\n}\n\n// \u2500\u2500 Match markdown paragraphs to PDF blocks \u2500\u2500\n\nexport function matchMarkdownToPdf(\n markdown: string,\n blocks: PdfBlock[],\n): MdSection[] {\n // Split by line breaks \u2014 layout.json / middle.json blocks are line-level\n const paragraphs = markdown.split(/\\n+/).filter((p) => p.trim())\n const textBlocks = blocks.filter(\n (b) => b.text && b.text.trim().length > 1,\n )\n\n if (textBlocks.length === 0) {\n return paragraphs.map((p) => ({ text: p, page: 1, bbox: null }))\n }\n\n return paragraphs.map((para) => {\n const norm = normalize(para)\n if (norm.length < 4) {\n return { text: para, page: textBlocks[0].page_idx + 1, bbox: textBlocks[0].bbox }\n }\n\n let best: PdfBlock | null = null\n let bestScore = 0\n\n // First pass: skip table internals\n const topBlocks = textBlocks.filter(\n (b) => b.type !== 'table-body' && b.type !== 'table-row',\n )\n for (const b of topBlocks) {\n const s = lcsSimilarity(norm, normalize(b.text!))\n if (s > bestScore) {\n bestScore = s\n best = b\n }\n }\n\n // Fallback: include table blocks\n if (bestScore < 0.2) {\n for (const b of textBlocks) {\n const s = lcsSimilarity(norm, normalize(b.text!))\n if (s > bestScore) {\n bestScore = s\n best = b\n }\n }\n }\n\n // If nothing matches well, estimate by paragraph position\n if (!best || bestScore < 0.1) {\n const ratio =\n paragraphs.indexOf(para) / Math.max(paragraphs.length, 1)\n const estPage = Math.floor(\n ratio *\n (blocks.length > 0\n ? Math.max(...blocks.map((b) => b.page_idx)) + 1\n : 1),\n )\n return { text: para, page: estPage + 1, bbox: null }\n }\n\n return { text: para, page: best.page_idx + 1, bbox: best.bbox }\n })\n}\n", "import { parseBlocks } from './parse-blocks.js'\nimport { matchMarkdownToPdf } from './match-markdown.js'\nimport type { PdfBlock, MdSection } from './parse-blocks.js'\nimport { normalize, lcsSimilarity } from './match-markdown.js'\n\n// We load pdf.js worker from CDN \u2014 consumer can override via window.PDFJS_WORKER_SRC\ndeclare const pdfjsLib: typeof import('pdfjs-dist')\n\nconst RENDER_SCALE = 2.0\n\nconst STYLES = `\n:host { display: flex; flex-direction: column; height: 100%; font-family: system-ui, sans-serif; color-scheme: light dark; }\n.toolbar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-bottom: 1px solid #e5e5e5; font-size: 12px; color: #888; flex-shrink: 0; flex-wrap: wrap; }\n.toolbar .sep { color: #ddd; }\n.toolbar .ok { color: #16a34a; }\n.toolbar .warn { color: #f59e0b; }\n@media (prefers-color-scheme: dark) {\n .toolbar { border-color: #333; }\n .toolbar .sep { color: #555; }\n}\n.split { flex: 1; display: grid; grid-template-columns: 1fr 1fr; min-height: 0; overflow: hidden; }\n.pane { overflow: auto; padding: 10px; }\n.pane-left { border-right: 1px solid #e5e5e5; background: #fff; }\n.pane-right { background: #fff; }\n.pdf-page { position: relative; margin: 0 auto 12px; border: 1px solid #e5e5e5; border-radius: 4px; overflow: hidden; }\n.pdf-page img { display: block; width: 100%; }\n.pdf-page .page-num { position: absolute; bottom: 2px; right: 4px; font-size: 9px; color: #999; background: rgba(255,255,255,.85); padding: 1px 4px; border-radius: 3px; }\n@media (prefers-color-scheme: dark) { .pdf-page { border-color: #333; } .pdf-page .page-num { background: rgba(0,0,0,.7); } }\n.block-overlay { position: absolute; border: 1px solid transparent; cursor: pointer; transition: all .15s; }\n.block-overlay:hover { border-color: #f59e0b; background: rgba(245,158,11,.12); }\n.block-overlay.active { border-color: #3b82f6 !important; background: rgba(59,130,246,.2) !important; z-index: 10; box-shadow: 0 0 0 1px #3b82f6; }\n.md-line { display: block; cursor: pointer; padding: 2px 8px; border-radius: 4px; border-left: 2px solid transparent; font-size: 13px; line-height: 1.5; font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace; white-space: pre-wrap; word-break: break-all; }\n.md-line.match { border-left-color: rgba(245,158,11,.4); }\n.md-line.match:hover { background: rgba(245,158,11,.08); }\n.md-line.no-match { color: #999; opacity: .6; }\n.md-line.active { background: rgba(59,130,246,.1); border-left-color: #3b82f6; box-shadow: inset 0 0 0 1px rgba(59,130,246,.3); }\n@media (prefers-color-scheme: dark) { .md-line.active { background: rgba(59,130,246,.15); } }\n.md-line .badge { font-size: 10px; color: #999; margin-left: 6px; }\n`\n\nexport class MineruLayoutViewer extends HTMLElement {\n private blocks: PdfBlock[] = []\n private sections: MdSection[] = []\n private pages: { p: number; w: number; h: number; src: string }[] = []\n private activeIdx: number | null = null\n private pdfUrl: string | null = null\n private layoutData: string | null = null\n private markdownText: string | null = null\n\n static observedAttributes = ['pdf', 'layout', 'markdown']\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.setupResize()\n }\n\n attributeChangedCallback(name: string, _old: string | null, newVal: string | null) {\n if (name === 'pdf' && newVal) {\n this.pdfUrl = newVal\n this.loadPdf(newVal)\n }\n if (name === 'layout' && newVal) {\n this.loadLayout(newVal)\n }\n if (name === 'markdown' && newVal) {\n this.markdownText = newVal\n this.rebuild()\n }\n }\n\n // \u2500\u2500 Public API \u2500\u2500\n\n set pdf(value: string) { this.setAttribute('pdf', value) }\n get pdf(): string { return this.getAttribute('pdf') || '' }\n\n set layout(value: string) { this.setAttribute('layout', value) }\n get layout(): string { return this.getAttribute('layout') || '' }\n\n set markdown(value: string) { this.setAttribute('markdown', value) }\n get markdown(): string { return this.getAttribute('markdown') || '' }\n\n /** Programmatic API: load layout JSON directly */\n async loadLayoutFromJson(data: Record<string, unknown> | string) {\n const jsonStr = typeof data === 'string' ? data : JSON.stringify(data)\n this.layoutData = jsonStr\n if (this.pdfUrl) this.rebuild()\n }\n\n /** Programmatic API: load markdown text directly */\n async loadMarkdown(text: string) {\n this.markdownText = text\n if (this.layoutData) this.rebuild()\n }\n\n /** Programmatic API: load PDF + layout from a MinerU zip Blob */\n async loadZip(zipBlob: Blob) {\n const JSZip = (window as any).JSZip || await import('jszip').then(m => m.default)\n const zip = await JSZip.loadAsync(zipBlob)\n let jsonStr = ''\n\n for (const name of ['layout.json', 'middle.json']) {\n const f = zip.file(name); if (f) { jsonStr = await f.async('text'); break }\n }\n if (!jsonStr) {\n for (const name of Object.keys(zip.files)) {\n if (name.endsWith('_layout.json') || name.endsWith('_middle.json')) {\n jsonStr = await zip.file(name)!.async('text'); break\n }\n }\n }\n if (!jsonStr) {\n for (const name of Object.keys(zip.files)) {\n if (name.endsWith('_content_list.json')) {\n jsonStr = await zip.file(name)!.async('text'); break\n }\n }\n }\n\n const mdFile = zip.file('full.md')\n if (mdFile) this.markdownText = await mdFile.async('text')\n\n this.layoutData = jsonStr\n\n // Find PDF\n for (const name of Object.keys(zip.files)) {\n if (name.endsWith('_origin.pdf')) {\n const blob = await zip.file(name)!.async('blob')\n this.pdfUrl = URL.createObjectURL(blob)\n break\n }\n }\n\n if (this.layoutData) this.rebuild()\n else throw new Error('zip \u7F3A\u5C11 layout.json \u6216 middle.json')\n }\n\n // \u2500\u2500 Internal \u2500\u2500\n\n private render() {\n if (!this.shadowRoot) return\n this.shadowRoot.innerHTML = `<style>${STYLES}</style>\n <div class=\"toolbar\">\n <span id=\"stat\"></span>\n <span style=\"flex:1\"></span>\n <a href=\"https://www.npmjs.com/package/mineru-layout-viewer\" target=\"_blank\" title=\"npm\" style=\"color:inherit;display:flex;align-items:center;opacity:.5;transition:opacity .15s\" onmouseenter=\"this.style.opacity='1'\" onmouseleave=\"this.style.opacity='.5'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v1.336h-1.336v1.336h-2.668V8.667h5.334v5.331z\"/></svg>\n </a>\n <a href=\"https://github.com/rand777gg/mineru-layout-viewer\" target=\"_blank\" title=\"GitHub\" style=\"color:inherit;display:flex;align-items:center;opacity:.5;transition:opacity .15s;margin-left:4px\" onmouseenter=\"this.style.opacity='1'\" onmouseleave=\"this.style.opacity='.5'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z\"/></svg>\n </a>\n </div>\n <div class=\"split\">\n <div class=\"pane pane-left\" id=\"pdfPane\"><slot name=\"loading\">\u52A0\u8F7D PDF + layout.json \u4EE5\u5F00\u59CB</slot></div>\n <div class=\"pane pane-right\" id=\"mdPane\"></div>\n </div>`\n }\n\n private setupResize() {\n const ro = new ResizeObserver(() => this.buildPdfOverlays())\n const pane = this.shadowRoot?.getElementById('pdfPane')\n if (pane) ro.observe(pane)\n }\n\n private async loadPdf(url: string) {\n this.pdfUrl = url\n if (this.layoutData || this.markdownText) await this.rebuild()\n }\n\n private async loadLayout(url: string) {\n const res = await fetch(url)\n this.layoutData = await res.text()\n if (this.pdfUrl) await this.rebuild()\n }\n\n private async rebuild() {\n if (!this.layoutData) return\n this.blocks = parseBlocks(this.layoutData)\n const md = this.markdownText || this.blocks.map(b => b.text || '').filter(Boolean).join('\\n')\n this.sections = matchMarkdownToPdf(md, this.blocks)\n if (this.pdfUrl) await this.renderPdfPages()\n this.buildUI()\n }\n\n private async renderPdfPages() {\n if (!this.pdfUrl) return\n const pdf = await pdfjsLib.getDocument(this.pdfUrl).promise\n this.pages = []\n for (let i = 1; i <= pdf.numPages; i++) {\n const page = await pdf.getPage(i)\n const vp = page.getViewport({ scale: RENDER_SCALE })\n const cvs = document.createElement('canvas')\n cvs.width = vp.width; cvs.height = vp.height\n await page.render({ canvasContext: cvs.getContext('2d')!, viewport: vp }).promise\n this.pages.push({ p: i, w: vp.width, h: vp.height, src: cvs.toDataURL() })\n page.cleanup()\n }\n pdf.destroy()\n }\n\n private buildUI() {\n const shadow = this.shadowRoot!\n const matched = this.sections.filter(s => s.bbox).length\n shadow.getElementById('stat')!.innerHTML =\n `${this.pages.length} \u9875 | ${this.sections.length} \u884C | <span class=\"${matched > 0 ? 'ok' : 'warn'}\">\u5339\u914D ${matched}</span> | ${this.blocks.length} \u5757`\n this.buildPdfOverlays()\n this.buildMarkdown()\n }\n\n private buildPdfOverlays() {\n const pane = this.shadowRoot!.getElementById('pdfPane')!\n pane.innerHTML = ''\n const containerW = pane.clientWidth - 20\n if (containerW <= 0 || this.pages.length === 0) return\n\n for (const rp of this.pages) {\n const cssW = containerW\n const cssH = rp.h * (containerW / rp.w)\n const pageBlocks = this.blocks.filter(b => b.page_idx === rp.p - 1)\n const pageScale = containerW / rp.w\n const s = RENDER_SCALE * pageScale\n\n const wrapper = document.createElement('div')\n wrapper.className = 'pdf-page'\n wrapper.style.width = cssW + 'px'; wrapper.style.height = cssH + 'px'\n wrapper.dataset.page = String(rp.p)\n\n const img = document.createElement('img'); img.src = rp.src\n wrapper.appendChild(img)\n const label = document.createElement('span'); label.className = 'page-num'; label.textContent = String(rp.p)\n wrapper.appendChild(label)\n\n for (const b of pageBlocks) {\n const [x0, y0, x1, y1] = b.bbox\n const ov = document.createElement('div'); ov.className = 'block-overlay'\n ov.style.left = (x0 * s) + 'px'; ov.style.top = (y0 * s) + 'px'\n ov.style.width = Math.max((x1 - x0) * s, 2) + 'px'\n ov.style.height = Math.max((y1 - y0) * s, 2) + 'px'\n ov.title = (b.text || '').slice(0, 120)\n ov.addEventListener('click', () => this.onBlockClick(b, ov))\n wrapper.appendChild(ov)\n }\n pane.appendChild(wrapper)\n }\n }\n\n private buildMarkdown() {\n const pane = this.shadowRoot!.getElementById('mdPane')!\n pane.innerHTML = ''\n for (let i = 0; i < this.sections.length; i++) {\n const sec = this.sections[i]\n const el = document.createElement('span')\n el.className = 'md-line' + (sec.bbox ? ' match' : ' no-match')\n el.dataset.idx = String(i)\n el.textContent = sec.text\n if (sec.bbox) { const b = document.createElement('span'); b.className = 'badge'; b.textContent = `p${sec.page}`; el.appendChild(b) }\n el.addEventListener('click', () => this.onMdClick(sec, i, el))\n pane.appendChild(el)\n }\n }\n\n private onMdClick(sec: MdSection, idx: number, el: HTMLElement) {\n const shadow = this.shadowRoot!\n shadow.querySelectorAll('.md-line.active').forEach(e => e.classList.remove('active'))\n shadow.querySelectorAll('.block-overlay.active').forEach(e => e.classList.remove('active'))\n el.classList.add('active'); this.activeIdx = idx\n if (sec.bbox) {\n const pageEl = shadow.querySelector(`.pdf-page[data-page=\"${sec.page}\"]`) as HTMLElement | null\n if (pageEl) pageEl.scrollIntoView({ behavior: 'smooth', block: 'start' })\n const overlays = shadow.querySelectorAll(`.pdf-page[data-page=\"${sec.page}\"] .block-overlay`)\n const page = this.pages[sec.page - 1]\n if (page) {\n const pw = shadow.getElementById('pdfPane')!.clientWidth - 20\n const s = RENDER_SCALE * (pw / page.w)\n overlays.forEach(ov => {\n const el2 = ov as HTMLElement\n const dx = Math.abs(parseFloat(el2.style.left) - sec.bbox![0] * s)\n const dy = Math.abs(parseFloat(el2.style.top) - sec.bbox![1] * s)\n if (dx < 2 && dy < 2) {\n el2.classList.add('active'); el2.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n })\n }\n }\n }\n\n private onBlockClick(block: PdfBlock, ov: HTMLElement) {\n const shadow = this.shadowRoot!\n shadow.querySelectorAll('.md-line.active').forEach(e => e.classList.remove('active'))\n shadow.querySelectorAll('.block-overlay.active').forEach(e => e.classList.remove('active'))\n ov.classList.add('active')\n const blockNorm = normalize(block.text || '')\n let bestIdx = -1, bestSim = 0\n for (let i = 0; i < this.sections.length; i++) {\n if (!this.sections[i].bbox) continue\n const sim = lcsSimilarity(blockNorm, normalize(this.sections[i].text))\n if (sim > bestSim && sim > 0.05) { bestSim = sim; bestIdx = i }\n }\n if (bestIdx >= 0) {\n this.activeIdx = bestIdx\n const el = shadow.querySelector(`[data-idx=\"${bestIdx}\"]`) as HTMLElement | null\n if (el) { el.classList.add('active'); el.scrollIntoView({ behavior: 'smooth', block: 'center' }) }\n }\n }\n}\n\nif (typeof customElements !== 'undefined' && !customElements.get('mineru-layout-viewer')) {\n customElements.define('mineru-layout-viewer', MineruLayoutViewer)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["window"]
|
|
7
7
|
}
|
|
@@ -2556,12 +2556,8 @@ var MineruViewer = (() => {
|
|
|
2556
2556
|
}
|
|
2557
2557
|
.split { flex: 1; display: grid; grid-template-columns: 1fr 1fr; min-height: 0; overflow: hidden; }
|
|
2558
2558
|
.pane { overflow: auto; padding: 10px; }
|
|
2559
|
-
.pane-left { border-right: 1px solid #e5e5e5; }
|
|
2560
|
-
.pane-right { background: #
|
|
2561
|
-
@media (prefers-color-scheme: dark) {
|
|
2562
|
-
.pane-left { border-color: #333; }
|
|
2563
|
-
.pane-right { background: #1e1e1e; }
|
|
2564
|
-
}
|
|
2559
|
+
.pane-left { border-right: 1px solid #e5e5e5; background: #fff; }
|
|
2560
|
+
.pane-right { background: #fff; }
|
|
2565
2561
|
.pdf-page { position: relative; margin: 0 auto 12px; border: 1px solid #e5e5e5; border-radius: 4px; overflow: hidden; }
|
|
2566
2562
|
.pdf-page img { display: block; width: 100%; }
|
|
2567
2563
|
.pdf-page .page-num { position: absolute; bottom: 2px; right: 4px; font-size: 9px; color: #999; background: rgba(255,255,255,.85); padding: 1px 4px; border-radius: 3px; }
|
|
@@ -2683,7 +2679,14 @@ var MineruViewer = (() => {
|
|
|
2683
2679
|
if (!this.shadowRoot) return;
|
|
2684
2680
|
this.shadowRoot.innerHTML = `<style>${STYLES}</style>
|
|
2685
2681
|
<div class="toolbar">
|
|
2686
|
-
<span id="stat"></span
|
|
2682
|
+
<span id="stat"></span>
|
|
2683
|
+
<span style="flex:1"></span>
|
|
2684
|
+
<a href="https://www.npmjs.com/package/mineru-layout-viewer" target="_blank" title="npm" style="color:inherit;display:flex;align-items:center;opacity:.5;transition:opacity .15s" onmouseenter="this.style.opacity='1'" onmouseleave="this.style.opacity='.5'">
|
|
2685
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v1.336h-1.336v1.336h-2.668V8.667h5.334v5.331z"/></svg>
|
|
2686
|
+
</a>
|
|
2687
|
+
<a href="https://github.com/rand777gg/mineru-layout-viewer" target="_blank" title="GitHub" style="color:inherit;display:flex;align-items:center;opacity:.5;transition:opacity .15s;margin-left:4px" onmouseenter="this.style.opacity='1'" onmouseleave="this.style.opacity='.5'">
|
|
2688
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
|
|
2689
|
+
</a>
|
|
2687
2690
|
</div>
|
|
2688
2691
|
<div class="split">
|
|
2689
2692
|
<div class="pane pane-left" id="pdfPane"><slot name="loading">\u52A0\u8F7D PDF + layout.json \u4EE5\u5F00\u59CB</slot></div>
|
|
@@ -2808,7 +2811,9 @@ var MineruViewer = (() => {
|
|
|
2808
2811
|
const s = RENDER_SCALE * (pw / page.w);
|
|
2809
2812
|
overlays.forEach((ov) => {
|
|
2810
2813
|
const el2 = ov;
|
|
2811
|
-
|
|
2814
|
+
const dx = Math.abs(parseFloat(el2.style.left) - sec.bbox[0] * s);
|
|
2815
|
+
const dy = Math.abs(parseFloat(el2.style.top) - sec.bbox[1] * s);
|
|
2816
|
+
if (dx < 2 && dy < 2) {
|
|
2812
2817
|
el2.classList.add("active");
|
|
2813
2818
|
el2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
2814
2819
|
}
|