feat(editor): migrate typst mermaid to native (#14499)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Native/WASM Mermaid and Typst SVG preview rendering on desktop and
mobile, plus cross-platform Preview plugin integrations.

* **Improvements**
* Centralized, sanitized rendering bridge with automatic Typst
font-directory handling and configurable native renderer selection.
* More consistent and robust error serialization and worker-backed
preview flows for improved stability and performance.

* **Tests**
* Extensive unit and integration tests for preview rendering, font
discovery, sanitization, and error serialization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-03-20 04:04:40 +08:00
committed by GitHub
parent 16a8f17717
commit 7ac8b14b65
85 changed files with 4926 additions and 835 deletions
+49 -6
View File
@@ -27,6 +27,9 @@ import {
type WorkerConfig = { name: string };
type CreateWorkerTargetConfig = (pkg: Package, entry: string) => WorkerConfig;
type BaseWorkerOptions = {
includeMermaidAndTypst?: boolean;
};
function assertRspackSupportedPackage(pkg: Package) {
assertRspackSupportedPackageName(pkg.name);
@@ -49,11 +52,13 @@ async function uploadAssetsForPackage(pkg: Package, logger: Logger) {
function getBaseWorkerConfigs(
pkg: Package,
createWorkerTargetConfig: CreateWorkerTargetConfig
createWorkerTargetConfig: CreateWorkerTargetConfig,
options: BaseWorkerOptions = {}
) {
const core = new Package('@affine/core');
const includeMermaidAndTypst = options.includeMermaidAndTypst ?? true;
return [
const workerConfigs = [
createWorkerTargetConfig(
pkg,
core.srcPath.join(
@@ -71,6 +76,21 @@ function getBaseWorkerConfigs(
).value
),
];
if (includeMermaidAndTypst) {
workerConfigs.push(
createWorkerTargetConfig(
pkg,
core.srcPath.join('modules/mermaid/renderer/mermaid.worker.ts').value
),
createWorkerTargetConfig(
pkg,
core.srcPath.join('modules/typst/renderer/typst.worker.ts').value
)
);
}
return workerConfigs;
}
function getRspackBundleConfigs(pkg: Package): MultiRspackOptions {
@@ -85,9 +105,7 @@ function getRspackBundleConfigs(pkg: Package): MultiRspackOptions {
] as MultiRspackOptions;
}
case '@affine/web':
case '@affine/mobile':
case '@affine/ios':
case '@affine/android': {
case '@affine/mobile': {
const workerConfigs = getBaseWorkerConfigs(
pkg,
createRspackWorkerTargetConfig
@@ -109,10 +127,35 @@ function getRspackBundleConfigs(pkg: Package): MultiRspackOptions {
...workerConfigs,
] as MultiRspackOptions;
}
case '@affine/ios':
case '@affine/android': {
const workerConfigs = getBaseWorkerConfigs(
pkg,
createRspackWorkerTargetConfig,
{ includeMermaidAndTypst: false }
);
workerConfigs.push(
createRspackWorkerTargetConfig(
pkg,
pkg.srcPath.join('nbstore.worker.ts').value
)
);
return [
createRspackHTMLTargetConfig(
pkg,
pkg.srcPath.join('index.tsx').value,
{},
workerConfigs.map(config => config.name)
),
...workerConfigs,
] as MultiRspackOptions;
}
case '@affine/electron-renderer': {
const workerConfigs = getBaseWorkerConfigs(
pkg,
createRspackWorkerTargetConfig
createRspackWorkerTargetConfig,
{ includeMermaidAndTypst: false }
);
return [