diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/__snapshots__/parser.spec.js.snap b/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/__snapshots__/parser.spec.js.snap
index 4c22ae72..74a86aab 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/__snapshots__/parser.spec.js.snap
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/__snapshots__/parser.spec.js.snap
@@ -1075,6 +1075,26 @@ Object {
}
`;
+exports[`Compile markdown to Prosemirror document structure should compile plugins 1`] = `
+Object {
+ "content": Array [
+ Object {
+ "type": "paragraph",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "{{< test >}}",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "doc",
+}
+`;
+
exports[`Compile markdown to Prosemirror document structure should compile simple markdown 1`] = `
Object {
"content": Array [
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/parser.spec.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/parser.spec.js
index 07972fa1..5b8fff61 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/parser.spec.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/parser.spec.js
@@ -1,3 +1,4 @@
+import { fromJS } from 'immutable';
import { Schema } from "prosemirror-model";
import { schema } from "prosemirror-markdown";
@@ -7,7 +8,51 @@ const testSchema = new Schema({
nodes: schema.nodeSpec,
marks: schema.markSpec,
});
-const parser = makeParser(testSchema);
+
+// Temporary plugins test, uses preloaded plugins from ../parser
+// TODO: make the parser more testable
+const testPlugins = fromJS([
+ {
+ label: 'Image',
+ id: 'image',
+ fromBlock: match => match && {
+ image: match[2],
+ alt: match[1],
+ },
+ toBlock: data => `![${ data.alt }](${ data.image })`,
+ toPreview: data => ,
+ pattern: /^!\[([^\]]+)]\(([^)]+)\)$/,
+ fields: [{
+ label: 'Image',
+ name: 'image',
+ widget: 'image',
+ }, {
+ label: 'Alt Text',
+ name: 'alt',
+ }],
+ },
+ {
+ id: "youtube",
+ label: "Youtube",
+ fields: [{name: 'id', label: 'Youtube Video ID'}],
+ pattern: /^{{<\s?youtube (\S+)\s?>}}/,
+ fromBlock: function(match) {
+ return {
+ id: match[1]
+ };
+ },
+ toBlock: function(obj) {
+ return '{{< youtube ' + obj.id + ' >}}';
+ },
+ toPreview: function(obj) {
+ return (
+ ''
+ );
+ }
+ },
+]);
+
+const parser = makeParser(testSchema, testPlugins);
describe("Compile markdown to Prosemirror document structure", () => {
it("should compile simple markdown", () => {
@@ -127,6 +172,15 @@ How far is it to [Google](https://google.com) land?
expect(parser(value)).toMatchSnapshot();
});
+ it("should compile plugins", () => {
+ const value = `
+![test](test.png)
+
+{{< test >}}
+`;
+ expect(parser(value)).toMatchSnapshot();
+ });
+
it("should compile kitchen sink example", () => {
const value = `
# An exhibit of Markdown
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js
index fe015ff8..a4605fcf 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js
@@ -9,6 +9,7 @@ const visit = require("unist-util-visit");
const { Mark } = require("prosemirror-model");
let schema;
+let plugins
let activeMarks = Mark.none;
let textsArray = [];
@@ -36,6 +37,38 @@ const processMdastNode = node => {
textsArray = [];
return pNode;
} else if (node.type === "paragraph") {
+
+ // TODO: improve plugin handling
+
+ // Handle externally defined plugins (they'll be wrapped in paragraphs)
+ if (node.children.length === 1 && node.children[0].type === 'text') {
+ const value = node.children[0].value;
+ const plugin = plugins.find(plugin => plugin.get('pattern').test(value));
+ if (plugin) {
+ const nodeType = schema.nodes[`plugin_${plugin.get('id')}`];
+ const data = plugin.get('fromBlock').call(plugin, value.match(plugin.get('pattern')));
+ return nodeType.create(data);
+ }
+ }
+
+ // 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.children.length === 1 && node.children[0].type === 'image') {
+ const { url, alt } = node.children[0];
+
+ // 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 matches = [ , alt, url ];
+ const plugin = plugins.find(plugin => plugin.id === 'image');
+ if (plugin) {
+ const nodeType = schema.nodes.plugin_image;
+ const data = plugin.get('fromBlock').call(plugin, matches);
+ return nodeType.create(data);
+ }
+ }
+
node.children.forEach(childNode => processMdastNode(childNode));
const pNode = schema.node("paragraph", {}, textsArray);
textsArray = [];
@@ -121,9 +154,10 @@ const compileMarkdownToProseMirror = src => {
return doc;
};
-module.exports = (s, plugins) => {
+module.exports = (s, p) => {
//console.log(s)
//console.log(s.nodes.code_block.create({ params: { language: 'javascript' } }))
schema = s;
+ plugins = p;
return compileMarkdownToProseMirror;
};