feat(editor): support footnote adapter (#9844)

[BS-2373](https://linear.app/affine-design/issue/BS-2373/适配-footnote-adapter)
This commit is contained in:
donteatfriedrice
2025-01-22 06:42:35 +00:00
parent a5025cf470
commit bf797c7a0c
15 changed files with 385 additions and 11 deletions

View File

@@ -2350,6 +2350,109 @@ World!
});
expect(target.file).toBe(docMd);
});
test('footnote', async () => {
const blockSnapshot: BlockSnapshot = {
type: 'block',
id: 'block:vu6SK6WJpW',
flavour: 'affine:page',
props: {
title: {
'$blocksuite:internal:text$': true,
delta: [],
},
},
children: [
{
type: 'block',
id: 'block:Tk4gSPocAt',
flavour: 'affine:surface',
props: {
elements: {},
},
children: [],
},
{
type: 'block',
id: 'block:WfnS5ZDCJT',
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: DefaultTheme.noteBackgrounColor,
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [
{
type: 'block',
id: 'block:zxDyvrg1Mh',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert: 'aaa',
},
{
insert: ' ',
attributes: {
footnote: {
label: '1',
reference: {
type: 'url',
url: 'https://www.example.com',
},
},
},
},
{
insert: ' ',
attributes: {
footnote: {
label: '2',
reference: {
type: 'doc',
docId: 'deadbeef',
},
},
},
},
{
insert: ' ',
attributes: {
footnote: {
label: '3',
reference: {
type: 'attachment',
blobId: 'abcdefg',
fileName: 'test.txt',
fileType: 'text/plain',
},
},
},
},
],
},
},
children: [],
},
],
},
],
};
const markdown =
'aaa[^1][^2][^3]\n\n[^1]: {"type":"url","url":"https%3A%2F%2Fwww.example.com"}\n\n[^2]: {"type":"doc","docId":"deadbeef"}\n\n[^3]: {"type":"attachment","blobId":"abcdefg","fileName":"test.txt","fileType":"text/plain"}\n';
const mdAdapter = new MarkdownAdapter(createJob(), provider);
const target = await mdAdapter.fromBlockSnapshot({
snapshot: blockSnapshot,
});
expect(target.file).toBe(markdown);
});
});
describe('markdown to snapshot', () => {
@@ -3858,4 +3961,85 @@ hhh
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
test('without footnote middleware', async () => {
const markdown =
'aaa[^1][^2][^3]\n\n[^1]: {"type":"url","url":"https%3A%2F%2Fwww.example.com"}\n\n[^2]: {"type":"doc","docId":"deadbeef"}\n\n[^3]: {"type":"attachment","blobId":"abcdefg","fileName":"test.txt","fileType":"text/plain"}\n';
const blockSnapshot: BlockSnapshot = {
type: 'block',
id: 'matchesReplaceMap[0]',
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: DefaultTheme.noteBackgrounColor,
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [
{
type: 'block',
id: 'matchesReplaceMap[1]',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert: 'aaa',
},
{
insert: ' ',
attributes: {
footnote: {
label: '1',
reference: {
type: 'url',
url: 'https://www.example.com',
},
},
},
},
{
insert: ' ',
attributes: {
footnote: {
label: '2',
reference: {
type: 'doc',
docId: 'deadbeef',
},
},
},
},
{
insert: ' ',
attributes: {
footnote: {
label: '3',
reference: {
type: 'attachment',
blobId: 'abcdefg',
fileName: 'test.txt',
fileType: 'text/plain',
},
},
},
},
],
},
},
children: [],
},
],
};
const mdAdapter = new MarkdownAdapter(createJob(), provider);
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
file: markdown,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
});