tsdown.config.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { readFileSync, readdirSync } from 'node:fs'
  2. import { createRequire } from 'node:module'
  3. import { dirname, join } from 'node:path'
  4. import type { UserConfig } from 'tsdown'
  5. import { clientBundle } from '../tsdown.client.ts'
  6. const bundle = clientBundle('@deepseek-ai/dsh-client-ui-sidebar-documentpreview', ['lib/types/index.js'], {
  7. clientBanner: fileName => fileName.endsWith('client.pdf.js') ? pdfLicenseBanner() : undefined,
  8. })
  9. const require = createRequire(import.meta.url)
  10. const workerSpecifier = 'pdfjs-dist/build/pdf.worker.min.mjs?raw'
  11. const workerModule = '\0dsh-pdf-worker.mjs'
  12. /** License files for PDF.js and the data embedded beside its runtime. */
  13. function pdfLicenseFiles(root: string): string[] {
  14. return ['LICENSE', ...['cmaps', 'standard_fonts', 'wasm'].flatMap(directory =>
  15. readdirSync(join(root, directory)).filter(name => name.startsWith('LICENSE')).sort()
  16. .map(name => `${directory}/${name}`),
  17. )]
  18. }
  19. /** Keep every bundled PDF.js license visible in the published client artifact. */
  20. function pdfLicenseBanner(): string {
  21. const root = dirname(require.resolve('pdfjs-dist/package.json'))
  22. const notice = pdfLicenseFiles(root).map(name =>
  23. `${name}\n\n${readFileSync(join(root, name), 'utf8').trimEnd()}`,
  24. ).join('\n\n')
  25. return ['//! Bundled PDF.js license notices', ...notice.split('\n').map(line => `// ${line}`)].join('\n')
  26. }
  27. /** Keep font mappings and image decoders in the same artifact as their PDF.js runtime. */
  28. function pdfAssets(): string {
  29. const root = dirname(require.resolve('pdfjs-dist/package.json'))
  30. return JSON.stringify(Object.fromEntries([
  31. ['cMapUrl', 'cmaps'], ['standardFontDataUrl', 'standard_fonts'], ['wasmUrl', 'wasm'],
  32. ].map(([kind, directory]) => [kind, Object.fromEntries(
  33. readdirSync(join(root, directory!)).filter(name => !name.startsWith('LICENSE')).sort()
  34. .map(name => [name, readFileSync(join(root, directory!, name)).toString('base64')]),
  35. )])))
  36. }
  37. /** The dynamic client factory has no module URL from which to resolve a Worker file. */
  38. const pdfWorker: NonNullable<UserConfig['plugins']> = [{
  39. name: 'dsh-pdf-worker-source',
  40. resolveId(source) {
  41. return source === workerSpecifier ? workerModule : null
  42. },
  43. load(id) {
  44. if (id !== workerModule) return null
  45. const path = require.resolve('pdfjs-dist/build/pdf.worker.min.mjs')
  46. this.addWatchFile(path)
  47. return `export default ${JSON.stringify(readFileSync(path, 'utf8'))};`
  48. },
  49. }]
  50. export default (options: Parameters<typeof bundle>[0]): UserConfig[] => bundle(options).map(config =>
  51. config.name?.endsWith('/client') === true ? {
  52. ...config,
  53. plugins: [config.plugins, pdfWorker],
  54. define: { ...config.define, __DSH_PDFJS_ASSETS__: pdfAssets() },
  55. } : config,
  56. )