|
2 | 2 |
|
3 | 3 | A React component for [ProseMirror](http://prosemirror.net/). |
4 | 4 |
|
5 | | -* [Documentation](https://github.com/hubgit/react-prosemirror/blob/master/react-prosemirror/README.md) |
6 | | -* [Demo](https://react-prosemirror-example.now.sh) |
7 | | -* [Example](https://github.com/hubgit/react-prosemirror/tree/master/react-prosemirror-example) |
8 | | - |
9 | 5 | ## Packages |
10 | 6 |
|
11 | | -* [prosemirror-footnotes](https://github.com/hubgit/react-prosemirror/blob/master/prosemirror-footnotes) — footnotes plugin for ProseMirror |
12 | | -* [prosemirror-placeholder](https://github.com/hubgit/react-prosemirror/blob/master/prosemirror-placeholder) — placeholder plugin for ProseMirror |
13 | | -* [react-prosemirror](https://github.com/hubgit/react-prosemirror/blob/master/react-prosemirror) — main package |
14 | | -* [react-prosemirror-config-default](https://github.com/hubgit/react-prosemirror/blob/master/react-prosemirror-config-default) — ProseMirror configuration adapted from prosemirror-schema-basic and prosemirror-menu |
15 | | -* [react-prosemirror-example](https://github.com/hubgit/react-prosemirror/blob/master/react-prosemirror) — an example implementation |
| 7 | +* [@aeaton/react-prosemirror](packages/react) - React components |
| 8 | +* [@aeaton/prosemirror-commands](packages/commands) - ProseMirror commands |
| 9 | +* [@aeaton/prosemirror-schema](packages/schema) - ProseMirror schema definitions (marks and nodes) |
| 10 | +* [@aeaton/prosemirror-transformers](packages/transformers) - conversion to/from ProseMirror |
| 11 | +* [@aeaton/react-prosemirror-config-default](packages/config-default) - an example configuration ready for use |
| 12 | +* [@aeaton/prosemirror-placeholder](packages/placeholder) - ProseMirror placeholder plugin (decoration and style) |
| 13 | +* [@aeaton/prosemirror-footnotes](packages/footnotes) - ProseMirror footnotes plugin (schema and node view) |
| 14 | + |
| 15 | +## Demo |
| 16 | + |
| 17 | +* [demo](demo) - a fully-configured editor |
| 18 | + |
| 19 | +## Usage |
| 20 | + |
| 21 | +### Quickstart: HTML Editor |
| 22 | + |
| 23 | +```js |
| 24 | +import { HtmlEditor } from '@aeaton/react-prosemirror' |
| 25 | +import { plugins, schema, toolbar } from '@aeaton/react-prosemirror-config-default' |
| 26 | + |
| 27 | +const initialValue = '<p></p>' |
| 28 | + |
| 29 | +export const RichTextEditor = () => { |
| 30 | + const [value, setValue] = useState(initialValue) |
| 31 | + |
| 32 | + return ( |
| 33 | + <HtmlEditor |
| 34 | + schema={schema} |
| 35 | + plugins={plugins} |
| 36 | + value={initialValue} |
| 37 | + handleChange={setValue} |
| 38 | + debounce={250} |
| 39 | + > |
| 40 | + <Toolbar toolbar={toolbar} /> |
| 41 | + <Editor autoFocus /> |
| 42 | + </HtmlEditor> |
| 43 | + ) |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +### Custom Editor |
| 48 | + |
| 49 | +Create a schema: |
| 50 | + |
| 51 | +```js |
| 52 | +import { Schema } from 'prosemirror-model' |
| 53 | + |
| 54 | +const schema = new Schema({ |
| 55 | + nodes: { |
| 56 | + // a text node |
| 57 | + text: {}, |
| 58 | + // a top-level doc node, which can contain at least one paragraph |
| 59 | + doc: { |
| 60 | + content: 'paragraph+' |
| 61 | + }, |
| 62 | + // a paragraph node, which can contain some text nodes, represented in HTML as `<p>` |
| 63 | + paragraph: { |
| 64 | + content: 'text*', |
| 65 | + parseDOM: [{ tag: 'p' }], |
| 66 | + toDOM: () => ['p', 0], |
| 67 | + }, |
| 68 | + }, |
| 69 | + marks: { |
| 70 | + // a strong mark, represented in HTML as `<strong>` |
| 71 | + strong: { |
| 72 | + parseDOM: [{ tag: 'strong' }], |
| 73 | + toDOM: () => ['strong', 0], |
| 74 | + }, |
| 75 | + // an emphasis mark, represented in HTML as `<em>` |
| 76 | + emphasis: { |
| 77 | + parseDOM: [{ tag: 'em' }], |
| 78 | + toDOM: () => ['em', 0], |
| 79 | + } |
| 80 | + } |
| 81 | +}) |
| 82 | +``` |
| 83 | + |
| 84 | +Create some commands: |
| 85 | + |
| 86 | +```js |
| 87 | +const toggleMarkStrong = toggleMark(schema.marks.strong) |
| 88 | +const toggleMarkEmphasis = toggleMark(schema.marks.emphasis) |
| 89 | +``` |
| 90 | + |
| 91 | + |
| 92 | +Create plugins for handling history and key presses: |
| 93 | + |
| 94 | +```js |
| 95 | +import { baseKeymap } from 'prosemirror-commands' |
| 96 | +import { keymap } from 'prosemirror-keymap' |
| 97 | +import { history, undo, redo } from 'prosemirror-history' |
| 98 | + |
| 99 | +const plugins = [ |
| 100 | + history(), |
| 101 | + keymap({ |
| 102 | + 'Mod-z': undo, |
| 103 | + 'Shift-Mod-z': redo, |
| 104 | + 'Meta-b': toggleMarkStrong, |
| 105 | + 'Meta-i': toggleMarkEmphasis, |
| 106 | + }), |
| 107 | + keymap(baseKeymap), |
| 108 | +] |
| 109 | +``` |
| 110 | + |
| 111 | +Create a toolbar definition: |
| 112 | + |
| 113 | +```js |
| 114 | +const toolbar = [ |
| 115 | + { |
| 116 | + id: 'marks', |
| 117 | + items: [ |
| 118 | + { |
| 119 | + id: 'toggle-strong', |
| 120 | + content: icons.strong, |
| 121 | + action: toggleMarkStrong, |
| 122 | + enable: toggleMarkStrong, |
| 123 | + active: isMarkActive(schema.marks.strong), |
| 124 | + }, |
| 125 | + { |
| 126 | + id: 'toggle-emphasis', |
| 127 | + title: 'Toggle emphasis', |
| 128 | + content: icons.emphasis, |
| 129 | + action: toggleMarkEmphasis, |
| 130 | + enable: toggleMarkEmphasis, |
| 131 | + active: isMarkActive(schema.marks.emphasis), |
| 132 | + }, |
| 133 | + ] |
| 134 | + } |
| 135 | +] |
| 136 | +``` |
| 137 | + |
| 138 | +Create a doc by parsing some HTML: |
| 139 | + |
| 140 | +```js |
| 141 | +import { createHTMLTransformer } from '@aeaton/prosemirror-transformers' |
| 142 | + |
| 143 | +const transformer = createHTMLTransformer(schema) |
| 144 | + |
| 145 | +const doc = transformer.parse('<p>Hello World!</p>') |
| 146 | +``` |
| 147 | + |
| 148 | +Connect everything together to make your editor: |
| 149 | + |
| 150 | +```jsx |
| 151 | +const CustomEditor = () => { |
| 152 | + return ( |
| 153 | + <EditorProvider doc={doc} plugins={plugins}> |
| 154 | + <Toolbar toolbar={toolbar} /> |
| 155 | + <Editor /> |
| 156 | + </EditorProvider> |
| 157 | + ) |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +The editor state is available in descendants of `EditorProvider` via a `useEditorState` hook: |
16 | 162 |
|
17 | | -## Authors and license |
| 163 | +```js |
| 164 | +import { useEditorState } from '@aeaton/react-prosemirror' |
18 | 165 |
|
19 | | -[Alf Eaton](https://github.com/hubgit) and [contributors](https://github.com/hubgit/react-prosemirror/graphs/contributors). |
| 166 | +const ExampleComponent = () => { |
| 167 | + const state = useEditorState() |
| 168 | + |
| 169 | + // do something with the current state |
| 170 | +} |
| 171 | +``` |
20 | 172 |
|
21 | | -MIT License. |
|
0 commit comments