implement initial unified/remark preview update

This commit is contained in:
Shawn Erquhart 2017-05-25 13:51:43 -04:00
parent 5048c7ca1d
commit 8bb18452e8
4 changed files with 81 additions and 19 deletions

View File

@ -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"
},

View File

@ -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() {
const doc = unified()
.use(markdown, { commonmark: true, footnotes: true, pedantic: true })
.use(rehype, { allowDangerousHTML: true })
.use(html, { allowDangerousHTML: true })
.processSync(this.props.value);
return <div dangerouslySetInnerHTML={{ __html: doc }} />; // eslint-disable-line react/no-danger
// 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(value);
return <div dangerouslySetInnerHTML={{ __html: doc }} />; // eslint-disable-line react/no-danger
}
export default MarkupItReactRenderer;
MarkupItReactRenderer.propTypes = {
value: PropTypes.string,
getAsset: PropTypes.func.isRequired,
};

View File

@ -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,

View File

@ -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 => {