Skip to content

Commit

Permalink
fix(widget-markdown): ensure remarkToSlate result matches slate schema (
Browse files Browse the repository at this point in the history
erezrokah authored and vladdu committed Jan 26, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 833971f commit d82ed44
Showing 4 changed files with 186 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -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",
},
Original file line number Diff line number Diff line change
@@ -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",
Original file line number Diff line number Diff line change
@@ -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: '' },
]);
});
});
});
Original file line number Diff line number Diff line change
@@ -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,16 +112,21 @@ 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);
}

/**
* Create a Slate Inline node.
*/
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);
}

/**

0 comments on commit d82ed44

Please sign in to comment.