diff --git a/docs/configs.md b/docs/configs.md index db636c3e1..6eb8cd2a7 100644 --- a/docs/configs.md +++ b/docs/configs.md @@ -35,3 +35,17 @@ Valid values for `homepage`: `pages` (default), `posts`, ``, jekyll_admin: homepage: "posts" ``` + +#### `editors` and `default_editor` + +Specify the list of editors you want to have, and the default one. + +```yaml +jekyll_admin: + editors: [SimpleMDE, TinyMDE, TextArea, TUI_WW, TUI_SS, TUI_Tab] + default_editor: TinyMDE +``` + + + + diff --git a/package-lock.json b/package-lock.json index 1ecaef352..ae723327e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "jekyll-admin", - "version": "0.11.0", + "version": "0.11.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1590,6 +1590,21 @@ "loader-utils": "^1.2.3" } }, + "@toast-ui/editor": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-3.2.1.tgz", + "integrity": "sha512-05nKfqK2n/6Mq8WpO1E7OnOjlhiFfxr1G2i/DpG/pFjKlY3E7uOtSAyuz7rybKWHgUzXRzRGv7MqDL6lXfqnWg==", + "requires": { + "dompurify": "^2.3.3", + "prosemirror-commands": "^1.1.9", + "prosemirror-history": "^1.1.3", + "prosemirror-inputrules": "^1.1.3", + "prosemirror-keymap": "^1.1.4", + "prosemirror-model": "^1.14.1", + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.18.7" + } + }, "@types/babel__core": { "version": "7.1.12", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz", @@ -5281,6 +5296,11 @@ "domelementtype": "1" } }, + "dompurify": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz", + "integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==" + }, "domutils": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", @@ -11982,6 +12002,11 @@ } } }, + "orderedmap": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.0.tgz", + "integrity": "sha512-/pIFexOm6S70EPdznemIz3BQZoJ4VTFrhqzu0ACBqBgeLsLxq8e6Jim63ImIfwW/zAD1AlXpRMlOv3aghmo4dA==" + }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -13637,6 +13662,80 @@ "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", "dev": true }, + "prosemirror-commands": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.3.1.tgz", + "integrity": "sha512-XTporPgoECkOQACVw0JTe3RZGi+fls3/byqt+tXwGTkD7qLuB4KdVrJamDMJf4kfKga3uB8hZ+kUUyZ5oWpnfg==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-history": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.0.tgz", + "integrity": "sha512-qo/9Wn4B/Bq89/YD+eNWFbAytu6dmIM85EhID+fz9Jcl9+DfGEo8TTSrRhP15+fFEoaPqpHSxlvSzSEbmlxlUA==", + "requires": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "rope-sequence": "^1.3.0" + } + }, + "prosemirror-inputrules": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.2.0.tgz", + "integrity": "sha512-eAW/M/NTSSzpCOxfR8Abw6OagdG0MiDAiWHQMQveIsZtoKVYzm0AflSPq/ymqJd56/Su1YPbwy9lM13wgHOFmQ==", + "requires": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-keymap": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.0.tgz", + "integrity": "sha512-TdSfu+YyLDd54ufN/ZeD1VtBRYpgZnTPnnbY+4R08DDgs84KrIPEPbJL8t1Lm2dkljFx6xeBE26YWH3aIzkPKg==", + "requires": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "prosemirror-model": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.18.1.tgz", + "integrity": "sha512-IxSVBKAEMjD7s3n8cgtwMlxAXZrC7Mlag7zYsAKDndAqnDScvSmp/UdnRTV/B33lTCVU3CCm7dyAn/rVVD0mcw==", + "requires": { + "orderedmap": "^2.0.0" + } + }, + "prosemirror-state": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.2.tgz", + "integrity": "sha512-puuzLD2mz/oTdfgd8msFbe0A42j5eNudKAAPDB0+QJRw8cO1ygjLmhLrg9RvDpf87Dkd6D4t93qdef00KKNacQ==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "prosemirror-transform": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.7.0.tgz", + "integrity": "sha512-O4T697Cqilw06Zvc3Wm+e237R6eZtJL/xGMliCi+Uo8VL6qHk6afz1qq0zNjT3eZMuYwnP8ZS0+YxX/tfcE9TQ==", + "requires": { + "prosemirror-model": "^1.0.0" + } + }, + "prosemirror-view": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.29.0.tgz", + "integrity": "sha512-bifVd5aD9uCNtpLL1AyhquG/cVbNZSv+ALBxTEGYv51a6OHDhq+aOuzqq4MermNdeBdT+5uyURXCALgzk0EN5g==", + "requires": { + "prosemirror-model": "^1.16.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -15097,6 +15196,11 @@ "inherits": "^2.0.1" } }, + "rope-sequence": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.3.tgz", + "integrity": "sha512-85aZYCxweiD5J8yTEbw+E6A27zSnLPNDL0WfPdw3YYodq7WjnTKo0q4dtyQ2gz23iPT8Q9CUyJtAaUNcTxRf5Q==" + }, "rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", @@ -16810,6 +16914,21 @@ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", "dev": true }, + "tiny-markdown-editor": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/tiny-markdown-editor/-/tiny-markdown-editor-0.1.5.tgz", + "integrity": "sha512-Vws5CYSI0Z2P6x+vSig22P5fDCX/bvteDtNmzX0TyNlGbw11jO42jNAgAhp4aCjO1keSlL+T7KkG4BtbnKmZ5w==", + "requires": { + "core-js": "^3.6.5" + }, + "dependencies": { + "core-js": { + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz", + "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==" + } + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -17342,6 +17461,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==" + }, "w3c-xmlserializer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", diff --git a/package.json b/package.json index 3505602a8..bc8bfbf10 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "author": "Mert Kahyaoğlu", "license": "MIT", "dependencies": { + "@toast-ui/editor": "^3.2.1", "brace": "0.9.1", "classnames": "2.2.6", "highlight.js": "^9.17.1", @@ -54,6 +55,7 @@ "rimraf": "^3.0.2", "simplemde": "1.11.2", "sortablejs": "1.8.4", + "tiny-markdown-editor": "^0.1.5", "underscore": "1.9.1" }, "devDependencies": { diff --git a/spec/fixtures/site/_config.yml b/spec/fixtures/site/_config.yml index 17aa0e5f6..15b5f51ad 100644 --- a/spec/fixtures/site/_config.yml +++ b/spec/fixtures/site/_config.yml @@ -99,3 +99,5 @@ collections: jekyll_admin: homepage: "posts" +# editors: [] + default_editor: TinyMDE diff --git a/spec/fixtures/site/_drafts/test.md b/spec/fixtures/site/_drafts/test.md new file mode 100644 index 000000000..ae0e5d973 --- /dev/null +++ b/spec/fixtures/site/_drafts/test.md @@ -0,0 +1,7 @@ +--- +tags: [] +categories: [] +title: test +--- + +
TestData
\\\\\\\\\\\\\\\\\\\\\\\\\~\\\\\\\\\\\\\\\\\\\\\\\\\~\\\\\\\\\\\\\\\\\\\\\\\\\~\\\\\\\\\\\\\\\\\\\\\\\\\~ \\\\\\\\\\\\\\\\{\\\\\\\\\\\\\\\\{ ' test' \\\\\\\\\\\\\\\\|relative\\\\\\\\\\\\\\\\_url \\\\\\\\\\\\\\\\}\\\\\\\\\\\\\\\\} Test\\\\\\[: style="color: red"\\\\\\} diff --git a/src/components/CreateMarkdownPage.js b/src/components/CreateMarkdownPage.js index 34b6d507c..bfeb3c775 100644 --- a/src/components/CreateMarkdownPage.js +++ b/src/components/CreateMarkdownPage.js @@ -32,6 +32,7 @@ export default function CreateMarkdownPage({
this.refs.filepicker.refs.trigger.click(), + className: 'fa fa-paperclip', + title: 'Insert Static File', + }, + '|', + 'preview', + 'side-by-side', + 'fullscreen', + '|', + ]; + if (onSave) { + toolbarIcons.push({ + name: 'save', + action: onSave, + className: 'fa fa-floppy-o', + title: 'Save', + }); + } + opts['toolbar'] = toolbarIcons; + const editor = new SimpleMDE(opts); + if (editor.codemirror) { + editor.codemirror.on('change', () => { + onChange(editor.value()); + }); + } + this.editor = editor; + } + + destroy() { + for (let i in classNames) { + let elementToRemove = this.refs.container.querySelector( + '.' + classNames[i] + ); + elementToRemove && elementToRemove.remove(); + } + } + + // Adapted from an internal helper function within SimpleMDE package. + _replaceSelectedText = (cm, headNTail, url) => { + const startPoint = cm.getCursor('start'); + const endPoint = cm.getCursor('end'); + const text = cm.getSelection(); + + let [head, tail] = headNTail; + if (url) { + tail = tail.replace('#url#', url); + } + + cm.replaceSelection(`${head}${text}${tail}`); + startPoint.ch += head.length; + + if (startPoint !== endPoint) { + endPoint.ch += head.length; + } + + cm.setSelection(startPoint, endPoint); + cm.focus(); + }; + + handleFilePick = path => { + const { codemirror, options } = this.editor; + const { image, link } = options.insertTexts; + const url = `{{ '${path}' | relative_url }}`; + const ext = getExtensionFromPath(path); + + const type = /png|jpg|gif|jpeg|svg|ico/i.test(ext) ? image : link; + this._replaceSelectedText(codemirror, type, url); + }; + + render() { + return ( +
+
+ +
+
+