├── README.md └── admin └── src └── components ├── EditorJs └── index.js └── WysiwygWithErrors └── index.js /README.md: -------------------------------------------------------------------------------- 1 | # strapi-editorjs 2 | 3 | This is a prototype to get strapi to replace the Wysiwyg editor with EditorJs. Not sure 4 | if I'm gonna use strapi, but I'm putting the code for this out in the world anyway. Have fun! 5 | 6 | Note: Opening existing posts won't work, because EditorJs can't handle the markdown language 7 | normally used by strapi. 8 | 9 | ## Installation 10 | 11 | ### Install dependencies 12 | 13 | To install this, add the following dependencies to your strapi project: 14 | 15 | ```json 16 | { 17 | "dependencies": { 18 | "@editorjs/checklist": "^1.1.0", 19 | "@editorjs/delimiter": "^1.1.0", 20 | "@editorjs/editorjs": "^2.16.1", 21 | "@editorjs/embed": "^2.2.1", 22 | "@editorjs/header": "^2.4.0", 23 | "@editorjs/image": "^2.3.3", 24 | "@editorjs/link": "^2.1.3", 25 | "@editorjs/list": "^1.4.0", 26 | "@editorjs/marker": "^1.2.2", 27 | "@editorjs/paragraph": "^2.6.1", 28 | "@editorjs/quote": "^2.3.0", 29 | "@editorjs/table": "^1.2.1", 30 | "@natterstefan/react-editor-js": "^0.3.1" 31 | } 32 | } 33 | ``` 34 | 35 | ### Clone this repo 36 | 37 | Clone this repo into your extensions folder. 38 | 39 | ### Build? 40 | 41 | Then build it I guess? Not sure on that part yet. Good luck. 42 | 43 | (I used `strapi develop --watch-admin` up until now) 44 | -------------------------------------------------------------------------------- /admin/src/components/EditorJs/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import styled from 'styled-components'; 4 | import ImageTool from '@editorjs/image'; 5 | import { auth, request } from 'strapi-helper-plugin'; 6 | import EditorJs from '@natterstefan/react-editor-js'; 7 | import Header from '@editorjs/header'; 8 | import Quote from '@editorjs/quote'; 9 | import Embed from '@editorjs/embed'; 10 | import Marker from '@editorjs/marker'; 11 | import Delimiter from '@editorjs/delimiter'; 12 | import Table from '@editorjs/table'; 13 | import List from '@editorjs/list'; 14 | import Checklist from '@editorjs/checklist'; 15 | 16 | const Wrapper = styled.div` 17 | .editorjs__main { 18 | min-height: 200px; 19 | > div { 20 | min-height: 200px; 21 | } 22 | } 23 | `; 24 | 25 | const Editor = ({ onChange, name, value }) => { 26 | var editor = null; 27 | 28 | const onSave = async () => { 29 | try { 30 | const outputData = await editor.save(); 31 | const dataString = JSON.stringify(outputData); 32 | onChange({ target: { name, value: dataString } }); 33 | console.log('Saving data: ' + dataString); 34 | } catch (e) { 35 | console.log('Saving failed: ', e); 36 | } 37 | }; 38 | 39 | return ( 40 | 41 | } 92 | */ 93 | uploadByFile(file) { 94 | // your own uploading logic here 95 | const formData = new FormData(); 96 | formData.append('files', file); 97 | const headers = {}; 98 | 99 | return request('/upload', { method: 'POST', headers, body: formData }, false, false).then(resp => { 100 | return { 101 | success: 1, 102 | file: { 103 | url: `${strapi.backendURL}${resp[0].url}`, 104 | }, 105 | }; 106 | }); 107 | }, 108 | }, 109 | }, 110 | }, 111 | }} 112 | editorInstance={editorInstance => { 113 | editor = editorInstance; 114 | }} 115 | /> 116 | 117 | ); 118 | }; 119 | 120 | Editor.propTypes = { 121 | onChange: PropTypes.func.isRequired, 122 | name: PropTypes.string.isRequired, 123 | value: PropTypes.string.isRequired, 124 | }; 125 | 126 | export default Editor; 127 | -------------------------------------------------------------------------------- /admin/src/components/WysiwygWithErrors/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { isEmpty } from 'lodash'; 4 | import { Label, InputDescription, InputErrors } from 'strapi-helper-plugin'; 5 | import EditorJs from '../EditorJs'; 6 | 7 | const WysiwygWithErrors = ({ 8 | inputDescription, 9 | errors, 10 | label, 11 | name, 12 | noErrorsDescription, 13 | onChange, 14 | value, 15 | }) => { 16 | let spacer = !isEmpty(inputDescription) ? ( 17 |
18 | ) : ( 19 |
20 | ); 21 | 22 | if (!noErrorsDescription && !isEmpty(errors)) { 23 | spacer =
; 24 | } 25 | 26 | return ( 27 |
35 |
51 | ); 52 | }; 53 | 54 | WysiwygWithErrors.defaultProps = { 55 | errors: [], 56 | label: '', 57 | noErrorsDescription: false, 58 | }; 59 | 60 | WysiwygWithErrors.propTypes = { 61 | errors: PropTypes.array, 62 | inputDescription: PropTypes.oneOfType([ 63 | PropTypes.string, 64 | PropTypes.func, 65 | PropTypes.shape({ 66 | id: PropTypes.string, 67 | params: PropTypes.object, 68 | }), 69 | ]), 70 | label: PropTypes.oneOfType([ 71 | PropTypes.string, 72 | PropTypes.func, 73 | PropTypes.shape({ 74 | id: PropTypes.string, 75 | params: PropTypes.object, 76 | }), 77 | ]), 78 | name: PropTypes.string.isRequired, 79 | noErrorsDescription: PropTypes.bool, 80 | onChange: PropTypes.func.isRequired, 81 | value: PropTypes.string.isRequired, 82 | }; 83 | 84 | export default WysiwygWithErrors; 85 | --------------------------------------------------------------------------------