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-notifications": "^2.1.1",
|
||||||
"redux-optimist": "^0.0.2",
|
"redux-optimist": "^0.0.2",
|
||||||
"redux-thunk": "^1.0.3",
|
"redux-thunk": "^1.0.3",
|
||||||
|
"rehype-parse": "^3.1.0",
|
||||||
"rehype-stringify": "^3.0.0",
|
"rehype-stringify": "^3.0.0",
|
||||||
"remark-html": "^6.0.0",
|
"remark-html": "^6.0.0",
|
||||||
"remark-parse": "^3.0.1",
|
"remark-parse": "^3.0.1",
|
||||||
@ -168,7 +169,6 @@
|
|||||||
"slug": "^0.9.1",
|
"slug": "^0.9.1",
|
||||||
"textarea-caret-position": "^0.1.1",
|
"textarea-caret-position": "^0.1.1",
|
||||||
"unified": "^6.1.4",
|
"unified": "^6.1.4",
|
||||||
"unist-util-visit": "^1.1.1",
|
|
||||||
"uuid": "^2.0.3",
|
"uuid": "^2.0.3",
|
||||||
"whatwg-fetch": "^1.0.0"
|
"whatwg-fetch": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
@ -1,30 +1,92 @@
|
|||||||
import React, { PropTypes } from "react";
|
import React, { PropTypes } from "react";
|
||||||
|
import { renderToStaticMarkup } from 'react-dom/server';
|
||||||
|
import { Map } from 'immutable';
|
||||||
import unified from 'unified';
|
import unified from 'unified';
|
||||||
import markdown from 'remark-parse';
|
import markdown from 'remark-parse';
|
||||||
import rehype from 'remark-rehype';
|
import rehype from 'remark-rehype';
|
||||||
|
import parseHtml from 'rehype-parse';
|
||||||
import html from 'rehype-stringify';
|
import html from 'rehype-stringify';
|
||||||
import registry from "../../lib/registry";
|
import registry from "../../lib/registry";
|
||||||
|
|
||||||
export default class MarkupItReactRenderer extends React.Component {
|
const getPlugins = () => registry.getEditorComponents();
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
const renderEditorPlugins = ({ getAsset }) => {
|
||||||
this.plugins = {};
|
return tree => {
|
||||||
// TODO add back support for this.
|
const result = renderEditorPluginsProcessor(tree, getAsset);
|
||||||
registry.getEditorComponents().forEach((component) => {
|
return result;
|
||||||
this.plugins[component.get("id")] = component;
|
};
|
||||||
});
|
};
|
||||||
|
|
||||||
|
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
|
||||||
const doc = unified()
|
// already been parsed as an image by Remark, so we have to catch it by
|
||||||
.use(markdown, { commonmark: true, footnotes: true, pedantic: true })
|
// checking for the 'image' type.
|
||||||
.use(rehype, { allowDangerousHTML: true })
|
if (node.tagName === 'img') {
|
||||||
.use(html, { allowDangerousHTML: true })
|
const { src, alt } = node.properties;
|
||||||
.processSync(this.props.value);
|
|
||||||
return <div dangerouslySetInnerHTML={{ __html: doc }} />; // eslint-disable-line react/no-danger
|
// 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 = {
|
MarkupItReactRenderer.propTypes = {
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
|
getAsset: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { fromJS } from 'immutable';
|
import { fromJS } from 'immutable';
|
||||||
import { Schema } from "prosemirror-model";
|
import { Schema } from "prosemirror-model";
|
||||||
import { schema } from "prosemirror-markdown";
|
import { schema } from "prosemirror-markdown";
|
||||||
|
import makeParser from '../parser';
|
||||||
const makeParser = require("../parser");
|
|
||||||
|
|
||||||
const testSchema = new Schema({
|
const testSchema = new Schema({
|
||||||
nodes: schema.nodeSpec,
|
nodes: schema.nodeSpec,
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
import unified from 'unified';
|
import unified from 'unified';
|
||||||
import markdown from 'remark-parse';
|
import markdown from 'remark-parse';
|
||||||
import visit from 'unist-util-visit';
|
|
||||||
import { Mark } from 'prosemirror-model';
|
import { Mark } from 'prosemirror-model';
|
||||||
|
|
||||||
let schema;
|
let schema;
|
||||||
@ -133,6 +132,8 @@ const processMdastNode = node => {
|
|||||||
activeMarks = mark.removeFromSet(activeMarks);
|
activeMarks = mark.removeFromSet(activeMarks);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
const compileMarkdownToProseMirror = src => {
|
const compileMarkdownToProseMirror = src => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user