fix(widget-markdown): ensure remarkToSlate result matches slate schema (#3085)
This commit is contained in:
parent
0a50efda8e
commit
fde0c5a9a7
@ -476,6 +476,10 @@ more important, there there are only so many sizes that you can use.",
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"title": null,
|
||||
@ -506,6 +510,10 @@ more important, there there are only so many sizes that you can use.",
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"title": null,
|
||||
@ -557,6 +565,12 @@ more important, there there are only so many sizes that you can use.",
|
||||
"type": "paragraph",
|
||||
},
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "block",
|
||||
"type": "thematic-break",
|
||||
},
|
||||
|
@ -279,6 +279,12 @@ Object {
|
||||
"type": "heading-one",
|
||||
},
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "block",
|
||||
"type": "thematic-break",
|
||||
},
|
||||
@ -321,6 +327,12 @@ Object {
|
||||
"type": "heading-one",
|
||||
},
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "block",
|
||||
"type": "thematic-break",
|
||||
},
|
||||
@ -357,6 +369,12 @@ Object {
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "inline",
|
||||
"type": "break",
|
||||
},
|
||||
@ -384,15 +402,29 @@ Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"alt": "super",
|
||||
"title": null,
|
||||
"url": "duper.jpg",
|
||||
},
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "inline",
|
||||
"type": "image",
|
||||
},
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "block",
|
||||
"type": "paragraph",
|
||||
@ -638,15 +670,29 @@ Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"alt": "test",
|
||||
"title": null,
|
||||
"url": "test.png",
|
||||
},
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "inline",
|
||||
"type": "image",
|
||||
},
|
||||
Object {
|
||||
"object": "text",
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
"object": "block",
|
||||
"type": "paragraph",
|
||||
|
@ -0,0 +1,77 @@
|
||||
import { wrapInlinesWithTexts } from '../remarkSlate';
|
||||
describe('remarkSlate', () => {
|
||||
describe('wrapInlinesWithTexts', () => {
|
||||
it('should handle empty array', () => {
|
||||
const children = [];
|
||||
expect(wrapInlinesWithTexts(children)).toBe(children);
|
||||
});
|
||||
|
||||
it('should wrap single inline node with texts', () => {
|
||||
expect(wrapInlinesWithTexts([{ object: 'inline' }])).toEqual([
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should insert text before inline', () => {
|
||||
expect(wrapInlinesWithTexts([{ object: 'inline' }, { object: 'text', text: '' }])).toEqual([
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should insert text after inline', () => {
|
||||
expect(wrapInlinesWithTexts([{ object: 'text', text: '' }, { object: 'inline' }])).toEqual([
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not modify valid children array', () => {
|
||||
const children = [
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
];
|
||||
expect(wrapInlinesWithTexts(children)).toBe(children);
|
||||
});
|
||||
|
||||
it('should wrap inlines with text nodes', () => {
|
||||
expect(
|
||||
wrapInlinesWithTexts([
|
||||
{ object: 'inline' },
|
||||
{ object: 'other' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'other' },
|
||||
{ object: 'text', text: 'hello' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: 'world' },
|
||||
{ object: 'inline' },
|
||||
]),
|
||||
).toEqual([
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'other' },
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'other' },
|
||||
{ object: 'text', text: 'hello' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: 'world' },
|
||||
{ object: 'inline' },
|
||||
{ object: 'text', text: '' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
@ -28,6 +28,42 @@ const markMap = {
|
||||
inlineCode: 'code',
|
||||
};
|
||||
|
||||
const isInline = node => node.object === 'inline';
|
||||
const isText = node => node.object === 'text';
|
||||
|
||||
export const wrapInlinesWithTexts = children => {
|
||||
if (children.length <= 0) {
|
||||
return children;
|
||||
}
|
||||
|
||||
const insertLocations = [];
|
||||
let prev = children[0];
|
||||
if (isInline(prev)) {
|
||||
insertLocations.push(0);
|
||||
}
|
||||
|
||||
for (let i = 1; i < children.length; i++) {
|
||||
const current = children[i];
|
||||
if (isInline(prev) && !isText(current)) {
|
||||
insertLocations.push(i);
|
||||
} else if (!isText(prev) && isInline(current)) {
|
||||
insertLocations.push(i);
|
||||
}
|
||||
|
||||
prev = current;
|
||||
}
|
||||
|
||||
if (isInline(prev)) {
|
||||
insertLocations.push(children.length);
|
||||
}
|
||||
|
||||
for (let i = 0; i < insertLocations.length; i++) {
|
||||
children.splice(insertLocations[i] + i, 0, { object: 'text', text: '' });
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -43,11 +79,16 @@ export default function remarkToSlate({ voidCodeBlock } = {}) {
|
||||
* translate from MDAST to Slate, such as definitions for link/image
|
||||
* references or footnotes.
|
||||
*/
|
||||
const children =
|
||||
let children =
|
||||
!['strong', 'emphasis', 'delete'].includes(node.type) &&
|
||||
!isEmpty(node.children) &&
|
||||
flatMap(node.children, transformNode).filter(val => val);
|
||||
|
||||
if (Array.isArray(children)) {
|
||||
// Ensure that inline nodes are surrounded by text nodes to conform to slate schema
|
||||
children = wrapInlinesWithTexts(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run individual nodes through the conversion factory.
|
||||
*/
|
||||
@ -71,8 +112,10 @@ export default function remarkToSlate({ voidCodeBlock } = {}) {
|
||||
nodes = undefined;
|
||||
}
|
||||
|
||||
// Ensure block nodes have at least one text child to conform to slate schema
|
||||
const children = isEmpty(nodes) ? [createText('')] : nodes;
|
||||
const node = { object: 'block', type, ...props };
|
||||
return addNodes(node, nodes);
|
||||
return addNodes(node, children);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +123,10 @@ export default function remarkToSlate({ voidCodeBlock } = {}) {
|
||||
*/
|
||||
function createInline(type, props = {}, nodes) {
|
||||
const node = { object: 'inline', type, ...props };
|
||||
return addNodes(node, nodes);
|
||||
|
||||
// Ensure inline nodes have at least one text child to conform to slate schema
|
||||
const children = isEmpty(nodes) ? [createText('')] : nodes;
|
||||
return addNodes(node, children);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user