diff --git a/src/components/MarkupItReactRenderer/index.js b/src/components/MarkupItReactRenderer/index.js
index f5ede88b..06ca60ee 100644
--- a/src/components/MarkupItReactRenderer/index.js
+++ b/src/components/MarkupItReactRenderer/index.js
@@ -1,6 +1,7 @@
import React, { PropTypes } from 'react';
import MarkupIt, { Syntax, BLOCKS, STYLES, ENTITIES } from 'markup-it';
import { omit } from 'lodash';
+import registry from '../../lib/registry';
const defaultSchema = {
[BLOCKS.DOCUMENT]: 'article',
@@ -44,43 +45,16 @@ function sanitizeProps(props) {
return omit(props, notAllowedAttributes);
}
-function renderToken(schema, token, index = 0, key = '0') {
- const type = token.get('type');
- const data = token.get('data');
- const text = token.get('text');
- const tokens = token.get('tokens');
- const nodeType = schema[type];
- key = `${ key }.${ index }`;
-
- // Only render if type is registered as renderer
- if (typeof nodeType !== 'undefined') {
- let children = null;
- if (tokens.size) {
- children = tokens.map((token, idx) => renderToken(schema, token, idx, key));
- } else if (type === 'text') {
- children = text;
- }
- if (nodeType !== null) {
- let props = { key, token };
- if (typeof nodeType !== 'function') {
- props = { key, ...sanitizeProps(data.toJS()) };
- }
- // If this is a react element
- return React.createElement(nodeType, props, children);
- } else {
- // If this is a text node
- return children;
- }
- }
- return null;
-}
-
export default class MarkupItReactRenderer extends React.Component {
constructor(props) {
super(props);
const { syntax } = props;
this.parser = new MarkupIt(syntax);
+ this.plugins = {};
+ registry.getEditorComponents().forEach((component) => {
+ this.plugins[component.get('id')] = component;
+ });
}
componentWillReceiveProps(nextProps) {
@@ -89,10 +63,51 @@ export default class MarkupItReactRenderer extends React.Component {
}
}
+ renderToken(schema, token, index = 0, key = '0') {
+ const type = token.get('type');
+ const data = token.get('data');
+ const text = token.get('text');
+ const tokens = token.get('tokens');
+ const nodeType = schema[type];
+ key = `${ key }.${ index }`;
+
+ // Only render if type is registered as renderer
+ if (typeof nodeType !== 'undefined') {
+ let children = null;
+ if (tokens.size) {
+ children = tokens.map((token, idx) => this.renderToken(schema, token, idx, key));
+ } else if (type === 'text') {
+ children = text;
+ }
+ if (nodeType !== null) {
+ let props = { key, token };
+ if (typeof nodeType !== 'function') {
+ props = { key, ...sanitizeProps(data.toJS()) };
+ }
+ // If this is a react element
+ return React.createElement(nodeType, props, children);
+ } else {
+ // If this is a text node
+ return children;
+ }
+ }
+
+ const plugin = this.plugins[token.get('type')];
+ if (plugin) {
+ const output = plugin.toPreview(token.get('data').toJS());
+ return output instanceof React.Component ?
+ output :
+ ;
+ }
+
+ return null;
+ }
+
+
render() {
const { value, schema } = this.props;
const content = this.parser.toContent(value);
- return renderToken({ ...defaultSchema, ...schema }, content.get('token'));
+ return this.renderToken({ ...defaultSchema, ...schema }, content.get('token'));
}
}
diff --git a/src/components/Widgets/MarkdownControlElements/RawEditor/BlockMenu.css b/src/components/Widgets/MarkdownControlElements/RawEditor/BlockMenu.css
index 5183a9e7..6f602ca7 100644
--- a/src/components/Widgets/MarkdownControlElements/RawEditor/BlockMenu.css
+++ b/src/components/Widgets/MarkdownControlElements/RawEditor/BlockMenu.css
@@ -3,6 +3,7 @@
left: -18px;
display: none;
width: 100%;
+ z-index: 1000;
}
.visible {
diff --git a/src/components/Widgets/MarkdownControlElements/RawEditor/index.js b/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
index 5f68e04a..d8ad8eb3 100644
--- a/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
+++ b/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
@@ -65,18 +65,17 @@ function getCleanPaste(e) {
});
}
-const buildtInPlugins = fromJS([{
+const buildtInPlugins = [{
label: 'Image',
id: 'image',
- fromBlock: (data) => {
- const m = data.match(/^!\[([^\]]+)\]\(([^\)]+)\)$/);
- return m && {
- image: m[2],
- alt: m[1],
- };
+ fromBlock: match => match && {
+ image: match[2],
+ alt: match[1],
},
toBlock: data => ``,
- toPreview: data => `
`,
+ toPreview: (data) => {
+ return
;
+ },
pattern: /^!\[([^\]]+)\]\(([^\)]+)\)$/,
fields: [{
label: 'Image',
@@ -86,14 +85,15 @@ const buildtInPlugins = fromJS([{
label: 'Alt Text',
name: 'alt',
}],
-}]);
+}];
+buildtInPlugins.forEach(plugin => registry.registerEditorComponent(plugin));
export default class RawEditor extends React.Component {
constructor(props) {
super(props);
const plugins = registry.getEditorComponents();
this.state = {
- plugins: buildtInPlugins.concat(plugins),
+ plugins: plugins,
};
this.shortcuts = {
meta: {
@@ -161,7 +161,7 @@ export default class RawEditor extends React.Component {
}
replaceSelection(chars) {
- const { value } = this.props;
+ const value = this.props.value || '';
const selection = this.getSelection();
const newSelection = Object.assign({}, selection);
const beforeSelection = value.substr(0, selection.start);
@@ -172,7 +172,7 @@ export default class RawEditor extends React.Component {
}
toggleHeader(header) {
- const { value } = this.props;
+ const value = this.props.value || '';
const selection = this.getSelection();
const newSelection = Object.assign({}, selection);
const lastNewline = value.lastIndexOf('\n', selection.start);
@@ -234,7 +234,7 @@ export default class RawEditor extends React.Component {
};
handleSelection = () => {
- const { value } = this.props;
+ const value = this.props.value || '';
const selection = this.getSelection();
if (selection.start !== selection.end && !HAS_LINE_BREAK.test(selection.selected)) {
try {