diff --git a/common/config/rush/common-versions.json b/common/config/rush/common-versions.json
index 1df9ccf987..6c75d33a8e 100644
--- a/common/config/rush/common-versions.json
+++ b/common/config/rush/common-versions.json
@@ -58,5 +58,9 @@
// "typescript": [
// "~2.4.0"
// ]
+
+ // rekoni vendors an older pdfjs-dist server-side for PDF text extraction,
+ // while packages/ui uses a modern build for browser canvas rendering.
+ "pdfjs-dist": ["2.12.313", "4.10.38"]
}
}
diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml
index 928464ae94..f4668a68a9 100644
--- a/common/config/rush/pnpm-lock.yaml
+++ b/common/config/rush/pnpm-lock.yaml
@@ -1808,6 +1808,9 @@ importers:
compression-webpack-plugin:
specifier: ^10.0.0
version: 10.0.0(webpack@5.102.1)
+ copy-webpack-plugin:
+ specifier: ^11.0.0
+ version: 11.0.0(webpack@5.102.1)
cross-env:
specifier: ~7.0.3
version: 7.0.3
@@ -14994,6 +14997,9 @@ importers:
fast-equals:
specifier: ^5.2.2
version: 5.3.2
+ pdfjs-dist:
+ specifier: 4.10.38
+ version: 4.10.38
plyr:
specifier: 3.7.8
version: 3.7.8
@@ -43178,6 +43184,76 @@ packages:
cpu: [x64]
os: [win32]
+ '@napi-rs/canvas-android-arm64@0.1.100':
+ resolution: {integrity: sha512-hjhCKhntPv9+t4ckHymdx0phYNcVW+GKQR6Lzw2zE+pOVjOplSmtx9nNNknTjbEDLcuLZqA1y8ufKg1XfgftzQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@napi-rs/canvas-darwin-arm64@0.1.100':
+ resolution: {integrity: sha512-2PcswRaC7Ly645DGt88///zuFDhJxJYdKAs1uU3mfk1atYkXufgcgLfBpk6Tm12nCQBaNt1wpybuPZ4qOhTo8A==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@napi-rs/canvas-darwin-x64@0.1.100':
+ resolution: {integrity: sha512-ePNZtj7pNIva/siZMg+HmbeozkIjqUIYdoymH8HaA3qK7LfzFN4WMBM8G6HQ9ZC+H3+Dnn5pqtiXpgLykaPOhw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@0.1.100':
+ resolution: {integrity: sha512-d5cDB48oWFGU8/XPhUOFAlySgb/VAu7D+s8fi55K1Pcfg8aPplHWqMgibhVLU8ky7Pyg/fuiVLz4Nf3JrSTuUA==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-gnu@0.1.100':
+ resolution: {integrity: sha512-rDxgxRu69RvDlX/bh9o22DxLsGr8EqsNgotL9+RwQE1S0b0cqeatqsw6aW45mukm0B42DIAaAacKaYQ8cqS1nw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-musl@0.1.100':
+ resolution: {integrity: sha512-K3mDW66N+xT2/V439u1alFANiBUjdEx2gLiNYnCmUsva5jZMxWTjafBYwTzYK+EMFMHrUoabuU+T1BIP5CgbYQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-riscv64-gnu@0.1.100':
+ resolution: {integrity: sha512-mooqUBTIsccZpnoQC4NgrC1v6C1vof39etLNMnBwCY+p0gajWJvAHLGQ6g/gGyS5YrpDW+GefSN4+Cvcr08UWw==}
+ engines: {node: '>= 10'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-x64-gnu@0.1.100':
+ resolution: {integrity: sha512-1eCvkDCazm7FFhsT7DfGOdSaHgZVK3bt/dSBl5EWHOWmnz+I7j8tPseJqqD81NF+MH21jKUK4wQSDjN0mdhnTg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-x64-musl@0.1.100':
+ resolution: {integrity: sha512-20arT6lnI19S68qNlii73TSEDbECNgzMz2EpldC1V3mZFuRkeujXkcebRk0LRJe9SEUAooYiLokfMViY8IX7yA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@napi-rs/canvas-win32-arm64-msvc@0.1.100':
+ resolution: {integrity: sha512-DZFFT1wIAg37LJw37yhMRFfjATd3vTQzjZ1Yki8u2vhO6Hi5VE6BVaGQ1aaDu7xb4iMErz+9EOwjpS7xcxFeBw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@napi-rs/canvas-win32-x64-msvc@0.1.100':
+ resolution: {integrity: sha512-MyT1j3mHC2+Lu4pBi9mKyMJhtP6U7k7EldY7sj/uS5gJA65gTXt8MefJQXLJo5d/vZbuWmfxzkEUNc/urV3pHA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@napi-rs/canvas@0.1.100':
+ resolution: {integrity: sha512-xglYA6q3XO5P3BNJYxVZ1IV7DLVjp1Py6nwag88YntrS+3vKHyYcMqXVS4ZztJmwz2uGvz1FWhI/4LgbR5uQDA==}
+ engines: {node: '>= 10'}
+
'@napi-rs/snappy-android-arm-eabi@7.3.3':
resolution: {integrity: sha512-d4vUFFzNBvazGfB/KU8MnEax6itTIgRWXodPdZDnWKHy9HwVBndpCiedQDcSNHcZNYV36rx034rpn7SAuTL2NA==}
engines: {node: '>= 10'}
@@ -49917,6 +49993,10 @@ packages:
worker-loader:
optional: true
+ pdfjs-dist@4.10.38:
+ resolution: {integrity: sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ==}
+ engines: {node: '>=20'}
+
pe-library@0.4.1:
resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==}
engines: {node: '>=12', npm: '>=6'}
@@ -53956,6 +54036,54 @@ snapshots:
'@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3':
optional: true
+ '@napi-rs/canvas-android-arm64@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-darwin-arm64@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-darwin-x64@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-gnu@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-musl@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-linux-riscv64-gnu@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-gnu@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-musl@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-win32-arm64-msvc@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas-win32-x64-msvc@0.1.100':
+ optional: true
+
+ '@napi-rs/canvas@0.1.100':
+ optionalDependencies:
+ '@napi-rs/canvas-android-arm64': 0.1.100
+ '@napi-rs/canvas-darwin-arm64': 0.1.100
+ '@napi-rs/canvas-darwin-x64': 0.1.100
+ '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.100
+ '@napi-rs/canvas-linux-arm64-gnu': 0.1.100
+ '@napi-rs/canvas-linux-arm64-musl': 0.1.100
+ '@napi-rs/canvas-linux-riscv64-gnu': 0.1.100
+ '@napi-rs/canvas-linux-x64-gnu': 0.1.100
+ '@napi-rs/canvas-linux-x64-musl': 0.1.100
+ '@napi-rs/canvas-win32-arm64-msvc': 0.1.100
+ '@napi-rs/canvas-win32-x64-msvc': 0.1.100
+ optional: true
+
'@napi-rs/snappy-android-arm-eabi@7.3.3':
optional: true
@@ -61601,7 +61729,7 @@ snapshots:
node-loader@2.0.0(webpack@5.102.1):
dependencies:
loader-utils: 2.0.4
- webpack: 5.102.1
+ webpack: 5.102.1(esbuild@0.25.12)(webpack-cli@5.1.4)
node-localstorage@2.2.1:
dependencies:
@@ -62025,6 +62153,10 @@ snapshots:
pdfjs-dist@2.12.313: {}
+ pdfjs-dist@4.10.38:
+ optionalDependencies:
+ '@napi-rs/canvas': 0.1.100
+
pe-library@0.4.1: {}
peberminta@0.9.0: {}
diff --git a/desktop/webpack.config.js b/desktop/webpack.config.js
index d955e51256..012c799f05 100644
--- a/desktop/webpack.config.js
+++ b/desktop/webpack.config.js
@@ -21,6 +21,13 @@ const { EsbuildPlugin } = require('esbuild-loader')
const doValidate = !prod || process.env.DO_VALIDATE === 'true'
+// pdfjs-dist is a dependency of @hcengineering/ui, not of this package directly.
+// Resolve it from there so the worker entry and the copied cmaps/standard_fonts
+// assets stay in sync with whatever version @hcengineering/ui declares.
+const pdfjsDistDir = path.dirname(
+ require.resolve('pdfjs-dist/package.json', { paths: [path.join(__dirname, '../packages/ui')] })
+)
+
/**
* @type {Configuration}
*/
@@ -127,6 +134,11 @@ module.exports = [
entry: {
bundle: ['@hcengineering/theme/styles/global.scss', ...['./src/ui/index.ts']],
'recorder-worker': '@hcengineering/recorder-resources/src/recorder-worker.ts',
+ // Flat, fixed-path fallback for the pdf.js worker (see createPdfWorker() in
+ // @hcengineering/ui's pdf-embed-utils.ts) — used when the primary
+ // `new Worker(new URL('pdfjs-dist/...', import.meta.url))` construction
+ // throws, mirroring the 'recorder-worker' entry above.
+ 'pdfjs-worker': path.join(pdfjsDistDir, 'build', 'pdf.worker.min.mjs'),
findInPageOverlay: './src/ui/findInPageOverlay.ts'
},
ignoreWarnings: [
@@ -321,7 +333,13 @@ module.exports = [
mode,
plugins: [
new CopyPlugin({
- patterns: [{ from: 'public', to: 'public' }]
+ patterns: [
+ { from: 'public', to: 'public' },
+ // pdf.js needs these served alongside the app to render CJK/subset
+ // text and the 14 standard PDF fonts without embedded glyph data.
+ { from: path.join(pdfjsDistDir, 'cmaps'), to: 'cmaps' },
+ { from: path.join(pdfjsDistDir, 'standard_fonts'), to: 'standard_fonts' }
+ ]
}),
new HtmlWebpackPlugin({
template: './src/ui/index.ejs',
diff --git a/dev/prod/package.json b/dev/prod/package.json
index eb365cf772..833f19c83f 100644
--- a/dev/prod/package.json
+++ b/dev/prod/package.json
@@ -28,6 +28,7 @@
"autoprefixer": "^10.4.14",
"browserslist": "^4.28.2",
"compression-webpack-plugin": "^10.0.0",
+ "copy-webpack-plugin": "^11.0.0",
"cross-env": "~7.0.3",
"css-loader": "^5.2.1",
"dotenv-webpack": "^8.0.1",
@@ -297,4 +298,4 @@
"readable-stream": "^4.7.0",
"svelte": "^4.2.20"
}
-}
\ No newline at end of file
+}
diff --git a/dev/prod/webpack.config.js b/dev/prod/webpack.config.js
index 54298c063c..8e319c9b34 100644
--- a/dev/prod/webpack.config.js
+++ b/dev/prod/webpack.config.js
@@ -21,8 +21,16 @@ const path = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
const DefinePlugin = require('webpack').DefinePlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
+const CopyPlugin = require('copy-webpack-plugin')
const { Configuration } = require('webpack')
+// pdfjs-dist is a dependency of @hcengineering/ui, not of this package directly.
+// Resolve it from there so the copied cmaps/standard_fonts assets stay in sync
+// with whatever version @hcengineering/ui declares.
+const pdfjsDistDir = path.dirname(
+ require.resolve('pdfjs-dist/package.json', { paths: [path.join(__dirname, '../../packages/ui')] })
+)
+
const mode = process.env.NODE_ENV || 'development'
const prod = mode === 'production'
const clientType = process.env.CLIENT_TYPE ?? ''
@@ -438,6 +446,14 @@ module.exports = [
viewport: 'width=device-width, initial-scale=1.0'
}
}),
+ new CopyPlugin({
+ patterns: [
+ // pdf.js needs these served alongside the app to render CJK/subset
+ // text and the 14 standard PDF fonts without embedded glyph data.
+ { from: path.join(pdfjsDistDir, 'cmaps'), to: 'cmaps' },
+ { from: path.join(pdfjsDistDir, 'standard_fonts'), to: 'standard_fonts' }
+ ]
+ }),
...(prod ? [new CompressionPlugin()] : []),
// new MiniCssExtractPlugin({
// filename: '[name].[id][contenthash].css'
diff --git a/packages/presentation/src/components/PDFViewer.svelte b/packages/presentation/src/components/PDFViewer.svelte
index 550d219f44..e37222aa78 100644
--- a/packages/presentation/src/components/PDFViewer.svelte
+++ b/packages/presentation/src/components/PDFViewer.svelte
@@ -15,6 +15,7 @@
@@ -97,7 +99,7 @@
{:else}
-