@veltra/desktop 1.7.13 → 1.7.16
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/components/batch-edit/batch-edit-form.js +9 -3
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit-list.js +2 -1
- package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +57 -30
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/style.d.ts +1 -0
- package/dist/components/batch-edit/style.js +1 -0
- package/dist/components/batch-edit/style2.css +14 -0
- package/dist/components/batch-edit/use-dialog-effect.js +20 -0
- package/dist/components/batch-edit/use-dialog-effect.js.map +1 -0
- package/dist/components/batch-edit/use-edit-state.js +22 -3
- package/dist/components/batch-edit/use-edit-state.js.map +1 -1
- package/dist/components/batch-edit/use-handlers.js +5 -0
- package/dist/components/batch-edit/use-handlers.js.map +1 -1
- package/dist/components/batch-edit/use-shortcut-key.js +5 -2
- package/dist/components/batch-edit/use-shortcut-key.js.map +1 -1
- package/dist/components/button/button.js +2 -2
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/file-viewer/file-viewer.js +21 -14
- package/dist/components/file-viewer/file-viewer.js.map +1 -1
- package/dist/components/file-viewer/helper.js +2 -0
- package/dist/components/file-viewer/helper.js.map +1 -1
- package/dist/components/file-viewer/previewers/ofd-previewer.js +196 -0
- package/dist/components/file-viewer/previewers/ofd-previewer.js.map +1 -0
- package/dist/components/file-viewer/style2.css +27 -0
- package/dist/components/form-item/style2.css +17 -2
- package/dist/components/table-editor/style2.css +48 -5
- package/dist/components/table-editor/table-editor.js +228 -63
- package/dist/components/table-editor/table-editor.js.map +1 -1
- package/dist/components/tip/style2.css +63 -0
- package/dist/components/tip/tip.js +6 -1
- package/dist/components/tip/tip.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/packages/ofd-core/dist/color.js +69 -0
- package/dist/packages/ofd-core/dist/color.js.map +1 -0
- package/dist/packages/ofd-core/dist/ctm.js +55 -0
- package/dist/packages/ofd-core/dist/ctm.js.map +1 -0
- package/dist/packages/ofd-core/dist/error.js +14 -0
- package/dist/packages/ofd-core/dist/error.js.map +1 -0
- package/dist/packages/ofd-core/dist/font.js +384 -0
- package/dist/packages/ofd-core/dist/font.js.map +1 -0
- package/dist/packages/ofd-core/dist/index.js +6 -0
- package/dist/packages/ofd-core/dist/number.js +13 -0
- package/dist/packages/ofd-core/dist/number.js.map +1 -0
- package/dist/packages/ofd-core/dist/page-objects.js +181 -0
- package/dist/packages/ofd-core/dist/page-objects.js.map +1 -0
- package/dist/packages/ofd-core/dist/parse.js +65 -0
- package/dist/packages/ofd-core/dist/parse.js.map +1 -0
- package/dist/packages/ofd-core/dist/render.js +361 -0
- package/dist/packages/ofd-core/dist/render.js.map +1 -0
- package/dist/packages/ofd-core/dist/xml.js +199 -0
- package/dist/packages/ofd-core/dist/xml.js.map +1 -0
- package/dist/packages/ofd-core/dist/zip.js +93 -0
- package/dist/packages/ofd-core/dist/zip.js.map +1 -0
- package/dist/style.d.ts +1 -1
- package/dist/style.js +1 -1
- package/dist/types/batch-edit.d.ts +6 -0
- package/dist/types/file-viewer.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/table-editor.d.ts +28 -7
- package/dist/types/tip.d.ts +5 -1
- package/package.json +8 -7
- package/src/components/batch-edit/__test__/batch-edit.test.ts +191 -4
- package/src/components/batch-edit/batch-edit-form.vue +17 -3
- package/src/components/batch-edit/batch-edit-list.vue +2 -1
- package/src/components/batch-edit/batch-edit.vue +22 -4
- package/src/components/batch-edit/style.scss +20 -0
- package/src/components/batch-edit/style.ts +1 -0
- package/src/components/batch-edit/use-dialog-effect.ts +9 -3
- package/src/components/batch-edit/use-edit-state.ts +32 -4
- package/src/components/batch-edit/use-handlers.ts +10 -0
- package/src/components/batch-edit/use-shortcut-key.ts +6 -2
- package/src/components/button/button.vue +3 -2
- package/src/components/file-viewer/__test__/helper.test.ts +13 -0
- package/src/components/file-viewer/file-viewer.vue +23 -16
- package/src/components/file-viewer/helper.ts +2 -0
- package/src/components/file-viewer/previewers/ofd-previewer.vue +216 -0
- package/src/components/file-viewer/style.scss +33 -0
- package/src/components/form-item/style.scss +11 -1
- package/src/components/table-editor/__test__/table-editor.test.ts +479 -0
- package/src/components/table-editor/style.scss +57 -5
- package/src/components/table-editor/table-editor.vue +286 -38
- package/src/components/tip/style.scss +15 -0
- package/src/components/tip/tip.vue +1 -1
- package/src/types/batch-edit.ts +6 -0
- package/src/types/file-viewer.ts +1 -1
- package/src/types/table-editor.ts +29 -7
- package/src/types/tip.ts +6 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font.js","names":[],"sources":["../../../../../ofd-core/dist/font.js"],"sourcesContent":["import { OfdParseError } from \"./error.js\";\nimport { formatNumber } from \"./number.js\";\n//#region src/font.ts\n/**\n* 内嵌 TTF 字体解析与 glyph 轮廓输出(OFD Font@FontFile 声明的内嵌字体)。\n*\n* 读取 TrueType 的 head/maxp/cmap/loca/glyf/hhea/hmtx 表:cmap 把字符码点映射到\n* glyph id(可省,省略时字符映射由渲染层 CGTransform 字形序号提供),glyf 提取\n* 轮廓点(on/off curve,复合 glyph 递归展开并平移/缩放)。\n* 二次贝塞尔轮廓按 unitsPerEm → 字号缩放、基线定位并翻转 y 轴后转成 SVG path\n* `d`。二进制结构非法时抛 OfdParseError('invalid-font')。\n*/\n/** 解析 TTF 二进制:结构非法抛 OfdParseError('invalid-font') */\nfunction parseEmbeddedFont(data, source) {\n\tif (data.length < 12) throw new OfdParseError(\"invalid-font\", `字体 ${source} 数据太短,不是 TTF 文件`);\n\tconst tables = parseTableDirectory(data, source);\n\tfor (const tag of REQUIRED_TABLES) {\n\t\tconst table = tables.get(tag);\n\t\tif (!table) throw new OfdParseError(\"invalid-font\", `字体 ${source} 缺少 ${tag} 表`);\n\t\tif (table.offset + table.length > data.length) throw new OfdParseError(\"invalid-font\", `字体 ${source} 的 ${tag} 表越界,数据被截断`);\n\t}\n\tconst headOffset = tables.get(\"head\").offset;\n\tconst unitsPerEm = new FontReader(data, source, headOffset + 18).u16();\n\tif (unitsPerEm === 0) throw new OfdParseError(\"invalid-font\", `字体 ${source} 的 unitsPerEm 为 0`);\n\tconst indexToLocFormat = new FontReader(data, source, headOffset + 50).i16();\n\tif (indexToLocFormat !== 0 && indexToLocFormat !== 1) throw new OfdParseError(\"invalid-font\", `字体 ${source} 的 indexToLocFormat 不合法:${indexToLocFormat}`);\n\tconst numGlyphs = new FontReader(data, source, tables.get(\"maxp\").offset + 4).u16();\n\tconst cmapTable = tables.get(\"cmap\");\n\tconst cmap = cmapTable ? parseCmap(data, cmapTable, source) : /* @__PURE__ */ new Map();\n\tconst glyfTable = tables.get(\"glyf\");\n\tconst locaView = new FontReader(data, source, tables.get(\"loca\").offset);\n\tconst loca = [];\n\tfor (let i = 0; i <= numGlyphs; i++) loca.push(indexToLocFormat === 0 ? locaView.u16() * 2 : locaView.u32());\n\tfor (let i = 0; i < numGlyphs; i++) if (loca[i + 1] < loca[i] || loca[i + 1] > glyfTable.length) throw new OfdParseError(\"invalid-font\", `字体 ${source} 的 loca 表越界`);\n\tconst numberOfHMetrics = Math.min(new FontReader(data, source, tables.get(\"hhea\").offset + 34).u16(), numGlyphs);\n\tconst hmtxView = new FontReader(data, source, tables.get(\"hmtx\").offset);\n\tconst advances = [];\n\tfor (let i = 0; i < numberOfHMetrics; i++) {\n\t\tadvances.push(hmtxView.u16());\n\t\thmtxView.i16();\n\t}\n\tconst glyf = data.subarray(glyfTable.offset, glyfTable.offset + glyfTable.length);\n\tconst outlineCache = /* @__PURE__ */ new Map();\n\treturn {\n\t\tunitsPerEm,\n\t\tnumGlyphs,\n\t\tglyphIndexOf: (codePoint) => cmap.get(codePoint) ?? null,\n\t\tadvanceWidth: (gid) => advances[Math.min(Math.max(gid, 0), advances.length - 1)] ?? 0,\n\t\tglyphOutline: (gid) => {\n\t\t\tconst cached = outlineCache.get(gid);\n\t\t\tif (cached) return cached;\n\t\t\tconst outline = readGlyphOutline(glyf, gid, /* @__PURE__ */ new Set([gid]), numGlyphs, loca, source);\n\t\t\toutlineCache.set(gid, outline);\n\t\t\treturn outline;\n\t\t}\n\t};\n}\n/**\n* glyph 轮廓转 SVG path `d`:unitsPerEm → 字号缩放,基线原点定位并翻转\n* y 轴(字体坐标向上,SVG 向下)。无轮廓返回空串。\n*/\nfunction glyphPathD(font, gid, fontSize, originX, originY) {\n\tif (!(fontSize > 0)) return \"\";\n\tconst scale = fontSize / font.unitsPerEm;\n\treturn font.glyphOutline(gid).map((contour) => contourPathD(contour, scale, originX, originY)).filter((d) => d !== \"\").join(\" \");\n}\nconst REQUIRED_TABLES = [\n\t\"glyf\",\n\t\"head\",\n\t\"hhea\",\n\t\"hmtx\",\n\t\"loca\",\n\t\"maxp\"\n];\n/** 带越界检查的大端读取器:越界抛 invalid-font */\nvar FontReader = class {\n\tdata;\n\tsource;\n\toffset;\n\tconstructor(data, source, offset = 0) {\n\t\tthis.data = data;\n\t\tthis.source = source;\n\t\tthis.offset = offset;\n\t}\n\tseek(offset) {\n\t\tthis.offset = offset;\n\t}\n\tu8() {\n\t\tthis.take(1);\n\t\treturn this.data[this.offset++];\n\t}\n\ti8() {\n\t\treturn this.u8() << 24 >> 24;\n\t}\n\tu16() {\n\t\tthis.take(2);\n\t\tconst value = this.data[this.offset] << 8 | this.data[this.offset + 1];\n\t\tthis.offset += 2;\n\t\treturn value;\n\t}\n\ti16() {\n\t\treturn this.u16() << 16 >> 16;\n\t}\n\tu32() {\n\t\treturn (this.u16() << 16 | this.u16()) >>> 0;\n\t}\n\t/** 读指定绝对偏移的 u16(cmap format 4 的 glyphIdArray 寻址用) */\n\tu16At(offset) {\n\t\tif (offset < 0 || offset + 2 > this.data.length) this.overrun();\n\t\treturn this.data[offset] << 8 | this.data[offset + 1];\n\t}\n\ttake(size) {\n\t\tif (this.offset + size > this.data.length) this.overrun();\n\t}\n\toverrun() {\n\t\tthrow new OfdParseError(\"invalid-font\", `字体 ${this.source} 数据被截断`);\n\t}\n};\nfunction parseTableDirectory(data, source) {\n\tconst view = new FontReader(data, source);\n\tview.u32();\n\tconst numTables = view.u16();\n\tview.seek(view.offset + 6);\n\tconst tables = /* @__PURE__ */ new Map();\n\tfor (let i = 0; i < numTables; i++) {\n\t\tconst tag = String.fromCharCode(view.u8(), view.u8(), view.u8(), view.u8());\n\t\tview.u32();\n\t\tconst offset = view.u32();\n\t\tconst length = view.u32();\n\t\ttables.set(tag, {\n\t\t\toffset,\n\t\t\tlength\n\t\t});\n\t}\n\treturn tables;\n}\nfunction parseCmap(data, table, source) {\n\tconst header = new FontReader(data, source, table.offset);\n\theader.u16();\n\tconst recordCount = header.u16();\n\tconst records = [];\n\tfor (let i = 0; i < recordCount; i++) records.push({\n\t\tplatform: header.u16(),\n\t\tencoding: header.u16(),\n\t\toffset: table.offset + header.u32()\n\t});\n\tconst score = (record) => record.platform === 3 && record.encoding === 10 ? 3 : record.platform === 0 ? 2 : record.platform === 3 && record.encoding === 1 ? 1 : 0;\n\trecords.sort((a, b) => score(b) - score(a));\n\tfor (const record of records) try {\n\t\treturn parseCmapSubtable(new FontReader(data, source, record.offset), source);\n\t} catch {}\n\tthrow new OfdParseError(\"invalid-font\", `字体 ${source} 没有可用的 cmap 子表`);\n}\nfunction parseCmapSubtable(view, source) {\n\tconst format = view.u16();\n\tswitch (format) {\n\t\tcase 4: return parseCmapFormat4(view);\n\t\tcase 12: return parseCmapFormat12(view);\n\t\tcase 0: return parseCmapFormat0(view);\n\t\tcase 6: return parseCmapFormat6(view);\n\t\tdefault: throw new OfdParseError(\"invalid-font\", `字体 ${source} 的 cmap 子表格式 ${format} 不支持`);\n\t}\n}\nfunction parseCmapFormat4(view) {\n\tview.u16();\n\tview.u16();\n\tconst segCount = view.u16() / 2;\n\tview.u16();\n\tview.u16();\n\tview.u16();\n\tif (segCount === 0) throw new OfdParseError(\"invalid-font\", \"cmap format 4 段数为 0\");\n\tconst ends = readU16Array(view, segCount);\n\tview.u16();\n\tconst starts = readU16Array(view, segCount);\n\tconst deltas = readU16Array(view, segCount);\n\tconst rangeOffsetBase = view.offset;\n\tconst rangeOffsets = readU16Array(view, segCount);\n\tconst map = /* @__PURE__ */ new Map();\n\tfor (let s = 0; s < segCount; s++) for (let code = starts[s]; code <= ends[s]; code++) {\n\t\tlet gid;\n\t\tif (rangeOffsets[s] === 0) gid = code + deltas[s] & 65535;\n\t\telse {\n\t\t\tconst address = rangeOffsetBase + 2 * s + rangeOffsets[s] + 2 * (code - starts[s]);\n\t\t\tgid = view.u16At(address);\n\t\t\tif (gid === 0) continue;\n\t\t\tgid = gid + deltas[s] & 65535;\n\t\t}\n\t\tif (gid !== 0) map.set(code, gid);\n\t}\n\treturn map;\n}\nfunction parseCmapFormat12(view) {\n\tview.u16();\n\tview.u32();\n\tview.u32();\n\tconst groupCount = view.u32();\n\tconst map = /* @__PURE__ */ new Map();\n\tfor (let g = 0; g < groupCount; g++) {\n\t\tconst start = view.u32();\n\t\tconst end = Math.min(view.u32(), 1114111);\n\t\tconst startGlyph = view.u32();\n\t\tfor (let code = start; code <= end; code++) {\n\t\t\tconst gid = startGlyph + (code - start);\n\t\t\tif (gid !== 0) map.set(code, gid);\n\t\t}\n\t}\n\treturn map;\n}\nfunction parseCmapFormat0(view) {\n\tview.u16();\n\tview.u16();\n\tconst map = /* @__PURE__ */ new Map();\n\tfor (let code = 0; code < 256; code++) {\n\t\tconst gid = view.u8();\n\t\tif (gid !== 0) map.set(code, gid);\n\t}\n\treturn map;\n}\nfunction parseCmapFormat6(view) {\n\tview.u16();\n\tview.u16();\n\tconst firstCode = view.u16();\n\tconst entryCount = view.u16();\n\tconst map = /* @__PURE__ */ new Map();\n\tfor (let i = 0; i < entryCount; i++) {\n\t\tconst gid = view.u16();\n\t\tif (gid !== 0) map.set(firstCode + i, gid);\n\t}\n\treturn map;\n}\nfunction readU16Array(view, count) {\n\treturn Array.from({ length: count }, () => view.u16());\n}\nconst COMPONENT_WORDS_ARGS = 1;\nconst COMPONENT_MORE = 32;\nconst COMPONENT_SCALE = 8;\nconst COMPONENT_XY_SCALE = 64;\nconst COMPONENT_TWO_BY_TWO = 128;\n/** 读单个 glyph 轮廓;复合 glyph 递归展开组件(带环检测),越界/空 glyph 返回空 */\nfunction readGlyphOutline(glyf, gid, visiting, numGlyphs, loca, source) {\n\tif (gid < 0 || gid >= numGlyphs) return [];\n\tconst start = loca[gid];\n\tif (start === loca[gid + 1]) return [];\n\tconst view = new FontReader(glyf, source, start);\n\tconst numberOfContours = view.i16();\n\tview.seek(view.offset + 8);\n\tif (numberOfContours >= 0) return readSimpleGlyph(view, numberOfContours);\n\treturn readCompositeGlyph(view, (componentGid) => {\n\t\tif (visiting.has(componentGid)) return [];\n\t\tconst next = new Set(visiting);\n\t\tnext.add(componentGid);\n\t\treturn readGlyphOutline(glyf, componentGid, next, numGlyphs, loca, source);\n\t});\n}\n/** 简单 glyph:标志位驱动的增量坐标解码 */\nfunction readSimpleGlyph(view, numberOfContours) {\n\tif (numberOfContours === 0) return [];\n\tconst endPoints = [];\n\tfor (let i = 0; i < numberOfContours; i++) endPoints.push(view.u16());\n\tconst pointCount = endPoints[endPoints.length - 1] + 1;\n\tconst instructionLength = view.u16();\n\tview.seek(view.offset + instructionLength);\n\tconst flags = [];\n\twhile (flags.length < pointCount) {\n\t\tconst flag = view.u8();\n\t\tflags.push(flag);\n\t\tif (flag & 8) {\n\t\t\tconst repeat = view.u8();\n\t\t\tfor (let r = 0; r < repeat && flags.length < pointCount; r++) flags.push(flag);\n\t\t}\n\t}\n\tconst xs = readDeltaCoords(view, flags, 2, 16);\n\tconst ys = readDeltaCoords(view, flags, 4, 32);\n\tconst points = [];\n\tfor (let i = 0; i < pointCount; i++) points.push({\n\t\tx: xs[i],\n\t\ty: ys[i],\n\t\tonCurve: (flags[i] & 1) !== 0\n\t});\n\tconst contours = [];\n\tlet start = 0;\n\tfor (const end of endPoints) {\n\t\tcontours.push(points.slice(start, end + 1));\n\t\tstart = end + 1;\n\t}\n\treturn contours;\n}\n/** x/y 增量坐标共用解码:短格式 1 字节(符号由 same 位决定),否则 0 或 i16 */\nfunction readDeltaCoords(view, flags, shortBit, sameBit) {\n\tconst coords = [];\n\tlet value = 0;\n\tfor (const flag of flags) {\n\t\tif (flag & shortBit) {\n\t\t\tconst delta = view.u8();\n\t\t\tvalue += (flag & sameBit) !== 0 ? delta : -delta;\n\t\t} else if ((flag & sameBit) === 0) value += view.i16();\n\t\tcoords.push(value);\n\t}\n\treturn coords;\n}\n/**\n* 复合 glyph:组件递归展开,先按组件矩阵变换再平移。\n* 极少见「点对齐」组件(args 为点序号而非 XY 偏移)按偏移量处理,不做点匹配。\n*/\nfunction readCompositeGlyph(view, resolve) {\n\tconst contours = [];\n\tlet flags;\n\tdo {\n\t\tflags = view.u16();\n\t\tconst glyphIndex = view.u16();\n\t\tconst wide = (flags & COMPONENT_WORDS_ARGS) !== 0;\n\t\tconst dx = wide ? view.i16() : view.i8();\n\t\tconst dy = wide ? view.i16() : view.i8();\n\t\tlet a = 1;\n\t\tlet b = 0;\n\t\tlet c = 0;\n\t\tlet d = 1;\n\t\tif (flags & COMPONENT_SCALE) a = d = readFixed214(view);\n\t\telse if (flags & COMPONENT_XY_SCALE) {\n\t\t\ta = readFixed214(view);\n\t\t\td = readFixed214(view);\n\t\t} else if (flags & COMPONENT_TWO_BY_TWO) {\n\t\t\ta = readFixed214(view);\n\t\t\tb = readFixed214(view);\n\t\t\tc = readFixed214(view);\n\t\t\td = readFixed214(view);\n\t\t}\n\t\tfor (const contour of resolve(glyphIndex)) contours.push(contour.map((point) => ({\n\t\t\tx: a * point.x + c * point.y + dx,\n\t\t\ty: b * point.x + d * point.y + dy,\n\t\t\tonCurve: point.onCurve\n\t\t})));\n\t} while (flags & COMPONENT_MORE);\n\treturn contours;\n}\nfunction readFixed214(view) {\n\treturn view.u16() / 16384;\n}\n/**\n* TrueType 轮廓转 path:相邻 off-curve 点之间补隐式中点(on-curve),\n* 旋转到 on-curve 点开头后逐段输出 L / Q,Z 闭合。\n*/\nfunction contourPathD(contour, scale, originX, originY) {\n\tconst points = normalizeContour(contour);\n\tif (points.length === 0) return \"\";\n\tconst count = points.length;\n\tconst at = (index) => points[index % count];\n\tconst x = (point) => formatNumber(point.x * scale + originX);\n\tconst y = (point) => formatNumber(originY - point.y * scale);\n\tconst parts = [`M ${x(points[0])} ${y(points[0])}`];\n\tfor (let i = 1; i < count; i++) {\n\t\tconst point = at(i);\n\t\tif (point.onCurve) parts.push(`L ${x(point)} ${y(point)}`);\n\t\telse {\n\t\t\tconst next = at(i + 1);\n\t\t\tparts.push(`Q ${x(point)} ${y(point)} ${x(next)} ${y(next)}`);\n\t\t\ti++;\n\t\t}\n\t}\n\tparts.push(\"Z\");\n\treturn parts.join(\" \");\n}\nfunction normalizeContour(contour) {\n\tconst count = contour.length;\n\tif (count === 0) return [];\n\tconst expanded = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tconst point = contour[i];\n\t\texpanded.push(point);\n\t\tconst next = contour[(i + 1) % count];\n\t\tif (!point.onCurve && !next.onCurve) expanded.push({\n\t\t\tx: (point.x + next.x) / 2,\n\t\t\ty: (point.y + next.y) / 2,\n\t\t\tonCurve: true\n\t\t});\n\t}\n\tconst start = expanded.findIndex((point) => point.onCurve);\n\tif (start <= 0) return expanded;\n\treturn [...expanded.slice(start), ...expanded.slice(0, start)];\n}\n//#endregion\nexport { glyphPathD, parseEmbeddedFont };\n\n//# sourceMappingURL=font.js.map"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { OfdParseError } from "./error.js";
|
|
2
|
+
import { openOfdZip } from "./zip.js";
|
|
3
|
+
import { parseOfd, parseOfdContainer } from "./parse.js";
|
|
4
|
+
import { glyphPathD, parseEmbeddedFont } from "./font.js";
|
|
5
|
+
import { pageToSvg } from "./render.js";
|
|
6
|
+
export { OfdParseError, glyphPathD, openOfdZip, pageToSvg, parseEmbeddedFont, parseOfd, parseOfdContainer };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region ../ofd-core/dist/number.js
|
|
2
|
+
/** SVG 输出共用的小数处理(render 与 font 两处调用) */
|
|
3
|
+
function roundTo(value, digits) {
|
|
4
|
+
return Math.round(value * 10 ** digits) / 10 ** digits;
|
|
5
|
+
}
|
|
6
|
+
/** 数值转 SVG 属性文本:截掉浮点噪声(如 0.30000000000000004 → 0.3) */
|
|
7
|
+
function formatNumber(value) {
|
|
8
|
+
return String(roundTo(value, 4));
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { formatNumber, roundTo };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=number.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number.js","names":[],"sources":["../../../../../ofd-core/dist/number.js"],"sourcesContent":["//#region src/number.ts\n/** SVG 输出共用的小数处理(render 与 font 两处调用) */\nfunction roundTo(value, digits) {\n\treturn Math.round(value * 10 ** digits) / 10 ** digits;\n}\n/** 数值转 SVG 属性文本:截掉浮点噪声(如 0.30000000000000004 → 0.3) */\nfunction formatNumber(value) {\n\treturn String(roundTo(value, 4));\n}\n//#endregion\nexport { formatNumber, roundTo };\n\n//# sourceMappingURL=number.js.map"],"mappings":";;AAEA,SAAS,QAAQ,OAAO,QAAQ;CAC/B,OAAO,KAAK,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM;AACjD;;AAEA,SAAS,aAAa,OAAO;CAC5B,OAAO,OAAO,QAAQ,OAAO,CAAC,CAAC;AAChC"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { parseBoundary, parseMatrix, parseNumberList } from "./ctm.js";
|
|
2
|
+
import { parseOfdColor } from "./color.js";
|
|
3
|
+
import { childElements, childrenNamed, firstChildNamed, localNameOf, parseLayerType, parseXml, rootElementOf } from "./xml.js";
|
|
4
|
+
//#region ../ofd-core/dist/page-objects.js
|
|
5
|
+
/**
|
|
6
|
+
* Page.xml 内容对象模型:图层内的文本 / 图片 / 路径 / 复合对象。
|
|
7
|
+
*
|
|
8
|
+
* 与 P1 的 OfdPage(图层声明)分离:渲染按页懒执行,这里在渲染前按需解析,
|
|
9
|
+
* 使页与页相互独立、未渲染页不产生解析开销。
|
|
10
|
+
*/
|
|
11
|
+
/** 页面内容文件根元素:普通页为 Page,模板页内容也有产出写作 TemplatePage */
|
|
12
|
+
const PAGE_ROOT_NAMES = ["Page", "TemplatePage"];
|
|
13
|
+
/** 解析页 / 模板页内容的图元对象;未知对象类型跳过 */
|
|
14
|
+
function parsePageContent(xml, source) {
|
|
15
|
+
const root = rootElementOf(parseXml(xml, source), PAGE_ROOT_NAMES, source);
|
|
16
|
+
const layerParent = firstChildNamed(root, "Content") ?? root;
|
|
17
|
+
const layers = [];
|
|
18
|
+
const objectsById = /* @__PURE__ */ new Map();
|
|
19
|
+
for (const layer of childrenNamed(layerParent, "Layer")) {
|
|
20
|
+
const objects = [];
|
|
21
|
+
collectLayerObjects(layer, objects, objectsById);
|
|
22
|
+
layers.push({
|
|
23
|
+
type: parseLayerType(layer.getAttribute("Type")),
|
|
24
|
+
drawParamId: layer.getAttribute("DrawParam"),
|
|
25
|
+
objects
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
layers,
|
|
30
|
+
objectsById,
|
|
31
|
+
templateRefs: childrenNamed(root, "Template").map(parseTemplateRef)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 图层内对象收集:PageBlock 是纯分组容器(新版数电票正文层实证,自身无
|
|
36
|
+
* Boundary/CTM),递归扁平化不改变成员对象坐标。
|
|
37
|
+
*/
|
|
38
|
+
function collectLayerObjects(container, out, objectsById) {
|
|
39
|
+
for (const element of childElements(container)) {
|
|
40
|
+
if (localNameOf(element) === "PageBlock") {
|
|
41
|
+
collectLayerObjects(element, out, objectsById);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const object = parsePageObject(element);
|
|
45
|
+
if (!object) continue;
|
|
46
|
+
if (object.id) objectsById.set(object.id, object);
|
|
47
|
+
out.push(object);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** 解析 Template 引用:TemplateID 取声明 ID,ZOrder 缺省按背景叠加 */
|
|
51
|
+
function parseTemplateRef(element) {
|
|
52
|
+
const stackedForeground = element.getAttribute("ZOrder")?.toLowerCase() === "foreground";
|
|
53
|
+
return {
|
|
54
|
+
templateId: element.getAttribute("TemplateID"),
|
|
55
|
+
zOrder: stackedForeground ? "foreground" : "background"
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function parsePageObject(element) {
|
|
59
|
+
const base = {
|
|
60
|
+
id: element.getAttribute("ID"),
|
|
61
|
+
boundary: parseBoundary(element.getAttribute("Boundary")),
|
|
62
|
+
ctm: parseMatrix(element.getAttribute("CTM")),
|
|
63
|
+
drawParamId: element.getAttribute("DrawParam")
|
|
64
|
+
};
|
|
65
|
+
switch (localNameOf(element)) {
|
|
66
|
+
case "TextObject": return {
|
|
67
|
+
...base,
|
|
68
|
+
kind: "text",
|
|
69
|
+
fontId: element.getAttribute("FontID") ?? element.getAttribute("Font"),
|
|
70
|
+
fontSize: parseNumber(element.getAttribute("FontSize") ?? element.getAttribute("Size")),
|
|
71
|
+
fillColor: objectColor(element, "FillColor"),
|
|
72
|
+
codes: childrenNamed(element, "TextCode").map(parseTextCode),
|
|
73
|
+
glyphSubstitutions: childrenNamed(element, "CGTransform").map(parseGlyphSubstitution)
|
|
74
|
+
};
|
|
75
|
+
case "ImageObject": return {
|
|
76
|
+
...base,
|
|
77
|
+
kind: "image",
|
|
78
|
+
resourceId: element.getAttribute("ResourceID")
|
|
79
|
+
};
|
|
80
|
+
case "PathObject": return {
|
|
81
|
+
...base,
|
|
82
|
+
kind: "path",
|
|
83
|
+
fill: element.getAttribute("Fill") === "true",
|
|
84
|
+
fillColor: objectColor(element, "FillColor"),
|
|
85
|
+
strokeColor: objectColor(element, "StrokeColor"),
|
|
86
|
+
lineWidth: parseNumber(element.getAttribute("LineWidth")),
|
|
87
|
+
dashPattern: parseNumberList(element.getAttribute("DashPattern")),
|
|
88
|
+
commands: parsePathCommands(firstChildNamed(element, "AbbreviatedData")?.textContent ?? null)
|
|
89
|
+
};
|
|
90
|
+
case "CompositeObject": return {
|
|
91
|
+
...base,
|
|
92
|
+
kind: "composite",
|
|
93
|
+
referenceId: element.getAttribute("ReferenceID")
|
|
94
|
+
};
|
|
95
|
+
default: return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 对象颜色声明兼容两种形式:属性 `FillColor="128 0 0"` 与子元素
|
|
100
|
+
* `<FillColor Value="128 0 0"/>`(新版数电票实证为子元素形式)。
|
|
101
|
+
*/
|
|
102
|
+
function objectColor(element, name) {
|
|
103
|
+
return parseOfdColor(element.getAttribute(name) ?? firstChildNamed(element, name)?.getAttribute("Value") ?? null);
|
|
104
|
+
}
|
|
105
|
+
/** 解析 CGTransform:Glyphs 支持 ST_Array 的 `g n v` 压缩写法 */
|
|
106
|
+
function parseGlyphSubstitution(element) {
|
|
107
|
+
return {
|
|
108
|
+
codePosition: parseNumber(element.getAttribute("CodePosition")) ?? 0,
|
|
109
|
+
codeCount: parseNumber(element.getAttribute("CodeCount")) ?? 0,
|
|
110
|
+
glyphIds: parseDeltaList(firstChildNamed(element, "Glyphs")?.textContent ?? null)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function parseTextCode(code) {
|
|
114
|
+
return {
|
|
115
|
+
x: parseNumber(code.getAttribute("X")),
|
|
116
|
+
y: parseNumber(code.getAttribute("Y")),
|
|
117
|
+
deltaX: parseDeltaList(code.getAttribute("DeltaX")),
|
|
118
|
+
deltaY: parseDeltaList(code.getAttribute("DeltaY")),
|
|
119
|
+
text: code.textContent ?? ""
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 解析 TextCode 位移数组:数值按序对应相邻字符位移;`g n v` 是 ST_Array 的
|
|
124
|
+
* 压缩写法(数电发票实证),表示 n 个连续位移均为 v。
|
|
125
|
+
*/
|
|
126
|
+
function parseDeltaList(value) {
|
|
127
|
+
const tokens = value?.trim().split(/[\s,]+/).filter((token) => token !== "") ?? [];
|
|
128
|
+
const deltas = [];
|
|
129
|
+
for (let index = 0; index < tokens.length;) {
|
|
130
|
+
if (tokens[index] === "g") {
|
|
131
|
+
const count = Number(tokens[index + 1]);
|
|
132
|
+
const repeated = Number(tokens[index + 2]);
|
|
133
|
+
if (Number.isInteger(count) && count > 0 && Number.isFinite(repeated)) {
|
|
134
|
+
for (let repeat = 0; repeat < count; repeat++) deltas.push(repeated);
|
|
135
|
+
index += 3;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
index += 1;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const delta = Number(tokens[index]);
|
|
142
|
+
if (Number.isFinite(delta)) deltas.push(delta);
|
|
143
|
+
index += 1;
|
|
144
|
+
}
|
|
145
|
+
return deltas;
|
|
146
|
+
}
|
|
147
|
+
const PATH_ARITY = {
|
|
148
|
+
M: 2,
|
|
149
|
+
L: 2,
|
|
150
|
+
C: 6,
|
|
151
|
+
B: 4,
|
|
152
|
+
Q: 4,
|
|
153
|
+
Z: 0
|
|
154
|
+
};
|
|
155
|
+
function parsePathCommands(data) {
|
|
156
|
+
const tokens = data?.trim().split(/[\s,]+/).filter((token) => token !== "") ?? [];
|
|
157
|
+
const commands = [];
|
|
158
|
+
for (let index = 0; index < tokens.length;) {
|
|
159
|
+
const type = tokens[index].toUpperCase();
|
|
160
|
+
const arity = PATH_ARITY[type];
|
|
161
|
+
if (arity === void 0) {
|
|
162
|
+
index += 1;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const points = tokens.slice(index + 1, index + 1 + arity).map(Number);
|
|
166
|
+
if (points.length === arity && points.every((point) => Number.isFinite(point))) commands.push({
|
|
167
|
+
type,
|
|
168
|
+
points
|
|
169
|
+
});
|
|
170
|
+
index += 1 + arity;
|
|
171
|
+
}
|
|
172
|
+
return commands;
|
|
173
|
+
}
|
|
174
|
+
function parseNumber(value) {
|
|
175
|
+
const numbers = parseNumberList(value);
|
|
176
|
+
return numbers.length > 0 ? numbers[0] : null;
|
|
177
|
+
}
|
|
178
|
+
//#endregion
|
|
179
|
+
export { parsePageContent };
|
|
180
|
+
|
|
181
|
+
//# sourceMappingURL=page-objects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-objects.js","names":[],"sources":["../../../../../ofd-core/dist/page-objects.js"],"sourcesContent":["import { parseBoundary, parseMatrix, parseNumberList } from \"./ctm.js\";\nimport { parseOfdColor } from \"./color.js\";\nimport { childElements, childrenNamed, firstChildNamed, localNameOf, parseLayerType, parseXml, rootElementOf } from \"./xml.js\";\n//#region src/page-objects.ts\n/**\n* Page.xml 内容对象模型:图层内的文本 / 图片 / 路径 / 复合对象。\n*\n* 与 P1 的 OfdPage(图层声明)分离:渲染按页懒执行,这里在渲染前按需解析,\n* 使页与页相互独立、未渲染页不产生解析开销。\n*/\n/** 页面内容文件根元素:普通页为 Page,模板页内容也有产出写作 TemplatePage */\nconst PAGE_ROOT_NAMES = [\"Page\", \"TemplatePage\"];\n/** 解析页 / 模板页内容的图元对象;未知对象类型跳过 */\nfunction parsePageContent(xml, source) {\n\tconst root = rootElementOf(parseXml(xml, source), PAGE_ROOT_NAMES, source);\n\tconst layerParent = firstChildNamed(root, \"Content\") ?? root;\n\tconst layers = [];\n\tconst objectsById = /* @__PURE__ */ new Map();\n\tfor (const layer of childrenNamed(layerParent, \"Layer\")) {\n\t\tconst objects = [];\n\t\tcollectLayerObjects(layer, objects, objectsById);\n\t\tlayers.push({\n\t\t\ttype: parseLayerType(layer.getAttribute(\"Type\")),\n\t\t\tdrawParamId: layer.getAttribute(\"DrawParam\"),\n\t\t\tobjects\n\t\t});\n\t}\n\treturn {\n\t\tlayers,\n\t\tobjectsById,\n\t\ttemplateRefs: childrenNamed(root, \"Template\").map(parseTemplateRef)\n\t};\n}\n/**\n* 图层内对象收集:PageBlock 是纯分组容器(新版数电票正文层实证,自身无\n* Boundary/CTM),递归扁平化不改变成员对象坐标。\n*/\nfunction collectLayerObjects(container, out, objectsById) {\n\tfor (const element of childElements(container)) {\n\t\tif (localNameOf(element) === \"PageBlock\") {\n\t\t\tcollectLayerObjects(element, out, objectsById);\n\t\t\tcontinue;\n\t\t}\n\t\tconst object = parsePageObject(element);\n\t\tif (!object) continue;\n\t\tif (object.id) objectsById.set(object.id, object);\n\t\tout.push(object);\n\t}\n}\n/** 解析 Template 引用:TemplateID 取声明 ID,ZOrder 缺省按背景叠加 */\nfunction parseTemplateRef(element) {\n\tconst stackedForeground = element.getAttribute(\"ZOrder\")?.toLowerCase() === \"foreground\";\n\treturn {\n\t\ttemplateId: element.getAttribute(\"TemplateID\"),\n\t\tzOrder: stackedForeground ? \"foreground\" : \"background\"\n\t};\n}\nfunction parsePageObject(element) {\n\tconst base = {\n\t\tid: element.getAttribute(\"ID\"),\n\t\tboundary: parseBoundary(element.getAttribute(\"Boundary\")),\n\t\tctm: parseMatrix(element.getAttribute(\"CTM\")),\n\t\tdrawParamId: element.getAttribute(\"DrawParam\")\n\t};\n\tswitch (localNameOf(element)) {\n\t\tcase \"TextObject\": return {\n\t\t\t...base,\n\t\t\tkind: \"text\",\n\t\t\tfontId: element.getAttribute(\"FontID\") ?? element.getAttribute(\"Font\"),\n\t\t\tfontSize: parseNumber(element.getAttribute(\"FontSize\") ?? element.getAttribute(\"Size\")),\n\t\t\tfillColor: objectColor(element, \"FillColor\"),\n\t\t\tcodes: childrenNamed(element, \"TextCode\").map(parseTextCode),\n\t\t\tglyphSubstitutions: childrenNamed(element, \"CGTransform\").map(parseGlyphSubstitution)\n\t\t};\n\t\tcase \"ImageObject\": return {\n\t\t\t...base,\n\t\t\tkind: \"image\",\n\t\t\tresourceId: element.getAttribute(\"ResourceID\")\n\t\t};\n\t\tcase \"PathObject\": return {\n\t\t\t...base,\n\t\t\tkind: \"path\",\n\t\t\tfill: element.getAttribute(\"Fill\") === \"true\",\n\t\t\tfillColor: objectColor(element, \"FillColor\"),\n\t\t\tstrokeColor: objectColor(element, \"StrokeColor\"),\n\t\t\tlineWidth: parseNumber(element.getAttribute(\"LineWidth\")),\n\t\t\tdashPattern: parseNumberList(element.getAttribute(\"DashPattern\")),\n\t\t\tcommands: parsePathCommands(firstChildNamed(element, \"AbbreviatedData\")?.textContent ?? null)\n\t\t};\n\t\tcase \"CompositeObject\": return {\n\t\t\t...base,\n\t\t\tkind: \"composite\",\n\t\t\treferenceId: element.getAttribute(\"ReferenceID\")\n\t\t};\n\t\tdefault: return null;\n\t}\n}\n/**\n* 对象颜色声明兼容两种形式:属性 `FillColor=\"128 0 0\"` 与子元素\n* `<FillColor Value=\"128 0 0\"/>`(新版数电票实证为子元素形式)。\n*/\nfunction objectColor(element, name) {\n\treturn parseOfdColor(element.getAttribute(name) ?? firstChildNamed(element, name)?.getAttribute(\"Value\") ?? null);\n}\n/** 解析 CGTransform:Glyphs 支持 ST_Array 的 `g n v` 压缩写法 */\nfunction parseGlyphSubstitution(element) {\n\treturn {\n\t\tcodePosition: parseNumber(element.getAttribute(\"CodePosition\")) ?? 0,\n\t\tcodeCount: parseNumber(element.getAttribute(\"CodeCount\")) ?? 0,\n\t\tglyphIds: parseDeltaList(firstChildNamed(element, \"Glyphs\")?.textContent ?? null)\n\t};\n}\nfunction parseTextCode(code) {\n\treturn {\n\t\tx: parseNumber(code.getAttribute(\"X\")),\n\t\ty: parseNumber(code.getAttribute(\"Y\")),\n\t\tdeltaX: parseDeltaList(code.getAttribute(\"DeltaX\")),\n\t\tdeltaY: parseDeltaList(code.getAttribute(\"DeltaY\")),\n\t\ttext: code.textContent ?? \"\"\n\t};\n}\n/**\n* 解析 TextCode 位移数组:数值按序对应相邻字符位移;`g n v` 是 ST_Array 的\n* 压缩写法(数电发票实证),表示 n 个连续位移均为 v。\n*/\nfunction parseDeltaList(value) {\n\tconst tokens = value?.trim().split(/[\\s,]+/).filter((token) => token !== \"\") ?? [];\n\tconst deltas = [];\n\tfor (let index = 0; index < tokens.length;) {\n\t\tif (tokens[index] === \"g\") {\n\t\t\tconst count = Number(tokens[index + 1]);\n\t\t\tconst repeated = Number(tokens[index + 2]);\n\t\t\tif (Number.isInteger(count) && count > 0 && Number.isFinite(repeated)) {\n\t\t\t\tfor (let repeat = 0; repeat < count; repeat++) deltas.push(repeated);\n\t\t\t\tindex += 3;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst delta = Number(tokens[index]);\n\t\tif (Number.isFinite(delta)) deltas.push(delta);\n\t\tindex += 1;\n\t}\n\treturn deltas;\n}\nconst PATH_ARITY = {\n\tM: 2,\n\tL: 2,\n\tC: 6,\n\tB: 4,\n\tQ: 4,\n\tZ: 0\n};\nfunction parsePathCommands(data) {\n\tconst tokens = data?.trim().split(/[\\s,]+/).filter((token) => token !== \"\") ?? [];\n\tconst commands = [];\n\tfor (let index = 0; index < tokens.length;) {\n\t\tconst type = tokens[index].toUpperCase();\n\t\tconst arity = PATH_ARITY[type];\n\t\tif (arity === void 0) {\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst points = tokens.slice(index + 1, index + 1 + arity).map(Number);\n\t\tif (points.length === arity && points.every((point) => Number.isFinite(point))) commands.push({\n\t\t\ttype,\n\t\t\tpoints\n\t\t});\n\t\tindex += 1 + arity;\n\t}\n\treturn commands;\n}\nfunction parseNumber(value) {\n\tconst numbers = parseNumberList(value);\n\treturn numbers.length > 0 ? numbers[0] : null;\n}\n//#endregion\nexport { parsePageContent };\n\n//# sourceMappingURL=page-objects.js.map"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { OfdParseError } from "./error.js";
|
|
2
|
+
import { openOfdZip } from "./zip.js";
|
|
3
|
+
import { joinZipPath, parseDocumentRes, parseDocumentXml, parseOfdRoot, parsePageXml } from "./xml.js";
|
|
4
|
+
//#region ../ofd-core/dist/parse.js
|
|
5
|
+
/** 解析 OFD 文件字节:解包 ZIP 容器并解析全部文档的页面模型 */
|
|
6
|
+
async function parseOfd(data) {
|
|
7
|
+
return parseOfdContainer(openOfdZip(data));
|
|
8
|
+
}
|
|
9
|
+
/** 在已打开的容器上解析(复用同一个 OfdZip 读多个文档) */
|
|
10
|
+
async function parseOfdContainer(zip) {
|
|
11
|
+
if (!zip.has("OFD.xml")) throw new OfdParseError("missing-entry", "容器中缺少 OFD.xml,不是合法的 OFD 文件");
|
|
12
|
+
const bodies = parseOfdRoot(await zip.text("OFD.xml"));
|
|
13
|
+
if (bodies.length === 0) throw new OfdParseError("invalid-structure", "OFD.xml 中没有 DocBody");
|
|
14
|
+
return { docs: await Promise.all(bodies.map((body) => parseDoc(zip, body.docRoot, body.info))) };
|
|
15
|
+
}
|
|
16
|
+
async function parseDoc(zip, docRoot, info) {
|
|
17
|
+
const docLocation = joinZipPath(docRoot);
|
|
18
|
+
const dir = docLocation.includes("/") ? docLocation.slice(0, docLocation.lastIndexOf("/")) : "";
|
|
19
|
+
const documentModel = parseDocumentXml(await zip.text(docLocation), docLocation);
|
|
20
|
+
const [resources, pages] = await Promise.all([loadResources(zip, dir, documentModel.resLocation, documentModel.publicResLocation), Promise.all(documentModel.pageLocations.map((baseLoc, index) => loadPage(zip, dir, baseLoc, index)))]);
|
|
21
|
+
return {
|
|
22
|
+
dir,
|
|
23
|
+
info,
|
|
24
|
+
pageSize: documentModel.pageSize,
|
|
25
|
+
templates: documentModel.templates,
|
|
26
|
+
resources,
|
|
27
|
+
pages
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** 合并文档资源与公共资源声明;同 ID 时文档资源声明在前、查找优先 */
|
|
31
|
+
async function loadResources(zip, dir, resLocation, publicResLocation) {
|
|
32
|
+
const locations = [resLocation, publicResLocation].filter((location) => location !== null);
|
|
33
|
+
if (locations.length === 0) return {
|
|
34
|
+
fonts: [],
|
|
35
|
+
medias: [],
|
|
36
|
+
drawParams: []
|
|
37
|
+
};
|
|
38
|
+
const parts = await Promise.all(locations.map(async (location) => parseDocumentRes(await zip.text(joinZipPath(dir, location)), location)));
|
|
39
|
+
return {
|
|
40
|
+
fonts: parts.flatMap((part) => part.fonts),
|
|
41
|
+
medias: parts.flatMap((part) => part.medias),
|
|
42
|
+
drawParams: parts.flatMap((part) => part.drawParams)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function loadPage(zip, dir, baseLoc, index) {
|
|
46
|
+
const pageLocation = resolveContentLocation(dir, baseLoc);
|
|
47
|
+
const pageModel = parsePageXml(await zip.text(pageLocation), pageLocation);
|
|
48
|
+
return {
|
|
49
|
+
index,
|
|
50
|
+
location: pageLocation,
|
|
51
|
+
size: pageModel.size,
|
|
52
|
+
layers: pageModel.layers
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 页 / 模板页内容定位共用:BaseLoc 以 .xml 结尾时是内容文件(WPS / 数科 /
|
|
57
|
+
* 数电发票的页与模板页均写 Content.xml),否则按页目录处理(内含 Page.xml)。
|
|
58
|
+
*/
|
|
59
|
+
function resolveContentLocation(dir, baseLoc) {
|
|
60
|
+
return /\.xml$/i.test(baseLoc) ? joinZipPath(dir, baseLoc) : joinZipPath(dir, baseLoc, "Page.xml");
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { joinZipPath, parseOfd, parseOfdContainer, resolveContentLocation };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","names":[],"sources":["../../../../../ofd-core/dist/parse.js"],"sourcesContent":["import { OfdParseError } from \"./error.js\";\nimport { joinZipPath, parseDocumentRes, parseDocumentXml, parseOfdRoot, parsePageXml } from \"./xml.js\";\nimport { openOfdZip } from \"./zip.js\";\n//#region src/parse.ts\n/** 解析 OFD 文件字节:解包 ZIP 容器并解析全部文档的页面模型 */\nasync function parseOfd(data) {\n\treturn parseOfdContainer(openOfdZip(data));\n}\n/** 在已打开的容器上解析(复用同一个 OfdZip 读多个文档) */\nasync function parseOfdContainer(zip) {\n\tif (!zip.has(\"OFD.xml\")) throw new OfdParseError(\"missing-entry\", \"容器中缺少 OFD.xml,不是合法的 OFD 文件\");\n\tconst bodies = parseOfdRoot(await zip.text(\"OFD.xml\"));\n\tif (bodies.length === 0) throw new OfdParseError(\"invalid-structure\", \"OFD.xml 中没有 DocBody\");\n\treturn { docs: await Promise.all(bodies.map((body) => parseDoc(zip, body.docRoot, body.info))) };\n}\nasync function parseDoc(zip, docRoot, info) {\n\tconst docLocation = joinZipPath(docRoot);\n\tconst dir = docLocation.includes(\"/\") ? docLocation.slice(0, docLocation.lastIndexOf(\"/\")) : \"\";\n\tconst documentModel = parseDocumentXml(await zip.text(docLocation), docLocation);\n\tconst [resources, pages] = await Promise.all([loadResources(zip, dir, documentModel.resLocation, documentModel.publicResLocation), Promise.all(documentModel.pageLocations.map((baseLoc, index) => loadPage(zip, dir, baseLoc, index)))]);\n\treturn {\n\t\tdir,\n\t\tinfo,\n\t\tpageSize: documentModel.pageSize,\n\t\ttemplates: documentModel.templates,\n\t\tresources,\n\t\tpages\n\t};\n}\n/** 合并文档资源与公共资源声明;同 ID 时文档资源声明在前、查找优先 */\nasync function loadResources(zip, dir, resLocation, publicResLocation) {\n\tconst locations = [resLocation, publicResLocation].filter((location) => location !== null);\n\tif (locations.length === 0) return {\n\t\tfonts: [],\n\t\tmedias: [],\n\t\tdrawParams: []\n\t};\n\tconst parts = await Promise.all(locations.map(async (location) => parseDocumentRes(await zip.text(joinZipPath(dir, location)), location)));\n\treturn {\n\t\tfonts: parts.flatMap((part) => part.fonts),\n\t\tmedias: parts.flatMap((part) => part.medias),\n\t\tdrawParams: parts.flatMap((part) => part.drawParams)\n\t};\n}\nasync function loadPage(zip, dir, baseLoc, index) {\n\tconst pageLocation = resolveContentLocation(dir, baseLoc);\n\tconst pageModel = parsePageXml(await zip.text(pageLocation), pageLocation);\n\treturn {\n\t\tindex,\n\t\tlocation: pageLocation,\n\t\tsize: pageModel.size,\n\t\tlayers: pageModel.layers\n\t};\n}\n/**\n* 页 / 模板页内容定位共用:BaseLoc 以 .xml 结尾时是内容文件(WPS / 数科 /\n* 数电发票的页与模板页均写 Content.xml),否则按页目录处理(内含 Page.xml)。\n*/\nfunction resolveContentLocation(dir, baseLoc) {\n\treturn /\\.xml$/i.test(baseLoc) ? joinZipPath(dir, baseLoc) : joinZipPath(dir, baseLoc, \"Page.xml\");\n}\n//#endregion\nexport { joinZipPath, parseOfd, parseOfdContainer, resolveContentLocation };\n\n//# sourceMappingURL=parse.js.map"],"mappings":";;;;;AAKA,eAAe,SAAS,MAAM;CAC7B,OAAO,kBAAkB,WAAW,IAAI,CAAC;AAC1C;;AAEA,eAAe,kBAAkB,KAAK;CACrC,IAAI,CAAC,IAAI,IAAI,SAAS,GAAG,MAAM,IAAI,cAAc,iBAAiB,4BAA4B;CAC9F,MAAM,SAAS,aAAa,MAAM,IAAI,KAAK,SAAS,CAAC;CACrD,IAAI,OAAO,WAAW,GAAG,MAAM,IAAI,cAAc,qBAAqB,qBAAqB;CAC3F,OAAO,EAAE,MAAM,MAAM,QAAQ,IAAI,OAAO,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,EAAE;AAChG;AACA,eAAe,SAAS,KAAK,SAAS,MAAM;CAC3C,MAAM,cAAc,YAAY,OAAO;CACvC,MAAM,MAAM,YAAY,SAAS,GAAG,IAAI,YAAY,MAAM,GAAG,YAAY,YAAY,GAAG,CAAC,IAAI;CAC7F,MAAM,gBAAgB,iBAAiB,MAAM,IAAI,KAAK,WAAW,GAAG,WAAW;CAC/E,MAAM,CAAC,WAAW,SAAS,MAAM,QAAQ,IAAI,CAAC,cAAc,KAAK,KAAK,cAAc,aAAa,cAAc,iBAAiB,GAAG,QAAQ,IAAI,cAAc,cAAc,KAAK,SAAS,UAAU,SAAS,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC;CACxO,OAAO;EACN;EACA;EACA,UAAU,cAAc;EACxB,WAAW,cAAc;EACzB;EACA;CACD;AACD;;AAEA,eAAe,cAAc,KAAK,KAAK,aAAa,mBAAmB;CACtE,MAAM,YAAY,CAAC,aAAa,iBAAiB,CAAC,CAAC,QAAQ,aAAa,aAAa,IAAI;CACzF,IAAI,UAAU,WAAW,GAAG,OAAO;EAClC,OAAO,CAAC;EACR,QAAQ,CAAC;EACT,YAAY,CAAC;CACd;CACA,MAAM,QAAQ,MAAM,QAAQ,IAAI,UAAU,IAAI,OAAO,aAAa,iBAAiB,MAAM,IAAI,KAAK,YAAY,KAAK,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;CACzI,OAAO;EACN,OAAO,MAAM,SAAS,SAAS,KAAK,KAAK;EACzC,QAAQ,MAAM,SAAS,SAAS,KAAK,MAAM;EAC3C,YAAY,MAAM,SAAS,SAAS,KAAK,UAAU;CACpD;AACD;AACA,eAAe,SAAS,KAAK,KAAK,SAAS,OAAO;CACjD,MAAM,eAAe,uBAAuB,KAAK,OAAO;CACxD,MAAM,YAAY,aAAa,MAAM,IAAI,KAAK,YAAY,GAAG,YAAY;CACzE,OAAO;EACN;EACA,UAAU;EACV,MAAM,UAAU;EAChB,QAAQ,UAAU;CACnB;AACD;;;;;AAKA,SAAS,uBAAuB,KAAK,SAAS;CAC7C,OAAO,UAAU,KAAK,OAAO,IAAI,YAAY,KAAK,OAAO,IAAI,YAAY,KAAK,SAAS,UAAU;AAClG"}
|