mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-09 21:25:45 +08:00
feat: implement export as PDF (#14057)
I used [pdfmake](https://www.npmjs.com/package/pdfmake) to implement an "export as PDF" feature, and I am happy to share with you! This should fix #13577, fix #8846, and fix #13959. A showcase: [Getting Started.pdf](https://github.com/user-attachments/files/24013057/Getting.Started.pdf) Although it might miss rendering some properties currently, it can evolve in the long run and provide a more native experience for the users. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** - Experimental "Export to PDF" option added to the export menu (behind a feature flag) - PDF export supports headings, paragraphs, lists, code blocks, tables, images, callouts, linked documents and embedded content * **Chores** - Added PDF rendering library and consolidated PDF utilities - Feature flag introduced to control rollout * **Tests** - Comprehensive unit tests added for PDF content rendering logic <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: DarkSky <darksky2048@gmail.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { ListBlockModel } from '@blocksuite/affine-model';
|
||||
import { getNumberPrefix } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
BulletedList01Icon,
|
||||
BulletedList02Icon,
|
||||
@@ -11,8 +12,6 @@ import {
|
||||
} from '@blocksuite/icons/lit';
|
||||
import { html } from 'lit';
|
||||
|
||||
import { getNumberPrefix } from './get-number-prefix.js';
|
||||
|
||||
const getListDeep = (model: ListBlockModel): number => {
|
||||
let deep = 0;
|
||||
let parent = model.store.getParent(model);
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
function number2letter(n: number) {
|
||||
const ordA = 'a'.charCodeAt(0);
|
||||
const ordZ = 'z'.charCodeAt(0);
|
||||
const len = ordZ - ordA + 1;
|
||||
let s = '';
|
||||
while (n >= 0) {
|
||||
s = String.fromCharCode((n % len) + ordA) + s;
|
||||
n = Math.floor(n / len) - 1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Derive from https://gist.github.com/imilu/00f32c61e50b7ca296f91e9d96d8e976
|
||||
export function number2roman(num: number) {
|
||||
const lookup: Record<string, number> = {
|
||||
M: 1000,
|
||||
CM: 900,
|
||||
D: 500,
|
||||
CD: 400,
|
||||
C: 100,
|
||||
XC: 90,
|
||||
L: 50,
|
||||
XL: 40,
|
||||
X: 10,
|
||||
IX: 9,
|
||||
V: 5,
|
||||
IV: 4,
|
||||
I: 1,
|
||||
};
|
||||
let romanStr = '';
|
||||
for (const i in lookup) {
|
||||
while (num >= lookup[i]) {
|
||||
romanStr += i;
|
||||
num -= lookup[i];
|
||||
}
|
||||
}
|
||||
return romanStr;
|
||||
}
|
||||
|
||||
function getPrefix(depth: number, index: number) {
|
||||
const map = [
|
||||
() => index,
|
||||
() => number2letter(index - 1),
|
||||
() => number2roman(index),
|
||||
];
|
||||
return map[depth % map.length]();
|
||||
}
|
||||
|
||||
export function getNumberPrefix(index: number, depth: number) {
|
||||
const prefix = getPrefix(depth, index);
|
||||
return `${prefix}.`;
|
||||
}
|
||||
Reference in New Issue
Block a user