fix: use documenso fork of skia-canvas for rendering

Use our fork of `skia-canvas` for rendering which handles
encoding characters correctly with the caveat font and other
similar fonts that can group glyphs like ligatures.

This resolves issues with pdf text extraction where characters
were unable to be extracted due to lacking any data within the cmaps.
This commit is contained in:
Lucas Smith
2026-08-14 14:58:34 +10:00
parent a5e37af3e8
commit 76e81b07de
12 changed files with 40 additions and 33 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
legacy-peer-deps = true legacy-peer-deps = true
prefer-dedupe = true prefer-dedupe = true
# min-release-age = 7 min-release-age = 7
+1 -1
View File
@@ -121,7 +121,7 @@ export default defineConfig({
'nodemailer', 'nodemailer',
/playwright/, /playwright/,
'@playwright/browser-chromium', '@playwright/browser-chromium',
'skia-canvas', '@documenso/skia-canvas',
], ],
}, },
}, },
+15 -14
View File
@@ -35,6 +35,7 @@
"@commitlint/cli": "^20.1.0", "@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0", "@commitlint/config-conventional": "^20.0.0",
"@datadog/pprof": "^5.13.5", "@datadog/pprof": "^5.13.5",
"@documenso/skia-canvas": "^3.0.8-documenso.3",
"@lingui/cli": "^5.6.0", "@lingui/cli": "^5.6.0",
"@prisma/client": "^6.19.0", "@prisma/client": "^6.19.0",
"@trpc/client": "11.8.1", "@trpc/client": "11.8.1",
@@ -3515,6 +3516,19 @@
"resolved": "packages/signing", "resolved": "packages/signing",
"link": true "link": true
}, },
"node_modules/@documenso/skia-canvas": {
"version": "3.0.8-documenso.3",
"resolved": "https://registry.npmjs.org/@documenso/skia-canvas/-/skia-canvas-3.0.8-documenso.3.tgz",
"integrity": "sha512-IeEr7RxJigCzidsRIQu6tcMX9+bt0tG3Y5kMArCPF4/jEgunPVx3qd7Wyh34mtSNufpzmVwazxR+U2BIz3iYvQ==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"detect-libc": "^2.1.1",
"follow-redirects": "^1.15.11",
"https-proxy-agent": "^7.0.6",
"string-split-by": "^1.0.0"
}
},
"node_modules/@documenso/tailwind-config": { "node_modules/@documenso/tailwind-config": {
"resolved": "packages/tailwind-config", "resolved": "packages/tailwind-config",
"link": true "link": true
@@ -28728,19 +28742,6 @@
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/skia-canvas": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/skia-canvas/-/skia-canvas-3.0.8.tgz",
"integrity": "sha512-FSYKxp8Ng2vOeeOBiyPhnn6ui6FirPJXMyjk4PKl8N/OWzVrkMawUgY9zubIWHMdYtyWFn0gfX3QlRwg6HBmdg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"detect-libc": "^2.1.1",
"follow-redirects": "^1.15.11",
"https-proxy-agent": "^7.0.6",
"string-split-by": "^1.0.0"
}
},
"node_modules/slice-ansi": { "node_modules/slice-ansi": {
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
@@ -33231,6 +33232,7 @@
"@documenso/email": "*", "@documenso/email": "*",
"@documenso/prisma": "*", "@documenso/prisma": "*",
"@documenso/signing": "*", "@documenso/signing": "*",
"@documenso/skia-canvas": "^3.0.8-documenso.3",
"@lingui/core": "^5.6.0", "@lingui/core": "^5.6.0",
"@lingui/macro": "^5.6.0", "@lingui/macro": "^5.6.0",
"@lingui/react": "^5.6.0", "@lingui/react": "^5.6.0",
@@ -33269,7 +33271,6 @@
"react": "^18", "react": "^18",
"remeda": "^2.32.0", "remeda": "^2.32.0",
"sharp": "0.34.5", "sharp": "0.34.5",
"skia-canvas": "^3.0.8",
"stripe": "^12.18.0", "stripe": "^12.18.0",
"ts-pattern": "^5.9.0", "ts-pattern": "^5.9.0",
"zod": "^3.25.76" "zod": "^3.25.76"
+1
View File
@@ -51,6 +51,7 @@
"@commitlint/cli": "^20.1.0", "@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0", "@commitlint/config-conventional": "^20.0.0",
"@datadog/pprof": "^5.13.5", "@datadog/pprof": "^5.13.5",
"@documenso/skia-canvas": "^3.0.8-documenso.3",
"@lingui/cli": "^5.6.0", "@lingui/cli": "^5.6.0",
"@prisma/client": "^6.19.0", "@prisma/client": "^6.19.0",
"@trpc/client": "11.8.1", "@trpc/client": "11.8.1",
+1 -1
View File
@@ -29,6 +29,7 @@
"@documenso/email": "*", "@documenso/email": "*",
"@documenso/prisma": "*", "@documenso/prisma": "*",
"@documenso/signing": "*", "@documenso/signing": "*",
"@documenso/skia-canvas": "^3.0.8-documenso.3",
"@lingui/core": "^5.6.0", "@lingui/core": "^5.6.0",
"@lingui/macro": "^5.6.0", "@lingui/macro": "^5.6.0",
"@lingui/react": "^5.6.0", "@lingui/react": "^5.6.0",
@@ -67,7 +68,6 @@
"react": "^18", "react": "^18",
"remeda": "^2.32.0", "remeda": "^2.32.0",
"sharp": "0.34.5", "sharp": "0.34.5",
"skia-canvas": "^3.0.8",
"stripe": "^12.18.0", "stripe": "^12.18.0",
"ts-pattern": "^5.9.0", "ts-pattern": "^5.9.0",
"zod": "^3.25.76" "zod": "^3.25.76"
+1 -1
View File
@@ -1,6 +1,6 @@
import { Canvas, Image, Path2D } from '@documenso/skia-canvas';
import pMap from 'p-map'; import pMap from 'p-map';
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf.mjs'; import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf.mjs';
import { Canvas, Image, Path2D } from 'skia-canvas';
// @ts-expect-error napi-rs/canvas satisfies the requirements // @ts-expect-error napi-rs/canvas satisfies the requirements
globalThis.Path2D = Path2D; globalThis.Path2D = Path2D;
@@ -2,8 +2,9 @@
* !: This is a workaround to fix the memory leak in the skia-canvas library. * !: This is a workaround to fix the memory leak in the skia-canvas library.
* !: Internals are ported from the original `konva/skia-backend.js` file. * !: Internals are ported from the original `konva/skia-backend.js` file.
*/ */
import { Canvas, DOMMatrix, Image, Path2D } from '@documenso/skia-canvas';
import { Konva } from 'konva/lib/_CoreInternals'; import { Konva } from 'konva/lib/_CoreInternals';
import { Canvas, DOMMatrix, Image, Path2D } from 'skia-canvas';
// @ts-expect-error skia-canvas satisfies the requirements // @ts-expect-error skia-canvas satisfies the requirements
global.DOMMatrix = DOMMatrix; global.DOMMatrix = DOMMatrix;
@@ -37,6 +38,6 @@ Konva.Util.createImageElement = () => {
return node as unknown as HTMLImageElement; return node as unknown as HTMLImageElement;
}; };
Konva._renderBackend = 'skia-canvas'; Konva._renderBackend = '@documenso/skia-canvas';
export default Konva; export default Konva;
+1 -1
View File
@@ -1,8 +1,8 @@
import path from 'node:path'; import path from 'node:path';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { FontLibrary } from '@documenso/skia-canvas';
import type { Recipient } from '@prisma/client'; import type { Recipient } from '@prisma/client';
import { FieldType } from '@prisma/client'; import { FieldType } from '@prisma/client';
import { FontLibrary } from 'skia-canvas';
import { match } from 'ts-pattern'; import { match } from 'ts-pattern';
/** /**
@@ -2,8 +2,8 @@
import '../konva/skia-backend'; import '../konva/skia-backend';
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature'; import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
import type { Canvas } from '@documenso/skia-canvas';
import Konva from 'konva'; import Konva from 'konva';
import type { Canvas } from 'skia-canvas';
import { renderField } from '../../universal/field-renderer/render-field'; import { renderField } from '../../universal/field-renderer/render-field';
import { ensureFontLibrary } from './helpers'; import { ensureFontLibrary } from './helpers';
@@ -1,14 +1,16 @@
// sort-imports-ignore
import '../konva/skia-backend';
import fs from 'node:fs';
import path from 'node:path';
import type { Canvas } from '@documenso/skia-canvas';
import { Image as SkiaImage } from '@documenso/skia-canvas';
import type { I18n } from '@lingui/core'; import type { I18n } from '@lingui/core';
import { msg } from '@lingui/core/macro'; import { msg } from '@lingui/core/macro';
import type { DocumentMeta, Envelope, RecipientRole } from '@prisma/client'; import type { DocumentMeta, Envelope, RecipientRole } from '@prisma/client';
import Konva from 'konva'; import Konva from 'konva';
import 'konva/skia-backend';
import fs from 'node:fs';
import path from 'node:path';
import type { DateTimeFormatOptions } from 'luxon'; import type { DateTimeFormatOptions } from 'luxon';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import type { Canvas } from 'skia-canvas';
import { Image as SkiaImage } from 'skia-canvas';
import { match, P } from 'ts-pattern'; import { match, P } from 'ts-pattern';
import { UAParser } from 'ua-parser-js'; import { UAParser } from 'ua-parser-js';
@@ -1,14 +1,16 @@
// sort-imports-ignore
import '../konva/skia-backend';
import fs from 'node:fs';
import path from 'node:path';
import type { Canvas } from '@documenso/skia-canvas';
import { Image as SkiaImage } from '@documenso/skia-canvas';
import type { I18n } from '@lingui/core'; import type { I18n } from '@lingui/core';
import { msg } from '@lingui/core/macro'; import { msg } from '@lingui/core/macro';
import type { Field, RecipientRole, Signature } from '@prisma/client'; import type { Field, RecipientRole, Signature } from '@prisma/client';
import { SigningStatus } from '@prisma/client'; import { SigningStatus } from '@prisma/client';
import Konva from 'konva'; import Konva from 'konva';
import 'konva/skia-backend';
import fs from 'node:fs';
import path from 'node:path';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import type { Canvas } from 'skia-canvas';
import { Image as SkiaImage } from 'skia-canvas';
import { UAParser } from 'ua-parser-js'; import { UAParser } from 'ua-parser-js';
import { renderSVG } from 'uqr'; import { renderSVG } from 'uqr';
@@ -14,7 +14,7 @@ let SkiaImage: any;
void (async () => { void (async () => {
if (typeof window === 'undefined') { if (typeof window === 'undefined') {
const mod = await import('skia-canvas'); const mod = await import('@documenso/skia-canvas');
SkiaImage = mod.Image; SkiaImage = mod.Image;
} }
})(); })();