mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-03-22 23:30:36 +08:00
<!-- 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 -->
86 lines
2.3 KiB
TypeScript
86 lines
2.3 KiB
TypeScript
import path from 'node:path';
|
|
|
|
import fs from 'fs-extra';
|
|
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
|
|
const { native } = vi.hoisted(() => ({
|
|
native: {
|
|
renderMermaidSvg: vi.fn(),
|
|
renderTypstSvg: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock('@affine/native', () => native);
|
|
|
|
const tmpDir = path.join(__dirname, 'tmp');
|
|
const typstFontDirA = path.join(tmpDir, 'fonts-a');
|
|
const typstFontDirB = path.join(tmpDir, 'fonts-b');
|
|
|
|
async function loadPreviewHandlers() {
|
|
vi.resetModules();
|
|
const module = await import('../../src/helper/preview');
|
|
return module.previewHandlers;
|
|
}
|
|
|
|
describe('helper preview handlers', () => {
|
|
beforeEach(async () => {
|
|
await fs.ensureDir(typstFontDirA);
|
|
await fs.ensureDir(typstFontDirB);
|
|
process.env.AFFINE_TYPST_FONT_DIRS = [
|
|
typstFontDirA,
|
|
typstFontDirB,
|
|
path.join(tmpDir, 'missing'),
|
|
].join(path.delimiter);
|
|
native.renderMermaidSvg.mockReset();
|
|
native.renderTypstSvg.mockReset();
|
|
native.renderMermaidSvg.mockReturnValue({
|
|
svg: '<svg><text>mermaid</text></svg>',
|
|
});
|
|
native.renderTypstSvg.mockReturnValue({
|
|
svg: '<svg><text>typst</text></svg>',
|
|
});
|
|
});
|
|
|
|
afterEach(async () => {
|
|
delete process.env.AFFINE_TYPST_FONT_DIRS;
|
|
await fs.remove(tmpDir);
|
|
});
|
|
|
|
test('passes mermaid request to native renderer', async () => {
|
|
const previewHandlers = await loadPreviewHandlers();
|
|
const request = { code: 'flowchart TD; A-->B' };
|
|
|
|
await previewHandlers.renderMermaidSvg(request);
|
|
|
|
expect(native.renderMermaidSvg).toHaveBeenCalledWith(request);
|
|
});
|
|
|
|
test('injects resolved fontDirs into typst requests', async () => {
|
|
const previewHandlers = await loadPreviewHandlers();
|
|
|
|
await previewHandlers.renderTypstSvg({ code: '= hello' });
|
|
|
|
const [request] = native.renderTypstSvg.mock.calls[0];
|
|
expect(request.options?.fontDirs).toEqual(
|
|
expect.arrayContaining([
|
|
path.resolve(typstFontDirA),
|
|
path.resolve(typstFontDirB),
|
|
])
|
|
);
|
|
});
|
|
|
|
test('keeps explicit typst fontDirs', async () => {
|
|
const previewHandlers = await loadPreviewHandlers();
|
|
const request = {
|
|
code: '= hello',
|
|
options: {
|
|
fontDirs: ['/tmp/custom-fonts'],
|
|
},
|
|
};
|
|
|
|
await previewHandlers.renderTypstSvg(request);
|
|
|
|
expect(native.renderTypstSvg).toHaveBeenCalledWith(request);
|
|
});
|
|
});
|