@l1yp/file-viewer 0.1.4 → 0.1.5

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.
Files changed (53) hide show
  1. package/README.md +2 -0
  2. package/dist/components/AnsiText.d.ts +47 -0
  3. package/dist/components/AnsiText.js +41 -0
  4. package/dist/components/AnsiText.js.map +1 -0
  5. package/dist/components/CodeView.js +1 -1
  6. package/dist/components/CodeView.js.map +1 -1
  7. package/dist/components/CodeView.vue_vue_type_script_setup_true_lang.js +80 -71
  8. package/dist/components/CodeView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/DocxEmbeddedFiles.js +9 -0
  10. package/dist/components/DocxEmbeddedFiles.js.map +1 -0
  11. package/dist/components/DocxEmbeddedFiles.vue.d.ts +15 -0
  12. package/dist/components/DocxEmbeddedFiles.vue_vue_type_script_setup_true_lang.js +69 -0
  13. package/dist/components/DocxEmbeddedFiles.vue_vue_type_script_setup_true_lang.js.map +1 -0
  14. package/dist/components/DocxViewer.js +1 -1
  15. package/dist/components/DocxViewer.js.map +1 -1
  16. package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js +180 -50
  17. package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/FileViewerBody.js +1 -1
  19. package/dist/components/FileViewerBody.js.map +1 -1
  20. package/dist/components/FileViewerBody.vue.d.ts +1 -0
  21. package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js +117 -114
  22. package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/FileViewerPanel.js +1 -1
  24. package/dist/components/FileViewerPanel.js.map +1 -1
  25. package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js +18 -18
  26. package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/components/LogViewer.js +1 -1
  28. package/dist/components/LogViewer.js.map +1 -1
  29. package/dist/components/LogViewer.vue.d.ts +3 -1
  30. package/dist/components/LogViewer.vue_vue_type_script_setup_true_lang.js +284 -280
  31. package/dist/components/LogViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/lib/ansi.d.ts +44 -0
  33. package/dist/lib/ansi.js +224 -0
  34. package/dist/lib/ansi.js.map +1 -0
  35. package/dist/lib/cfb.d.ts +37 -0
  36. package/dist/lib/cfb.js +112 -0
  37. package/dist/lib/cfb.js.map +1 -0
  38. package/dist/lib/docxEmbeddedDom.d.ts +22 -0
  39. package/dist/lib/docxEmbeddedDom.js +128 -0
  40. package/dist/lib/docxEmbeddedDom.js.map +1 -0
  41. package/dist/lib/docxEmbeddings.d.ts +41 -0
  42. package/dist/lib/docxEmbeddings.js +226 -0
  43. package/dist/lib/docxEmbeddings.js.map +1 -0
  44. package/dist/lib/msi.js +62 -154
  45. package/dist/lib/msi.js.map +1 -1
  46. package/dist/lib/olePackage.d.ts +8 -0
  47. package/dist/lib/olePackage.js +37 -0
  48. package/dist/lib/olePackage.js.map +1 -0
  49. package/dist/lib/pptxFirstSlide.d.ts +11 -0
  50. package/dist/lib/pptxFirstSlide.js +34 -0
  51. package/dist/lib/pptxFirstSlide.js.map +1 -0
  52. package/dist/style.css +1 -1
  53. package/package.json +1 -1
@@ -0,0 +1,226 @@
1
+ import { extractZipEntry as e, readZip as t } from "./zip.js";
2
+ import { extractOlePackage as n } from "./olePackage.js";
3
+ //#region src/lib/docxEmbeddings.ts
4
+ var r = "word/document.xml", i = "word/_rels/document.xml.rels", a = "[Content_Types].xml", o = 100 * 1024 * 1024, s = 20 * 1024 * 1024, c = {
5
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
6
+ pdf: "application/pdf",
7
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
8
+ xls: "application/vnd.ms-excel",
9
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
10
+ };
11
+ function l(e, t) {
12
+ let n = new DOMParser().parseFromString(e, "application/xml"), r = Array.from(n.getElementsByTagNameNS("*", "parsererror"))[0];
13
+ if (r) throw Error(`${t} XML 无法解析:${r.textContent?.trim() || "格式错误"}`);
14
+ return n;
15
+ }
16
+ function u(e, t) {
17
+ return Array.from(e.getElementsByTagNameNS("*", t));
18
+ }
19
+ function d(e, t) {
20
+ return Array.from(e.attributes).find((e) => e.localName === t)?.value ?? "";
21
+ }
22
+ function f(e) {
23
+ return new TextDecoder("utf-8").decode(e);
24
+ }
25
+ function p(e) {
26
+ let t = e.lastIndexOf(".");
27
+ return t > 0 && t < e.length - 1 ? e.slice(t + 1).toLowerCase() : "";
28
+ }
29
+ function m(e) {
30
+ return e.slice(e.lastIndexOf("/") + 1);
31
+ }
32
+ function h(e) {
33
+ for (let t of e) if (t.charCodeAt(0) < 32) return !0;
34
+ return !1;
35
+ }
36
+ function g(e) {
37
+ let t = "";
38
+ for (let n of e) t += n.charCodeAt(0) < 32 || "<>:\"/\\|?*".includes(n) ? "_" : n;
39
+ return t;
40
+ }
41
+ function _(e, t) {
42
+ let n = t.split(/[?#]/, 1)[0]?.replace(/\\/g, "/") ?? "";
43
+ if (!n || h(n)) return "";
44
+ let r = n.startsWith("/") ? [] : e.split("/").slice(0, -1);
45
+ for (let e of n.split("/")) {
46
+ let t;
47
+ try {
48
+ t = decodeURIComponent(e);
49
+ } catch {
50
+ return "";
51
+ }
52
+ if (!(!t || t === ".")) {
53
+ if (t === "..") {
54
+ if (r.length === 0) return "";
55
+ r.pop();
56
+ continue;
57
+ }
58
+ if (t.includes("/") || t.includes("\\")) return "";
59
+ r.push(t);
60
+ }
61
+ }
62
+ return r.join("/");
63
+ }
64
+ function v(e) {
65
+ return u(e, "t").map((e) => e.textContent ?? "").join("").replace(/\s+/g, " ").trim();
66
+ }
67
+ function y(e) {
68
+ let t = e.replace(/\s+/g, " ").trim();
69
+ return /^(?:点击|双击).*(?:查看|打开).*(?:文件|表格)/.test(t) ? "" : t.slice(0, 100);
70
+ }
71
+ function b(e, t) {
72
+ if (!e) return t;
73
+ let n = g(e).replace(/[. ]+$/g, "").trim().slice(0, 120);
74
+ if (!n) return t;
75
+ let r = p(t);
76
+ return r && !n.toLowerCase().endsWith(`.${r}`) ? `${n}.${r}` : n;
77
+ }
78
+ function x(e) {
79
+ let t = l(e, "DOCX relationship"), n = /* @__PURE__ */ new Map();
80
+ for (let e of u(t, "Relationship")) {
81
+ let t = e.getAttribute("Id") ?? "", r = e.getAttribute("Target") ?? "";
82
+ !t || !r || n.set(t, {
83
+ target: r,
84
+ type: e.getAttribute("Type") ?? "",
85
+ external: (e.getAttribute("TargetMode") ?? "").toLowerCase() === "external"
86
+ });
87
+ }
88
+ return n;
89
+ }
90
+ function S(e) {
91
+ let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
92
+ if (!e) return {
93
+ defaults: t,
94
+ overrides: n
95
+ };
96
+ let r = l(e, "DOCX content types");
97
+ for (let e of u(r, "Default")) {
98
+ let n = (e.getAttribute("Extension") ?? "").toLowerCase(), r = e.getAttribute("ContentType") ?? "";
99
+ n && r && t.set(n, r);
100
+ }
101
+ for (let e of u(r, "Override")) {
102
+ let t = (e.getAttribute("PartName") ?? "").replace(/^\/+/, ""), r = e.getAttribute("ContentType") ?? "";
103
+ t && r && n.set(t, r);
104
+ }
105
+ return {
106
+ defaults: t,
107
+ overrides: n
108
+ };
109
+ }
110
+ function C(e, t) {
111
+ let n = p(e);
112
+ return t.overrides.get(e) ?? t.defaults.get(n) ?? c[n] ?? "application/octet-stream";
113
+ }
114
+ function w(e) {
115
+ let t = e.toLowerCase();
116
+ return t === "powerpoint.show.12" || t === "powerpoint.slide.12" ? {
117
+ extension: "pptx",
118
+ contentType: c.pptx,
119
+ label: "PowerPoint 演示文稿"
120
+ } : t === "excel.sheet.12" ? {
121
+ extension: "xlsx",
122
+ contentType: c.xlsx,
123
+ label: "Excel 工作簿"
124
+ } : t === "word.document.12" ? {
125
+ extension: "docx",
126
+ contentType: c.docx,
127
+ label: "Word 文档"
128
+ } : null;
129
+ }
130
+ function T(e, t) {
131
+ let n = e;
132
+ for (; n;) {
133
+ if (n.localName === t) return n;
134
+ n = n.parentElement;
135
+ }
136
+ return null;
137
+ }
138
+ function E(e, t) {
139
+ let n = e.match(RegExp(`(?:^|;)\\s*${t}\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)(pt|px|in|cm|mm)`, "i"));
140
+ if (!n) return;
141
+ let r = Number(n[1]), i = n[2]?.toLowerCase(), a = i === "pt" ? r : i === "px" ? r * .75 : i === "in" ? r * 72 : i === "cm" ? r * 72 / 2.54 : r * 72 / 25.4;
142
+ return Number.isFinite(a) && a > 0 && a <= 2e3 ? a : void 0;
143
+ }
144
+ function D(e, t, n, i) {
145
+ let a = T(e, "object");
146
+ if (!a) return;
147
+ let o = u(a, "imagedata")[0], s = o ? d(o, "id") : "", c = t.get(s);
148
+ if (!s || !c || c.external || !c.type.toLowerCase().endsWith("/image")) return;
149
+ let l = _(r, c.target), f = n.get(l);
150
+ if (!l || !f) return;
151
+ let p = u(a, "shape")[0]?.getAttribute("style") ?? "";
152
+ return {
153
+ path: l,
154
+ size: f.size,
155
+ contentType: C(l, i),
156
+ widthPt: E(p, "width"),
157
+ heightPt: E(p, "height"),
158
+ entry: f
159
+ };
160
+ }
161
+ function O(e, t) {
162
+ return e.length >= 8 && e[0] === 137 && e[1] === 80 && e[2] === 78 && e[3] === 71 ? "image/png" : e.length >= 3 && e[0] === 255 && e[1] === 216 && e[2] === 255 ? "image/jpeg" : e.length >= 6 && e[0] === 71 && e[1] === 73 && e[2] === 70 && e[3] === 56 ? "image/gif" : e.length >= 2 && e[0] === 66 && e[1] === 77 ? "image/bmp" : e.length >= 12 && e[0] === 82 && e[1] === 73 && e[2] === 70 && e[3] === 70 && e[8] === 87 && e[9] === 69 && e[10] === 66 && e[11] === 80 ? "image/webp" : t.startsWith("image/") ? t : "application/octet-stream";
163
+ }
164
+ async function k(n) {
165
+ let o = t(n), s = new Map(o.filter((e) => !e.isDir).map((e) => [e.path, e])), c = s.get(r), p = s.get(i);
166
+ if (!c || !p) return [];
167
+ let [h, g, T] = await Promise.all([
168
+ e(n, c).then(f),
169
+ e(n, p).then(f),
170
+ s.has(a) ? e(n, s.get(a)).then(f) : Promise.resolve(null)
171
+ ]), E = l(h, "DOCX document"), O = x(g), k = S(T), A = [], j = /* @__PURE__ */ new Set(), M = "";
172
+ for (let e of u(E, "p")) {
173
+ let t = v(e);
174
+ for (let n of u(e, "OLEObject")) {
175
+ let e = d(n, "id"), i = O.get(e);
176
+ if (!e || !i || i.external) continue;
177
+ let a = i.type.toLowerCase(), o = a.endsWith("/package"), c = a.endsWith("/oleobject");
178
+ if (!o && !c) continue;
179
+ let l = n.getAttribute("ProgID") ?? d(n, "ProgID"), u = c ? w(l) : null;
180
+ if (c && !u) continue;
181
+ let f = _(r, i.target), p = s.get(f);
182
+ if (!f || !p || j.has(f)) continue;
183
+ j.add(f);
184
+ let h = m(f), g = u ? `${u.label}.${u.extension}` : h, v = y(t || (u ? u.label : M));
185
+ A.push({
186
+ id: e,
187
+ label: v,
188
+ name: b(v, g),
189
+ originalName: g,
190
+ path: f,
191
+ size: p.size,
192
+ contentType: u?.contentType ?? C(f, k),
193
+ storage: u ? "ole-package" : "package",
194
+ preview: D(n, O, s, k),
195
+ entry: p
196
+ });
197
+ }
198
+ t && (M = t);
199
+ }
200
+ return A;
201
+ }
202
+ async function A(t, r) {
203
+ if (r.size > o) throw Error(`内嵌文件超过 ${o / 1024 / 1024} MiB,已拒绝在浏览器中展开`);
204
+ let i = await e(t, r.entry);
205
+ return r.storage === "ole-package" ? n(i, o) : i;
206
+ }
207
+ async function j(t, n) {
208
+ let r = n.preview;
209
+ if (!r) return null;
210
+ if (r.size > s) throw Error(`内嵌预览图超过 ${s / 1024 / 1024} MiB,已跳过正文预览`);
211
+ let i = await e(t, r.entry), a = O(i, r.contentType);
212
+ return [
213
+ "image/png",
214
+ "image/jpeg",
215
+ "image/gif",
216
+ "image/bmp",
217
+ "image/webp"
218
+ ].includes(a) ? {
219
+ bytes: i,
220
+ contentType: a
221
+ } : null;
222
+ }
223
+ //#endregion
224
+ export { A as extractDocxEmbeddedFile, j as extractDocxEmbeddedPreview, k as readDocxEmbeddedFiles };
225
+
226
+ //# sourceMappingURL=docxEmbeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docxEmbeddings.js","names":[],"sources":["../../src/lib/docxEmbeddings.ts"],"sourcesContent":["import { extractZipEntry, readZip, type ZipEntry } from '@/lib/zip'\nimport { extractOlePackage } from '@/lib/olePackage'\n\nconst DOCUMENT_PART = 'word/document.xml'\nconst DOCUMENT_RELS_PART = 'word/_rels/document.xml.rels'\nconst CONTENT_TYPES_PART = '[Content_Types].xml'\nconst MAX_EMBEDDED_FILE_BYTES = 100 * 1024 * 1024\nconst MAX_PREVIEW_IMAGE_BYTES = 20 * 1024 * 1024\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n pdf: 'application/pdf',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n xls: 'application/vnd.ms-excel',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n}\n\nexport interface DocxEmbeddedFile {\n /** Stable relationship id inside word/document.xml. */\n id: string\n /** Human-facing caption inferred from the nearest preceding Word paragraph. */\n label: string\n /** Friendly download name (caption + original extension when a caption exists). */\n name: string\n /** Original package basename, e.g. Microsoft_Excel_Worksheet1.xlsx. */\n originalName: string\n /** Resolved package path inside the DOCX ZIP. */\n path: string\n size: number\n contentType: string\n storage: 'package' | 'ole-package'\n /** Word/WPS-generated visual snapshot for the embedded object, when present. */\n preview?: DocxEmbeddedPreview\n /** Internal ZIP descriptor retained so extraction stays on-demand. */\n entry: ZipEntry\n}\n\nexport interface DocxEmbeddedPreview {\n path: string\n size: number\n contentType: string\n widthPt?: number\n heightPt?: number\n entry: ZipEntry\n}\n\nexport interface ExtractedDocxPreview {\n bytes: Uint8Array\n contentType: string\n}\n\ninterface Relationship {\n target: string\n type: string\n external: boolean\n}\n\ninterface OlePackageKind {\n extension: string\n contentType: string\n label: string\n}\n\nfunction parseXml(xml: string, label: string): XMLDocument {\n const document = new DOMParser().parseFromString(xml, 'application/xml')\n const error = Array.from(document.getElementsByTagNameNS('*', 'parsererror'))[0]\n if (error) throw new Error(`${label} XML 无法解析:${error.textContent?.trim() || '格式错误'}`)\n return document\n}\n\nfunction elements(root: Document | Element, localName: string): Element[] {\n return Array.from(root.getElementsByTagNameNS('*', localName))\n}\n\nfunction attrByLocalName(element: Element, localName: string): string {\n return (\n Array.from(element.attributes).find((attribute) => attribute.localName === localName)?.value ??\n ''\n )\n}\n\nfunction decodeEntry(bytes: Uint8Array): string {\n return new TextDecoder('utf-8').decode(bytes)\n}\n\nfunction extension(name: string): string {\n const i = name.lastIndexOf('.')\n return i > 0 && i < name.length - 1 ? name.slice(i + 1).toLowerCase() : ''\n}\n\nfunction basename(path: string): string {\n return path.slice(path.lastIndexOf('/') + 1)\n}\n\nfunction hasControlCharacters(value: string): boolean {\n for (const character of value) if (character.charCodeAt(0) < 0x20) return true\n return false\n}\n\nfunction sanitizeFileName(value: string): string {\n const invalid = '<>:\"/\\\\|?*'\n let result = ''\n for (const character of value) {\n result += character.charCodeAt(0) < 0x20 || invalid.includes(character) ? '_' : character\n }\n return result\n}\n\n/** Resolve an OPC relationship target relative to its source part without allowing it above the package root. */\nfunction resolvePartTarget(sourcePart: string, target: string): string {\n const raw = target.split(/[?#]/, 1)[0]?.replace(/\\\\/g, '/') ?? ''\n if (!raw || hasControlCharacters(raw)) return ''\n const parts = raw.startsWith('/') ? [] : sourcePart.split('/').slice(0, -1)\n for (const encoded of raw.split('/')) {\n let segment: string\n try {\n segment = decodeURIComponent(encoded)\n } catch {\n return ''\n }\n if (!segment || segment === '.') continue\n if (segment === '..') {\n if (parts.length === 0) return ''\n parts.pop()\n continue\n }\n if (segment.includes('/') || segment.includes('\\\\')) return ''\n parts.push(segment)\n }\n return parts.join('/')\n}\n\nfunction paragraphText(paragraph: Element): string {\n return elements(paragraph, 't')\n .map((node) => node.textContent ?? '')\n .join('')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction cleanLabel(value: string): string {\n const label = value.replace(/\\s+/g, ' ').trim()\n if (/^(?:点击|双击).*(?:查看|打开).*(?:文件|表格)/.test(label)) return ''\n return label.slice(0, 100)\n}\n\nfunction friendlyName(label: string, originalName: string): string {\n if (!label) return originalName\n const safe = sanitizeFileName(label)\n .replace(/[. ]+$/g, '')\n .trim()\n .slice(0, 120)\n if (!safe) return originalName\n const ext = extension(originalName)\n return ext && !safe.toLowerCase().endsWith(`.${ext}`) ? `${safe}.${ext}` : safe\n}\n\nfunction readRelationships(xml: string): Map<string, Relationship> {\n const document = parseXml(xml, 'DOCX relationship')\n const out = new Map<string, Relationship>()\n for (const node of elements(document, 'Relationship')) {\n const id = node.getAttribute('Id') ?? ''\n const target = node.getAttribute('Target') ?? ''\n if (!id || !target) continue\n out.set(id, {\n target,\n type: node.getAttribute('Type') ?? '',\n external: (node.getAttribute('TargetMode') ?? '').toLowerCase() === 'external',\n })\n }\n return out\n}\n\nfunction readContentTypes(xml: string | null): {\n defaults: Map<string, string>\n overrides: Map<string, string>\n} {\n const defaults = new Map<string, string>()\n const overrides = new Map<string, string>()\n if (!xml) return { defaults, overrides }\n const document = parseXml(xml, 'DOCX content types')\n for (const node of elements(document, 'Default')) {\n const ext = (node.getAttribute('Extension') ?? '').toLowerCase()\n const type = node.getAttribute('ContentType') ?? ''\n if (ext && type) defaults.set(ext, type)\n }\n for (const node of elements(document, 'Override')) {\n const path = (node.getAttribute('PartName') ?? '').replace(/^\\/+/, '')\n const type = node.getAttribute('ContentType') ?? ''\n if (path && type) overrides.set(path, type)\n }\n return { defaults, overrides }\n}\n\nfunction contentTypeFor(path: string, contentTypes: ReturnType<typeof readContentTypes>): string {\n const ext = extension(path)\n return (\n contentTypes.overrides.get(path) ??\n contentTypes.defaults.get(ext) ??\n MIME_BY_EXTENSION[ext] ??\n 'application/octet-stream'\n )\n}\n\nfunction olePackageKind(programId: string): OlePackageKind | null {\n const normalized = programId.toLowerCase()\n if (normalized === 'powerpoint.show.12' || normalized === 'powerpoint.slide.12') {\n return {\n extension: 'pptx',\n contentType: MIME_BY_EXTENSION.pptx,\n label: 'PowerPoint 演示文稿',\n }\n }\n if (normalized === 'excel.sheet.12') {\n return { extension: 'xlsx', contentType: MIME_BY_EXTENSION.xlsx, label: 'Excel 工作簿' }\n }\n if (normalized === 'word.document.12') {\n return { extension: 'docx', contentType: MIME_BY_EXTENSION.docx, label: 'Word 文档' }\n }\n return null\n}\n\nfunction ancestorByLocalName(element: Element, localName: string): Element | null {\n let current: Element | null = element\n while (current) {\n if (current.localName === localName) return current\n current = current.parentElement\n }\n return null\n}\n\nfunction vmlLengthInPoints(style: string, property: 'width' | 'height'): number | undefined {\n const match = style.match(\n new RegExp(`(?:^|;)\\\\s*${property}\\\\s*:\\\\s*([0-9]+(?:\\\\.[0-9]+)?)(pt|px|in|cm|mm)`, 'i'),\n )\n if (!match) return undefined\n const value = Number(match[1])\n const unit = match[2]?.toLowerCase()\n const points =\n unit === 'pt'\n ? value\n : unit === 'px'\n ? value * 0.75\n : unit === 'in'\n ? value * 72\n : unit === 'cm'\n ? (value * 72) / 2.54\n : (value * 72) / 25.4\n return Number.isFinite(points) && points > 0 && points <= 2000 ? points : undefined\n}\n\nfunction embeddedPreview(\n object: Element,\n relationships: ReadonlyMap<string, Relationship>,\n byPath: ReadonlyMap<string, ZipEntry>,\n contentTypes: ReturnType<typeof readContentTypes>,\n): DocxEmbeddedPreview | undefined {\n const wrapper = ancestorByLocalName(object, 'object')\n if (!wrapper) return undefined\n const imageData = elements(wrapper, 'imagedata')[0]\n const relationshipId = imageData ? attrByLocalName(imageData, 'id') : ''\n const relationship = relationships.get(relationshipId)\n if (\n !relationshipId ||\n !relationship ||\n relationship.external ||\n !relationship.type.toLowerCase().endsWith('/image')\n )\n return undefined\n const path = resolvePartTarget(DOCUMENT_PART, relationship.target)\n const entry = byPath.get(path)\n if (!path || !entry) return undefined\n const shape = elements(wrapper, 'shape')[0]\n const style = shape?.getAttribute('style') ?? ''\n return {\n path,\n size: entry.size,\n contentType: contentTypeFor(path, contentTypes),\n widthPt: vmlLengthInPoints(style, 'width'),\n heightPt: vmlLengthInPoints(style, 'height'),\n entry,\n }\n}\n\nfunction sniffImageContentType(bytes: Uint8Array, declared: string): string {\n if (\n bytes.length >= 8 &&\n bytes[0] === 0x89 &&\n bytes[1] === 0x50 &&\n bytes[2] === 0x4e &&\n bytes[3] === 0x47\n )\n return 'image/png'\n if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff)\n return 'image/jpeg'\n if (\n bytes.length >= 6 &&\n bytes[0] === 0x47 &&\n bytes[1] === 0x49 &&\n bytes[2] === 0x46 &&\n bytes[3] === 0x38\n )\n return 'image/gif'\n if (bytes.length >= 2 && bytes[0] === 0x42 && bytes[1] === 0x4d) return 'image/bmp'\n if (\n bytes.length >= 12 &&\n bytes[0] === 0x52 &&\n bytes[1] === 0x49 &&\n bytes[2] === 0x46 &&\n bytes[3] === 0x46 &&\n bytes[8] === 0x57 &&\n bytes[9] === 0x45 &&\n bytes[10] === 0x42 &&\n bytes[11] === 0x50\n )\n return 'image/webp'\n return declared.startsWith('image/') ? declared : 'application/octet-stream'\n}\n\n/**\n * Discover embedded package relationships (`w:object` / `o:OLEObject`) in document order.\n * `docx-preview` currently drops these nodes, so the caller can expose the original bytes separately.\n */\nexport async function readDocxEmbeddedFiles(buffer: ArrayBuffer): Promise<DocxEmbeddedFile[]> {\n const entries = readZip(buffer)\n const byPath = new Map(\n entries.filter((entry) => !entry.isDir).map((entry) => [entry.path, entry]),\n )\n const documentEntry = byPath.get(DOCUMENT_PART)\n const relationshipsEntry = byPath.get(DOCUMENT_RELS_PART)\n if (!documentEntry || !relationshipsEntry) return []\n\n const [documentXml, relationshipsXml, contentTypesXml] = await Promise.all([\n extractZipEntry(buffer, documentEntry).then(decodeEntry),\n extractZipEntry(buffer, relationshipsEntry).then(decodeEntry),\n byPath.has(CONTENT_TYPES_PART)\n ? extractZipEntry(buffer, byPath.get(CONTENT_TYPES_PART) as ZipEntry).then(decodeEntry)\n : Promise.resolve(null),\n ])\n const document = parseXml(documentXml, 'DOCX document')\n const relationships = readRelationships(relationshipsXml)\n const contentTypes = readContentTypes(contentTypesXml)\n const result: DocxEmbeddedFile[] = []\n const seenPaths = new Set<string>()\n let previousText = ''\n\n for (const paragraph of elements(document, 'p')) {\n const currentText = paragraphText(paragraph)\n for (const object of elements(paragraph, 'OLEObject')) {\n const relationshipId = attrByLocalName(object, 'id')\n const relationship = relationships.get(relationshipId)\n if (!relationshipId || !relationship || relationship.external) continue\n const relationshipType = relationship.type.toLowerCase()\n const directPackage = relationshipType.endsWith('/package')\n const oleObject = relationshipType.endsWith('/oleobject')\n if (!directPackage && !oleObject) continue\n const programId = object.getAttribute('ProgID') ?? attrByLocalName(object, 'ProgID')\n const oleKind = oleObject ? olePackageKind(programId) : null\n if (oleObject && !oleKind) continue\n\n const path = resolvePartTarget(DOCUMENT_PART, relationship.target)\n const entry = byPath.get(path)\n if (!path || !entry || seenPaths.has(path)) continue\n seenPaths.add(path)\n\n const sourceName = basename(path)\n const originalName = oleKind ? `${oleKind.label}.${oleKind.extension}` : sourceName\n const label = cleanLabel(currentText || (oleKind ? oleKind.label : previousText))\n result.push({\n id: relationshipId,\n label,\n name: friendlyName(label, originalName),\n originalName,\n path,\n size: entry.size,\n contentType: oleKind?.contentType ?? contentTypeFor(path, contentTypes),\n storage: oleKind ? 'ole-package' : 'package',\n preview: embeddedPreview(object, relationships, byPath, contentTypes),\n entry,\n })\n }\n if (currentText) previousText = currentText\n }\n return result\n}\n\n/** Extract one discovered embedded package on demand, with the same per-file ceiling as server exports. */\nexport async function extractDocxEmbeddedFile(\n buffer: ArrayBuffer,\n file: DocxEmbeddedFile,\n): Promise<Uint8Array> {\n if (file.size > MAX_EMBEDDED_FILE_BYTES) {\n throw new Error(\n `内嵌文件超过 ${MAX_EMBEDDED_FILE_BYTES / 1024 / 1024} MiB,已拒绝在浏览器中展开`,\n )\n }\n const bytes = await extractZipEntry(buffer, file.entry)\n return file.storage === 'ole-package' ? extractOlePackage(bytes, MAX_EMBEDDED_FILE_BYTES) : bytes\n}\n\n/** Extract the inert Word/WPS snapshot paired with an embedded object. */\nexport async function extractDocxEmbeddedPreview(\n buffer: ArrayBuffer,\n file: DocxEmbeddedFile,\n): Promise<ExtractedDocxPreview | null> {\n const preview = file.preview\n if (!preview) return null\n if (preview.size > MAX_PREVIEW_IMAGE_BYTES) {\n throw new Error(`内嵌预览图超过 ${MAX_PREVIEW_IMAGE_BYTES / 1024 / 1024} MiB,已跳过正文预览`)\n }\n const bytes = await extractZipEntry(buffer, preview.entry)\n const contentType = sniffImageContentType(bytes, preview.contentType)\n if (!['image/png', 'image/jpeg', 'image/gif', 'image/bmp', 'image/webp'].includes(contentType)) {\n return null\n }\n return { bytes, contentType }\n}\n"],"mappings":";;;AAGA,IAAM,IAAgB,qBAChB,IAAqB,gCACrB,IAAqB,uBACrB,IAA0B,MAAM,OAAO,MACvC,IAA0B,KAAK,OAAO,MAEtC,IAA4C;CAChD,MAAM;CACN,KAAK;CACL,MAAM;CACN,KAAK;CACL,MAAM;AACR;AAgDA,SAAS,EAAS,GAAa,GAA4B;CACzD,IAAM,IAAW,IAAI,UAAU,CAAC,CAAC,gBAAgB,GAAK,iBAAiB,GACjE,IAAQ,MAAM,KAAK,EAAS,uBAAuB,KAAK,aAAa,CAAC,CAAC,CAAC;CAC9E,IAAI,GAAO,MAAU,MAAM,GAAG,EAAM,YAAY,EAAM,aAAa,KAAK,KAAK,QAAQ;CACrF,OAAO;AACT;AAEA,SAAS,EAAS,GAA0B,GAA8B;CACxE,OAAO,MAAM,KAAK,EAAK,uBAAuB,KAAK,CAAS,CAAC;AAC/D;AAEA,SAAS,EAAgB,GAAkB,GAA2B;CACpE,OACE,MAAM,KAAK,EAAQ,UAAU,CAAC,CAAC,MAAM,MAAc,EAAU,cAAc,CAAS,CAAC,EAAE,SACvF;AAEJ;AAEA,SAAS,EAAY,GAA2B;CAC9C,OAAO,IAAI,YAAY,OAAO,CAAC,CAAC,OAAO,CAAK;AAC9C;AAEA,SAAS,EAAU,GAAsB;CACvC,IAAM,IAAI,EAAK,YAAY,GAAG;CAC9B,OAAO,IAAI,KAAK,IAAI,EAAK,SAAS,IAAI,EAAK,MAAM,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI;AAC1E;AAEA,SAAS,EAAS,GAAsB;CACtC,OAAO,EAAK,MAAM,EAAK,YAAY,GAAG,IAAI,CAAC;AAC7C;AAEA,SAAS,EAAqB,GAAwB;CACpD,KAAK,IAAM,KAAa,GAAO,IAAI,EAAU,WAAW,CAAC,IAAI,IAAM,OAAO;CAC1E,OAAO;AACT;AAEA,SAAS,EAAiB,GAAuB;CAC/C,IACI,IAAS;CACb,KAAK,IAAM,KAAa,GACtB,KAAU,EAAU,WAAW,CAAC,IAAI,MAAQ,cAAQ,SAAS,CAAS,IAAI,MAAM;CAElF,OAAO;AACT;AAGA,SAAS,EAAkB,GAAoB,GAAwB;CACrE,IAAM,IAAM,EAAO,MAAM,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,OAAO,GAAG,KAAK;CAC/D,IAAI,CAAC,KAAO,EAAqB,CAAG,GAAG,OAAO;CAC9C,IAAM,IAAQ,EAAI,WAAW,GAAG,IAAI,CAAC,IAAI,EAAW,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE;CAC1E,KAAK,IAAM,KAAW,EAAI,MAAM,GAAG,GAAG;EACpC,IAAI;EACJ,IAAI;GACF,IAAU,mBAAmB,CAAO;EACtC,QAAQ;GACN,OAAO;EACT;EACI,OAAC,KAAW,MAAY,MAC5B;OAAI,MAAY,MAAM;IACpB,IAAI,EAAM,WAAW,GAAG,OAAO;IAC/B,EAAM,IAAI;IACV;GACF;GACA,IAAI,EAAQ,SAAS,GAAG,KAAK,EAAQ,SAAS,IAAI,GAAG,OAAO;GAC5D,EAAM,KAAK,CAAO;EAFlB;CAGF;CACA,OAAO,EAAM,KAAK,GAAG;AACvB;AAEA,SAAS,EAAc,GAA4B;CACjD,OAAO,EAAS,GAAW,GAAG,CAAC,CAC5B,KAAK,MAAS,EAAK,eAAe,EAAE,CAAC,CACrC,KAAK,EAAE,CAAC,CACR,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK;AACV;AAEA,SAAS,EAAW,GAAuB;CACzC,IAAM,IAAQ,EAAM,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;CAE9C,OADI,mCAAmC,KAAK,CAAK,IAAU,KACpD,EAAM,MAAM,GAAG,GAAG;AAC3B;AAEA,SAAS,EAAa,GAAe,GAA8B;CACjE,IAAI,CAAC,GAAO,OAAO;CACnB,IAAM,IAAO,EAAiB,CAAK,CAAC,CACjC,QAAQ,WAAW,EAAE,CAAC,CACtB,KAAK,CAAC,CACN,MAAM,GAAG,GAAG;CACf,IAAI,CAAC,GAAM,OAAO;CAClB,IAAM,IAAM,EAAU,CAAY;CAClC,OAAO,KAAO,CAAC,EAAK,YAAY,CAAC,CAAC,SAAS,IAAI,GAAK,IAAI,GAAG,EAAK,GAAG,MAAQ;AAC7E;AAEA,SAAS,EAAkB,GAAwC;CACjE,IAAM,IAAW,EAAS,GAAK,mBAAmB,GAC5C,oBAAM,IAAI,IAA0B;CAC1C,KAAK,IAAM,KAAQ,EAAS,GAAU,cAAc,GAAG;EACrD,IAAM,IAAK,EAAK,aAAa,IAAI,KAAK,IAChC,IAAS,EAAK,aAAa,QAAQ,KAAK;EAC1C,CAAC,KAAM,CAAC,KACZ,EAAI,IAAI,GAAI;GACV;GACA,MAAM,EAAK,aAAa,MAAM,KAAK;GACnC,WAAW,EAAK,aAAa,YAAY,KAAK,GAAA,CAAI,YAAY,MAAM;EACtE,CAAC;CACH;CACA,OAAO;AACT;AAEA,SAAS,EAAiB,GAGxB;CACA,IAAM,oBAAW,IAAI,IAAoB,GACnC,oBAAY,IAAI,IAAoB;CAC1C,IAAI,CAAC,GAAK,OAAO;EAAE;EAAU;CAAU;CACvC,IAAM,IAAW,EAAS,GAAK,oBAAoB;CACnD,KAAK,IAAM,KAAQ,EAAS,GAAU,SAAS,GAAG;EAChD,IAAM,KAAO,EAAK,aAAa,WAAW,KAAK,GAAA,CAAI,YAAY,GACzD,IAAO,EAAK,aAAa,aAAa,KAAK;EACjD,AAAI,KAAO,KAAM,EAAS,IAAI,GAAK,CAAI;CACzC;CACA,KAAK,IAAM,KAAQ,EAAS,GAAU,UAAU,GAAG;EACjD,IAAM,KAAQ,EAAK,aAAa,UAAU,KAAK,GAAA,CAAI,QAAQ,QAAQ,EAAE,GAC/D,IAAO,EAAK,aAAa,aAAa,KAAK;EACjD,AAAI,KAAQ,KAAM,EAAU,IAAI,GAAM,CAAI;CAC5C;CACA,OAAO;EAAE;EAAU;CAAU;AAC/B;AAEA,SAAS,EAAe,GAAc,GAA2D;CAC/F,IAAM,IAAM,EAAU,CAAI;CAC1B,OACE,EAAa,UAAU,IAAI,CAAI,KAC/B,EAAa,SAAS,IAAI,CAAG,KAC7B,EAAkB,MAClB;AAEJ;AAEA,SAAS,EAAe,GAA0C;CAChE,IAAM,IAAa,EAAU,YAAY;CAczC,OAbI,MAAe,wBAAwB,MAAe,wBACjD;EACL,WAAW;EACX,aAAa,EAAkB;EAC/B,OAAO;CACT,IAEE,MAAe,mBACV;EAAE,WAAW;EAAQ,aAAa,EAAkB;EAAM,OAAO;CAAY,IAElF,MAAe,qBACV;EAAE,WAAW;EAAQ,aAAa,EAAkB;EAAM,OAAO;CAAU,IAE7E;AACT;AAEA,SAAS,EAAoB,GAAkB,GAAmC;CAChF,IAAI,IAA0B;CAC9B,OAAO,IAAS;EACd,IAAI,EAAQ,cAAc,GAAW,OAAO;EAC5C,IAAU,EAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAS,EAAkB,GAAe,GAAkD;CAC1F,IAAM,IAAQ,EAAM,MACd,OAAO,cAAc,EAAS,kDAAkD,GAAG,CACzF;CACA,IAAI,CAAC,GAAO;CACZ,IAAM,IAAQ,OAAO,EAAM,EAAE,GACvB,IAAO,EAAM,EAAE,EAAE,YAAY,GAC7B,IACJ,MAAS,OACL,IACA,MAAS,OACP,IAAQ,MACR,MAAS,OACP,IAAQ,KACR,MAAS,OACN,IAAQ,KAAM,OACd,IAAQ,KAAM;CAC3B,OAAO,OAAO,SAAS,CAAM,KAAK,IAAS,KAAK,KAAU,MAAO,IAAS,KAAA;AAC5E;AAEA,SAAS,EACP,GACA,GACA,GACA,GACiC;CACjC,IAAM,IAAU,EAAoB,GAAQ,QAAQ;CACpD,IAAI,CAAC,GAAS;CACd,IAAM,IAAY,EAAS,GAAS,WAAW,CAAC,CAAC,IAC3C,IAAiB,IAAY,EAAgB,GAAW,IAAI,IAAI,IAChE,IAAe,EAAc,IAAI,CAAc;CACrD,IACE,CAAC,KACD,CAAC,KACD,EAAa,YACb,CAAC,EAAa,KAAK,YAAY,CAAC,CAAC,SAAS,QAAQ,GAElD;CACF,IAAM,IAAO,EAAkB,GAAe,EAAa,MAAM,GAC3D,IAAQ,EAAO,IAAI,CAAI;CAC7B,IAAI,CAAC,KAAQ,CAAC,GAAO;CAErB,IAAM,IADQ,EAAS,GAAS,OAAO,CAAC,CAAC,EAC3B,EAAO,aAAa,OAAO,KAAK;CAC9C,OAAO;EACL;EACA,MAAM,EAAM;EACZ,aAAa,EAAe,GAAM,CAAY;EAC9C,SAAS,EAAkB,GAAO,OAAO;EACzC,UAAU,EAAkB,GAAO,QAAQ;EAC3C;CACF;AACF;AAEA,SAAS,EAAsB,GAAmB,GAA0B;CAgC1E,OA9BE,EAAM,UAAU,KAChB,EAAM,OAAO,OACb,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,KAEN,cACL,EAAM,UAAU,KAAK,EAAM,OAAO,OAAQ,EAAM,OAAO,OAAQ,EAAM,OAAO,MACvE,eAEP,EAAM,UAAU,KAChB,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,KAEN,cACL,EAAM,UAAU,KAAK,EAAM,OAAO,MAAQ,EAAM,OAAO,KAAa,cAEtE,EAAM,UAAU,MAChB,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,OAAO,MACb,EAAM,QAAQ,MACd,EAAM,QAAQ,KAEP,eACF,EAAS,WAAW,QAAQ,IAAI,IAAW;AACpD;AAMA,eAAsB,EAAsB,GAAkD;CAC5F,IAAM,IAAU,EAAQ,CAAM,GACxB,IAAS,IAAI,IACjB,EAAQ,QAAQ,MAAU,CAAC,EAAM,KAAK,CAAC,CAAC,KAAK,MAAU,CAAC,EAAM,MAAM,CAAK,CAAC,CAC5E,GACM,IAAgB,EAAO,IAAI,CAAa,GACxC,IAAqB,EAAO,IAAI,CAAkB;CACxD,IAAI,CAAC,KAAiB,CAAC,GAAoB,OAAO,CAAC;CAEnD,IAAM,CAAC,GAAa,GAAkB,KAAmB,MAAM,QAAQ,IAAI;EACzE,EAAgB,GAAQ,CAAa,CAAC,CAAC,KAAK,CAAW;EACvD,EAAgB,GAAQ,CAAkB,CAAC,CAAC,KAAK,CAAW;EAC5D,EAAO,IAAI,CAAkB,IACzB,EAAgB,GAAQ,EAAO,IAAI,CAAkB,CAAa,CAAC,CAAC,KAAK,CAAW,IACpF,QAAQ,QAAQ,IAAI;CAC1B,CAAC,GACK,IAAW,EAAS,GAAa,eAAe,GAChD,IAAgB,EAAkB,CAAgB,GAClD,IAAe,EAAiB,CAAe,GAC/C,IAA6B,CAAC,GAC9B,oBAAY,IAAI,IAAY,GAC9B,IAAe;CAEnB,KAAK,IAAM,KAAa,EAAS,GAAU,GAAG,GAAG;EAC/C,IAAM,IAAc,EAAc,CAAS;EAC3C,KAAK,IAAM,KAAU,EAAS,GAAW,WAAW,GAAG;GACrD,IAAM,IAAiB,EAAgB,GAAQ,IAAI,GAC7C,IAAe,EAAc,IAAI,CAAc;GACrD,IAAI,CAAC,KAAkB,CAAC,KAAgB,EAAa,UAAU;GAC/D,IAAM,IAAmB,EAAa,KAAK,YAAY,GACjD,IAAgB,EAAiB,SAAS,UAAU,GACpD,IAAY,EAAiB,SAAS,YAAY;GACxD,IAAI,CAAC,KAAiB,CAAC,GAAW;GAClC,IAAM,IAAY,EAAO,aAAa,QAAQ,KAAK,EAAgB,GAAQ,QAAQ,GAC7E,IAAU,IAAY,EAAe,CAAS,IAAI;GACxD,IAAI,KAAa,CAAC,GAAS;GAE3B,IAAM,IAAO,EAAkB,GAAe,EAAa,MAAM,GAC3D,IAAQ,EAAO,IAAI,CAAI;GAC7B,IAAI,CAAC,KAAQ,CAAC,KAAS,EAAU,IAAI,CAAI,GAAG;GAC5C,EAAU,IAAI,CAAI;GAElB,IAAM,IAAa,EAAS,CAAI,GAC1B,IAAe,IAAU,GAAG,EAAQ,MAAM,GAAG,EAAQ,cAAc,GACnE,IAAQ,EAAW,MAAgB,IAAU,EAAQ,QAAQ,EAAa;GAChF,EAAO,KAAK;IACV,IAAI;IACJ;IACA,MAAM,EAAa,GAAO,CAAY;IACtC;IACA;IACA,MAAM,EAAM;IACZ,aAAa,GAAS,eAAe,EAAe,GAAM,CAAY;IACtE,SAAS,IAAU,gBAAgB;IACnC,SAAS,EAAgB,GAAQ,GAAe,GAAQ,CAAY;IACpE;GACF,CAAC;EACH;EACA,AAAI,MAAa,IAAe;CAClC;CACA,OAAO;AACT;AAGA,eAAsB,EACpB,GACA,GACqB;CACrB,IAAI,EAAK,OAAO,GACd,MAAU,MACR,UAAU,IAA0B,OAAO,KAAK,gBAClD;CAEF,IAAM,IAAQ,MAAM,EAAgB,GAAQ,EAAK,KAAK;CACtD,OAAO,EAAK,YAAY,gBAAgB,EAAkB,GAAO,CAAuB,IAAI;AAC9F;AAGA,eAAsB,EACpB,GACA,GACsC;CACtC,IAAM,IAAU,EAAK;CACrB,IAAI,CAAC,GAAS,OAAO;CACrB,IAAI,EAAQ,OAAO,GACjB,MAAU,MAAM,WAAW,IAA0B,OAAO,KAAK,aAAa;CAEhF,IAAM,IAAQ,MAAM,EAAgB,GAAQ,EAAQ,KAAK,GACnD,IAAc,EAAsB,GAAO,EAAQ,WAAW;CAIpE,OAHK;EAAC;EAAa;EAAc;EAAa;EAAa;CAAY,CAAC,CAAC,SAAS,CAAW,IAGtF;EAAE;EAAO;CAAY,IAFnB;AAGX"}
package/dist/lib/msi.js CHANGED
@@ -1,126 +1,28 @@
1
+ import { CompoundFile as e, CompoundFileError as t } from "./cfb.js";
1
2
  //#region src/lib/msi.ts
2
- var e = class extends Error {
3
+ var n = class extends Error {
3
4
  constructor(e) {
4
5
  super(e), this.name = "NotMsiError";
5
6
  }
6
- }, t = [
7
- 208,
8
- 207,
9
- 17,
10
- 224,
11
- 161,
12
- 177,
13
- 26,
14
- 225
15
- ], n = 4294967294, r = 4294967295, i = class {
16
- dv;
17
- buf;
18
- sectorSize;
19
- miniSectorSize;
20
- miniCutoff;
21
- fat = [];
22
- miniFat = [];
23
- miniStream = new Uint8Array();
24
- entries = [];
25
- constructor(i) {
26
- this.buf = i;
27
- let a = new DataView(i);
28
- if (this.dv = a, i.byteLength < 512) throw new e("文件过小,不是有效的复合文件");
29
- for (let n = 0; n < 8; n++) if (a.getUint8(n) !== t[n]) throw new e("不是 OLE 复合文件(缺少 D0CF11E0 魔数)");
30
- let o = a.getUint16(26, !0);
31
- this.sectorSize = 1 << a.getUint16(30, !0), this.miniSectorSize = 1 << a.getUint16(32, !0);
32
- let s = a.getUint32(48, !0);
33
- this.miniCutoff = a.getUint32(56, !0);
34
- let c = a.getUint32(60, !0), l = a.getUint32(68, !0), u = this.sectorSize / 4, d = [];
35
- for (let e = 0; e < 109; e++) {
36
- let t = a.getUint32(76 + e * 4, !0);
37
- t !== r && t !== n && d.push(t);
38
- }
39
- let f = l, p = 0;
40
- for (; f !== n && f !== r && p++ < 1e6;) {
41
- let e = this.sectorOffset(f);
42
- for (let t = 0; t < u - 1; t++) {
43
- let n = a.getUint32(e + t * 4, !0);
44
- n !== r && d.push(n);
45
- }
46
- f = a.getUint32(e + (u - 1) * 4, !0);
47
- }
48
- for (let e of d) {
49
- let t = this.sectorOffset(e);
50
- for (let e = 0; e < u; e++) this.fat.push(a.getUint32(t + e * 4, !0));
51
- }
52
- let m = this.readFatStream(s, this.chain(s).length * this.sectorSize), h = new DataView(m.buffer, m.byteOffset, m.byteLength);
53
- for (let e = 0; e + 128 <= m.length; e += 128) {
54
- let t = h.getUint8(e + 66);
55
- if (t === 0) continue;
56
- let n = h.getUint16(e + 64, !0), r = "";
57
- for (let t = 0; t + 1 < n; t += 2) {
58
- let n = h.getUint16(e + t, !0);
59
- if (n === 0) break;
60
- r += String.fromCharCode(n);
61
- }
62
- let i = h.getUint32(e + 116, !0), a = o <= 3 ? h.getUint32(e + 120, !0) : Number(h.getBigUint64(e + 120, !0));
63
- this.entries.push({
64
- name: r,
65
- type: t,
66
- start: i,
67
- size: a
68
- });
69
- }
70
- let g = this.entries.find((e) => e.type === 5);
71
- g && (this.miniStream = this.readFatStream(g.start, g.size));
72
- for (let e of this.chain(c)) {
73
- let t = this.sectorOffset(e);
74
- for (let e = 0; e < u; e++) this.miniFat.push(a.getUint32(t + e * 4, !0));
75
- }
76
- }
77
- sectorOffset(e) {
78
- return (e + 1) * this.sectorSize;
79
- }
80
- chain(e) {
81
- let t = [], i = e, a = 0;
82
- for (; i !== n && i !== r && i < this.fat.length && a++ < 1e7;) t.push(i), i = this.fat[i];
83
- return t;
84
- }
85
- sectorBytes(e) {
86
- let t = this.sectorOffset(e), n = Math.min(this.buf.byteLength, t + this.sectorSize), r = new Uint8Array(this.sectorSize);
87
- return t < this.buf.byteLength && r.set(new Uint8Array(this.buf, t, n - t)), r;
88
- }
89
- readFatStream(e, t) {
90
- let n = this.chain(e), r = new Uint8Array(n.length * this.sectorSize);
91
- for (let e = 0; e < n.length; e++) r.set(this.sectorBytes(n[e]), e * this.sectorSize);
92
- return r.subarray(0, t);
93
- }
94
- readMiniStream(e, t) {
95
- let i = Math.ceil(t / this.miniSectorSize), a = new Uint8Array(i * this.miniSectorSize), o = e, s = 0;
96
- for (; o !== n && o !== r && s < i;) {
97
- let e = o * this.miniSectorSize;
98
- a.set(this.miniStream.subarray(e, e + this.miniSectorSize), s * this.miniSectorSize), s++, o = this.miniFat[o];
99
- }
100
- return a.subarray(0, t);
101
- }
102
- stream(e) {
103
- return e.size === 0 ? new Uint8Array() : e.type === 5 || e.size >= this.miniCutoff ? this.readFatStream(e.start, e.size) : this.readMiniStream(e.start, e.size);
104
- }
105
7
  };
106
- function a(e) {
8
+ function r(e) {
107
9
  return e < 10 ? String.fromCharCode(e + 48) : e < 36 ? String.fromCharCode(e - 10 + 65) : e < 62 ? String.fromCharCode(e - 36 + 97) : e === 62 ? "." : "_";
108
10
  }
109
- function o(e) {
11
+ function i(e) {
110
12
  let t = "", n = !1;
111
- for (let r = 0; r < e.length; r++) {
112
- let i = e.charCodeAt(r);
113
- if (i >= 14336 && i < 18432) {
114
- let e = i - 14336;
115
- t += a(e & 63) + a(e >> 6 & 63);
116
- } else i >= 18432 && i < 18496 ? t += a(i - 18432) : i === 18496 ? n = !0 : t += String.fromCharCode(i);
13
+ for (let i = 0; i < e.length; i++) {
14
+ let a = e.charCodeAt(i);
15
+ if (a >= 14336 && a < 18432) {
16
+ let e = a - 14336;
17
+ t += r(e & 63) + r(e >> 6 & 63);
18
+ } else a >= 18432 && a < 18496 ? t += r(a - 18432) : a === 18496 ? n = !0 : t += String.fromCharCode(a);
117
19
  }
118
20
  return {
119
21
  name: t,
120
22
  isTable: n
121
23
  };
122
24
  }
123
- function s(e) {
25
+ function a(e) {
124
26
  let t = new DataView(e.buffer, e.byteOffset, e.byteLength), n = t.getUint32(44, !0), r = t.getUint32(n + 4, !0), i = [];
125
27
  for (let e = 0; e < r; e++) {
126
28
  let r = t.getUint32(n + 8 + e * 8, !0), a = t.getUint32(n + 8 + e * 8 + 4, !0);
@@ -134,7 +36,7 @@ function s(e) {
134
36
  let e = t.getInt16(o.abs + 4, !0);
135
37
  e < 0 && (e += 65536), a = e;
136
38
  }
137
- let s = new TextDecoder(p(a)), c = /* @__PURE__ */ new Map();
39
+ let s = new TextDecoder(d(a)), c = /* @__PURE__ */ new Map();
138
40
  for (let { pid: n, abs: r } of i) {
139
41
  let i = t.getUint32(r, !0);
140
42
  if (i === 2) c.set(n, {
@@ -153,7 +55,7 @@ function s(e) {
153
55
  });
154
56
  } else i === 64 && c.set(n, {
155
57
  type: i,
156
- value: m(t.getUint32(r + 4, !0), t.getUint32(r + 8, !0))
58
+ value: f(t.getUint32(r + 4, !0), t.getUint32(r + 8, !0))
157
59
  });
158
60
  }
159
61
  return {
@@ -161,7 +63,7 @@ function s(e) {
161
63
  props: c
162
64
  };
163
65
  }
164
- function c(e) {
66
+ function o(e) {
165
67
  let t = [], n = (n, r, i) => {
166
68
  let a = e.get(n);
167
69
  if (a == null) return;
@@ -171,12 +73,12 @@ function c(e) {
171
73
  value: o
172
74
  });
173
75
  };
174
- return n(3, "主题", String), n(4, "作者 / 厂商", String), n(6, "备注", String), n(2, "标题", String), n(5, "关键字", String), n(7, "平台 / 语言", (e) => h(String(e))), n(9, "包代码", String), n(18, "制作工具", String), n(12, "创建时间", String), n(13, "上次保存", String), n(14, "架构版本", (e) => g(Number(e))), n(15, "源类型", (e) => _(Number(e))), n(19, "安全", (e) => v(Number(e))), t;
76
+ return n(3, "主题", String), n(4, "作者 / 厂商", String), n(6, "备注", String), n(2, "标题", String), n(5, "关键字", String), n(7, "平台 / 语言", (e) => p(String(e))), n(9, "包代码", String), n(18, "制作工具", String), n(12, "创建时间", String), n(13, "上次保存", String), n(14, "架构版本", (e) => m(Number(e))), n(15, "源类型", (e) => h(Number(e))), n(19, "安全", (e) => g(Number(e))), t;
175
77
  }
176
- function l(e, t, n) {
78
+ function s(e, t, n) {
177
79
  let r = new DataView(e.buffer, e.byteOffset, e.byteLength), i = r.getUint16(0, !0) | r.getUint16(2, !0) << 16, a = (i & 2147483648) != 0, o = i & 2147483647;
178
80
  o === 0 && (o = n || 1252);
179
- let s = new TextDecoder(p(o)), c = [""], l = 0, u = Math.floor(e.length / 4);
81
+ let s = new TextDecoder(d(o)), c = [""], l = 0, u = Math.floor(e.length / 4);
180
82
  for (let e = 1; e < u; e++) {
181
83
  let n = r.getUint16(e * 4, !0);
182
84
  if (n === 0) {
@@ -190,7 +92,7 @@ function l(e, t, n) {
190
92
  longRefs: a
191
93
  };
192
94
  }
193
- function u(e, t) {
95
+ function c(e, t) {
194
96
  let n = t.longRefs ? 3 : 2, r = new DataView(e.buffer, e.byteOffset, e.byteLength), i = Math.floor(e.length / (n * 2)), a = (e) => {
195
97
  let t = e * n, i = r.getUint16(t, !0);
196
98
  return n === 3 && (i += r.getUint8(t + 2) << 16), i;
@@ -204,42 +106,48 @@ function u(e, t) {
204
106
  }
205
107
  return o;
206
108
  }
207
- function d(e) {
208
- let t = new i(e), n = t.entries.map((e) => ({
209
- e,
210
- ...o(e.name)
211
- })), r = [], a = n.filter((e) => e.isTable).map((e) => e.name).sort((e, t) => e.localeCompare(t)), d = [], p = 0, m = n.find((e) => e.name === "SummaryInformation");
212
- if (m) try {
213
- let e = s(t.stream(m.e));
214
- p = e.codepage, d = c(e.props);
109
+ function l(r) {
110
+ let l;
111
+ try {
112
+ l = new e(r);
215
113
  } catch (e) {
216
- r.push("SummaryInformation 解析失败:" + f(e));
114
+ throw e instanceof t ? new n(e.message) : e;
217
115
  }
218
- let h = [], g = n.find((e) => e.name === "_StringData"), _ = n.find((e) => e.name === "_StringPool"), v = n.find((e) => e.name === "Property");
219
- if (g && _ && v) try {
220
- let e = l(t.stream(_.e), t.stream(g.e), p);
221
- h = u(t.stream(v.e), e);
116
+ let d = l.entries.map((e) => ({
117
+ e,
118
+ ...i(e.name)
119
+ })), f = [], p = d.filter((e) => e.isTable).map((e) => e.name).sort((e, t) => e.localeCompare(t)), m = [], h = 0, g = d.find((e) => e.name === "SummaryInformation");
120
+ if (g) try {
121
+ let e = a(l.stream(g.e));
122
+ h = e.codepage, m = o(e.props);
222
123
  } catch (e) {
223
- r.push("Property 表解析失败:" + f(e));
124
+ f.push("SummaryInformation 解析失败:" + u(e));
224
125
  }
225
- let y = new Map(h.map((e) => [e.name, e.value])), x = y.get("ProductLanguage"), S = {
226
- productName: y.get("ProductName"),
227
- productVersion: y.get("ProductVersion"),
228
- manufacturer: y.get("Manufacturer"),
229
- productCode: y.get("ProductCode"),
230
- upgradeCode: y.get("UpgradeCode"),
231
- language: x ? b(x) : void 0,
232
- properties: h,
233
- summary: d,
234
- tables: a,
235
- notes: r
126
+ let _ = [], y = d.find((e) => e.name === "_StringData"), b = d.find((e) => e.name === "_StringPool"), x = d.find((e) => e.name === "Property");
127
+ if (y && b && x) try {
128
+ let e = s(l.stream(b.e), l.stream(y.e), h);
129
+ _ = c(l.stream(x.e), e);
130
+ } catch (e) {
131
+ f.push("Property 表解析失败:" + u(e));
132
+ }
133
+ let S = new Map(_.map((e) => [e.name, e.value])), C = S.get("ProductLanguage"), w = {
134
+ productName: S.get("ProductName"),
135
+ productVersion: S.get("ProductVersion"),
136
+ manufacturer: S.get("Manufacturer"),
137
+ productCode: S.get("ProductCode"),
138
+ upgradeCode: S.get("UpgradeCode"),
139
+ language: C ? v(C) : void 0,
140
+ properties: _,
141
+ summary: m,
142
+ tables: p,
143
+ notes: f
236
144
  };
237
- return !h.length && !d.length && r.push("未找到 MSI 摘要信息或属性表(可能是别的复合文件,而非 MSI 数据库)"), S;
145
+ return !_.length && !m.length && f.push("未找到 MSI 摘要信息或属性表(可能是别的复合文件,而非 MSI 数据库)"), w;
238
146
  }
239
- function f(e) {
147
+ function u(e) {
240
148
  return e instanceof Error ? e.message : String(e);
241
149
  }
242
- function p(e) {
150
+ function d(e) {
243
151
  switch (e) {
244
152
  case 65001: return "utf-8";
245
153
  case 1200: return "utf-16le";
@@ -259,7 +167,7 @@ function p(e) {
259
167
  default: return "windows-1252";
260
168
  }
261
169
  }
262
- function m(e, t) {
170
+ function f(e, t) {
263
171
  let n = t * 4294967296 + e;
264
172
  if (!n) return "";
265
173
  let r = n / 1e4 - 0xa9730b66800, i = new Date(r);
@@ -267,18 +175,18 @@ function m(e, t) {
267
175
  let a = (e) => String(e).padStart(2, "0");
268
176
  return `${i.getUTCFullYear()}-${a(i.getUTCMonth() + 1)}-${a(i.getUTCDate())} ${a(i.getUTCHours())}:${a(i.getUTCMinutes())} UTC`;
269
177
  }
270
- function h(e) {
271
- let [t, n] = e.split(";"), r = (n ?? "").split(",").map((e) => e.trim()).filter(Boolean).map((e) => b(e)), i = [];
178
+ function p(e) {
179
+ let [t, n] = e.split(";"), r = (n ?? "").split(",").map((e) => e.trim()).filter(Boolean).map((e) => v(e)), i = [];
272
180
  return t && t.trim() && i.push(t.trim()), r.length && i.push(r.join(", ")), i.join(" · ") || e;
273
181
  }
274
- function g(e) {
182
+ function m(e) {
275
183
  return e ? `${Math.floor(e / 100)}.${String(e % 100).padStart(2, "0")}` : "";
276
184
  }
277
- function _(e) {
185
+ function h(e) {
278
186
  let t = [];
279
187
  return t.push(e & 2 ? "压缩 (cabinet)" : "未压缩"), e & 1 && t.push("短文件名"), e & 4 && t.push("管理映像"), e & 8 && t.push("从源运行"), t.join(" · ");
280
188
  }
281
- function v(e) {
189
+ function g(e) {
282
190
  switch (e) {
283
191
  case 0: return "无限制";
284
192
  case 1: return "建议只读";
@@ -287,7 +195,7 @@ function v(e) {
287
195
  default: return String(e);
288
196
  }
289
197
  }
290
- var y = {
198
+ var _ = {
291
199
  0: "语言中性",
292
200
  1025: "阿拉伯语",
293
201
  1028: "中文(繁体)",
@@ -324,11 +232,11 @@ var y = {
324
232
  3082: "西班牙语(西班牙)",
325
233
  4100: "中文(新加坡)"
326
234
  };
327
- function b(e) {
328
- let t = y[Number(e)];
235
+ function v(e) {
236
+ let t = _[Number(e)];
329
237
  return t ? `${t} (${e})` : e;
330
238
  }
331
239
  //#endregion
332
- export { e as NotMsiError, d as parseMsi };
240
+ export { n as NotMsiError, l as parseMsi };
333
241
 
334
242
  //# sourceMappingURL=msi.js.map