Make editor plugins work in preview
This commit is contained in:
parent
378be79a76
commit
aca88ef441
@ -1,6 +1,7 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import MarkupIt, { Syntax, BLOCKS, STYLES, ENTITIES } from 'markup-it';
|
import MarkupIt, { Syntax, BLOCKS, STYLES, ENTITIES } from 'markup-it';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
|
import registry from '../../lib/registry';
|
||||||
|
|
||||||
const defaultSchema = {
|
const defaultSchema = {
|
||||||
[BLOCKS.DOCUMENT]: 'article',
|
[BLOCKS.DOCUMENT]: 'article',
|
||||||
@ -44,7 +45,25 @@ function sanitizeProps(props) {
|
|||||||
return omit(props, notAllowedAttributes);
|
return omit(props, notAllowedAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderToken(schema, token, index = 0, key = '0') {
|
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) {
|
||||||
|
if (nextProps.syntax != this.props.syntax) {
|
||||||
|
this.parser = new MarkupIt(nextProps.syntax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderToken(schema, token, index = 0, key = '0') {
|
||||||
const type = token.get('type');
|
const type = token.get('type');
|
||||||
const data = token.get('data');
|
const data = token.get('data');
|
||||||
const text = token.get('text');
|
const text = token.get('text');
|
||||||
@ -56,7 +75,7 @@ function renderToken(schema, token, index = 0, key = '0') {
|
|||||||
if (typeof nodeType !== 'undefined') {
|
if (typeof nodeType !== 'undefined') {
|
||||||
let children = null;
|
let children = null;
|
||||||
if (tokens.size) {
|
if (tokens.size) {
|
||||||
children = tokens.map((token, idx) => renderToken(schema, token, idx, key));
|
children = tokens.map((token, idx) => this.renderToken(schema, token, idx, key));
|
||||||
} else if (type === 'text') {
|
} else if (type === 'text') {
|
||||||
children = text;
|
children = text;
|
||||||
}
|
}
|
||||||
@ -72,27 +91,23 @@ function renderToken(schema, token, index = 0, key = '0') {
|
|||||||
return children;
|
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 :
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: output}} />;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class MarkupItReactRenderer extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
const { syntax } = props;
|
|
||||||
this.parser = new MarkupIt(syntax);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if (nextProps.syntax != this.props.syntax) {
|
|
||||||
this.parser = new MarkupIt(nextProps.syntax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { value, schema } = this.props;
|
const { value, schema } = this.props;
|
||||||
const content = this.parser.toContent(value);
|
const content = this.parser.toContent(value);
|
||||||
return renderToken({ ...defaultSchema, ...schema }, content.get('token'));
|
return this.renderToken({ ...defaultSchema, ...schema }, content.get('token'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
left: -18px;
|
left: -18px;
|
||||||
display: none;
|
display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visible {
|
.visible {
|
||||||
|
@ -65,18 +65,17 @@ function getCleanPaste(e) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildtInPlugins = fromJS([{
|
const buildtInPlugins = [{
|
||||||
label: 'Image',
|
label: 'Image',
|
||||||
id: 'image',
|
id: 'image',
|
||||||
fromBlock: (data) => {
|
fromBlock: match => match && {
|
||||||
const m = data.match(/^!\[([^\]]+)\]\(([^\)]+)\)$/);
|
image: match[2],
|
||||||
return m && {
|
alt: match[1],
|
||||||
image: m[2],
|
|
||||||
alt: m[1],
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
toBlock: data => ``,
|
toBlock: data => ``,
|
||||||
toPreview: data => `<img src="${ data.image }" alt="${ data.alt }" />`,
|
toPreview: (data) => {
|
||||||
|
return <img src={data.image} alt={data.alt} />;
|
||||||
|
},
|
||||||
pattern: /^!\[([^\]]+)\]\(([^\)]+)\)$/,
|
pattern: /^!\[([^\]]+)\]\(([^\)]+)\)$/,
|
||||||
fields: [{
|
fields: [{
|
||||||
label: 'Image',
|
label: 'Image',
|
||||||
@ -86,14 +85,15 @@ const buildtInPlugins = fromJS([{
|
|||||||
label: 'Alt Text',
|
label: 'Alt Text',
|
||||||
name: 'alt',
|
name: 'alt',
|
||||||
}],
|
}],
|
||||||
}]);
|
}];
|
||||||
|
buildtInPlugins.forEach(plugin => registry.registerEditorComponent(plugin));
|
||||||
|
|
||||||
export default class RawEditor extends React.Component {
|
export default class RawEditor extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
const plugins = registry.getEditorComponents();
|
const plugins = registry.getEditorComponents();
|
||||||
this.state = {
|
this.state = {
|
||||||
plugins: buildtInPlugins.concat(plugins),
|
plugins: plugins,
|
||||||
};
|
};
|
||||||
this.shortcuts = {
|
this.shortcuts = {
|
||||||
meta: {
|
meta: {
|
||||||
@ -161,7 +161,7 @@ export default class RawEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
replaceSelection(chars) {
|
replaceSelection(chars) {
|
||||||
const { value } = this.props;
|
const value = this.props.value || '';
|
||||||
const selection = this.getSelection();
|
const selection = this.getSelection();
|
||||||
const newSelection = Object.assign({}, selection);
|
const newSelection = Object.assign({}, selection);
|
||||||
const beforeSelection = value.substr(0, selection.start);
|
const beforeSelection = value.substr(0, selection.start);
|
||||||
@ -172,7 +172,7 @@ export default class RawEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toggleHeader(header) {
|
toggleHeader(header) {
|
||||||
const { value } = this.props;
|
const value = this.props.value || '';
|
||||||
const selection = this.getSelection();
|
const selection = this.getSelection();
|
||||||
const newSelection = Object.assign({}, selection);
|
const newSelection = Object.assign({}, selection);
|
||||||
const lastNewline = value.lastIndexOf('\n', selection.start);
|
const lastNewline = value.lastIndexOf('\n', selection.start);
|
||||||
@ -234,7 +234,7 @@ export default class RawEditor extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleSelection = () => {
|
handleSelection = () => {
|
||||||
const { value } = this.props;
|
const value = this.props.value || '';
|
||||||
const selection = this.getSelection();
|
const selection = this.getSelection();
|
||||||
if (selection.start !== selection.end && !HAS_LINE_BREAK.test(selection.selected)) {
|
if (selection.start !== selection.end && !HAS_LINE_BREAK.test(selection.selected)) {
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user