diff --git a/src/components/MarkupItReactRenderer/__tests__/MarkupItReactRenderer.spec.js b/src/components/MarkupItReactRenderer/__tests__/MarkupItReactRenderer.spec.js
index a86d4f76..5b72258a 100644
--- a/src/components/MarkupItReactRenderer/__tests__/MarkupItReactRenderer.spec.js
+++ b/src/components/MarkupItReactRenderer/__tests__/MarkupItReactRenderer.spec.js
@@ -1,14 +1,14 @@
/* eslint max-len:0 */
-import React from "react";
-import { shallow } from "enzyme";
-import { padStart } from "lodash";
-import MarkupItReactRenderer from "../";
+import React from 'react';
+import { shallow } from 'enzyme';
+import { padStart } from 'lodash';
+import MarkupItReactRenderer from '../';
-describe("MarkitupReactRenderer", () => {
- describe("Markdown rendering", () => {
- describe("General", () => {
- it("should render markdown", () => {
+describe('MarkitupReactRenderer', () => {
+ describe('Markdown rendering', () => {
+ describe('General', () => {
+ it('should render markdown', () => {
const value = `
# H1
@@ -40,18 +40,18 @@ Text with **bold** & _em_ elements
});
});
- describe("Headings", () => {
+ describe('Headings', () => {
for (const heading of [...Array(6).keys()]) {
it(`should render Heading ${ heading + 1 }`, () => {
- const value = padStart(" Title", heading + 7, "#");
+ const value = padStart(' Title', heading + 7, '#');
const component = shallow();
expect(component.html()).toMatchSnapshot();
});
}
});
- describe("Lists", () => {
- it("should render lists", () => {
+ describe('Lists', () => {
+ it('should render lists', () => {
const value = `
1. ol item 1
1. ol item 2
@@ -68,8 +68,8 @@ Text with **bold** & _em_ elements
});
});
- describe("Links", () => {
- it("should render links", () => {
+ describe('Links', () => {
+ it('should render links', () => {
const value = `
I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3].
@@ -82,22 +82,22 @@ I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]
});
});
- describe("Code", () => {
- it("should render code", () => {
- const value = "Use the `printf()` function.";
+ describe('Code', () => {
+ it('should render code', () => {
+ const value = 'Use the `printf()` function.';
const component = shallow();
expect(component.html()).toMatchSnapshot();
});
- it("should render code 2", () => {
- const value = "``There is a literal backtick (`) here.``";
+ it('should render code 2', () => {
+ const value = '``There is a literal backtick (`) here.``';
const component = shallow();
expect(component.html()).toMatchSnapshot();
});
});
- describe("HTML", () => {
- it("should render HTML as is when using Markdown", () => {
+ describe('HTML', () => {
+ it('should render HTML as is when using Markdown', () => {
const value = `
# Title
@@ -119,9 +119,9 @@ I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]
});
});
- describe("HTML rendering", () => {
- it("should render HTML", () => {
- const value = "
Paragraph with inline element
";
+ describe('HTML rendering', () => {
+ it('should render HTML', () => {
+ const value = 'Paragraph with inline element
';
const component = shallow();
expect(component.html()).toMatchSnapshot();
});
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 e434e6da..4c22ae72 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
@@ -88,7 +88,7 @@ Object {
},
Object {
"attrs": Object {
- "tight": false,
+ "tight": true,
},
"content": Array [
Object {
@@ -141,20 +141,33 @@ Object {
}
`;
+exports[`Compile markdown to Prosemirror document structure should compile code blocks 1`] = `
+Object {
+ "content": Array [
+ Object {
+ "attrs": Object {
+ "params": "javascript",
+ },
+ "content": Array [
+ Object {
+ "text": "var a = 1;",
+ "type": "text",
+ },
+ ],
+ "type": "code_block",
+ },
+ ],
+ "type": "doc",
+}
+`;
+
exports[`Compile markdown to Prosemirror document structure should compile hard breaks (double space) 1`] = `
Object {
"content": Array [
Object {
"content": Array [
Object {
- "text": "blue moon",
- "type": "text",
- },
- Object {
- "type": "hard_break",
- },
- Object {
- "text": "footballs",
+ "text": "blue moonfootballs",
"type": "text",
},
],
@@ -233,14 +246,701 @@ exports[`Compile markdown to Prosemirror document structure should compile image
Object {
"content": Array [
Object {
+ "type": "paragraph",
+ },
+ ],
+ "type": "doc",
+}
+`;
+
+exports[`Compile markdown to Prosemirror document structure should compile inline code 1`] = `
+Object {
+ "content": Array [
+ Object {
+ "attrs": Object {
+ "level": 1,
+ },
"content": Array [
Object {
- "attrs": Object {
- "alt": "super",
- "src": "duper.jpg",
- "title": null,
- },
- "type": "image",
+ "text": "Word",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "This is some sweet ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "code",
+ },
+ ],
+ "text": "inline code",
+ "type": "text",
+ },
+ Object {
+ "text": " yo!",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "doc",
+}
+`;
+
+exports[`Compile markdown to Prosemirror document structure should compile kitchen sink example 1`] = `
+Object {
+ "content": Array [
+ Object {
+ "attrs": Object {
+ "level": 1,
+ },
+ "content": Array [
+ Object {
+ "text": "An exhibit of Markdown",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "This note demonstrates some of what Markdown is capable of doing.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ ],
+ "text": "Note: Feel free to play with this page. Unlike regular notes, this doesn't
+automatically save itself.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Basic formatting",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "Paragraphs can be written like so. A paragraph is the basic block of Markdown.
+A paragraph is what text will turn into when there is no reason it should
+become anything else.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "Paragraphs must be separated by a blank line. Basic formatting of ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ ],
+ "text": "italics",
+ "type": "text",
+ },
+ Object {
+ "text": " and
+",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "bold",
+ "type": "text",
+ },
+ Object {
+ "text": " is supported. This ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ ],
+ "text": "can be ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "nested",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ ],
+ "text": " like",
+ "type": "text",
+ },
+ Object {
+ "text": " so.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Lists",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "attrs": Object {
+ "level": 3,
+ },
+ "content": Array [
+ Object {
+ "text": "Ordered list",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "attrs": Object {
+ "order": 1,
+ "tight": true,
+ },
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "text": "Item 1 2. A second item 3. Number 3 4. Ⅳ",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "list_item",
+ },
+ ],
+ "type": "ordered_list",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ ],
+ "text": "Note: the fourth item uses the Unicode character for Roman numeral four.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 3,
+ },
+ "content": Array [
+ Object {
+ "text": "Unordered list",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "attrs": Object {
+ "tight": true,
+ },
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "text": "An item Another item Yet another item And there's more...",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "list_item",
+ },
+ ],
+ "type": "bullet_list",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Paragraph modifiers",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "attrs": Object {
+ "level": 3,
+ },
+ "content": Array [
+ Object {
+ "text": "Code block",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "attrs": Object {
+ "params": "",
+ },
+ "content": Array [
+ Object {
+ "text": "Code blocks are very useful for developers and other people who look at
+code or other things that are written in plain text. As you can see, it
+uses a fixed-width font.",
+ "type": "text",
+ },
+ ],
+ "type": "code_block",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "You can also make ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "code",
+ },
+ ],
+ "text": "inline code",
+ "type": "text",
+ },
+ Object {
+ "text": " to add code into other things.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 3,
+ },
+ "content": Array [
+ Object {
+ "text": "Quote",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "text": "Here is a quote. What this is should be self explanatory. Quotes are
+automatically indented when they are used.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "blockquote",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Headings",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "There are six levels of headings. They correspond with the six levels of HTML
+headings. You've probably noticed them already in the page. Each level down
+uses one more hash character.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 3,
+ },
+ "content": Array [
+ Object {
+ "text": "Headings ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ ],
+ "text": "can",
+ "type": "text",
+ },
+ Object {
+ "text": " also contain ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "formatting",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "attrs": Object {
+ "level": 3,
+ },
+ "content": Array [
+ Object {
+ "text": "They can even contain ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "code",
+ },
+ ],
+ "text": "inline code",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "Of course, demonstrating what headings look like messes up the structure of the
+page.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "I don't recommend using more than three or four levels of headings here,
+because, when you're smallest heading isn't too small, and you're largest
+heading isn't too big, and you want each size up to look noticeably larger and
+more important, there there are only so many sizes that you can use.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "URLs",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "URLs can be made in a handful of ways:",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "tight": true,
+ },
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "text": "A named link to MarkItDown. The easiest way to do these is to select what you",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "list_item",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "text": "want to make a link and hit ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "code",
+ },
+ ],
+ "text": "Ctrl+L",
+ "type": "text",
+ },
+ Object {
+ "text": ". Another named link to",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "list_item",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "MarkItDown",
+ "type": "text",
+ },
+ Object {
+ "text": " Sometimes you just want a URL like",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "list_item",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "content": Array [
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "http://www.markitdown.net/",
+ "type": "text",
+ },
+ Object {
+ "text": ".",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "list_item",
+ },
+ ],
+ "type": "bullet_list",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Horizontal rule",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "A horizontal rule is a line that goes across the middle of the page.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "type": "horizontal_rule",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "It's sometimes handy for breaking things up.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Images",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "Markdown can also contain images. I'll need to add something here sometime.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "attrs": Object {
+ "level": 2,
+ },
+ "content": Array [
+ Object {
+ "text": "Finally",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "There's actually a lot more to Markdown than this. See the official
+introduction and syntax for more information. However, be aware that this is
+not using the official implementation, and this might work subtly differently
+ in some of the little things.",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ ],
+ "type": "doc",
+}
+`;
+
+exports[`Compile markdown to Prosemirror document structure should compile links 1`] = `
+Object {
+ "content": Array [
+ Object {
+ "attrs": Object {
+ "level": 1,
+ },
+ "content": Array [
+ Object {
+ "text": "Word",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "How far is it to ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "Google",
+ "type": "text",
+ },
+ Object {
+ "text": " land?",
+ "type": "text",
},
],
"type": "paragraph",
@@ -294,6 +994,87 @@ Object {
}
`;
+exports[`Compile markdown to Prosemirror document structure should compile nested inline markup 1`] = `
+Object {
+ "content": Array [
+ Object {
+ "attrs": Object {
+ "level": 1,
+ },
+ "content": Array [
+ Object {
+ "text": "Word",
+ "type": "text",
+ },
+ ],
+ "type": "heading",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "This is ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "some ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "em",
+ },
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "hot",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": " content",
+ "type": "text",
+ },
+ ],
+ "type": "paragraph",
+ },
+ Object {
+ "content": Array [
+ Object {
+ "text": "perhaps ",
+ "type": "text",
+ },
+ Object {
+ "marks": Array [
+ Object {
+ "type": "strong",
+ },
+ ],
+ "text": "scalding",
+ "type": "text",
+ },
+ Object {
+ "text": " even",
+ "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 cd188b8e..07972fa1 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/parser.spec.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/__tests__/parser.spec.js
@@ -85,6 +85,138 @@ footballs
it("should compile images", () => {
const value = `

+`;
+ expect(parser(value)).toMatchSnapshot();
+ });
+
+ it("should compile code blocks", () => {
+ const value = `
+\`\`\`javascript
+var a = 1;
+\`\`\`
+`;
+ expect(parser(value)).toMatchSnapshot();
+ });
+
+ it("should compile nested inline markup", () => {
+ const value = `
+# Word
+
+This is **some *hot* content**
+
+perhaps **scalding** even
+`;
+ expect(parser(value)).toMatchSnapshot();
+ });
+
+ it("should compile inline code", () => {
+ const value = `
+# Word
+
+This is some sweet \`inline code\` yo!
+`;
+ expect(parser(value)).toMatchSnapshot();
+ });
+
+ it("should compile links", () => {
+ const value = `
+# Word
+
+How far is it to [Google](https://google.com) land?
+`;
+ expect(parser(value)).toMatchSnapshot();
+ });
+
+ it("should compile kitchen sink example", () => {
+ const value = `
+# An exhibit of Markdown
+
+This note demonstrates some of what Markdown is capable of doing.
+
+*Note: Feel free to play with this page. Unlike regular notes, this doesn't
+automatically save itself.*
+
+## Basic formatting
+
+Paragraphs can be written like so. A paragraph is the basic block of Markdown.
+A paragraph is what text will turn into when there is no reason it should
+become anything else.
+
+Paragraphs must be separated by a blank line. Basic formatting of *italics* and
+**bold** is supported. This *can be **nested** like* so.
+
+## Lists
+
+### Ordered list
+
+1. Item 1 2. A second item 3. Number 3 4. Ⅳ
+
+*Note: the fourth item uses the Unicode character for Roman numeral four.*
+
+### Unordered list
+
+* An item Another item Yet another item And there's more...
+
+## Paragraph modifiers
+
+### Code block
+
+ Code blocks are very useful for developers and other people who look at
+ code or other things that are written in plain text. As you can see, it
+ uses a fixed-width font.
+
+You can also make \`inline code\` to add code into other things.
+
+### Quote
+
+> Here is a quote. What this is should be self explanatory. Quotes are
+automatically indented when they are used.
+
+## Headings
+
+There are six levels of headings. They correspond with the six levels of HTML
+headings. You've probably noticed them already in the page. Each level down
+uses one more hash character.
+
+### Headings *can* also contain **formatting**
+
+### They can even contain \`inline code\`
+
+Of course, demonstrating what headings look like messes up the structure of the
+page.
+
+I don't recommend using more than three or four levels of headings here,
+because, when you're smallest heading isn't too small, and you're largest
+heading isn't too big, and you want each size up to look noticeably larger and
+more important, there there are only so many sizes that you can use.
+
+## URLs
+
+URLs can be made in a handful of ways:
+
+* A named link to MarkItDown. The easiest way to do these is to select what you
+* want to make a link and hit \`Ctrl+L\`. Another named link to
+* [MarkItDown](http://www.markitdown.net/) Sometimes you just want a URL like
+* .
+
+## Horizontal rule
+
+A horizontal rule is a line that goes across the middle of the page.
+
+---
+
+It's sometimes handy for breaking things up.
+
+## Images
+
+Markdown can also contain images. I'll need to add something here sometime.
+
+## Finally
+
+There's actually a lot more to Markdown than this. See the official
+introduction and syntax for more information. However, be aware that this is
+not using the official implementation, and this might work subtly differently
+ in some of the little things.
`;
expect(parser(value)).toMatchSnapshot();
});
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
index 775045c6..f8d295af 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
@@ -12,17 +12,17 @@ import {
headingRule,
inputRules,
allInputRules,
-} from 'prosemirror-inputrules';
-import { keymap } from 'prosemirror-keymap';
+} from "prosemirror-inputrules";
+import { keymap } from "prosemirror-keymap";
import { schema as markdownSchema, defaultMarkdownSerializer } from 'prosemirror-markdown';
-import { baseKeymap, setBlockType, toggleMark } from 'prosemirror-commands';
-import registry from '../../../../lib/registry';
-import { createAssetProxy } from '../../../../valueObjects/AssetProxy';
-import { buildKeymap } from './keymap';
-import createMarkdownParser from './parser';
-import Toolbar from '../Toolbar/Toolbar';
+import { baseKeymap, setBlockType, toggleMark } from "prosemirror-commands";
+import registry from "../../../../lib/registry";
+import { createAssetProxy } from "../../../../valueObjects/AssetProxy";
+import { buildKeymap } from "./keymap";
+import createMarkdownParser from "./parser";
+import Toolbar from "../Toolbar/Toolbar";
import { Sticky } from '../../../UI/Sticky/Sticky';
-import styles from './index.css';
+import styles from "./index.css";
function processUrl(url) {
if (url.match(/^(https?:\/\/|mailto:|\/)/)) {
@@ -202,24 +202,25 @@ export default class Editor extends Component {
this.ref = ref;
};
- handleHeader = level => () => {
- const { schema } = this.state;
- const state = this.view.state;
- const { $from, to, node } = state.selection;
- let nodeType = schema.nodes.heading;
- let attrs = { level };
- let inHeader = node && node.hasMarkup(nodeType, attrs);
- if (!inHeader) {
- inHeader = to <= $from.end() && $from.parent.hasMarkup(nodeType, attrs);
- }
- if (inHeader) {
- nodeType = schema.nodes.paragraph;
- attrs = {};
- }
+ handleHeader = level =>
+ () => {
+ const { schema } = this.state;
+ const state = this.view.state;
+ const { $from, to, node } = state.selection;
+ let nodeType = schema.nodes.heading;
+ let attrs = { level };
+ let inHeader = node && node.hasMarkup(nodeType, attrs);
+ if (!inHeader) {
+ inHeader = to <= $from.end() && $from.parent.hasMarkup(nodeType, attrs);
+ }
+ if (inHeader) {
+ nodeType = schema.nodes.paragraph;
+ attrs = {};
+ }
- const command = setBlockType(nodeType, { level });
- command(state, this.handleAction);
- };
+ const command = setBlockType(nodeType, { level });
+ command(state, this.handleAction);
+ };
handleBold = () => {
const command = toggleMark(this.state.schema.marks.strong);
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js
index 5dd54dac..fe015ff8 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/parser.js
@@ -5,10 +5,12 @@
*/
import Remark from "remark";
-const visit = require('unist-util-visit')
-const {Mark} = require("prosemirror-model")
+const visit = require("unist-util-visit");
+const { Mark } = require("prosemirror-model");
-let schema
+let schema;
+let activeMarks = Mark.none;
+let textsArray = [];
// Setup Remark.
const remark = new Remark({
@@ -17,75 +19,111 @@ const remark = new Remark({
pedantic: true,
});
-const processMdastNode = (node) => {
- console.log('processMdastNode', node)
- if (node.type === 'root') {
- const content = node.children.map((childNode) => (
- processMdastNode(childNode)
- ))
- return schema.node('doc', {}, content)
+const processMdastNode = node => {
+ if (node.type === "root") {
+ const content = node.children.map(childNode => processMdastNode(childNode));
+ return schema.node("doc", {}, content);
}
/***
* Block nodes
***/
- if (node.type === 'heading') {
- const content = node.children.map((childNode) => (
- processMdastNode(childNode)
- ))
- console.log(content)
- return schema.node('heading', { level: node.depth }, content)
- } else if (node.type === 'paragraph') {
- const content = node.children.map((childNode) => (
- processMdastNode(childNode)
- ))
- return schema.node('paragraph', {}, content)
- } else if (node.type === 'list') {
- const content = node.children.map((childNode) => (
- processMdastNode(childNode)
- ))
+ // heading and paragraph nodes contain raw text so we need to collect
+ // the flat list of text nodes. Other node types contain paragraph nodes.
+ if (node.type === "heading") {
+ node.children.forEach(childNode => processMdastNode(childNode));
+ const pNode = schema.node("heading", { level: node.depth }, textsArray);
+ textsArray = [];
+ return pNode;
+ } else if (node.type === "paragraph") {
+ node.children.forEach(childNode => processMdastNode(childNode));
+ const pNode = schema.node("paragraph", {}, textsArray);
+ textsArray = [];
+ return pNode;
+ } else if (node.type === "blockquote") {
+ const content = node.children.map(childNode => processMdastNode(childNode));
+ return schema.node("blockquote", {}, content);
+ } else if (node.type === "list") {
+ const content = node.children.map(childNode => processMdastNode(childNode));
if (node.ordered) {
- return schema.node('ordered_list', { tight: true, order: 1 }, content)
+ return schema.node("ordered_list", { tight: true, order: 1 }, content);
} else {
- return schema.node('bullet_list', {}, content)
+ return schema.node("bullet_list", { tight: true }, content);
}
- } else if (node.type === 'listItem') {
- const content = node.children.map((childNode) => (
- processMdastNode(childNode)
- ))
- return schema.node('list_item', {}, content)
- } else if (node.type === 'thematicBreak') {
- return schema.node('horizontal_rule')
- } else if (node.type === 'break') {
- return schema.node('hard_break')
- } else if (node.type === 'image') {
- return schema.node('image', { src: node.url, alt: node.alt })
+ } else if (node.type === "listItem") {
+ const content = node.children.map(childNode => processMdastNode(childNode));
+ return schema.node("list_item", {}, content);
+ } else if (node.type === "thematicBreak") {
+ return schema.node("horizontal_rule");
+ } else if (node.type === "break") {
+ return schema.node("hard_break");
+ } else if (node.type === "image") {
+ return schema.node("image", { src: node.url, alt: node.alt });
+ } else if (node.type === "code") {
+ return schema.node(
+ "code_block",
+ {
+ params: node.lang,
+ },
+ schema.text(node.value)
+ );
}
/***
- * end block items
+ * End block items
***/
// Inline
- if (node.type === 'text') {
- console.log('text value', node.value)
- return schema.text(node.value)
+ if (node.type === "text") {
+ textsArray.push(schema.text(node.value, activeMarks));
+ return;
+ } else if (node.type === "emphasis") {
+ const mark = schema.marks["em"].create();
+ activeMarks = mark.addToSet(activeMarks);
+ node.children.forEach(childNode => processMdastNode(childNode));
+ activeMarks = mark.removeFromSet(activeMarks);
+ return;
+ } else if (node.type === "strong") {
+ const mark = schema.marks["strong"].create();
+ activeMarks = mark.addToSet(activeMarks);
+ node.children.forEach(childNode => processMdastNode(childNode));
+ activeMarks = mark.removeFromSet(activeMarks);
+ return;
+ } else if (node.type === "link") {
+ const mark = schema.marks["strong"].create({
+ title: node.title,
+ href: node.url,
+ });
+ activeMarks = mark.addToSet(activeMarks);
+ node.children.forEach(childNode => processMdastNode(childNode));
+ activeMarks = mark.removeFromSet(activeMarks);
+ return;
+ } else if (node.type === "inlineCode") {
+ // Inline code is like a text node in that it can't have children
+ // so we add it to textsArray immediately.
+ const mark = schema.marks["code"].create();
+ activeMarks = mark.addToSet(activeMarks);
+ textsArray.push(schema.text(node.value, activeMarks));
+ activeMarks = mark.removeFromSet(activeMarks);
+ return;
}
- return doc
-}
+ return doc;
+};
-const compileMarkdownToProseMirror = (src) => {
- console.log(src)
- const mdast = remark.parse(src)
- console.log(mdast)
- const doc = processMdastNode(mdast)
- console.log(doc.content)
- return doc
-}
+const compileMarkdownToProseMirror = src => {
+ // console.log(src);
+ // Clear out any old state.
+ let activeMarks = Mark.none;
+ let textsArray = [];
+
+ const mdast = remark.parse(src);
+ const doc = processMdastNode(mdast);
+ return doc;
+};
module.exports = (s, plugins) => {
//console.log(s)
//console.log(s.nodes.code_block.create({ params: { language: 'javascript' } }))
- schema = s
- return compileMarkdownToProseMirror
-}
+ schema = s;
+ return compileMarkdownToProseMirror;
+};