fix(editor): merge adjacent text nodes with same marks (#3173)

This commit is contained in:
Erez Rokah 2020-01-31 16:49:10 -08:00 committed by GitHub
parent 0d7e36ba79
commit b4c5fc7783
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 2 deletions

View File

@ -1,4 +1,4 @@
import { wrapInlinesWithTexts } from '../remarkSlate';
import { wrapInlinesWithTexts, mergeAdjacentTexts } from '../remarkSlate';
describe('remarkSlate', () => {
describe('wrapInlinesWithTexts', () => {
it('should handle empty array', () => {
@ -74,4 +74,72 @@ describe('remarkSlate', () => {
]);
});
});
describe('mergeAdjacentTexts', () => {
it('should handle empty array', () => {
const children = [];
expect(mergeAdjacentTexts(children)).toBe(children);
});
it('should merge adjacent texts with same marks', () => {
const children = [
{ object: 'text', text: '<a href="https://www.netlify.com" target="_blank">', marks: [] },
{ object: 'text', text: 'Netlify', marks: [] },
{ object: 'text', text: '</a>', marks: [] },
];
expect(mergeAdjacentTexts(children)).toEqual([
{
object: 'text',
text: '<a href="https://www.netlify.com" target="_blank">Netlify</a>',
marks: [],
},
]);
});
it('should not merge adjacent texts with different marks', () => {
const children = [
{ object: 'text', text: '<a href="https://www.netlify.com" target="_blank">', marks: [] },
{ object: 'text', text: 'Netlify', marks: ['b'] },
{ object: 'text', text: '</a>', marks: [] },
];
expect(mergeAdjacentTexts(children)).toEqual(children);
});
it('should handle mixed children array', () => {
const children = [
{ object: 'inline' },
{ object: 'text', text: '<a href="https://www.netlify.com" target="_blank">', marks: [] },
{ object: 'text', text: 'Netlify', marks: [] },
{ object: 'text', text: '</a>', marks: [] },
{ object: 'inline' },
{ object: 'text', text: '<a href="https://www.netlify.com" target="_blank">', marks: [] },
{ object: 'text', text: 'Netlify', marks: ['b'] },
{ object: 'text', text: '</a>', marks: [] },
{ object: 'text', text: '<a href="https://www.netlify.com" target="_blank">', marks: [] },
{ object: 'inline' },
{ object: 'text', text: '</a>', marks: [] },
];
expect(mergeAdjacentTexts(children)).toEqual([
{ object: 'inline' },
{
object: 'text',
text: '<a href="https://www.netlify.com" target="_blank">Netlify</a>',
marks: [],
},
{ object: 'inline' },
{ object: 'text', text: '<a href="https://www.netlify.com" target="_blank">', marks: [] },
{ object: 'text', text: 'Netlify', marks: ['b'] },
{
object: 'text',
text: '</a><a href="https://www.netlify.com" target="_blank">',
marks: [],
},
{ object: 'inline' },
{ object: 'text', text: '</a>', marks: [] },
]);
});
});
});

View File

@ -1,4 +1,4 @@
import { isEmpty, isArray, flatMap, map, flatten } from 'lodash';
import { isEmpty, isArray, flatMap, map, flatten, isEqual } from 'lodash';
/**
* Map of MDAST node types to Slate node types.
@ -30,6 +30,7 @@ const markMap = {
const isInline = node => node.object === 'inline';
const isText = node => node.object === 'text';
const isMarksEqual = (node1, node2) => isEqual(node1.marks, node2.marks);
export const wrapInlinesWithTexts = children => {
if (children.length <= 0) {
@ -64,6 +65,39 @@ export const wrapInlinesWithTexts = children => {
return children;
};
export const mergeAdjacentTexts = children => {
if (children.length <= 0) {
return children;
}
const mergedChildren = [];
let isMerging = false;
let current;
for (let i = 0; i < children.length - 1; i++) {
if (!isMerging) {
current = children[i];
}
const next = children[i + 1];
if (isText(current) && isText(next) && isMarksEqual(current, next)) {
isMerging = true;
current = { ...current, text: `${current.text}${next.text}` };
} else {
mergedChildren.push(current);
isMerging = false;
}
}
if (isMerging) {
mergedChildren.push(current);
} else {
mergedChildren.push(children[children.length - 1]);
}
return mergedChildren;
};
/**
* A Remark plugin for converting an MDAST to Slate Raw AST. Remark plugins
* return a `transformNode` function that receives the MDAST as it's first argument.
@ -87,6 +121,8 @@ export default function remarkToSlate({ voidCodeBlock } = {}) {
if (Array.isArray(children)) {
// Ensure that inline nodes are surrounded by text nodes to conform to slate schema
children = wrapInlinesWithTexts(children);
// Merge adjacent text nodes with the same marks to conform to slate schema
children = mergeAdjacentTexts(children);
}
/**