mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-31 19:01:54 +02:00
Add controller (#2221)
* fold Stack into Editor * switch Change objects to be tied to editors, not values * introduce controller * add the "commands" concept * convert history into commands on `value.data` * add the ability to not normalize on editor creation/setting * convert schema to a mutable constructor * add editor.command method * convert plugin handlers to receive `next` * switch commands to use the onCommand middleware * add queries support, convert schema to queries * split out browser plugin * remove noop util * fixes * fixes * start fixing tests, refactor hyperscript to be more literal * fix slate-html-serializer tests * fix schema tests with hyperscript * fix text model tests with hyperscript * fix more tests * get all tests passing * fix lint * undo decorations example update * update examples * small changes to the api to make it nicer * update docs * update commands/queries plugin logic * change normalizeNode and validateNode to be middleware * fix decoration removal * rename commands tests * add useful errors to existing APIs * update changelogs * cleanup * fixes * update docs * add editor docs
This commit is contained in:
@@ -41,8 +41,9 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
// Define a new handler which prints the key that was pressed.
|
||||
onKeyDown = (event, change) => {
|
||||
onKeyDown = (event, change, next) => {
|
||||
console.log(event.key)
|
||||
return next()
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -73,9 +74,9 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
onKeyDown = (event, change, next) => {
|
||||
// Return with no changes if the keypress is not '&'
|
||||
if (event.key !== '&') return
|
||||
if (event.key !== '&') return next()
|
||||
|
||||
// Prevent the ampersand character from being inserted.
|
||||
event.preventDefault()
|
||||
|
@@ -20,8 +20,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (event.key != '`' || !event.ctrlKey) return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (event.key != '`' || !event.ctrlKey) return next()
|
||||
event.preventDefault()
|
||||
const isCode = change.value.blocks.some(block => block.type == 'code')
|
||||
|
||||
@@ -40,10 +40,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,8 +63,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (!event.ctrlKey) return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (!event.ctrlKey) return next()
|
||||
|
||||
// Decide what to do based on the key code...
|
||||
switch (event.key) {
|
||||
@@ -79,6 +81,10 @@ class App extends React.Component {
|
||||
change.setBlocks(isCode ? 'paragraph' : 'code')
|
||||
return true
|
||||
}
|
||||
// Otherwise, let other plugins handle it.
|
||||
default: {
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +99,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,8 +139,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (!event.ctrlKey) return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (!event.ctrlKey) return next()
|
||||
|
||||
switch (event.key) {
|
||||
case 'b': {
|
||||
@@ -146,6 +154,9 @@ class App extends React.Component {
|
||||
change.setBlocks(isCode ? 'paragraph' : 'code')
|
||||
return true
|
||||
}
|
||||
default: {
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,18 +173,22 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
|
||||
// Add a `renderMark` method to render marks.
|
||||
renderMark = props => {
|
||||
renderMark = (props, next) => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold':
|
||||
return <BoldMark {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,8 +20,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (event.key != '&') return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (event.key != '&') return next()
|
||||
event.preventDefault()
|
||||
change.insertText('and')
|
||||
return true
|
||||
@@ -82,8 +82,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (event.key != '&') return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (event.key != '&') return next()
|
||||
event.preventDefault()
|
||||
change.insertText('and')
|
||||
return true
|
||||
@@ -102,10 +102,12 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
// Add a `renderNode` method to render a `CodeNode` for code blocks.
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,9 +133,9 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
onKeyDown = (event, change, next) => {
|
||||
// Return with no changes if it's not the "`" key with ctrl pressed.
|
||||
if (event.key != '`' || !event.ctrlKey) return
|
||||
if (event.key != '`' || !event.ctrlKey) return next()
|
||||
|
||||
// Prevent the "`" from being inserted by default.
|
||||
event.preventDefault()
|
||||
@@ -154,10 +156,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,8 +191,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (event.key != '`' || !event.ctrlKey) return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (event.key != '`' || !event.ctrlKey) return next()
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
@@ -211,10 +215,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -263,7 +263,7 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = props => {
|
||||
renderNode = (props, next) => {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return (
|
||||
@@ -279,11 +279,13 @@ class App extends React.Component {
|
||||
)
|
||||
case 'quote':
|
||||
return <blockquote {...props.attributes}>{props.children}</blockquote>
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
|
||||
// Add a `renderMark` method to render marks.
|
||||
renderMark = props => {
|
||||
renderMark = (props, next) => {
|
||||
const { mark, attributes } = props
|
||||
switch (mark.type) {
|
||||
case 'bold':
|
||||
@@ -292,6 +294,8 @@ class App extends React.Component {
|
||||
return <em {...attributes}>{props.children}</em>
|
||||
case 'underline':
|
||||
return <u {...attributes}>{props.children}</u>
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,8 +22,8 @@ class App extends React.Component {
|
||||
this.setState({ value })
|
||||
}
|
||||
|
||||
onKeyDown = (event, change) => {
|
||||
if (event.key != 'b' || !event.ctrlKey) return
|
||||
onKeyDown = (event, change, next) => {
|
||||
if (event.key != 'b' || !event.ctrlKey) return next()
|
||||
event.preventDefault()
|
||||
change.toggleMark('bold')
|
||||
return true
|
||||
@@ -40,10 +40,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderMark = props => {
|
||||
renderMark = (props, next) => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold':
|
||||
return <strong {...props.attributes}>{props.children}</strong>
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,9 +72,9 @@ function MarkHotkey(options) {
|
||||
|
||||
// Return our "plugin" object, containing the `onKeyDown` handler.
|
||||
return {
|
||||
onKeyDown(event, change) {
|
||||
// Check that the key pressed matches our `key` option.
|
||||
if (!event.ctrlKey || event.key != key) return
|
||||
onKeyDown(event, change, next) {
|
||||
// If it doesn't match our `key`, let other plugins handle it.
|
||||
if (!event.ctrlKey || event.key != key) return next()
|
||||
|
||||
// Prevent the default characters from being inserted.
|
||||
event.preventDefault()
|
||||
@@ -120,10 +122,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderMark = props => {
|
||||
renderMark = (props, next) => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold':
|
||||
return <strong>{props.children}</strong>
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,7 +167,7 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderMark = props => {
|
||||
renderMark = (props, next) => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold':
|
||||
return <strong>{props.children}</strong>
|
||||
@@ -176,6 +180,8 @@ class App extends React.Component {
|
||||
return <del>{props.children}</del>
|
||||
case 'underline':
|
||||
return <u>{props.children}</u>
|
||||
default:
|
||||
return next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user