chore: add code formatting and linting (#952)
This commit is contained in:
@ -99,5 +99,5 @@ RawEditor.propTypes = {
|
||||
onMode: PropTypes.func.isRequired,
|
||||
className: PropTypes.string.isRequired,
|
||||
value: PropTypes.string,
|
||||
field: ImmutablePropTypes.map
|
||||
field: ImmutablePropTypes.map,
|
||||
};
|
||||
|
@ -12,22 +12,24 @@ const ShortcodeContainer = styled.div`
|
||||
margin: 12px 0;
|
||||
padding: 14px;
|
||||
|
||||
${props => props.collapsed && css`
|
||||
background-color: ${colors.textFieldBorder};
|
||||
cursor: pointer;
|
||||
`}
|
||||
`
|
||||
${props =>
|
||||
props.collapsed &&
|
||||
css`
|
||||
background-color: ${colors.textFieldBorder};
|
||||
cursor: pointer;
|
||||
`};
|
||||
`;
|
||||
|
||||
const ShortcodeTopBar = styled(ListItemTopBar)`
|
||||
background-color: ${colors.textFieldBorder};
|
||||
margin: -14px -14px 0;
|
||||
border-radius: 0;
|
||||
`
|
||||
`;
|
||||
|
||||
const ShortcodeTitle = styled.div`
|
||||
padding: 8px;
|
||||
color: ${colors.controlLabel};
|
||||
`
|
||||
`;
|
||||
|
||||
export default class Shortcode extends React.Component {
|
||||
constructor(props) {
|
||||
@ -51,16 +53,14 @@ export default class Shortcode extends React.Component {
|
||||
|
||||
handleCollapseToggle = () => {
|
||||
this.setState({ collapsed: !this.state.collapsed });
|
||||
}
|
||||
};
|
||||
|
||||
handleRemove = () => {
|
||||
const { editor, node } = this.props;
|
||||
editor.change(change => {
|
||||
change
|
||||
.removeNodeByKey(node.key)
|
||||
.focus();
|
||||
change.removeNodeByKey(node.key).focus();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleClick = event => {
|
||||
/**
|
||||
@ -75,18 +75,18 @@ export default class Shortcode extends React.Component {
|
||||
if (this.state.collapsed) {
|
||||
this.handleCollapseToggle();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
renderControl = (shortcodeData, field) => {
|
||||
if (field.get('widget') === 'hidden') return null;
|
||||
const value = shortcodeData.get(field.get('name'));
|
||||
const key = `field-${ field.get('name') }`;
|
||||
const key = `field-${field.get('name')}`;
|
||||
const Control = getEditorControl();
|
||||
const controlProps = { field, value, onChange: this.handleChange };
|
||||
|
||||
return (
|
||||
<div key={key}>
|
||||
<Control {...controlProps}/>
|
||||
<Control {...controlProps} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -104,11 +104,11 @@ export default class Shortcode extends React.Component {
|
||||
onCollapseToggle={this.handleCollapseToggle}
|
||||
onRemove={this.handleRemove}
|
||||
/>
|
||||
{
|
||||
collapsed
|
||||
? <ShortcodeTitle>{capitalize(pluginId)}</ShortcodeTitle>
|
||||
: plugin.get('fields').map(partial(this.renderControl, shortcodeData))
|
||||
}
|
||||
{collapsed ? (
|
||||
<ShortcodeTitle>{capitalize(pluginId)}</ShortcodeTitle>
|
||||
) : (
|
||||
plugin.get('fields').map(partial(this.renderControl, shortcodeData))
|
||||
)}
|
||||
</ShortcodeContainer>
|
||||
);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ const ToolbarContainer = styled.div`
|
||||
const ToolbarDropdownWrapper = styled.div`
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
`
|
||||
`;
|
||||
|
||||
const ToolbarToggle = styled.div`
|
||||
flex-shrink: 0;
|
||||
@ -35,7 +35,7 @@ const ToolbarToggle = styled.div`
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
margin: 0 10px;
|
||||
`
|
||||
`;
|
||||
|
||||
const StyledToggle = ToolbarToggle.withComponent(Toggle);
|
||||
|
||||
@ -44,13 +44,15 @@ const ToolbarToggleLabel = styled.span`
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
line-height: 20px;
|
||||
width: ${props => props.offPosition ? '62px' : '70px'};
|
||||
width: ${props => (props.offPosition ? '62px' : '70px')};
|
||||
|
||||
${props => props.isActive && css`
|
||||
font-weight: 600;
|
||||
color: ${colors.active};
|
||||
`}
|
||||
`
|
||||
${props =>
|
||||
props.isActive &&
|
||||
css`
|
||||
font-weight: 600;
|
||||
color: ${colors.active};
|
||||
`};
|
||||
`;
|
||||
|
||||
export default class Toolbar extends React.Component {
|
||||
static propTypes = {
|
||||
@ -67,7 +69,7 @@ export default class Toolbar extends React.Component {
|
||||
isHidden = button => {
|
||||
const { buttons } = this.props;
|
||||
return List.isList(buttons) ? !buttons.includes(button) : false;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
@ -191,15 +193,24 @@ export default class Toolbar extends React.Component {
|
||||
</DropdownButton>
|
||||
)}
|
||||
>
|
||||
{plugins && plugins.toList().map((plugin, idx) => (
|
||||
<DropdownItem key={idx} label={plugin.get('label')} onClick={() => onSubmit(plugin.get('id'))} />
|
||||
))}
|
||||
{plugins &&
|
||||
plugins
|
||||
.toList()
|
||||
.map((plugin, idx) => (
|
||||
<DropdownItem
|
||||
key={idx}
|
||||
label={plugin.get('label')}
|
||||
onClick={() => onSubmit(plugin.get('id'))}
|
||||
/>
|
||||
))}
|
||||
</Dropdown>
|
||||
</ToolbarDropdownWrapper>
|
||||
</div>
|
||||
<ToolbarToggle>
|
||||
<ToolbarToggleLabel isActive={!rawMode} offPosition>Rich Text</ToolbarToggleLabel>
|
||||
<StyledToggle active={rawMode} onChange={onToggleMode}/>
|
||||
<ToolbarToggleLabel isActive={!rawMode} offPosition>
|
||||
Rich Text
|
||||
</ToolbarToggleLabel>
|
||||
<StyledToggle active={rawMode} onChange={onToggleMode} />
|
||||
<ToolbarToggleLabel isActive={rawMode}>Markdown</ToolbarToggleLabel>
|
||||
</ToolbarToggle>
|
||||
</ToolbarContainer>
|
||||
|
@ -10,7 +10,7 @@ const StyledToolbarButton = styled.button`
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 16px;
|
||||
color: ${props => props.isActive ? '#1e2532' : 'inherit'};
|
||||
color: ${props => (props.isActive ? '#1e2532' : 'inherit')};
|
||||
cursor: pointer;
|
||||
|
||||
&:disabled {
|
||||
@ -21,7 +21,7 @@ const StyledToolbarButton = styled.button`
|
||||
${Icon} {
|
||||
display: block;
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
||||
const ToolbarButton = ({ type, label, icon, onClick, isActive, isHidden, disabled }) => {
|
||||
if (isHidden) {
|
||||
@ -35,7 +35,7 @@ const ToolbarButton = ({ type, label, icon, onClick, isActive, isHidden, disable
|
||||
title={label}
|
||||
disabled={disabled}
|
||||
>
|
||||
{ icon ? <Icon type={icon}/> : label }
|
||||
{icon ? <Icon type={icon} /> : label}
|
||||
</StyledToolbarButton>
|
||||
);
|
||||
};
|
||||
|
@ -17,20 +17,20 @@ import { EditorControlBar } from '../styles';
|
||||
|
||||
const VisualEditorContainer = styled.div`
|
||||
position: relative;
|
||||
`
|
||||
`;
|
||||
|
||||
const createEmptyRawDoc = () => {
|
||||
const emptyText = Text.create('');
|
||||
const emptyBlock = Block.create({ kind: 'block', type: 'paragraph', nodes: [ emptyText ] });
|
||||
const emptyBlock = Block.create({ kind: 'block', type: 'paragraph', nodes: [emptyText] });
|
||||
return { nodes: [emptyBlock] };
|
||||
};
|
||||
|
||||
const createSlateValue = (rawValue) => {
|
||||
const createSlateValue = rawValue => {
|
||||
const rawDoc = rawValue && markdownToSlate(rawValue);
|
||||
const rawDocHasNodes = !isEmpty(get(rawDoc, 'nodes'))
|
||||
const rawDocHasNodes = !isEmpty(get(rawDoc, 'nodes'));
|
||||
const document = Document.fromJSON(rawDocHasNodes ? rawDoc : createEmptyRawDoc());
|
||||
return Value.create({ document });
|
||||
}
|
||||
};
|
||||
|
||||
export default class Editor extends React.Component {
|
||||
static propTypes = {
|
||||
@ -40,7 +40,7 @@ export default class Editor extends React.Component {
|
||||
onMode: PropTypes.func.isRequired,
|
||||
className: PropTypes.string.isRequired,
|
||||
value: PropTypes.string,
|
||||
field: ImmutablePropTypes.map
|
||||
field: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@ -61,14 +61,17 @@ export default class Editor extends React.Component {
|
||||
const ast = htmlToSlate(data.html);
|
||||
const doc = Document.fromJSON(ast);
|
||||
return change.insertFragment(doc);
|
||||
}
|
||||
};
|
||||
|
||||
selectionHasMark = type => this.state.value.activeMarks.some(mark => mark.type === type);
|
||||
selectionHasBlock = type => this.state.value.blocks.some(node => node.type === type);
|
||||
|
||||
handleMarkClick = (event, type) => {
|
||||
event.preventDefault();
|
||||
const resolvedChange = this.state.value.change().focus().toggleMark(type);
|
||||
const resolvedChange = this.state.value
|
||||
.change()
|
||||
.focus()
|
||||
.toggleMark(type);
|
||||
this.ref.onChange(resolvedChange);
|
||||
this.setState({ value: resolvedChange.value });
|
||||
};
|
||||
@ -119,9 +122,7 @@ export default class Editor extends React.Component {
|
||||
// should simply unlink them.
|
||||
if (this.hasLinks()) {
|
||||
change = change.unwrapInline('link');
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
const url = window.prompt('Enter the URL of the link');
|
||||
|
||||
// If nothing is entered in the URL prompt, do nothing.
|
||||
@ -129,14 +130,10 @@ export default class Editor extends React.Component {
|
||||
|
||||
// If no text is selected, use the entered URL as text.
|
||||
if (change.value.isCollapsed) {
|
||||
change = change
|
||||
.insertText(url)
|
||||
.extend(0 - url.length);
|
||||
change = change.insertText(url).extend(0 - url.length);
|
||||
}
|
||||
|
||||
change = change
|
||||
.wrapInline({ type: 'link', data: { url } })
|
||||
.collapseToEnd();
|
||||
change = change.wrapInline({ type: 'link', data: { url } }).collapseToEnd();
|
||||
}
|
||||
|
||||
this.ref.onChange(change);
|
||||
@ -155,7 +152,7 @@ export default class Editor extends React.Component {
|
||||
shortcodeData: Map(),
|
||||
},
|
||||
isVoid: true,
|
||||
nodes
|
||||
nodes,
|
||||
};
|
||||
let change = value.change();
|
||||
const { focusBlock } = change.value;
|
||||
@ -176,7 +173,6 @@ export default class Editor extends React.Component {
|
||||
this.props.onMode('raw');
|
||||
};
|
||||
|
||||
|
||||
handleDocumentChange = debounce(change => {
|
||||
const { onChange } = this.props;
|
||||
const raw = change.value.document.toJSON();
|
||||
@ -193,7 +189,7 @@ export default class Editor extends React.Component {
|
||||
|
||||
processRef = ref => {
|
||||
this.ref = ref;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { onAddAsset, getAsset, className, field, getEditorComponents } = this.props;
|
||||
|
@ -2,8 +2,8 @@ import { markdownToSlate } from '../../serializers';
|
||||
|
||||
const parser = markdownToSlate;
|
||||
|
||||
describe("Compile markdown to Slate Raw AST", () => {
|
||||
it("should compile simple markdown", () => {
|
||||
describe('Compile markdown to Slate Raw AST', () => {
|
||||
it('should compile simple markdown', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
@ -12,7 +12,7 @@ sweet body
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile a markdown ordered list", () => {
|
||||
it('should compile a markdown ordered list', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
@ -23,7 +23,7 @@ sweet body
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile bulleted lists", () => {
|
||||
it('should compile bulleted lists', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
@ -34,7 +34,7 @@ sweet body
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile multiple header levels", () => {
|
||||
it('should compile multiple header levels', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
@ -45,7 +45,7 @@ sweet body
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile horizontal rules", () => {
|
||||
it('should compile horizontal rules', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
@ -56,7 +56,7 @@ blue moon
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile horizontal rules", () => {
|
||||
it('should compile horizontal rules', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
@ -67,7 +67,7 @@ blue moon
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile soft breaks (double space)", () => {
|
||||
it('should compile soft breaks (double space)', () => {
|
||||
const value = `
|
||||
blue moon
|
||||
footballs
|
||||
@ -75,14 +75,14 @@ footballs
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile images", () => {
|
||||
it('should compile images', () => {
|
||||
const value = `
|
||||

|
||||
`;
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile code blocks", () => {
|
||||
it('should compile code blocks', () => {
|
||||
const value = `
|
||||
\`\`\`javascript
|
||||
var a = 1;
|
||||
@ -91,7 +91,7 @@ var a = 1;
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile nested inline markup", () => {
|
||||
it('should compile nested inline markup', () => {
|
||||
const value = `
|
||||
# Word
|
||||
|
||||
@ -102,7 +102,7 @@ perhaps **scalding** even
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile inline code", () => {
|
||||
it('should compile inline code', () => {
|
||||
const value = `
|
||||
# Word
|
||||
|
||||
@ -111,7 +111,7 @@ This is some sweet \`inline code\` yo!
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile links", () => {
|
||||
it('should compile links', () => {
|
||||
const value = `
|
||||
# Word
|
||||
|
||||
@ -120,7 +120,7 @@ How far is it to [Google](https://google.com) land?
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile plugins", () => {
|
||||
it('should compile plugins', () => {
|
||||
const value = `
|
||||

|
||||
|
||||
@ -129,7 +129,7 @@ How far is it to [Google](https://google.com) land?
|
||||
expect(parser(value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should compile kitchen sink example", () => {
|
||||
it('should compile kitchen sink example', () => {
|
||||
const value = `
|
||||
# An exhibit of Markdown
|
||||
|
||||
|
@ -32,12 +32,12 @@ export default class MarkdownControl extends React.Component {
|
||||
this.state = { mode: localStorage.getItem(MODE_STORAGE_KEY) || 'visual' };
|
||||
}
|
||||
|
||||
handleMode = (mode) => {
|
||||
handleMode = mode => {
|
||||
this.setState({ mode });
|
||||
localStorage.setItem(MODE_STORAGE_KEY, mode);
|
||||
};
|
||||
|
||||
processRef = ref => this.ref = ref;
|
||||
processRef = ref => (this.ref = ref);
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -38,14 +38,9 @@ function onKeyDown(event, change) {
|
||||
.collapseToStartOf(newBlock);
|
||||
}
|
||||
|
||||
const marks = [
|
||||
[ 'b', 'bold' ],
|
||||
[ 'i', 'italic' ],
|
||||
[ 's', 'strikethrough' ],
|
||||
[ '`', 'code' ],
|
||||
];
|
||||
const marks = [['b', 'bold'], ['i', 'italic'], ['s', 'strikethrough'], ['`', 'code']];
|
||||
|
||||
const [ , markName ] = marks.find(([ key ]) => isHotkey(`mod+${key}`, event)) || [];
|
||||
const [, markName] = marks.find(([key]) => isHotkey(`mod+${key}`, event)) || [];
|
||||
|
||||
if (markName) {
|
||||
event.preventDefault();
|
||||
|
@ -15,18 +15,16 @@ const SoftBreak = (options = {}) => ({
|
||||
|
||||
const shouldClose = text.endsWith('\n');
|
||||
if (shouldClose) {
|
||||
return change
|
||||
.deleteBackward(1)
|
||||
.insertBlock(defaultBlock);
|
||||
return change.deleteBackward(1).insertBlock(defaultBlock);
|
||||
}
|
||||
|
||||
const textNode = Text.create('\n');
|
||||
const breakNode = Inline.create({ type: 'break', nodes: [ textNode ] });
|
||||
const breakNode = Inline.create({ type: 'break', nodes: [textNode] });
|
||||
return change
|
||||
.insertInline(breakNode)
|
||||
.insertText('')
|
||||
.collapseToStartOfNextText();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const SoftBreakOpts = {
|
||||
@ -44,11 +42,18 @@ const BreakToDefaultBlock = ({ onlyIn = [], defaultBlock = 'paragraph' }) => ({
|
||||
if (onlyIn.includes(value.startBlock.type)) {
|
||||
return change.insertBlock(defaultBlock);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const BreakToDefaultBlockOpts = {
|
||||
onlyIn: ['heading-one', 'heading-two', 'heading-three', 'heading-four', 'heading-five', 'heading-six'],
|
||||
onlyIn: [
|
||||
'heading-one',
|
||||
'heading-two',
|
||||
'heading-three',
|
||||
'heading-four',
|
||||
'heading-five',
|
||||
'heading-six',
|
||||
],
|
||||
};
|
||||
|
||||
export const BreakToDefaultBlockConfigured = BreakToDefaultBlock(BreakToDefaultBlockOpts);
|
||||
@ -67,7 +72,7 @@ const BackspaceCloseBlock = (options = {}) => ({
|
||||
if (startBlock.text === '') {
|
||||
return change.setBlock(defaultBlock).focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const BackspaceCloseBlockOpts = {
|
||||
|
@ -21,30 +21,46 @@ const Code = props => <code>{props.children}</code>;
|
||||
const Paragraph = props => <p {...props.attributes}>{props.children}</p>;
|
||||
const ListItem = props => <li {...props.attributes}>{props.children}</li>;
|
||||
const Quote = props => <blockquote {...props.attributes}>{props.children}</blockquote>;
|
||||
const CodeBlock = props => <pre><code {...props.attributes}>{props.children}</code></pre>;
|
||||
const CodeBlock = props => (
|
||||
<pre>
|
||||
<code {...props.attributes}>{props.children}</code>
|
||||
</pre>
|
||||
);
|
||||
const HeadingOne = props => <h1 {...props.attributes}>{props.children}</h1>;
|
||||
const HeadingTwo = props => <h2 {...props.attributes}>{props.children}</h2>;
|
||||
const HeadingThree = props => <h3 {...props.attributes}>{props.children}</h3>;
|
||||
const HeadingFour = props => <h4 {...props.attributes}>{props.children}</h4>;
|
||||
const HeadingFive = props => <h5 {...props.attributes}>{props.children}</h5>;
|
||||
const HeadingSix = props => <h6 {...props.attributes}>{props.children}</h6>;
|
||||
const Table = props => <table><tbody {...props.attributes}>{props.children}</tbody></table>;
|
||||
const Table = props => (
|
||||
<table>
|
||||
<tbody {...props.attributes}>{props.children}</tbody>
|
||||
</table>
|
||||
);
|
||||
const TableRow = props => <tr {...props.attributes}>{props.children}</tr>;
|
||||
const TableCell = props => <td {...props.attributes}>{props.children}</td>;
|
||||
const ThematicBreak = props => <hr {...props.attributes}/>;
|
||||
const ThematicBreak = props => <hr {...props.attributes} />;
|
||||
const BulletedList = props => <ul {...props.attributes}>{props.children}</ul>;
|
||||
const NumberedList = props => (
|
||||
<ol {...props.attributes} start={props.node.data.get('start') || 1}>{props.children}</ol>
|
||||
<ol {...props.attributes} start={props.node.data.get('start') || 1}>
|
||||
{props.children}
|
||||
</ol>
|
||||
);
|
||||
const Link = props => {
|
||||
const data = props.node.get('data');
|
||||
const marks = data.get('marks');
|
||||
const url = data.get('url');
|
||||
const title = data.get('title');
|
||||
const link = <a href={url} title={title} {...props.attributes}>{props.children}</a>;
|
||||
const result = !marks ? link : marks.reduce((acc, mark) => {
|
||||
return renderMark({ mark, children: acc });
|
||||
}, link);
|
||||
const link = (
|
||||
<a href={url} title={title} {...props.attributes}>
|
||||
{props.children}
|
||||
</a>
|
||||
);
|
||||
const result = !marks
|
||||
? link
|
||||
: marks.reduce((acc, mark) => {
|
||||
return renderMark({ mark, children: acc });
|
||||
}, link);
|
||||
return result;
|
||||
};
|
||||
const Image = props => {
|
||||
@ -53,42 +69,67 @@ const Image = props => {
|
||||
const url = data.get('url');
|
||||
const title = data.get('title');
|
||||
const alt = data.get('alt');
|
||||
const image = <img src={url} title={title} alt={alt} {...props.attributes}/>;
|
||||
const result = !marks ? image : marks.reduce((acc, mark) => {
|
||||
return renderMark({ mark, children: acc });
|
||||
}, image);
|
||||
const image = <img src={url} title={title} alt={alt} {...props.attributes} />;
|
||||
const result = !marks
|
||||
? image
|
||||
: marks.reduce((acc, mark) => {
|
||||
return renderMark({ mark, children: acc });
|
||||
}, image);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const renderMark = props => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold': return <Bold {...props}/>;
|
||||
case 'italic': return <Italic {...props}/>;
|
||||
case 'strikethrough': return <Strikethrough {...props}/>;
|
||||
case 'code': return <Code {...props}/>;
|
||||
case 'bold':
|
||||
return <Bold {...props} />;
|
||||
case 'italic':
|
||||
return <Italic {...props} />;
|
||||
case 'strikethrough':
|
||||
return <Strikethrough {...props} />;
|
||||
case 'code':
|
||||
return <Code {...props} />;
|
||||
}
|
||||
};
|
||||
|
||||
export const renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'paragraph': return <Paragraph {...props}/>;
|
||||
case 'list-item': return <ListItem {...props}/>;
|
||||
case 'quote': return <Quote {...props}/>;
|
||||
case 'code': return <CodeBlock {...props}/>;
|
||||
case 'heading-one': return <HeadingOne {...props}/>;
|
||||
case 'heading-two': return <HeadingTwo {...props}/>;
|
||||
case 'heading-three': return <HeadingThree {...props}/>;
|
||||
case 'heading-four': return <HeadingFour {...props}/>;
|
||||
case 'heading-five': return <HeadingFive {...props}/>;
|
||||
case 'heading-six': return <HeadingSix {...props}/>;
|
||||
case 'table': return <Table {...props}/>;
|
||||
case 'table-row': return <TableRow {...props}/>;
|
||||
case 'table-cell': return <TableCell {...props}/>;
|
||||
case 'thematic-break': return <ThematicBreak {...props}/>;
|
||||
case 'bulleted-list': return <BulletedList {...props}/>;
|
||||
case 'numbered-list': return <NumberedList {...props}/>;
|
||||
case 'link': return <Link {...props}/>;
|
||||
case 'image': return <Image {...props}/>;
|
||||
case 'shortcode': return <Shortcode {...props}/>;
|
||||
case 'paragraph':
|
||||
return <Paragraph {...props} />;
|
||||
case 'list-item':
|
||||
return <ListItem {...props} />;
|
||||
case 'quote':
|
||||
return <Quote {...props} />;
|
||||
case 'code':
|
||||
return <CodeBlock {...props} />;
|
||||
case 'heading-one':
|
||||
return <HeadingOne {...props} />;
|
||||
case 'heading-two':
|
||||
return <HeadingTwo {...props} />;
|
||||
case 'heading-three':
|
||||
return <HeadingThree {...props} />;
|
||||
case 'heading-four':
|
||||
return <HeadingFour {...props} />;
|
||||
case 'heading-five':
|
||||
return <HeadingFive {...props} />;
|
||||
case 'heading-six':
|
||||
return <HeadingSix {...props} />;
|
||||
case 'table':
|
||||
return <Table {...props} />;
|
||||
case 'table-row':
|
||||
return <TableRow {...props} />;
|
||||
case 'table-cell':
|
||||
return <TableCell {...props} />;
|
||||
case 'thematic-break':
|
||||
return <ThematicBreak {...props} />;
|
||||
case 'bulleted-list':
|
||||
return <BulletedList {...props} />;
|
||||
case 'numbered-list':
|
||||
return <NumberedList {...props} />;
|
||||
case 'link':
|
||||
return <Link {...props} />;
|
||||
case 'image':
|
||||
return <Image {...props} />;
|
||||
case 'shortcode':
|
||||
return <Shortcode {...props} />;
|
||||
}
|
||||
};
|
||||
|
@ -66,24 +66,24 @@ export function validateNode(node) {
|
||||
if (trailingShortcode) {
|
||||
return change => {
|
||||
const text = Text.create('');
|
||||
const block = Block.create({ type: 'paragraph', nodes: [ text ] });
|
||||
const block = Block.create({ type: 'paragraph', nodes: [text] });
|
||||
return change.insertNodeByKey(doc.key, doc.get('nodes').size, block);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensure that code blocks contain no marks.
|
||||
*/
|
||||
if (node.type === 'code') {
|
||||
const invalidChild = node.getTexts().find(text => !text.getMarks().isEmpty());
|
||||
if (invalidChild) {
|
||||
return change => (
|
||||
invalidChild.getMarks().forEach(mark => (
|
||||
change.removeMarkByKey(invalidChild.key, 0, invalidChild.get('characters').size, mark)
|
||||
))
|
||||
);
|
||||
return change =>
|
||||
invalidChild
|
||||
.getMarks()
|
||||
.forEach(mark =>
|
||||
change.removeMarkByKey(invalidChild.key, 0, invalidChild.get('characters').size, mark),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,12 +39,21 @@ export default css`
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
p, pre, blockquote, ul, ol {
|
||||
p,
|
||||
pre,
|
||||
blockquote,
|
||||
ul,
|
||||
ol {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
@ -62,7 +71,8 @@ export default css`
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
ul,
|
||||
ol {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
@ -98,7 +108,8 @@ export default css`
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
td,
|
||||
th {
|
||||
border: 2px solid black;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
|
@ -8,7 +8,7 @@ const MarkdownPreview = ({ value, getAsset }) => {
|
||||
return null;
|
||||
}
|
||||
const html = markdownToHtml(value, getAsset);
|
||||
return <WidgetPreviewContainer dangerouslySetInnerHTML={{__html: html}}/>
|
||||
return <WidgetPreviewContainer dangerouslySetInnerHTML={{ __html: html }} />;
|
||||
};
|
||||
|
||||
MarkdownPreview.propTypes = {
|
||||
|
@ -35,18 +35,18 @@ Text with **bold** & _em_ elements
|
||||
###### H6
|
||||
`;
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Headings', () => {
|
||||
for (const heading of [...Array(6).keys()]) {
|
||||
it(`should render Heading ${ heading + 1 }`, () => {
|
||||
it(`should render Heading ${heading + 1}`, () => {
|
||||
const value = padStart(' Title', heading + 7, '#');
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -65,8 +65,8 @@ Text with **bold** & _em_ elements
|
||||
1. ol item 3
|
||||
`;
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@ -80,8 +80,8 @@ I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]
|
||||
[3]: http://search.msn.com/ "MSN Search"
|
||||
`;
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@ -89,15 +89,15 @@ I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]
|
||||
it('should render code', () => {
|
||||
const value = 'Use the `printf()` function.';
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render code 2', () => {
|
||||
const value = '``There is a literal backtick (`) here.``';
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@ -119,8 +119,8 @@ I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]
|
||||
<h1 style="display: block; border: 10px solid #f00; width: 100%">Test</h1>
|
||||
`;
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -129,8 +129,8 @@ I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]
|
||||
it('should render HTML', () => {
|
||||
const value = '<p>Paragraph with <em>inline</em> element</p>';
|
||||
expect(
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON()
|
||||
).toMatchSnapshot()
|
||||
renderer.create(<MarkdownPreview value={markdownToHtml(value)} />).toJSON(),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,2 +1,2 @@
|
||||
export MarkdownControl from './MarkdownControl'
|
||||
export MarkdownPreview from './MarkdownPreview'
|
||||
export MarkdownControl from './MarkdownControl';
|
||||
export MarkdownPreview from './MarkdownPreview';
|
||||
|
@ -8,7 +8,6 @@ export function joinPatternSegments(patterns) {
|
||||
return patterns.map(p => p.source).join('');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Combines an array of regular expressions into a single expression, wrapping
|
||||
* each in a non-capturing group and interposing alternation characters (|) so
|
||||
@ -18,7 +17,6 @@ export function combinePatterns(patterns) {
|
||||
return patterns.map(p => `(?:${p.source})`).join('|');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Modify substrings within a string if they match a (global) pattern. Can be
|
||||
* inverted to only modify non-matches.
|
||||
@ -63,34 +61,28 @@ export function replaceWhen(matchPattern, replaceFn, text, invertMatchPattern) {
|
||||
*/
|
||||
if (match.index === 0) {
|
||||
addSubstring(acc, 0, match[0], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there are no entries in the accumulator, convert the substring before
|
||||
* the match to a data object (without the `match` flag set to true) and
|
||||
* push to the accumulator, followed by a data object for the matching
|
||||
* substring.
|
||||
*/
|
||||
else if (!lastEntry) {
|
||||
} else if (!lastEntry) {
|
||||
/**
|
||||
* If there are no entries in the accumulator, convert the substring before
|
||||
* the match to a data object (without the `match` flag set to true) and
|
||||
* push to the accumulator, followed by a data object for the matching
|
||||
* substring.
|
||||
*/
|
||||
addSubstring(acc, 0, match.input.slice(0, match.index));
|
||||
addSubstring(acc, match.index, match[0], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the last entry in the accumulator immediately preceded the current
|
||||
* matched substring in the original string, just add the data object for
|
||||
* the matching substring to the accumulator.
|
||||
*/
|
||||
else if (match.index === lastEntry.index + lastEntry.text.length) {
|
||||
} else if (match.index === lastEntry.index + lastEntry.text.length) {
|
||||
/**
|
||||
* If the last entry in the accumulator immediately preceded the current
|
||||
* matched substring in the original string, just add the data object for
|
||||
* the matching substring to the accumulator.
|
||||
*/
|
||||
addSubstring(acc, match.index, match[0], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the substring before the match to a data object (without the
|
||||
* `match` flag set to true), followed by a data object for the matching
|
||||
* substring.
|
||||
*/
|
||||
else {
|
||||
} else {
|
||||
/**
|
||||
* Convert the substring before the match to a data object (without the
|
||||
* `match` flag set to true), followed by a data object for the matching
|
||||
* substring.
|
||||
*/
|
||||
const nextIndex = lastEntry.index + lastEntry.text.length;
|
||||
const nextText = match.input.slice(nextIndex, match.index);
|
||||
addSubstring(acc, nextIndex, nextText);
|
||||
|
@ -3,7 +3,10 @@ import markdownToRemark from 'remark-parse';
|
||||
import remarkAllowHtmlEntities from '../remarkAllowHtmlEntities';
|
||||
|
||||
const process = markdown => {
|
||||
const mdast = unified().use(markdownToRemark).use(remarkAllowHtmlEntities).parse(markdown);
|
||||
const mdast = unified()
|
||||
.use(markdownToRemark)
|
||||
.use(remarkAllowHtmlEntities)
|
||||
.parse(markdown);
|
||||
|
||||
/**
|
||||
* The MDAST will look like:
|
||||
|
@ -7,23 +7,23 @@ describe('remarkAssertParents', () => {
|
||||
it('should unnest invalidly nested blocks', () => {
|
||||
const input = u('root', [
|
||||
u('paragraph', [
|
||||
u('paragraph', [ u('text', 'Paragraph text.') ]),
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
u('paragraph', [u('text', 'Paragraph text.')]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Heading text.')]),
|
||||
u('code', 'someCode()'),
|
||||
u('blockquote', [ u('text', 'Quote text.') ]),
|
||||
u('list', [ u('listItem', [ u('text', 'A list item.') ]) ]),
|
||||
u('table', [ u('tableRow', [ u('tableCell', [ u('text', 'Text in a table cell.') ]) ]) ]),
|
||||
u('blockquote', [u('text', 'Quote text.')]),
|
||||
u('list', [u('listItem', [u('text', 'A list item.')])]),
|
||||
u('table', [u('tableRow', [u('tableCell', [u('text', 'Text in a table cell.')])])]),
|
||||
u('thematicBreak'),
|
||||
]),
|
||||
]);
|
||||
|
||||
const output = u('root', [
|
||||
u('paragraph', [ u('text', 'Paragraph text.') ]),
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
u('paragraph', [u('text', 'Paragraph text.')]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Heading text.')]),
|
||||
u('code', 'someCode()'),
|
||||
u('blockquote', [ u('text', 'Quote text.') ]),
|
||||
u('list', [ u('listItem', [ u('text', 'A list item.') ]) ]),
|
||||
u('table', [ u('tableRow', [ u('tableCell', [ u('text', 'Text in a table cell.') ]) ]) ]),
|
||||
u('blockquote', [u('text', 'Quote text.')]),
|
||||
u('list', [u('listItem', [u('text', 'A list item.')])]),
|
||||
u('table', [u('tableRow', [u('tableCell', [u('text', 'Text in a table cell.')])])]),
|
||||
u('thematicBreak'),
|
||||
]);
|
||||
|
||||
@ -35,20 +35,14 @@ describe('remarkAssertParents', () => {
|
||||
u('paragraph', [
|
||||
u('paragraph', [
|
||||
u('paragraph', [
|
||||
u('paragraph', [ u('text', 'Paragraph text.') ]),
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
u('paragraph', [u('text', 'Paragraph text.')]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Heading text.')]),
|
||||
u('code', 'someCode()'),
|
||||
u('blockquote', [
|
||||
u('paragraph', [
|
||||
u('strong', [
|
||||
u('heading', [
|
||||
u('text', 'Quote text.'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
u('paragraph', [u('strong', [u('heading', [u('text', 'Quote text.')])])]),
|
||||
]),
|
||||
u('list', [ u('listItem', [ u('text', 'A list item.') ]) ]),
|
||||
u('table', [ u('tableRow', [ u('tableCell', [ u('text', 'Text in a table cell.') ]) ]) ]),
|
||||
u('list', [u('listItem', [u('text', 'A list item.')])]),
|
||||
u('table', [u('tableRow', [u('tableCell', [u('text', 'Text in a table cell.')])])]),
|
||||
u('thematicBreak'),
|
||||
]),
|
||||
]),
|
||||
@ -56,16 +50,12 @@ describe('remarkAssertParents', () => {
|
||||
]);
|
||||
|
||||
const output = u('root', [
|
||||
u('paragraph', [ u('text', 'Paragraph text.') ]),
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
u('paragraph', [u('text', 'Paragraph text.')]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Heading text.')]),
|
||||
u('code', 'someCode()'),
|
||||
u('blockquote', [
|
||||
u('heading', [
|
||||
u('text', 'Quote text.'),
|
||||
]),
|
||||
]),
|
||||
u('list', [ u('listItem', [ u('text', 'A list item.') ]) ]),
|
||||
u('table', [ u('tableRow', [ u('tableCell', [ u('text', 'Text in a table cell.') ]) ]) ]),
|
||||
u('blockquote', [u('heading', [u('text', 'Quote text.')])]),
|
||||
u('list', [u('listItem', [u('text', 'A list item.')])]),
|
||||
u('table', [u('tableRow', [u('tableCell', [u('text', 'Text in a table cell.')])])]),
|
||||
u('thematicBreak'),
|
||||
]);
|
||||
|
||||
@ -74,42 +64,30 @@ describe('remarkAssertParents', () => {
|
||||
|
||||
it('should remove blocks that are emptied as a result of denesting', () => {
|
||||
const input = u('root', [
|
||||
u('paragraph', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]),
|
||||
u('paragraph', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]),
|
||||
]);
|
||||
|
||||
const output = u('root', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]);
|
||||
const output = u('root', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]);
|
||||
|
||||
expect(transform(input)).toEqual(output);
|
||||
});
|
||||
|
||||
it('should remove blocks that are emptied as a result of denesting', () => {
|
||||
const input = u('root', [
|
||||
u('paragraph', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]),
|
||||
u('paragraph', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]),
|
||||
]);
|
||||
|
||||
const output = u('root', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]);
|
||||
const output = u('root', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]);
|
||||
|
||||
expect(transform(input)).toEqual(output);
|
||||
});
|
||||
|
||||
it('should handle assymetrical splits', () => {
|
||||
const input = u('root', [
|
||||
u('paragraph', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]),
|
||||
u('paragraph', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]),
|
||||
]);
|
||||
|
||||
const output = u('root', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]);
|
||||
const output = u('root', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]);
|
||||
|
||||
expect(transform(input)).toEqual(output);
|
||||
});
|
||||
@ -117,18 +95,12 @@ describe('remarkAssertParents', () => {
|
||||
it('should nest invalidly nested blocks in the nearest valid ancestor', () => {
|
||||
const input = u('root', [
|
||||
u('paragraph', [
|
||||
u('blockquote', [
|
||||
u('strong', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]),
|
||||
]),
|
||||
u('blockquote', [u('strong', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])])]),
|
||||
]),
|
||||
]);
|
||||
|
||||
const output = u('root', [
|
||||
u('blockquote', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
]),
|
||||
u('blockquote', [u('heading', { depth: 1 }, [u('text', 'Heading text.')])]),
|
||||
]);
|
||||
|
||||
expect(transform(input)).toEqual(output);
|
||||
@ -140,7 +112,7 @@ describe('remarkAssertParents', () => {
|
||||
u('blockquote', [
|
||||
u('strong', [
|
||||
u('text', 'Deep validly nested text a.'),
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Heading text.')]),
|
||||
u('text', 'Deep validly nested text b.'),
|
||||
]),
|
||||
]),
|
||||
@ -150,17 +122,11 @@ describe('remarkAssertParents', () => {
|
||||
|
||||
const output = u('root', [
|
||||
u('blockquote', [
|
||||
u('strong', [
|
||||
u('text', 'Deep validly nested text a.'),
|
||||
]),
|
||||
u('heading', { depth: 1 }, [ u('text', 'Heading text.') ]),
|
||||
u('strong', [
|
||||
u('text', 'Deep validly nested text b.'),
|
||||
]),
|
||||
]),
|
||||
u('paragraph', [
|
||||
u('text', 'Validly nested text.'),
|
||||
u('strong', [u('text', 'Deep validly nested text a.')]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Heading text.')]),
|
||||
u('strong', [u('text', 'Deep validly nested text b.')]),
|
||||
]),
|
||||
u('paragraph', [u('text', 'Validly nested text.')]),
|
||||
]);
|
||||
|
||||
expect(transform(input)).toEqual(output);
|
||||
@ -174,7 +140,7 @@ describe('remarkAssertParents', () => {
|
||||
u('table', [
|
||||
u('tableRow', [
|
||||
u('tableCell', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Validly nested heading text.') ]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Validly nested heading text.')]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
@ -190,7 +156,7 @@ describe('remarkAssertParents', () => {
|
||||
u('table', [
|
||||
u('tableRow', [
|
||||
u('tableCell', [
|
||||
u('heading', { depth: 1 }, [ u('text', 'Validly nested heading text.') ]),
|
||||
u('heading', { depth: 1 }, [u('text', 'Validly nested heading text.')]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
|
@ -3,7 +3,7 @@ import u from 'unist-builder';
|
||||
import remarkEscapeMarkdownEntities from '../remarkEscapeMarkdownEntities';
|
||||
|
||||
const process = text => {
|
||||
const tree = u('root', [ u('text', text) ]);
|
||||
const tree = u('root', [u('text', text)]);
|
||||
const escapedMdast = unified()
|
||||
.use(remarkEscapeMarkdownEntities)
|
||||
.runSync(tree);
|
||||
@ -22,8 +22,9 @@ describe('remarkEscapeMarkdownEntities', () => {
|
||||
expect(process('[]')).toEqual('\\[]');
|
||||
expect(process('[]()')).toEqual('\\[]()');
|
||||
expect(process('[a](b)')).toEqual('\\[a](b)');
|
||||
expect(process('[Test sentence.](https://www.example.com)'))
|
||||
.toEqual('\\[Test sentence.](https://www.example.com)');
|
||||
expect(process('[Test sentence.](https://www.example.com)')).toEqual(
|
||||
'\\[Test sentence.](https://www.example.com)',
|
||||
);
|
||||
expect(process('')).toEqual('!\\[a](b)');
|
||||
});
|
||||
|
||||
|
@ -8,15 +8,13 @@ const input = markdown =>
|
||||
.use(markdownToRemark)
|
||||
.use(remarkPaddedLinks)
|
||||
.use(remarkToMarkdown)
|
||||
.processSync(markdown)
|
||||
.contents;
|
||||
.processSync(markdown).contents;
|
||||
|
||||
const output = markdown =>
|
||||
unified()
|
||||
.use(markdownToRemark)
|
||||
.use(remarkToMarkdown)
|
||||
.processSync(markdown)
|
||||
.contents;
|
||||
.processSync(markdown).contents;
|
||||
|
||||
describe('remarkPaddedLinks', () => {
|
||||
it('should move leading and trailing spaces outside of a link', () => {
|
||||
|
@ -56,7 +56,6 @@ import { getEditorComponents } from '../MarkdownControl';
|
||||
* for serialization to/from Slate's Raw AST and MDAST.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize a Markdown string to an MDAST.
|
||||
*/
|
||||
@ -82,17 +81,16 @@ export const markdownToRemark = markdown => {
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove named tokenizers from the parser, effectively deactivating them.
|
||||
*/
|
||||
function markdownToRemarkRemoveTokenizers({ inlineTokenizers }) {
|
||||
inlineTokenizers && inlineTokenizers.forEach(tokenizer => {
|
||||
delete this.Parser.prototype.inlineTokenizers[tokenizer];
|
||||
});
|
||||
inlineTokenizers &&
|
||||
inlineTokenizers.forEach(tokenizer => {
|
||||
delete this.Parser.prototype.inlineTokenizers[tokenizer];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize an MDAST to a Markdown string.
|
||||
*/
|
||||
@ -146,7 +144,6 @@ export const remarkToMarkdown = obj => {
|
||||
return trimEnd(markdown);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert Markdown to HTML.
|
||||
*/
|
||||
@ -163,8 +160,7 @@ export const markdownToHtml = (markdown, getAsset) => {
|
||||
.stringify(hast);
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Deserialize an HTML string to Slate's Raw AST. Currently used for HTML
|
||||
@ -192,7 +188,6 @@ export const htmlToSlate = html => {
|
||||
return slateRaw;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert Markdown to Slate's Raw AST.
|
||||
*/
|
||||
@ -207,7 +202,6 @@ export const markdownToSlate = markdown => {
|
||||
return slateRaw;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert a Slate Raw AST to Markdown.
|
||||
*
|
||||
|
@ -13,7 +13,6 @@ const patternSegments = {
|
||||
htmlOpeningTagEnd: /(?: *\w+=(?:(?:"[^"]*")|(?:'[^']*')))* *>/,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Patterns matching substrings that should not be escaped. Array values must be
|
||||
* joined before use.
|
||||
@ -37,7 +36,6 @@ const nonEscapePatterns = {
|
||||
patternSegments.htmlOpeningTagEnd,
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* Preformatted HTML Blocks
|
||||
*
|
||||
@ -72,7 +70,6 @@ const nonEscapePatterns = {
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escape patterns
|
||||
*
|
||||
@ -137,7 +134,6 @@ const escapePatterns = [
|
||||
/(\[)[^\]]*]/g,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Generate new non-escape expression. The non-escape expression matches
|
||||
* substrings whose contents should not be processed for escaping.
|
||||
@ -147,14 +143,12 @@ const joinedNonEscapePatterns = map(nonEscapePatterns, pattern => {
|
||||
});
|
||||
const nonEscapePattern = combinePatterns(joinedNonEscapePatterns);
|
||||
|
||||
|
||||
/**
|
||||
* Create chain of successive escape functions for various markdown entities.
|
||||
*/
|
||||
const escapeFunctions = escapePatterns.map(pattern => partial(escapeDelimiters, pattern));
|
||||
const escapeAll = flow(escapeFunctions);
|
||||
|
||||
|
||||
/**
|
||||
* Executes both the `escapeCommonChars` and `escapeLeadingChars` functions.
|
||||
*/
|
||||
@ -163,7 +157,6 @@ function escapeAllChars(text) {
|
||||
return escapeLeadingChars(partiallyEscapedMarkdown);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* escapeLeadingChars
|
||||
*
|
||||
@ -178,7 +171,6 @@ function escapeLeadingChars(text) {
|
||||
return text.replace(/^\s*([-#*>=|]| {4,}|`{3,})/, '$`\\$1');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* escapeCommonChars
|
||||
*
|
||||
@ -199,7 +191,6 @@ function escapeCommonChars(text) {
|
||||
return replaceWhen(nonEscapeExpression, escapeAll, text, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* escapeDelimiters
|
||||
*
|
||||
@ -216,7 +207,6 @@ function escapeDelimiters(pattern, text) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* escape
|
||||
*
|
||||
@ -231,7 +221,6 @@ function escape(delim) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A Remark plugin for escaping markdown entities.
|
||||
*
|
||||
@ -261,7 +250,6 @@ export default function remarkEscapeMarkdownEntities() {
|
||||
* text in html nodes to keep Remark from escaping html entities.
|
||||
*/
|
||||
if (['text', 'html'].includes(node.type)) {
|
||||
|
||||
/**
|
||||
* Escape all characters if this is the first child node, otherwise only
|
||||
* common characters.
|
||||
@ -273,7 +261,7 @@ export default function remarkEscapeMarkdownEntities() {
|
||||
/**
|
||||
* Always return nodes with recursively mapped children.
|
||||
*/
|
||||
return {...node, children };
|
||||
return { ...node, children };
|
||||
};
|
||||
|
||||
return transform;
|
||||
|
@ -11,9 +11,9 @@ export default function remarkImagesToText() {
|
||||
function transform(node) {
|
||||
const children = node.children.map(child => {
|
||||
if (
|
||||
child.type === 'paragraph'
|
||||
&& child.children.length === 1
|
||||
&& child.children[0].type === 'image'
|
||||
child.type === 'paragraph' &&
|
||||
child.children.length === 1 &&
|
||||
child.children[0].type === 'image'
|
||||
) {
|
||||
const { alt = '', url = '', title = '' } = child.children[0];
|
||||
const value = ``;
|
||||
|
@ -1,12 +1,4 @@
|
||||
import {
|
||||
find,
|
||||
findLast,
|
||||
startsWith,
|
||||
endsWith,
|
||||
trimStart,
|
||||
trimEnd,
|
||||
flatMap
|
||||
} from 'lodash';
|
||||
import { find, findLast, startsWith, endsWith, trimStart, trimEnd, flatMap } from 'lodash';
|
||||
import u from 'unist-builder';
|
||||
import toString from 'mdast-util-to-string';
|
||||
|
||||
@ -20,9 +12,7 @@ import toString from 'mdast-util-to-string';
|
||||
* children one at a time.
|
||||
*/
|
||||
export default function remarkPaddedLinks() {
|
||||
|
||||
function transform(node) {
|
||||
|
||||
/**
|
||||
* Because we're operating on link nodes and their children at once, we can
|
||||
* exit if the current node has no children.
|
||||
@ -40,7 +30,9 @@ export default function remarkPaddedLinks() {
|
||||
* this seems unlikely to produce a noticeable perf gain.
|
||||
*/
|
||||
const hasLinkChild = node.children.some(child => child.type === 'link');
|
||||
const processedChildren = hasLinkChild ? flatMap(node.children, transformChildren) : node.children;
|
||||
const processedChildren = hasLinkChild
|
||||
? flatMap(node.children, transformChildren)
|
||||
: node.children;
|
||||
|
||||
/**
|
||||
* Run all children through the transform recursively.
|
||||
@ -83,7 +75,7 @@ export default function remarkPaddedLinks() {
|
||||
const nodes = [
|
||||
leadingWhitespaceNode && u('text', ' '),
|
||||
node,
|
||||
trailingWhitespaceNode && u('text', ' ')
|
||||
trailingWhitespaceNode && u('text', ' '),
|
||||
];
|
||||
|
||||
return nodes.filter(val => val);
|
||||
@ -95,14 +87,17 @@ export default function remarkPaddedLinks() {
|
||||
*/
|
||||
function getEdgeTextChild(node, end) {
|
||||
/**
|
||||
* This was changed from a ternary to a long form if due to issues with istanbul's instrumentation and babel's code
|
||||
* generation.
|
||||
* This was changed from a ternary to a long form if due to issues with istanbul's instrumentation and babel's code
|
||||
* generation.
|
||||
* TODO: watch https://github.com/istanbuljs/babel-plugin-istanbul/issues/95
|
||||
* when it is resolved then revert to ```const findFn = end ? findLast : find;```
|
||||
*/
|
||||
let findFn;
|
||||
if (end) { findFn = findLast }
|
||||
else { findFn = find }
|
||||
if (end) {
|
||||
findFn = findLast;
|
||||
} else {
|
||||
findFn = find;
|
||||
}
|
||||
|
||||
let edgeChildWithValue;
|
||||
setEdgeChildWithValue(node);
|
||||
|
@ -44,7 +44,7 @@ export default function remarkToRehypeShortcodes({ plugins, getAsset }) {
|
||||
* Return a new 'html' type node containing the shortcode preview markup.
|
||||
*/
|
||||
const textNode = u('html', valueHtml);
|
||||
const children = [ textNode ];
|
||||
const children = [textNode];
|
||||
return { ...node, children };
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ export default function remarkToSlate() {
|
||||
}
|
||||
|
||||
function transform(node) {
|
||||
|
||||
/**
|
||||
* Call `transform` recursively on child nodes.
|
||||
*
|
||||
@ -17,9 +16,10 @@ function transform(node) {
|
||||
* translate from MDAST to Slate, such as definitions for link/image
|
||||
* references or footnotes.
|
||||
*/
|
||||
const children = !['strong', 'emphasis', 'delete'].includes(node.type)
|
||||
&& !isEmpty(node.children)
|
||||
&& flatMap(node.children, transform).filter(val => val);
|
||||
const children =
|
||||
!['strong', 'emphasis', 'delete'].includes(node.type) &&
|
||||
!isEmpty(node.children) &&
|
||||
flatMap(node.children, transform).filter(val => val);
|
||||
|
||||
/**
|
||||
* Run individual nodes through the conversion factory.
|
||||
@ -45,7 +45,6 @@ const typeMap = {
|
||||
shortcode: 'shortcode',
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Map of MDAST node types to Slate mark types.
|
||||
*/
|
||||
@ -56,7 +55,6 @@ const markMap = {
|
||||
inlineCode: 'code',
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add nodes to a parent node only if `nodes` is truthy.
|
||||
*/
|
||||
@ -64,7 +62,6 @@ function addNodes(parent, nodes) {
|
||||
return nodes ? { ...parent, nodes } : parent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Slate Inline node.
|
||||
*/
|
||||
@ -78,7 +75,6 @@ function createBlock(type, nodes, props = {}) {
|
||||
return addNodes(node, nodes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Slate Block node.
|
||||
*/
|
||||
@ -87,7 +83,6 @@ function createInline(type, props = {}, nodes) {
|
||||
return addNodes(node, nodes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Slate Raw text node.
|
||||
*/
|
||||
@ -122,7 +117,7 @@ function processMarkNode(node, parentMarks = []) {
|
||||
* first add the inline code mark to the marks array.
|
||||
*/
|
||||
case 'inlineCode': {
|
||||
const childMarks = [ ...marks, { type: markMap['inlineCode'] } ];
|
||||
const childMarks = [...marks, { type: markMap['inlineCode'] }];
|
||||
return { text: childNode.value, marks: childMarks };
|
||||
}
|
||||
|
||||
@ -156,11 +151,9 @@ function convertMarkNode(node) {
|
||||
const lastConvertedNode = last(acc);
|
||||
if (node.text && lastConvertedNode && lastConvertedNode.leaves) {
|
||||
lastConvertedNode.leaves.push(node);
|
||||
}
|
||||
else if (node.text) {
|
||||
} else if (node.text) {
|
||||
acc.push(createText([node]));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
acc.push(transform(node));
|
||||
}
|
||||
|
||||
@ -176,7 +169,6 @@ function convertMarkNode(node) {
|
||||
* transformer.
|
||||
*/
|
||||
function convertNode(node, nodes) {
|
||||
|
||||
/**
|
||||
* Unified/Remark processors use mutable operations, so we don't want to
|
||||
* change a node's type directly for conversion purposes, as that tends to
|
||||
@ -185,7 +177,6 @@ function convertNode(node, nodes) {
|
||||
const type = get(node, ['data', 'shortcode']) ? 'shortcode' : node.type;
|
||||
|
||||
switch (type) {
|
||||
|
||||
/**
|
||||
* General
|
||||
*
|
||||
@ -201,7 +192,6 @@ function convertNode(node, nodes) {
|
||||
return createBlock(typeMap[type], nodes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shortcodes
|
||||
*
|
||||
@ -211,7 +201,7 @@ function convertNode(node, nodes) {
|
||||
*/
|
||||
case 'shortcode': {
|
||||
const { data } = node;
|
||||
const nodes = [ createText('') ];
|
||||
const nodes = [createText('')];
|
||||
return createBlock(typeMap[type], nodes, { data, isVoid: true });
|
||||
}
|
||||
|
||||
@ -240,7 +230,7 @@ function convertNode(node, nodes) {
|
||||
text: node.value,
|
||||
marks: [{ type: 'code' }],
|
||||
};
|
||||
return createText([ leaf ]);
|
||||
return createText([leaf]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -308,7 +298,7 @@ function convertNode(node, nodes) {
|
||||
*/
|
||||
case 'break': {
|
||||
const textNode = createText('\n');
|
||||
return createInline('break', {}, [ textNode ]);
|
||||
return createInline('break', {}, [textNode]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -345,7 +335,6 @@ function convertNode(node, nodes) {
|
||||
return createInline(typeMap[type], { isVoid: true, data: newData });
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tables
|
||||
*
|
||||
|
@ -32,7 +32,6 @@ export default function remarkSquashReferences() {
|
||||
}
|
||||
|
||||
function transform(getDefinition, node) {
|
||||
|
||||
/**
|
||||
* Bind the `getDefinition` function to `transform` and recursively map all
|
||||
* nodes.
|
||||
@ -55,15 +54,15 @@ export default function remarkSquashReferences() {
|
||||
|
||||
const pre = u('text', node.type === 'imageReference' ? '![' : '[');
|
||||
const post = u('text', ']');
|
||||
const nodes = children || [ u('text', node.alt) ];
|
||||
return [ pre, ...nodes, post];
|
||||
const nodes = children || [u('text', node.alt)];
|
||||
return [pre, ...nodes, post];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove definition nodes and filter the resulting null values from the
|
||||
* filtered children array.
|
||||
*/
|
||||
if(node.type === 'definition') {
|
||||
if (node.type === 'definition') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ export default function remarkStripTrailingBreaks() {
|
||||
if (node.children) {
|
||||
node.children = node.children
|
||||
.map((child, idx, children) => {
|
||||
|
||||
/**
|
||||
* Only touch break nodes. Convert all subsequent nodes to their text
|
||||
* value and exclude the break node if no non-whitespace characters
|
||||
|
@ -5,7 +5,6 @@ import u from 'unist-builder';
|
||||
* are used for text nodes that we don't want Remark or Rehype to parse.
|
||||
*/
|
||||
export default function remarkWrapHtml() {
|
||||
|
||||
function transform(tree) {
|
||||
tree.children = tree.children.map(node => {
|
||||
if (node.type === 'html') {
|
||||
|
@ -5,29 +5,28 @@ import u from 'unist-builder';
|
||||
* Map of Slate node types to MDAST/Remark node types.
|
||||
*/
|
||||
const typeMap = {
|
||||
'root': 'root',
|
||||
'paragraph': 'paragraph',
|
||||
root: 'root',
|
||||
paragraph: 'paragraph',
|
||||
'heading-one': 'heading',
|
||||
'heading-two': 'heading',
|
||||
'heading-three': 'heading',
|
||||
'heading-four': 'heading',
|
||||
'heading-five': 'heading',
|
||||
'heading-six': 'heading',
|
||||
'quote': 'blockquote',
|
||||
'code': 'code',
|
||||
quote: 'blockquote',
|
||||
code: 'code',
|
||||
'numbered-list': 'list',
|
||||
'bulleted-list': 'list',
|
||||
'list-item': 'listItem',
|
||||
'table': 'table',
|
||||
table: 'table',
|
||||
'table-row': 'tableRow',
|
||||
'table-cell': 'tableCell',
|
||||
'break': 'break',
|
||||
break: 'break',
|
||||
'thematic-break': 'thematicBreak',
|
||||
'link': 'link',
|
||||
'image': 'image',
|
||||
link: 'link',
|
||||
image: 'image',
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Map of Slate mark types to MDAST/Remark node types.
|
||||
*/
|
||||
@ -55,7 +54,6 @@ export default function slateToRemark(raw, opts) {
|
||||
return transform(raw);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The transform function mimics the approach of a Remark plugin for
|
||||
* conformity with the other serialization functions. This function converts
|
||||
@ -83,7 +81,6 @@ function transform(node) {
|
||||
: convertNode(node, children, shortcodePlugins);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Includes inline nodes as leaves in adjacent text nodes where appropriate, so
|
||||
* that mark node combining logic can apply to both text and inline nodes. This
|
||||
@ -140,7 +137,6 @@ function combineTextAndInline(nodes) {
|
||||
}, []);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Slate treats inline code decoration as a standard mark, but MDAST does
|
||||
* not allow inline code nodes to contain children, only a single text
|
||||
@ -232,7 +228,6 @@ function convertTextNode(node) {
|
||||
return u('html', node.text);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process Slate node leaves in preparation for MDAST transformation.
|
||||
*/
|
||||
@ -256,7 +251,6 @@ function processLeaves(leaf) {
|
||||
return { node: leaf.node, marks: markTypes };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Slate's AST doesn't group adjacent text nodes with the same marks - a
|
||||
* change in marks from letter to letter, even if some are in common, results
|
||||
@ -311,47 +305,51 @@ function condenseNodesReducer(acc, node, idx, nodes) {
|
||||
* children.
|
||||
*/
|
||||
const children = nodes.slice(idx, newNextIndex);
|
||||
const denestedChildren = children.map(child => ({ ...child, marks: without(child.marks, parentType) }));
|
||||
const mdastChildren = denestedChildren.reduce(condenseNodesReducer, { nodes: [], parentType }).nodes;
|
||||
const denestedChildren = children.map(child => ({
|
||||
...child,
|
||||
marks: without(child.marks, parentType),
|
||||
}));
|
||||
const mdastChildren = denestedChildren.reduce(condenseNodesReducer, { nodes: [], parentType })
|
||||
.nodes;
|
||||
const mdastNode = u(parentType, mdastChildren);
|
||||
|
||||
return { ...acc, nodes: [ ...acc.nodes, mdastNode ], nextIndex: newNextIndex };
|
||||
return { ...acc, nodes: [...acc.nodes, mdastNode], nextIndex: newNextIndex };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the base text node, and pass in the array of mark types as data
|
||||
* (helpful when optimizing/condensing the final structure).
|
||||
*/
|
||||
const baseNode = typeof node.text === 'string'
|
||||
? u(node.textNodeType, { marks: node.marks }, node.text)
|
||||
: transform(node.node);
|
||||
const baseNode =
|
||||
typeof node.text === 'string'
|
||||
? u(node.textNodeType, { marks: node.marks }, node.text)
|
||||
: transform(node.node);
|
||||
|
||||
/**
|
||||
* Recursively wrap the base text node in the individual mark nodes, if
|
||||
* any exist.
|
||||
*/
|
||||
return { ...acc, nodes: [ ...acc.nodes, baseNode ] };
|
||||
return { ...acc, nodes: [...acc.nodes, baseNode] };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the number of consecutive Slate nodes containing a given mark beginning
|
||||
* from the first received node.
|
||||
*/
|
||||
function getMarkLength(markType, nodes) {
|
||||
let length = 0;
|
||||
while(nodes[length] && nodes[length].marks.includes(markType)) { ++length; }
|
||||
while (nodes[length] && nodes[length].marks.includes(markType)) {
|
||||
++length;
|
||||
}
|
||||
return { markType, length };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a single Slate Raw node to an MDAST node. Uses the unist-builder `u`
|
||||
* function to create MDAST nodes and parses shortcodes.
|
||||
*/
|
||||
function convertNode(node, children, shortcodePlugins) {
|
||||
switch (node.type) {
|
||||
|
||||
/**
|
||||
* General
|
||||
*
|
||||
@ -390,7 +388,7 @@ function convertNode(node, children, shortcodePlugins) {
|
||||
const plugin = shortcodePlugins.get(data.shortcode);
|
||||
const text = plugin.toBlock(data.shortcodeData);
|
||||
const textNode = u('html', text);
|
||||
return u('paragraph', { data }, [ textNode ]);
|
||||
return u('paragraph', { data }, [textNode]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -480,7 +478,6 @@ function convertNode(node, children, shortcodePlugins) {
|
||||
return u(typeMap[node.type], { url, title, alt, data });
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* No default case is supplied because an unhandled case should never
|
||||
* occur. In the event that it does, let the error throw (for now).
|
||||
|
@ -9,4 +9,4 @@ export const EditorControlBar = styled.div`
|
||||
position: sticky;
|
||||
top: 0;
|
||||
margin-bottom: ${editorStyleVars.stickyDistanceBottom};
|
||||
`
|
||||
`;
|
||||
|
Reference in New Issue
Block a user