@file-viewer/vite-plugin 2.1.27 → 2.1.29

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 (2) hide show
  1. package/dist/index.js +115 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
2
- import { copyFile, cp, mkdir, rm, stat, writeFile } from 'node:fs/promises';
2
+ import { copyFile, cp, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
3
3
  import { createRequire } from 'node:module';
4
- import { dirname, extname, isAbsolute, join, resolve } from 'node:path';
4
+ import { dirname, extname, isAbsolute, join, resolve, sep } from 'node:path';
5
5
  const virtualModuleId = 'virtual:file-viewer-renderers';
6
6
  const resolvedVirtualModuleId = `\0${virtualModuleId}`;
7
7
  const pluginRequire = createRequire(import.meta.url);
@@ -404,6 +404,7 @@ const fileViewerOptimizationExcludedPackages = [
404
404
  ];
405
405
  const cjsInteropPackages = [
406
406
  '@file-viewer/docx',
407
+ '@xmldom/xmldom',
407
408
  'jszip'
408
409
  ];
409
410
  const defaultScanRoots = ['src', 'app', 'pages', 'components'];
@@ -852,7 +853,8 @@ function resolveWorkspacePackageJson(packageName) {
852
853
  return workspacePackageJsonCache.packages.get(packageName) || null;
853
854
  }
854
855
  function resolvePackageJson(packageName, anchorPackages = []) {
855
- const requireFns = [projectRequire(), pluginRequire];
856
+ const rootRequireFns = [projectRequire(), pluginRequire];
857
+ const requireFns = [...rootRequireFns];
856
858
  const effectiveAnchorPackages = unique([
857
859
  ...Object.values(presetModules).map((preset) => preset.packageName),
858
860
  ...anchorPackages
@@ -873,7 +875,16 @@ function resolvePackageJson(packageName, anchorPackages = []) {
873
875
  }
874
876
  }
875
877
  }
876
- for (const requireFn of requireFns) {
878
+ const preferredAnchorPackageJsons = unique(anchorPackages
879
+ .map((anchorPackage) => requireFns
880
+ .map((requireFn) => tryResolvePackageJson(anchorPackage, requireFn))
881
+ .find(Boolean) || resolveWorkspacePackageJson(anchorPackage))
882
+ .filter((packageJson) => Boolean(packageJson)));
883
+ const targetRequireFns = [
884
+ ...preferredAnchorPackageJsons.map((packageJson) => createRequire(packageJson)),
885
+ ...requireFns
886
+ ];
887
+ for (const requireFn of targetRequireFns) {
877
888
  const packageJson = tryResolvePackageJson(packageName, requireFn);
878
889
  if (packageJson) {
879
890
  return packageJson;
@@ -931,6 +942,37 @@ function resolvePackageRoot(packageName, anchorPackages = []) {
931
942
  const packageJson = resolvePackageJson(packageName, anchorPackages);
932
943
  return packageJson ? dirname(packageJson) : null;
933
944
  }
945
+ function readPackageVersion(packageRoot) {
946
+ if (!packageRoot) {
947
+ return null;
948
+ }
949
+ try {
950
+ const packageJson = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'));
951
+ return packageJson.version || null;
952
+ }
953
+ catch {
954
+ return null;
955
+ }
956
+ }
957
+ function assertOwnedPackageVersion(packageName, packageRoot, ownerPackageName) {
958
+ if (!packageRoot) {
959
+ return null;
960
+ }
961
+ const ownerPackageJsonPath = resolvePackageJson(ownerPackageName);
962
+ if (!ownerPackageJsonPath) {
963
+ return readPackageVersion(packageRoot);
964
+ }
965
+ const ownerPackageJson = JSON.parse(readFileSync(ownerPackageJsonPath, 'utf8'));
966
+ const expectedVersion = ownerPackageJson.dependencies?.[packageName];
967
+ const actualVersion = readPackageVersion(packageRoot);
968
+ if (expectedVersion &&
969
+ /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(expectedVersion) &&
970
+ actualVersion !== expectedVersion) {
971
+ throw new Error(`[file-viewer:vite-plugin] ${ownerPackageName} requires ${packageName}@${expectedVersion}, ` +
972
+ `but renderer assets resolved from ${packageName}@${actualVersion || 'unknown'} (${packageRoot}).`);
973
+ }
974
+ return actualVersion;
975
+ }
934
976
  function resolvePackageEntry(packageName, anchorPackages = []) {
935
977
  const packageJsonPath = resolvePackageJson(packageName, anchorPackages);
936
978
  if (!packageJsonPath) {
@@ -1096,7 +1138,7 @@ async function copyPdfCjkFontAssets(from, to) {
1096
1138
  async function copyKnownRendererAssets(targetRoot, rendererIds) {
1097
1139
  const selected = new Set(rendererIds);
1098
1140
  const results = [];
1099
- const push = async (rendererId, id, to, copyAction, reason) => {
1141
+ const push = async (rendererId, id, to, copyAction, reason, source) => {
1100
1142
  if (!selected.has(rendererId)) {
1101
1143
  return;
1102
1144
  }
@@ -1106,14 +1148,19 @@ async function copyKnownRendererAssets(targetRoot, rendererIds) {
1106
1148
  id,
1107
1149
  to,
1108
1150
  copied,
1109
- reason: copied ? undefined : reason || 'source asset not found'
1151
+ reason: copied ? undefined : reason || 'source asset not found',
1152
+ ...source,
1110
1153
  });
1111
1154
  };
1112
1155
  const pdfRoot = resolvePackageRoot('pdfjs-dist', ['@file-viewer/renderer-pdf']);
1113
- await push('pdf', 'pdf-worker', join(targetRoot, 'vendor/pdf/pdf.worker.mjs'), () => copyFileIfPresent(pdfRoot ? join(pdfRoot, 'legacy/build/pdf.worker.mjs') : null, join(targetRoot, 'vendor/pdf/pdf.worker.mjs')));
1114
- await push('pdf', 'pdf-cmaps', join(targetRoot, 'vendor/pdf/cmaps'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'cmaps') : null, join(targetRoot, 'vendor/pdf/cmaps')));
1115
- await push('pdf', 'pdf-wasm', join(targetRoot, 'vendor/pdf/wasm'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'wasm') : null, join(targetRoot, 'vendor/pdf/wasm')));
1116
- await push('pdf', 'pdf-standard-fonts', join(targetRoot, 'vendor/pdf/standard_fonts'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'standard_fonts') : null, join(targetRoot, 'vendor/pdf/standard_fonts')));
1156
+ const pdfVersion = assertOwnedPackageVersion('pdfjs-dist', pdfRoot, '@file-viewer/renderer-pdf');
1157
+ const pdfSource = pdfRoot
1158
+ ? { sourcePackage: 'pdfjs-dist', sourceVersion: pdfVersion || undefined }
1159
+ : undefined;
1160
+ await push('pdf', 'pdf-worker', join(targetRoot, 'vendor/pdf/pdf.worker.mjs'), () => copyFileIfPresent(pdfRoot ? join(pdfRoot, 'legacy/build/pdf.worker.mjs') : null, join(targetRoot, 'vendor/pdf/pdf.worker.mjs')), undefined, pdfSource);
1161
+ await push('pdf', 'pdf-cmaps', join(targetRoot, 'vendor/pdf/cmaps'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'cmaps') : null, join(targetRoot, 'vendor/pdf/cmaps')), undefined, pdfSource);
1162
+ await push('pdf', 'pdf-wasm', join(targetRoot, 'vendor/pdf/wasm'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'wasm') : null, join(targetRoot, 'vendor/pdf/wasm')), undefined, pdfSource);
1163
+ await push('pdf', 'pdf-standard-fonts', join(targetRoot, 'vendor/pdf/standard_fonts'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'standard_fonts') : null, join(targetRoot, 'vendor/pdf/standard_fonts')), undefined, pdfSource);
1117
1164
  const pdfCjkFontRoot = resolvePackageRoot('@fontsource-variable/noto-sans-sc', [
1118
1165
  '@file-viewer/renderer-pdf'
1119
1166
  ]);
@@ -1152,9 +1199,9 @@ async function copyKnownRendererAssets(targetRoot, rendererIds) {
1152
1199
  }, null, 2)}\n`);
1153
1200
  return results;
1154
1201
  }
1155
- function resolveTargetDir(value, fallback) {
1202
+ function resolveTargetDir(value, fallback, projectRoot) {
1156
1203
  const target = value || fallback;
1157
- return isAbsolute(target) ? target : resolve(process.cwd(), target);
1204
+ return isAbsolute(target) ? target : resolve(projectRoot || process.cwd(), target);
1158
1205
  }
1159
1206
  function copyOptions(value) {
1160
1207
  return typeof value === 'object' ? value : {};
@@ -1289,13 +1336,66 @@ export function fileViewerRenderers(options = {}) {
1289
1336
  }
1290
1337
  }
1291
1338
  },
1292
- async configureServer() {
1339
+ async configureServer(server) {
1293
1340
  if (!options.copyAssets || copyOptions(options.copyAssets).mode === 'build') {
1294
1341
  return;
1295
1342
  }
1296
- const targetRoot = resolveTargetDir(copyOptions(options.copyAssets).publicDir, resolvedConfig?.publicDir || 'public');
1343
+ const targetRoot = resolveTargetDir(copyOptions(options.copyAssets).publicDir, resolvedConfig?.publicDir || 'public', resolvedConfig?.root);
1297
1344
  const results = await copyKnownRendererAssets(targetRoot, collectAssetRendererIds(selection, autoPresetIds));
1298
1345
  reportAssetCopy(results, targetRoot, missingMode);
1346
+ const base = resolvedConfig?.base || '/';
1347
+ if (base.startsWith('/') && base !== '/') {
1348
+ const normalizedBase = base.endsWith('/') ? base : `${base}/`;
1349
+ server.middlewares.use(async (request, response, next) => {
1350
+ const requestUrl = request.url || '';
1351
+ const queryIndex = requestUrl.indexOf('?');
1352
+ const pathname = queryIndex >= 0 ? requestUrl.slice(0, queryIndex) : requestUrl;
1353
+ if (pathname.startsWith(normalizedBase)) {
1354
+ let relativePath = pathname.slice(normalizedBase.length);
1355
+ try {
1356
+ relativePath = decodeURIComponent(relativePath);
1357
+ }
1358
+ catch {
1359
+ next();
1360
+ return;
1361
+ }
1362
+ if (relativePath.startsWith('vendor/') || relativePath.startsWith('wasm/')) {
1363
+ const assetPath = resolve(targetRoot, relativePath);
1364
+ if (assetPath.startsWith(`${targetRoot}${sep}`)) {
1365
+ try {
1366
+ const info = await stat(assetPath);
1367
+ if (info.isFile()) {
1368
+ const contentTypes = {
1369
+ '.bcmap': 'application/octet-stream',
1370
+ '.css': 'text/css; charset=utf-8',
1371
+ '.js': 'text/javascript; charset=utf-8',
1372
+ '.json': 'application/json; charset=utf-8',
1373
+ '.mjs': 'text/javascript; charset=utf-8',
1374
+ '.ttf': 'font/ttf',
1375
+ '.wasm': 'application/wasm',
1376
+ '.woff': 'font/woff',
1377
+ '.woff2': 'font/woff2'
1378
+ };
1379
+ response.statusCode = 200;
1380
+ response.setHeader('Content-Type', contentTypes[extname(assetPath).toLowerCase()] || 'application/octet-stream');
1381
+ if (request.method === 'HEAD') {
1382
+ response.end();
1383
+ }
1384
+ else {
1385
+ response.end(await readFile(assetPath));
1386
+ }
1387
+ return;
1388
+ }
1389
+ }
1390
+ catch {
1391
+ // Let Vite return its normal 404/fallback response.
1392
+ }
1393
+ }
1394
+ }
1395
+ }
1396
+ next();
1397
+ });
1398
+ }
1299
1399
  },
1300
1400
  transformIndexHtml: {
1301
1401
  order: 'pre',
@@ -1340,7 +1440,7 @@ export function fileViewerRenderers(options = {}) {
1340
1440
  return;
1341
1441
  }
1342
1442
  const outDir = resolvedConfig?.build.outDir || 'dist';
1343
- const targetRoot = resolveTargetDir(copyOptions(options.copyAssets).outDir, outDir);
1443
+ const targetRoot = resolveTargetDir(copyOptions(options.copyAssets).outDir, outDir, resolvedConfig?.root);
1344
1444
  const results = await copyKnownRendererAssets(targetRoot, collectAssetRendererIds(selection, autoPresetIds));
1345
1445
  reportAssetCopy(results, targetRoot, missingMode);
1346
1446
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/vite-plugin",
3
- "version": "2.1.27",
3
+ "version": "2.1.29",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Vite plugin for Flyfish File Viewer on-demand renderer assembly, chunk planning, and offline asset deployment.",