omni-viewer-core 0.8.0 → 0.9.0
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.
|
@@ -1883,42 +1883,43 @@ export class PptxXmlParser {
|
|
|
1883
1883
|
vectorFallback: metafile && selectedTarget !== target
|
|
1884
1884
|
};
|
|
1885
1885
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1886
|
+
// Preferred: convert the actual metafile to a raster/vector via the injected renderer.
|
|
1887
|
+
if (context.deps.renderMetafile) {
|
|
1888
|
+
try {
|
|
1889
|
+
context.guard.checkpoint(target);
|
|
1890
|
+
const bytes = await media.async('uint8array');
|
|
1891
|
+
const converted = await context.deps.renderMetafile(bytes, sourceExt.slice(1), context.guard.options.signal);
|
|
1892
|
+
context.guard.checkpoint(target);
|
|
1893
|
+
if (typeof converted === 'string' && converted) {
|
|
1894
|
+
if (/^(?:data:|blob:|https?:)/i.test(converted)) {
|
|
1895
|
+
return { src: converted };
|
|
1896
|
+
}
|
|
1897
|
+
if (converted.trimStart().startsWith('<svg')) {
|
|
1898
|
+
return {
|
|
1899
|
+
src: `data:image/svg+xml;charset=utf-8,${encodeURIComponent(converted)}`
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1901
1902
|
}
|
|
1902
|
-
if (converted.
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1903
|
+
else if (converted instanceof Uint8Array && converted.byteLength > 0) {
|
|
1904
|
+
let binary = '';
|
|
1905
|
+
for (let i = 0; i < converted.length; i += 0x8000) {
|
|
1906
|
+
binary += String.fromCharCode(...converted.subarray(i, i + 0x8000));
|
|
1907
|
+
}
|
|
1908
|
+
return { src: `data:image/png;base64,${btoa(binary)}` };
|
|
1906
1909
|
}
|
|
1907
1910
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
binary += String.fromCharCode(...converted.subarray(i, i + 0x8000));
|
|
1912
|
-
}
|
|
1913
|
-
return { src: `data:image/png;base64,${btoa(binary)}` };
|
|
1911
|
+
catch (error) {
|
|
1912
|
+
if (error?.name === 'PptxLimitError')
|
|
1913
|
+
throw error;
|
|
1914
1914
|
}
|
|
1915
1915
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
}
|
|
1916
|
+
// No conversion available/successful: a clean placeholder is safer than
|
|
1917
|
+
// substituting an unrelated same-directory raster (in PPTX every image lives
|
|
1918
|
+
// in ppt/media/, so a name-mismatched raster is almost certainly a different asset).
|
|
1920
1919
|
this.addObjectDiagnostic(context, 'image', 'placeholder', frame, {
|
|
1921
|
-
reason:
|
|
1920
|
+
reason: context.deps.renderMetafile
|
|
1921
|
+
? 'metafile-conversion-failed'
|
|
1922
|
+
: 'metafile-converter-missing',
|
|
1922
1923
|
type: sourceExt.slice(1)
|
|
1923
1924
|
});
|
|
1924
1925
|
return undefined;
|
|
@@ -1936,10 +1937,7 @@ export class PptxXmlParser {
|
|
|
1936
1937
|
if (zip.file(candidate))
|
|
1937
1938
|
return candidate;
|
|
1938
1939
|
}
|
|
1939
|
-
|
|
1940
|
-
.filter((name) => name.startsWith(`${dir}/`) && /\.(png|jpe?g|webp|gif|svg)$/i.test(name))
|
|
1941
|
-
.sort();
|
|
1942
|
-
return anyRaster[0] || target;
|
|
1940
|
+
return target;
|
|
1943
1941
|
}
|
|
1944
1942
|
static getMimeTypeByExtension(filePath) {
|
|
1945
1943
|
const ext = path.extname(filePath).toLowerCase();
|
|
@@ -3,7 +3,9 @@ import type { ViewerInput } from '../types.js';
|
|
|
3
3
|
import type { PdfJsModule } from '../pdf/index.js';
|
|
4
4
|
import { type PptMountOptions, type PptViewerDeps, type PptViewerHandle } from './index.js';
|
|
5
5
|
export * from './index.js';
|
|
6
|
+
export declare function renderPptMetafile(input: Uint8Array, type: 'wmf' | 'emf'): Promise<string | undefined>;
|
|
6
7
|
export declare const selfLoadingPptPdfDeps: {
|
|
7
8
|
loadPdfjs: () => Promise<PdfJsModule>;
|
|
9
|
+
renderMetafile: typeof renderPptMetafile;
|
|
8
10
|
};
|
|
9
11
|
export declare function mountSelfLoadingPptViewer(input: ViewerInput, container: HTMLElement, ctx: HostContext, deps?: Omit<PptViewerDeps, 'loadPdfjs'>, options?: PptMountOptions): Promise<PptViewerHandle>;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { mountPptViewer } from './index.js';
|
|
2
2
|
export * from './index.js';
|
|
3
|
-
|
|
3
|
+
// Rasterize an EMF/WMF metafile to a PNG data URL via emf-converter (lazily imported).
|
|
4
|
+
// Returns undefined on failure so the parser falls back to its own placeholder path.
|
|
5
|
+
export async function renderPptMetafile(input, type) { const buffer = input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength); const { convertEmfToDataUrl, convertWmfToDataUrl } = await import('emf-converter'); const url = type === 'wmf' ? await convertWmfToDataUrl(buffer) : await convertEmfToDataUrl(buffer); return url ?? undefined; }
|
|
6
|
+
export const selfLoadingPptPdfDeps = { loadPdfjs: () => import('pdfjs-dist/build/pdf.mjs'), renderMetafile: renderPptMetafile };
|
|
4
7
|
export function mountSelfLoadingPptViewer(input, container, ctx, deps = {}, options = {}) { return mountPptViewer(input, container, ctx, { ...deps, ...selfLoadingPptPdfDeps }, options); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omni-viewer-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Shared parsing + rendering core for Omni Viewer (vscode / chrome / obsidian / web)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -298,6 +298,9 @@
|
|
|
298
298
|
"verify:pdf-package": "node scripts/verify-pdf-package.mjs",
|
|
299
299
|
"prepublishOnly": "npm run build && npm test"
|
|
300
300
|
},
|
|
301
|
+
"dependencies": {
|
|
302
|
+
"emf-converter": "^2.0.0"
|
|
303
|
+
},
|
|
301
304
|
"devDependencies": {
|
|
302
305
|
"@rhwp/core": "0.7.3",
|
|
303
306
|
"@types/node": "^20.14.0",
|