commit
fd606938e2
23
package.json
23
package.json
@ -41,9 +41,15 @@
|
||||
"^.+\\.s?css$": "<rootDir>/__mocks__/styleLoaderMock.js"
|
||||
},
|
||||
"mapCoverage": true,
|
||||
"coverageReporters": ["lcov"],
|
||||
"collectCoverageFrom": [ "src/**/*.js" ],
|
||||
"coveragePathIgnorePatterns": [ "/__tests__/" ]
|
||||
"coverageReporters": [
|
||||
"lcov"
|
||||
],
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.js"
|
||||
],
|
||||
"coveragePathIgnorePatterns": [
|
||||
"/__tests__/"
|
||||
]
|
||||
},
|
||||
"keywords": [
|
||||
"netlify",
|
||||
@ -151,10 +157,13 @@
|
||||
"remark-stringify": "^3.0.1",
|
||||
"sanitize-filename": "^1.6.1",
|
||||
"semaphore": "^1.0.5",
|
||||
"slate": "^0.21.0",
|
||||
"slate-edit-list": "^0.7.1",
|
||||
"slate-edit-table": "^0.10.1",
|
||||
"slate-soft-break": "^0.3.0",
|
||||
"slate": "^0.25.0",
|
||||
"slate-edit-list": "^0.8.0",
|
||||
"slate-edit-table": "^0.11.0",
|
||||
"slate-plain-serializer": "^0.1.10",
|
||||
"slate-react": "^0.1.10",
|
||||
"slate-soft-break": "^0.4.0",
|
||||
"slug": "^0.9.1",
|
||||
"toml-j0.4": "^1.1.1",
|
||||
"unified": "^6.1.4",
|
||||
"unist-builder": "^1.0.2",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { Editor as Slate, Plain } from 'slate';
|
||||
import { Editor as Slate } from 'slate-react';
|
||||
import Plain from 'slate-plain-serializer';
|
||||
import { debounce } from 'lodash';
|
||||
import Toolbar from '../Toolbar/Toolbar';
|
||||
import { Sticky } from '../../../../UI/Sticky/Sticky';
|
||||
@ -18,16 +19,19 @@ export default class RawEditor extends React.Component {
|
||||
return !this.state.editorState.equals(nextState.editorState);
|
||||
}
|
||||
|
||||
handleChange = editorState => {
|
||||
this.setState({ editorState });
|
||||
}
|
||||
handleChange = change => {
|
||||
if (!this.state.editorState.document.equals(change.state.document)) {
|
||||
this.handleDocumentChange(change);
|
||||
}
|
||||
this.setState({ editorState: change.state });
|
||||
};
|
||||
|
||||
/**
|
||||
* When the document value changes, serialize from Slate's AST back to plain
|
||||
* text (which is Markdown) and pass that up as the new value.
|
||||
*/
|
||||
handleDocumentChange = debounce((doc, editorState) => {
|
||||
const value = Plain.serialize(editorState);
|
||||
handleDocumentChange = debounce(change => {
|
||||
const value = Plain.serialize(change.state);
|
||||
this.props.onChange(value);
|
||||
}, 150);
|
||||
|
||||
@ -36,10 +40,10 @@ export default class RawEditor extends React.Component {
|
||||
* to the document. Selection logic (where to insert, whether to replace) is
|
||||
* handled by Slate.
|
||||
*/
|
||||
handlePaste = (e, data, state) => {
|
||||
handlePaste = (e, data, change) => {
|
||||
if (data.text) {
|
||||
const fragment = Plain.deserialize(data.text).document;
|
||||
return state.transform().insertFragment(fragment).apply();
|
||||
return change.insertFragment(fragment);
|
||||
}
|
||||
};
|
||||
|
||||
@ -61,7 +65,6 @@ export default class RawEditor extends React.Component {
|
||||
className={styles.rawEditor}
|
||||
state={this.state.editorState}
|
||||
onChange={this.handleChange}
|
||||
onDocumentChange={this.handleDocumentChange}
|
||||
onPaste={this.handlePaste}
|
||||
/>
|
||||
</div>
|
||||
|
@ -10,7 +10,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H1",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -30,7 +34,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "yo",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "yo",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -47,7 +55,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "bro",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "bro",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -64,7 +76,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "fro",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "fro",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -90,7 +106,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H1",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -110,7 +130,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "yo",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "yo",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -127,7 +151,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "bro",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "bro",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -144,7 +172,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "fro",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "fro",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -173,7 +205,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "var a = 1;",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "var a = 1;",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "code",
|
||||
@ -193,7 +229,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H1",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -210,7 +250,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "blue moon",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "blue moon",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -230,7 +274,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H1",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -247,7 +295,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "blue moon",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "blue moon",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -267,7 +319,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -287,7 +343,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Word",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Word",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -298,7 +358,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "This is some sweet ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "This is some sweet ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -317,7 +381,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " yo!",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " yo!",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -337,7 +405,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "An exhibit of Markdown",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "An exhibit of Markdown",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -348,7 +420,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "This note demonstrates some of what Markdown is capable of doing.",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "This note demonstrates some of what Markdown is capable of doing.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -380,7 +456,11 @@ automatically save itself.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Basic formatting",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Basic formatting",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -391,9 +471,13 @@ automatically save itself.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Paragraphs can be written like so. A paragraph is the basic block of Markdown.
|
||||
"ranges": 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": "paragraph",
|
||||
@ -404,7 +488,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Paragraphs must be separated by a blank line. Basic formatting of ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Paragraphs must be separated by a blank line. Basic formatting of ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -423,8 +511,12 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " and
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " and
|
||||
",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -443,7 +535,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " is supported. This ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " is supported. This ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -481,7 +577,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " so.",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " so.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -492,7 +592,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Lists",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Lists",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -503,7 +607,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Ordered list",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Ordered list",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-three",
|
||||
@ -523,7 +631,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Item 1 2. A second item 3. Number 3 4. Ⅳ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Item 1 2. A second item 3. Number 3 4. Ⅳ",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -560,7 +672,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Unordered list",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Unordered list",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-three",
|
||||
@ -580,7 +696,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "An item Another item Yet another item And there's more...",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "An item Another item Yet another item And there's more...",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -597,7 +717,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Paragraph modifiers",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Paragraph modifiers",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -608,7 +732,11 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Code block",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Code block",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-three",
|
||||
@ -622,9 +750,13 @@ become anything else.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Code blocks are very useful for developers and other people who look at
|
||||
"ranges": 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": "code",
|
||||
@ -635,7 +767,11 @@ uses a fixed-width font.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "You can also make ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "You can also make ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -654,7 +790,11 @@ uses a fixed-width font.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " to add code into other things.",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " to add code into other things.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -665,7 +805,11 @@ uses a fixed-width font.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Quote",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Quote",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-three",
|
||||
@ -679,8 +823,12 @@ uses a fixed-width font.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Here is a quote. What this is should be self explanatory. Quotes are
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Here is a quote. What this is should be self explanatory. Quotes are
|
||||
automatically indented when they are used.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -694,7 +842,11 @@ automatically indented when they are used.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Headings",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Headings",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -705,9 +857,13 @@ automatically indented when they are used.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "There are six levels of headings. They correspond with the six levels of HTML
|
||||
"ranges": 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": "paragraph",
|
||||
@ -718,7 +874,11 @@ uses one more hash character.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Headings ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Headings ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -737,7 +897,11 @@ uses one more hash character.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " also contain ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " also contain ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -762,7 +926,11 @@ uses one more hash character.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "They can even contain ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "They can even contain ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -787,8 +955,12 @@ uses one more hash character.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Of course, demonstrating what headings look like messes up the structure of the
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Of course, demonstrating what headings look like messes up the structure of the
|
||||
page.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -799,10 +971,14 @@ page.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "I don't recommend using more than three or four levels of headings here,
|
||||
"ranges": 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": "paragraph",
|
||||
@ -813,7 +989,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "URLs",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "URLs",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -824,7 +1004,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "URLs can be made in a handful of ways:",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "URLs can be made in a handful of ways:",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -844,7 +1028,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "A named link to MarkItDown. The easiest way to do these is to select what you",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "A named link to MarkItDown. The easiest way to do these is to select what you",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -861,7 +1049,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "want to make a link and hit ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "want to make a link and hit ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -880,7 +1072,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": ". Another named link to",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": ". Another named link to",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -904,7 +1100,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "MarkItDown",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "MarkItDown",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "link",
|
||||
@ -912,7 +1112,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " Sometimes you just want a URL like",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " Sometimes you just want a URL like",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -936,7 +1140,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "http://www.markitdown.net/",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "http://www.markitdown.net/",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "link",
|
||||
@ -944,7 +1152,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": ".",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": ".",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -961,7 +1173,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Horizontal rule",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Horizontal rule",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -972,7 +1188,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "A horizontal rule is a line that goes across the middle of the page.",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "A horizontal rule is a line that goes across the middle of the page.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -989,7 +1209,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "It's sometimes handy for breaking things up.",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "It's sometimes handy for breaking things up.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1000,7 +1224,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Images",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Images",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -1011,7 +1239,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Markdown can also contain images. I'll need to add something here sometime.",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Markdown can also contain images. I'll need to add something here sometime.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1022,7 +1254,11 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Finally",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Finally",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -1033,10 +1269,14 @@ more important, there there are only so many sizes that you can use.",
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "There's actually a lot more to Markdown than this. See the official
|
||||
"ranges": 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": "paragraph",
|
||||
@ -1056,7 +1296,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Word",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Word",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -1067,7 +1311,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "How far is it to ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "How far is it to ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
@ -1079,7 +1327,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Google",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Google",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "link",
|
||||
@ -1087,7 +1339,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " land?",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " land?",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1107,7 +1363,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H1",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -1118,7 +1378,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H2",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H2",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-two",
|
||||
@ -1129,7 +1393,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H3",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H3",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-three",
|
||||
@ -1149,7 +1417,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "Word",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "Word",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -1160,7 +1432,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "This is ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "This is ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -1204,7 +1480,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "perhaps ",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "perhaps ",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"data": undefined,
|
||||
@ -1223,7 +1503,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": " even",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": " even",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1243,7 +1527,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1254,7 +1542,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "{{< test >}}",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "{{< test >}}",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1274,7 +1566,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "H1",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "H1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "heading-one",
|
||||
@ -1285,7 +1581,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "sweet body",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "sweet body",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
@ -1305,7 +1605,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "blue moon",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "blue moon",
|
||||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"kind": "inline",
|
||||
@ -1313,8 +1617,12 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "
|
||||
",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "break",
|
||||
@ -1322,7 +1630,11 @@ Object {
|
||||
Object {
|
||||
"data": undefined,
|
||||
"kind": "text",
|
||||
"text": "footballs",
|
||||
"ranges": Array [
|
||||
Object {
|
||||
"text": "footballs",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
|
@ -1,7 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { get, isEmpty, debounce } from 'lodash';
|
||||
import { Editor as Slate, Raw, Block, Text } from 'slate';
|
||||
import { State, Document, Block, Text } from 'slate';
|
||||
import { Editor as Slate } from 'slate-react';
|
||||
import { slateToMarkdown, markdownToSlate, htmlToSlate } from '../../serializers';
|
||||
import registry from '../../../../../lib/registry';
|
||||
import Toolbar from '../Toolbar/Toolbar';
|
||||
@ -15,11 +16,13 @@ import styles from './index.css';
|
||||
export default class Editor extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const emptyBlock = Block.create({ kind: 'block', type: 'paragraph'});
|
||||
const emptyText = Text.create('');
|
||||
const emptyBlock = Block.create({ kind: 'block', type: 'paragraph', nodes: [ emptyText ] });
|
||||
const emptyRawDoc = { nodes: [emptyBlock] };
|
||||
const rawDoc = this.props.value && markdownToSlate(this.props.value);
|
||||
const rawDocHasNodes = !isEmpty(get(rawDoc, 'nodes'))
|
||||
const editorState = Raw.deserialize(rawDocHasNodes ? rawDoc : emptyRawDoc, { terse: true });
|
||||
const document = Document.fromJSON(rawDocHasNodes ? rawDoc : emptyRawDoc);
|
||||
const editorState = State.create({ document });
|
||||
this.state = {
|
||||
editorState,
|
||||
schema: {
|
||||
@ -35,42 +38,36 @@ export default class Editor extends Component {
|
||||
return !this.state.editorState.equals(nextState.editorState);
|
||||
}
|
||||
|
||||
handlePaste = (e, data, state) => {
|
||||
handlePaste = (e, data, change) => {
|
||||
if (data.type !== 'html' || data.isShift) {
|
||||
return;
|
||||
}
|
||||
const ast = htmlToSlate(data.html);
|
||||
const { document: doc } = Raw.deserialize(ast, { terse: true });
|
||||
return state.transform().insertFragment(doc).apply();
|
||||
const doc = Document.fromJSON(ast);
|
||||
return change.insertFragment(doc);
|
||||
}
|
||||
|
||||
handleDocumentChange = debounce((doc, editorState) => {
|
||||
const raw = Raw.serialize(editorState, { terse: true });
|
||||
const plugins = this.state.shortcodePlugins;
|
||||
const markdown = slateToMarkdown(raw, plugins);
|
||||
this.props.onChange(markdown);
|
||||
}, 150);
|
||||
|
||||
hasMark = type => this.state.editorState.marks.some(mark => mark.type === type);
|
||||
hasBlock = type => this.state.editorState.blocks.some(node => node.type === type);
|
||||
|
||||
handleMarkClick = (event, type) => {
|
||||
event.preventDefault();
|
||||
const resolvedState = this.state.editorState.transform().focus().toggleMark(type).apply();
|
||||
this.ref.onChange(resolvedState);
|
||||
this.setState({ editorState: resolvedState });
|
||||
const resolvedChange = this.state.editorState.change().focus().toggleMark(type);
|
||||
this.ref.onChange(resolvedChange);
|
||||
this.setState({ editorState: resolvedChange.state });
|
||||
};
|
||||
|
||||
handleBlockClick = (event, type) => {
|
||||
event.preventDefault();
|
||||
let { editorState } = this.state;
|
||||
const { document: doc, selection } = editorState;
|
||||
const transform = editorState.transform();
|
||||
const { unwrapList, wrapInList } = EditListConfigured.changes;
|
||||
let change = editorState.change();
|
||||
|
||||
// Handle everything except list buttons.
|
||||
if (!['bulleted-list', 'numbered-list'].includes(type)) {
|
||||
const isActive = this.hasBlock(type);
|
||||
const transformed = transform.setBlock(isActive ? 'paragraph' : type);
|
||||
change = change.setBlock(isActive ? 'paragraph' : type);
|
||||
}
|
||||
|
||||
// Handle the extra wrapping required for list buttons.
|
||||
@ -81,19 +78,18 @@ export default class Editor extends Component {
|
||||
const isInList = EditListConfigured.utils.isSelectionInList(editorState);
|
||||
|
||||
if (isInList && isSameListType) {
|
||||
EditListConfigured.transforms.unwrapList(transform, type);
|
||||
change = change.call(unwrapList, type);
|
||||
} else if (isInList) {
|
||||
const currentListType = type === 'bulleted-list' ? 'numbered-list' : 'bulleted-list';
|
||||
EditListConfigured.transforms.unwrapList(transform, currentListType);
|
||||
EditListConfigured.transforms.wrapInList(transform, type);
|
||||
change = change.call(unwrapList, currentListType).call(wrapInList, type);
|
||||
} else {
|
||||
EditListConfigured.transforms.wrapInList(transform, type);
|
||||
change = change.call(wrapInList, type);
|
||||
}
|
||||
}
|
||||
|
||||
const resolvedState = transform.focus().apply();
|
||||
this.ref.onChange(resolvedState);
|
||||
this.setState({ editorState: resolvedState });
|
||||
const resolvedChange = change.focus();
|
||||
this.ref.onChange(resolvedChange);
|
||||
this.setState({ editorState: resolvedChange.state });
|
||||
};
|
||||
|
||||
hasLinks = () => {
|
||||
@ -101,12 +97,12 @@ export default class Editor extends Component {
|
||||
};
|
||||
|
||||
handleLink = () => {
|
||||
let { editorState } = this.state;
|
||||
let change = this.state.editorState.change();
|
||||
|
||||
// If the current selection contains links, clicking the "link" button
|
||||
// should simply unlink them.
|
||||
if (this.hasLinks()) {
|
||||
editorState = editorState.transform().unwrapInline('link').apply();
|
||||
change = change.unwrapInline('link');
|
||||
}
|
||||
|
||||
else {
|
||||
@ -115,23 +111,20 @@ export default class Editor extends Component {
|
||||
// If nothing is entered in the URL prompt, do nothing.
|
||||
if (!url) return;
|
||||
|
||||
let transform = editorState.transform();
|
||||
|
||||
// If no text is selected, use the entered URL as text.
|
||||
if (editorState.isCollapsed) {
|
||||
transform = transform
|
||||
if (change.state.isCollapsed) {
|
||||
change = change
|
||||
.insertText(url)
|
||||
.extend(0 - url.length);
|
||||
}
|
||||
|
||||
editorState = transform
|
||||
change = change
|
||||
.wrapInline({ type: 'link', data: { url } })
|
||||
.collapseToEnd()
|
||||
.apply();
|
||||
.collapseToEnd();
|
||||
}
|
||||
|
||||
this.ref.onChange(editorState);
|
||||
this.setState({ editorState });
|
||||
this.ref.onChange(change);
|
||||
this.setState({ editorState: change.state });
|
||||
};
|
||||
|
||||
handlePluginSubmit = (plugin, shortcodeData) => {
|
||||
@ -140,11 +133,21 @@ export default class Editor extends Component {
|
||||
shortcode: plugin.id,
|
||||
shortcodeData,
|
||||
};
|
||||
const nodes = [Text.createFromString('')];
|
||||
const nodes = [Text.create('')];
|
||||
const block = { kind: 'block', type: 'shortcode', data, isVoid: true, nodes };
|
||||
const resolvedState = editorState.transform().insertBlock(block).focus().apply();
|
||||
this.ref.onChange(resolvedState);
|
||||
this.setState({ editorState: resolvedState });
|
||||
let change = editorState.change();
|
||||
const { focusBlock } = change.state;
|
||||
|
||||
if (focusBlock.text === '') {
|
||||
change = change.setNodeByKey(focusBlock.key, block);
|
||||
} else {
|
||||
change = change.insertBlock(block);
|
||||
}
|
||||
|
||||
change = change.focus();
|
||||
|
||||
this.ref.onChange(change);
|
||||
this.setState({ editorState: change.state });
|
||||
};
|
||||
|
||||
handleToggle = () => {
|
||||
@ -158,6 +161,20 @@ export default class Editor extends Component {
|
||||
return { onAction: e => handler(e, type), active: isActive(type) };
|
||||
};
|
||||
|
||||
handleDocumentChange = debounce(change => {
|
||||
const raw = change.state.document.toJSON();
|
||||
const plugins = this.state.shortcodePlugins;
|
||||
const markdown = slateToMarkdown(raw, plugins);
|
||||
this.props.onChange(markdown);
|
||||
}, 150);
|
||||
|
||||
handleChange = change => {
|
||||
if (!this.state.editorState.document.equals(change.state.document)) {
|
||||
this.handleDocumentChange(change);
|
||||
}
|
||||
this.setState({ editorState: change.state });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { onAddAsset, onRemoveAsset, getAsset } = this.props;
|
||||
|
||||
@ -194,8 +211,7 @@ export default class Editor extends Component {
|
||||
state={this.state.editorState}
|
||||
schema={this.state.schema}
|
||||
plugins={plugins}
|
||||
onChange={editorState => this.setState({ editorState })}
|
||||
onDocumentChange={this.handleDocumentChange}
|
||||
onChange={this.handleChange}
|
||||
onKeyDown={onKeyDown}
|
||||
onPaste={this.handlePaste}
|
||||
ref={ref => this.ref = ref}
|
||||
|
@ -2,11 +2,11 @@ import { Block, Text } from 'slate';
|
||||
|
||||
export default onKeyDown;
|
||||
|
||||
function onKeyDown(e, data, state) {
|
||||
function onKeyDown(e, data, change) {
|
||||
const createDefaultBlock = () => {
|
||||
return Block.create({
|
||||
type: 'paragraph',
|
||||
nodes: [Text.createFromString('')]
|
||||
nodes: [Text.create('')]
|
||||
});
|
||||
};
|
||||
if (data.key === 'enter') {
|
||||
@ -18,7 +18,7 @@ function onKeyDown(e, data, state) {
|
||||
* If the selected block is the first block in the document, create the
|
||||
* new block above it. If not, create the new block below it.
|
||||
*/
|
||||
const { document: doc, selection, anchorBlock, focusBlock } = state;
|
||||
const { document: doc, selection, anchorBlock, focusBlock } = change.state;
|
||||
const singleBlockSelected = anchorBlock === focusBlock;
|
||||
if (!singleBlockSelected || !focusBlock.isVoid) return;
|
||||
|
||||
@ -31,24 +31,12 @@ function onKeyDown(e, data, state) {
|
||||
const newBlock = createDefaultBlock();
|
||||
const newBlockIndex = focusBlockIsFirstChild ? 0 : focusBlockIndex + 1;
|
||||
|
||||
return state.transform()
|
||||
return change
|
||||
.insertNodeByKey(focusBlockParent.key, newBlockIndex, newBlock)
|
||||
.collapseToStartOf(newBlock)
|
||||
.apply();
|
||||
.collapseToStartOf(newBlock);
|
||||
}
|
||||
|
||||
if (data.isMod) {
|
||||
|
||||
if (data.key === 'y') {
|
||||
e.preventDefault();
|
||||
return state.transform().redo().focus().apply({ save: false });
|
||||
}
|
||||
|
||||
if (data.key === 'z') {
|
||||
e.preventDefault();
|
||||
return state.transform()[data.isShift ? 'redo' : 'undo']().focus().apply({ save: false });
|
||||
}
|
||||
|
||||
const marks = {
|
||||
b: 'bold',
|
||||
i: 'italic',
|
||||
@ -61,7 +49,7 @@ function onKeyDown(e, data, state) {
|
||||
|
||||
if (mark) {
|
||||
e.preventDefault();
|
||||
return state.transform().toggleMark(mark).apply();
|
||||
return change.toggleMark(mark);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -4,37 +4,32 @@ import EditList from 'slate-edit-list';
|
||||
import EditTable from 'slate-edit-table';
|
||||
|
||||
const SoftBreak = (options = {}) => ({
|
||||
onKeyDown(e, data, state) {
|
||||
onKeyDown(e, data, change) {
|
||||
if (data.key != 'enter') return;
|
||||
if (options.shift && e.shiftKey == false) return;
|
||||
|
||||
const { onlyIn, ignoreIn, closeAfter, unwrapBlocks, defaultBlock = 'paragraph' } = options;
|
||||
const { type, nodes } = state.startBlock;
|
||||
const { onlyIn, ignoreIn, defaultBlock = 'paragraph' } = options;
|
||||
const { type, nodes } = change.state.startBlock;
|
||||
if (onlyIn && !onlyIn.includes(type)) return;
|
||||
if (ignoreIn && ignoreIn.includes(type)) return;
|
||||
|
||||
const shouldClose = nodes.last().characters.takeLast(closeAfter).every(c => c.text === '\n');
|
||||
if (closeAfter && shouldClose) {
|
||||
const trimmed = state.transform().deleteBackward(closeAfter);
|
||||
const unwrapped = unwrapBlocks
|
||||
? unwrapBlocks.reduce((acc, blockType) => acc.unwrapBlock(blockType), trimmed)
|
||||
: trimmed;
|
||||
return unwrapped.insertBlock(defaultBlock).apply();
|
||||
const shouldClose = nodes.last().characters.last() === '\n';
|
||||
if (shouldClose) {
|
||||
const trimmed = change.deleteBackward(1);
|
||||
return trimmed.insertBlock(defaultBlock);
|
||||
}
|
||||
|
||||
const textNode = Text.createFromString('\n');
|
||||
const textNode = Text.create('\n');
|
||||
const breakNode = Inline.create({ type: 'break', nodes: [ textNode ] });
|
||||
return state.transform()
|
||||
return change
|
||||
.insertInline(breakNode)
|
||||
.insertText('')
|
||||
.collapseToStartOfNextText()
|
||||
.apply();
|
||||
.collapseToStartOfNextText();
|
||||
}
|
||||
});
|
||||
|
||||
const SoftBreakOpts = {
|
||||
onlyIn: ['quote', 'code'],
|
||||
closeAfter: 1
|
||||
};
|
||||
|
||||
export const SoftBreakConfigured = SoftBreak(SoftBreakOpts);
|
||||
@ -42,10 +37,11 @@ export const SoftBreakConfigured = SoftBreak(SoftBreakOpts);
|
||||
export const ParagraphSoftBreakConfigured = SoftBreak({ onlyIn: ['paragraph'], shift: true });
|
||||
|
||||
const BreakToDefaultBlock = ({ onlyIn = [], defaultBlock = 'paragraph' }) => ({
|
||||
onKeyDown(e, data, state) {
|
||||
onKeyDown(e, data, change) {
|
||||
const { state } = change;
|
||||
if (data.key != 'enter' || e.shiftKey == true || state.isExpanded) return;
|
||||
if (onlyIn.includes(state.startBlock.type)) {
|
||||
return state.transform().insertBlock(defaultBlock).apply();
|
||||
return change.insertBlock(defaultBlock);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -57,21 +53,18 @@ const BreakToDefaultBlockOpts = {
|
||||
export const BreakToDefaultBlockConfigured = BreakToDefaultBlock(BreakToDefaultBlockOpts);
|
||||
|
||||
const BackspaceCloseBlock = (options = {}) => ({
|
||||
onKeyDown(e, data, state) {
|
||||
onKeyDown(e, data, change) {
|
||||
if (data.key != 'backspace') return;
|
||||
|
||||
const { defaultBlock = 'paragraph', ignoreIn, onlyIn } = options;
|
||||
const { startBlock } = state;
|
||||
const { startBlock } = change.state;
|
||||
const { type } = startBlock;
|
||||
|
||||
if (onlyIn && !onlyIn.includes(type)) return;
|
||||
if (ignoreIn && ignoreIn.includes(type)) return;
|
||||
|
||||
const characters = startBlock.getFirstText().characters;
|
||||
const isEmpty = !characters || characters.isEmpty();
|
||||
|
||||
if (isEmpty) {
|
||||
return state.transform().insertBlock(defaultBlock).focus().apply();
|
||||
if (startBlock.text === '') {
|
||||
return change.setBlock(defaultBlock).focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -15,13 +15,13 @@ const enforceNeverEmpty = {
|
||||
const hasBlocks = !doc.getBlocks().isEmpty();
|
||||
return hasBlocks ? null : {};
|
||||
},
|
||||
normalize: transform => {
|
||||
normalize: change => {
|
||||
const block = Block.create({
|
||||
type: 'paragraph',
|
||||
nodes: [Text.createFromString('')],
|
||||
nodes: [Text.create('')],
|
||||
});
|
||||
const { key } = transform.state.document;
|
||||
return transform.insertNodeByKey(key, 0, block).focus();
|
||||
const { key } = change.state.document;
|
||||
return change.insertNodeByKey(key, 0, block).focus();
|
||||
},
|
||||
};
|
||||
|
||||
@ -35,8 +35,8 @@ const shortcodesAtRoot = {
|
||||
return node.type === 'shortcode' && doc.getParent(node.key).key !== doc.key;
|
||||
});
|
||||
},
|
||||
normalize: (transform, doc, node) => {
|
||||
return transform.unwrapNodeByKey(node.key);
|
||||
normalize: (change, doc, node) => {
|
||||
return change.unwrapNodeByKey(node.key);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -84,10 +84,8 @@ function createInline(type, props = {}, nodes) {
|
||||
*/
|
||||
function createText(value, data) {
|
||||
const node = { kind: 'text', data };
|
||||
if (isArray(value)) {
|
||||
return { ...node, ranges: value };
|
||||
}
|
||||
return {...node, text: value };
|
||||
const ranges = isArray(value) ? value : [{ text: value }];
|
||||
return { ...node, ranges };
|
||||
}
|
||||
|
||||
function processMarkNode(node, parentMarks = []) {
|
||||
|
@ -435,7 +435,9 @@ function convertNode(node, children, shortcodePlugins) {
|
||||
* value and the "lang" data property to the new MDAST node.
|
||||
*/
|
||||
case 'code': {
|
||||
const value = get(node.nodes, [0, 'text']);
|
||||
const value = flatMap(node.nodes, child => {
|
||||
return flatMap(child.ranges, 'text');
|
||||
}).join('');
|
||||
const { lang, ...data } = get(node, 'data', {});
|
||||
return u(typeMap[node.type], { lang, data }, value);
|
||||
}
|
||||
|
83
yarn.lock
83
yarn.lock
@ -3830,7 +3830,7 @@ immediate@~3.0.5:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
|
||||
immutable@^3.7.6, immutable@^3.8.1:
|
||||
immutable@^3.7.6:
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.1.tgz#200807f11ab0f72710ea485542de088075f68cd2"
|
||||
|
||||
@ -4164,6 +4164,12 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||
|
||||
is-plain-object@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
||||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
is-posix-bracket@^0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
|
||||
@ -4292,6 +4298,10 @@ isobject@^2.0.0:
|
||||
dependencies:
|
||||
isarray "1.0.0"
|
||||
|
||||
isobject@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
|
||||
isomorphic-fetch@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
||||
@ -7783,38 +7793,67 @@ slash@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||
|
||||
slate-edit-list@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/slate-edit-list/-/slate-edit-list-0.7.1.tgz#84ee960d2d5b5a20ce267ad9df894395a91b93d5"
|
||||
slate-base64-serializer@^0.1.9:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/slate-base64-serializer/-/slate-base64-serializer-0.1.10.tgz#5fb7fe6de52ef56d2619dc34f8960fe81a866bfb"
|
||||
|
||||
slate-edit-table@^0.10.1:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/slate-edit-table/-/slate-edit-table-0.10.1.tgz#4f01bf26bac2de26e8d25bfbe7116a2f643e5934"
|
||||
slate-dev-logger@^0.1.10, slate-dev-logger@^0.1.11:
|
||||
version "0.1.11"
|
||||
resolved "https://registry.yarnpkg.com/slate-dev-logger/-/slate-dev-logger-0.1.11.tgz#740fd2e23b1dda1f4629419fc914eea91272b6f0"
|
||||
|
||||
slate-edit-list@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/slate-edit-list/-/slate-edit-list-0.8.0.tgz#3f8904fc9cb308d3c614efa5586953a6de6a4608"
|
||||
|
||||
slate-edit-table@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/slate-edit-table/-/slate-edit-table-0.11.0.tgz#4ab175a02146ec1c45a4a2826eaa66b5db0d2266"
|
||||
|
||||
slate-plain-serializer@^0.1.10:
|
||||
version "0.1.11"
|
||||
resolved "https://registry.yarnpkg.com/slate-plain-serializer/-/slate-plain-serializer-0.1.11.tgz#0b70cd870a935b294d6418785084be33ae23b96e"
|
||||
dependencies:
|
||||
immutable "^3.8.1"
|
||||
slate-dev-logger "^0.1.11"
|
||||
|
||||
slate-soft-break@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/slate-soft-break/-/slate-soft-break-0.3.0.tgz#3d28dea9e0aa4783ddcea785ff5db7277214d65f"
|
||||
slate-prop-types@^0.1.9:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/slate-prop-types/-/slate-prop-types-0.1.10.tgz#a0c21d880ae72cb7f38a0d0fb025b7db2fa5d5b1"
|
||||
dependencies:
|
||||
slate-dev-logger "^0.1.11"
|
||||
|
||||
slate@^0.21.0:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/slate/-/slate-0.21.4.tgz#ae6113379cd838b7ec68ecd94834ce9741bc36f3"
|
||||
slate-react@^0.1.10:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.1.10.tgz#1d5886fb89bc9f03cb5cf15b74c3e8b9600d52e7"
|
||||
dependencies:
|
||||
debug "^2.3.2"
|
||||
get-window "^1.1.1"
|
||||
is-in-browser "^1.1.3"
|
||||
is-window "^1.0.2"
|
||||
keycode "^2.1.2"
|
||||
prop-types "^15.5.8"
|
||||
react-portal "^3.1.0"
|
||||
selection-is-backward "^1.0.0"
|
||||
slate-base64-serializer "^0.1.9"
|
||||
slate-dev-logger "^0.1.10"
|
||||
slate-plain-serializer "^0.1.10"
|
||||
slate-prop-types "^0.1.9"
|
||||
|
||||
slate-soft-break@^0.4.0:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/slate-soft-break/-/slate-soft-break-0.4.3.tgz#e3a9279a9b92ca173915467f5fbd359f739a7e96"
|
||||
|
||||
slate@^0.25.0:
|
||||
version "0.25.3"
|
||||
resolved "https://registry.yarnpkg.com/slate/-/slate-0.25.3.tgz#d232ee168135269f10fbd3534307560e8ebf38b6"
|
||||
dependencies:
|
||||
debug "^2.3.2"
|
||||
direction "^0.1.5"
|
||||
es6-map "^0.1.4"
|
||||
esrever "^0.2.0"
|
||||
get-window "^1.1.1"
|
||||
immutable "^3.8.1"
|
||||
is-empty "^1.0.0"
|
||||
is-in-browser "^1.1.3"
|
||||
is-window "^1.0.2"
|
||||
keycode "^2.1.2"
|
||||
is-plain-object "^2.0.4"
|
||||
lodash "^4.17.4"
|
||||
prop-types "^15.5.8"
|
||||
react-portal "^3.1.0"
|
||||
selection-is-backward "^1.0.0"
|
||||
slate-dev-logger "^0.1.11"
|
||||
type-of "^2.0.1"
|
||||
|
||||
slice-ansi@0.0.4:
|
||||
|
Loading…
x
Reference in New Issue
Block a user