implement initial unified/remark preview update
This commit is contained in:
parent
5048c7ca1d
commit
8bb18452e8
@ -157,6 +157,7 @@
|
||||
"redux-notifications": "^2.1.1",
|
||||
"redux-optimist": "^0.0.2",
|
||||
"redux-thunk": "^1.0.3",
|
||||
"rehype-parse": "^3.1.0",
|
||||
"rehype-stringify": "^3.0.0",
|
||||
"remark-html": "^6.0.0",
|
||||
"remark-parse": "^3.0.1",
|
||||
@ -168,7 +169,6 @@
|
||||
"slug": "^0.9.1",
|
||||
"textarea-caret-position": "^0.1.1",
|
||||
"unified": "^6.1.4",
|
||||
"unist-util-visit": "^1.1.1",
|
||||
"uuid": "^2.0.3",
|
||||
"whatwg-fetch": "^1.0.0"
|
||||
},
|
||||
|
@ -1,30 +1,92 @@
|
||||
import React, { PropTypes } from "react";
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import { Map } from 'immutable';
|
||||
import unified from 'unified';
|
||||
import markdown from 'remark-parse';
|
||||
import rehype from 'remark-rehype';
|
||||
import parseHtml from 'rehype-parse';
|
||||
import html from 'rehype-stringify';
|
||||
import registry from "../../lib/registry";
|
||||
|
||||
export default class MarkupItReactRenderer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.plugins = {};
|
||||
// TODO add back support for this.
|
||||
registry.getEditorComponents().forEach((component) => {
|
||||
this.plugins[component.get("id")] = component;
|
||||
});
|
||||
const getPlugins = () => registry.getEditorComponents();
|
||||
|
||||
const renderEditorPlugins = ({ getAsset }) => {
|
||||
return tree => {
|
||||
const result = renderEditorPluginsProcessor(tree, getAsset);
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
const renderEditorPluginsProcessor = (node, getAsset) => {
|
||||
|
||||
if (node.children) {
|
||||
|
||||
node.children = node.children.map(n => renderEditorPluginsProcessor(n, getAsset));
|
||||
|
||||
// Handle externally defined plugins (they'll be wrapped in paragraphs)
|
||||
if (node.tagName === 'p' && node.children.length === 1 && node.children[0].type === 'text') {
|
||||
const value = node.children[0].value;
|
||||
const plugin = getPlugins().find(plugin => plugin.get('pattern').test(value));
|
||||
if (plugin) {
|
||||
const data = plugin.get('fromBlock')(value.match(plugin.get('pattern')));
|
||||
const preview = plugin.get('toPreview')(data);
|
||||
const output = typeof preview === 'string' ?
|
||||
<div dangerouslySetInnerHTML={{ __html: preview }}/> :
|
||||
preview;
|
||||
|
||||
const result = unified()
|
||||
.use(parseHtml, { fragment: true })
|
||||
.parse(renderToStaticMarkup(output));
|
||||
|
||||
return result.children[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
// Handle the internally defined image plugin. At this point the token has
|
||||
// already been parsed as an image by Remark, so we have to catch it by
|
||||
// checking for the 'image' type.
|
||||
if (node.tagName === 'img') {
|
||||
const { src, alt } = node.properties;
|
||||
|
||||
// Until we improve the editor components API for built in components,
|
||||
// we'll mock the result of String.prototype.match to pass in to the image
|
||||
// plugin's fromBlock method.
|
||||
const plugin = getPlugins().get('image');
|
||||
if (plugin) {
|
||||
const matches = [ , alt, src ];
|
||||
const data = plugin.get('fromBlock')(matches);
|
||||
const extendedData = { ...data, image: getAsset(data.image).toString() };
|
||||
const preview = plugin.get('toPreview')(extendedData);
|
||||
const output = typeof preview === 'string' ?
|
||||
<div dangerouslySetInnerHTML={{ __html: preview }}/> :
|
||||
preview;
|
||||
|
||||
const result = unified()
|
||||
.use(parseHtml, { fragment: true })
|
||||
.parse(renderToStaticMarkup(output));
|
||||
|
||||
return result.children[0];
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
const MarkupItReactRenderer = ({ value, getAsset }) => {
|
||||
const doc = unified()
|
||||
.use(markdown, { commonmark: true, footnotes: true, pedantic: true })
|
||||
.use(rehype, { allowDangerousHTML: true })
|
||||
.use(renderEditorPlugins, { getAsset })
|
||||
.use(html, { allowDangerousHTML: true })
|
||||
.processSync(this.props.value);
|
||||
.processSync(value);
|
||||
|
||||
return <div dangerouslySetInnerHTML={{ __html: doc }} />; // eslint-disable-line react/no-danger
|
||||
}
|
||||
}
|
||||
|
||||
export default MarkupItReactRenderer;
|
||||
|
||||
MarkupItReactRenderer.propTypes = {
|
||||
value: PropTypes.string,
|
||||
getAsset: PropTypes.func.isRequired,
|
||||
};
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import { Schema } from "prosemirror-model";
|
||||
import { schema } from "prosemirror-markdown";
|
||||
|
||||
const makeParser = require("../parser");
|
||||
import makeParser from '../parser';
|
||||
|
||||
const testSchema = new Schema({
|
||||
nodes: schema.nodeSpec,
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
import unified from 'unified';
|
||||
import markdown from 'remark-parse';
|
||||
import visit from 'unist-util-visit';
|
||||
import { Mark } from 'prosemirror-model';
|
||||
|
||||
let schema;
|
||||
@ -133,6 +132,8 @@ const processMdastNode = node => {
|
||||
activeMarks = mark.removeFromSet(activeMarks);
|
||||
return;
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
const compileMarkdownToProseMirror = src => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user