Name: pubpub-editor
Owner: PubPub
Description: A stand alone, extensible WSIWYG editor based on ProseMirror
Created: 2017-09-18 16:30:02.0
Updated: 2017-12-21 23:28:14.0
Pushed: 2018-01-16 23:31:30.0
Homepage: https://pubpub.github.io/pubpub-editor/
Size: 4303
Language: JavaScript
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
A stand alone, extensible WSIWYG editor based on ProseMirror.
install @pubpub/editor
rt { Editor } from '@pubpub/editor';
t component = (props)=> {
return (
<Editor />
);
The first step is to create a stories/_config.js
file. There is a stories/_sampleConfig.js
file that can be used as a template. The stories/_config.js
file is necessary to store access keys for external services used by the Editor. Currently, the only external dependency is an Amazon S3 bucket which is used to store uploading files. The stories/_config.js
file is not and should not be synced into your Github repository (it is listed in the .gitignore file) because the sensitive credentials it contains should never be shared publicly.
After that, the following commands will get you running!
install
start
The PubPub Editor uses a system of Addons to extend functionality of the editor beyond basic text. Addons enable everything from interactive menus, to custom document elements, to custom editor behavior.
Addons are imported and passed as children to the main Editor component.
rt { Editor } from '@pubpub/editor';
rt FormattingMenu from '@pubpub/editor/addons/FormattingMenu';
rt InsertMenu from '@pubpub/editor/addons/InsertMenu';
rt Image from '@pubpub/editor/addons/Image';
rt Latex from '@pubpub/editor/addons/Latex';
t component = (props)=> {
return (
<Editor>
<FormattingMenu />
<InsertMenu />
<Latex renderFunction={renderLatex} />
<Image handleFileUpload={uploadFunction} />
</Editor>
);
A list of available addons can be found in the documentation;
New addons for the PubPub editor can be written and submitted as pull-requests to the main repo, or created within your local app for personal use.
Addons are written simply as React components. All addons are passed the following props, in addition to their original props:
view: object, // ProseMirror view object
editorState: object, // Prosemirror editorState object
transaction: object, // Most recent ProseMirror transaction
containerId: string, // unique ID of the Editor container
pluginKey: object, // Prosemirror PluginKey object for this Addon
Addons can take advantage of ProseMirror's Plugin System by including a plugin name: static PluginName = 'string';
and getPlugins function: static getPlugins() { }
as static variables on the addon component. For example:
rt React, { Component } from 'react';
rt { Plugin } from 'prosemirror-state';
s NewAddon extends Component {
static pluginName = 'newAddonPlugin';
static getPlugins({ pluginKey }) {
return [new Plugin({
key: pluginKey,
view: function() { }
})];
}
render() {
return <div>Hello</div>
}
The getPlugins
function is passed the pluginKey (which can be used to access the plugin - see ProseMirror docs) in addition to any original props passed to the addon component when instantiated.
Addons can take advantage of ProseMirror's NodeView interface to create custom editable elements inside the document. Addons are able to add a schema element to the ProseMirror schema that will render as a React component of your design.
To do so, specify a static schema() {}
function in your addon component that returns a ProseMirror schema element. This custom schema element must have two additional functions to enable React rendering: toEditable
and toStatic
. These functions should return the React component that should be rendered inside the document in editing and read-only mode, respectively. For example:
rt React, { Component } from 'react';
rt { Plugin } from 'prosemirror-state';
s NewAddon extends Component {
static schema(props) {
return {
nodes: {
mySchemaItem: {
atom: true,
group: 'inline',
attrs: {
value: { default: '' },
count: { default: 0 },
},
inline: true,
draggable: false,
selectable: true,
insertMenu: {
label: 'Insert MySchemaItem',
icon: 'pt-icon-asterisk',
onInsert: (view) => {
const newNode = view.state.schema.nodes.mySchemaItem.create();
view.dispatch(view.state.tr.replaceSelectionWith(newNode));
},
},
toEditable(node, view, decorations, isSelected, helperFunctions) {
return (
<EditableComponent
value={node.attrs.value}
count={node.attrs.count}
isSelected={isSelected}
view={view}
{...helperFunctions}
/>
);
},
toStatic(node) {
return (
<StaticComponent
value={node.attrs.value}
count={node.attrs.count}
/>
);
},
},
}
}
}
render() {
return <div>Hello</div>
}
The schema()
functions is passed the original props given to the instantiated addon component. Review the documentation for ProseMirror Schema Nodes and ProseMirror Schema Marks for the full list of default configuration parameters.
Note, that because the schema is interpretted and created at the creation of the Editor component, updating the props passed to the addon component will not update the props passed to the toEditable and toStatic components. The schema() function is called only once, and therefore lives outside the normal React lifecycle.
If using the InsertMenu
addon, an insertMenu object can be defined in the schema object to populate the insert menu with the new addon.
The toEditable
and toStatic
functions are passed the following parameters:
node: object, // the ProseMirror node of this instance of the addon
view: object, // the curent ProseMirror view
decorations: object, // the current ProseMirror decorations
isSelected: boolean, // whether the node is currently selected or not
helperFunctions: object, // an object with the following functions that can be helpful when interacting with ProseMirror: updateAttrs, changeNode, updateContent, getPos