Update parser to support remaining node types + add inline styled text support
This commit is contained in:
parent
0eb109cb73
commit
8763666570
@ -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(<MarkupItReactRenderer value={value} />);
|
||||
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(<MarkupItReactRenderer value={value} />);
|
||||
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(<MarkupItReactRenderer value={value} />);
|
||||
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 = "<p>Paragraph with <em>inline</em> element</p>";
|
||||
describe('HTML rendering', () => {
|
||||
it('should render HTML', () => {
|
||||
const value = '<p>Paragraph with <em>inline</em> element</p>';
|
||||
const component = shallow(<MarkupItReactRenderer value={value} />);
|
||||
expect(component.html()).toMatchSnapshot();
|
||||
});
|
||||
|
@ -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 [
|
||||
|
@ -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
|
||||
* <http://www.markitdown.net/>.
|
||||
|
||||
## 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();
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user