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 = ` ![super](duper.jpg) +`; + 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; +};