mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-02 01:49:51 +08:00
fix(editor): notion text adapter should handle text without styles correctly (#12248)
Closes: [BS-3486](https://linear.app/affine-design/issue/BS-3486/粘贴从-notion-复制的内容出错) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved handling of Notion text segments with empty or invalid style arrays, ensuring plain text and styled text are both processed correctly and preventing errors from malformed input. - **Tests** - Added a test case to verify correct conversion of Notion text with empty styles arrays. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -106,4 +106,65 @@ describe('notion-text to snapshot', () => {
|
|||||||
});
|
});
|
||||||
expect(nanoidReplacement(target!)).toEqual(sliceSnapshot);
|
expect(nanoidReplacement(target!)).toEqual(sliceSnapshot);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('notion text with empty styles array', () => {
|
||||||
|
const notionText =
|
||||||
|
'{"blockType":"text","editing":[["a "],["bold text",[["b"]]],[" hello world"]],"selection":{"startIndex":0,"endIndex":23},"action":"copy"}';
|
||||||
|
|
||||||
|
const sliceSnapshot: SliceSnapshot = {
|
||||||
|
type: 'slice',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[0]',
|
||||||
|
flavour: 'affine:note',
|
||||||
|
props: {
|
||||||
|
xywh: '[0,0,800,95]',
|
||||||
|
background: DefaultTheme.noteBackgrounColor,
|
||||||
|
index: 'a0',
|
||||||
|
hidden: false,
|
||||||
|
displayMode: 'both',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[1]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [
|
||||||
|
{
|
||||||
|
insert: 'a ',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insert: 'bold text',
|
||||||
|
attributes: {
|
||||||
|
bold: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insert: ' hello world',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
workspaceId: '',
|
||||||
|
pageId: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const ntAdapter = new NotionTextAdapter(createJob(), provider);
|
||||||
|
const target = ntAdapter.toSliceSnapshot({
|
||||||
|
file: notionText,
|
||||||
|
workspaceId: '',
|
||||||
|
pageId: '',
|
||||||
|
});
|
||||||
|
expect(nanoidReplacement(target!)).toEqual(sliceSnapshot);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -94,28 +94,49 @@ export class NotionTextAdapter extends BaseAdapter<NotionText> {
|
|||||||
const notionText = JSON.parse(payload.file) as NotionTextSerialized;
|
const notionText = JSON.parse(payload.file) as NotionTextSerialized;
|
||||||
const content: SliceSnapshot['content'] = [];
|
const content: SliceSnapshot['content'] = [];
|
||||||
const deltas: DeltaInsert<AffineTextAttributes>[] = [];
|
const deltas: DeltaInsert<AffineTextAttributes>[] = [];
|
||||||
|
|
||||||
|
// Check if the notionText.editing is an array
|
||||||
|
if (!Array.isArray(notionText.editing)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
for (const editing of notionText.editing) {
|
for (const editing of notionText.editing) {
|
||||||
const delta: DeltaInsert<AffineTextAttributes> = {
|
const delta: DeltaInsert<AffineTextAttributes> = {
|
||||||
insert: editing[0],
|
insert: editing[0],
|
||||||
attributes: Object.create(null),
|
|
||||||
};
|
};
|
||||||
for (const styleElement of editing[1]) {
|
|
||||||
switch (styleElement[0]) {
|
// Check if the stylesArray of editing[1] is an array
|
||||||
case 'b':
|
const stylesArray = editing[1];
|
||||||
delta.attributes!.bold = true;
|
if (Array.isArray(stylesArray)) {
|
||||||
break;
|
for (const styleElement of stylesArray) {
|
||||||
case 'i':
|
// Skip invalid style entries
|
||||||
delta.attributes!.italic = true;
|
if (!styleElement || typeof styleElement[0] !== 'string') {
|
||||||
break;
|
continue;
|
||||||
case '_':
|
}
|
||||||
delta.attributes!.underline = true;
|
|
||||||
break;
|
// Check if the delta.attributes exists, if not, create a new object
|
||||||
case 'c':
|
if (!delta.attributes) {
|
||||||
delta.attributes!.code = true;
|
delta.attributes = Object.create(null);
|
||||||
break;
|
}
|
||||||
case 's':
|
|
||||||
delta.attributes!.strike = true;
|
// Add the style to the delta.attributes
|
||||||
break;
|
switch (styleElement[0]) {
|
||||||
|
case 'b':
|
||||||
|
delta.attributes!.bold = true;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
delta.attributes!.italic = true;
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
delta.attributes!.underline = true;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
delta.attributes!.code = true;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
delta.attributes!.strike = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deltas.push(delta);
|
deltas.push(delta);
|
||||||
|
|||||||
Reference in New Issue
Block a user