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
- if (!context.deps.renderMetafile) {
1887
- this.addObjectDiagnostic(context, 'image', 'placeholder', frame, {
1888
- reason: 'metafile-converter-missing',
1889
- type: sourceExt.slice(1)
1890
- });
1891
- return undefined;
1892
- }
1893
- try {
1894
- context.guard.checkpoint(target);
1895
- const bytes = await media.async('uint8array');
1896
- const converted = await context.deps.renderMetafile(bytes, sourceExt.slice(1), context.guard.options.signal);
1897
- context.guard.checkpoint(target);
1898
- if (typeof converted === 'string' && converted) {
1899
- if (/^(?:data:|blob:|https?:)/i.test(converted)) {
1900
- return { src: converted };
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.trimStart().startsWith('<svg')) {
1903
- return {
1904
- src: `data:image/svg+xml;charset=utf-8,${encodeURIComponent(converted)}`
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
- else if (converted instanceof Uint8Array && converted.byteLength > 0) {
1909
- let binary = '';
1910
- for (let i = 0; i < converted.length; i += 0x8000) {
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
- catch (error) {
1917
- if (error?.name === 'PptxLimitError')
1918
- throw error;
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: 'metafile-conversion-failed',
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
- const anyRaster = Object.keys(zip.files)
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();
@@ -0,0 +1,2 @@
1
+ import type { HwpViewerDeps } from './index.js';
2
+ export declare function loadHwpViewerDeps(): Promise<HwpViewerDeps>;
@@ -0,0 +1,6 @@
1
+ export async function loadHwpViewerDeps() {
2
+ const imported = await import('@rhwp/core');
3
+ if (typeof imported.default === 'function')
4
+ await imported.default();
5
+ return { loadRhwp: async () => imported };
6
+ }
@@ -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
- export const selfLoadingPptPdfDeps = { loadPdfjs: () => import('pdfjs-dist/build/pdf.mjs') };
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.8.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",