diff --git a/docs/guides/adding-custom-formatting.md b/docs/guides/adding-custom-formatting.md
deleted file mode 100644
index 1a205087b..000000000
--- a/docs/guides/adding-custom-formatting.md
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
Previous:
Adding Event Handlers
-
-
-### Adding Custom Formatting
-
-In the last guide we learned how to use Slate's event handlers to change its content, but we didn't do anything really that useful with it.
-
-In this guide, we'll show you how to add custom formatting options, like **bold**, _italic_, `code` or ~~strikethrough~~.
-
-So we start with our app from earlier, but we'll get rid of that useless `onKeyDown` handler logic, and we'll replace it with logic that will add a **bold** format to the currently selected text:
-
-```js
-class App extends React.Component {
-
- constructor(props) {
- super(props)
- this.state = {
- state: initialState
- }
- }
-
- render() {
- return (
- this.onChange(state)}
- onKeyDown={e, state => this.onKeyDown(e, state)}
- />
- )
- }
-
- onChange(state) {
- this.setState({ state })
- }
-
- onKeyDown(event, state) {
- // Return with no changes if it's not the "B" key with cmd/ctrl pressed.
- if (event.which != 66 || !event.metaKey) return
-
- // Otherwise, transform the state by adding a `bold` mark to the selection.
- const newState = state
- .transform()
- .mark('bold')
- .apply()
-
- // Return the new state, which will cause the editor to update it.
- return newState
- }
-
-}
-```
-
-Now if you read through `onKeyDown`, it should be fairly clear.
-
-But! If you happen to now try selecting text and hitting **⌘-B**, you'll get an error in your console. That's because we haven't told Slate how to render a "bold" mark.
-
-For every mark type you want to add to your schema, you need to give Slate a "renderer" for that mark, which is just an object of styles that will be passed to React's `style=` property.
-
-So let's define our `bold` mark:
-
-
-```js
-// Define a set of styles that make text bold.
-const BOLD_MARK = {
- fontWeight: 'bold'
-}
-```
-
-Pretty simple, right?
-
-And now, let's tell Slate about that mark. To do that, we'll need to pass in a `renderMark` function to the `Editor`, which it will call with any mark it finds. And when it calls it with a bold mark, we'll return our `BOLD_MARK` styles. Like so:
-
-```js
-const BOLD_MARK = {
- fontWeight: 'bold'
-}
-
-class App extends React.Component {
-
- constructor(props) {
- super(props)
- this.state = {
- state: initialState
- }
- }
-
- render() {
- return (
- this.onChange(state)}
- onKeyDown={e, state => this.onKeyDown(e, state)}
- renderMark={mark => this.renderMark(mark)}
- />
- )
- }
-
- // Define a mark rendering function that knows about "bold" marks.
- renderMark(mark) {
- if (mark.type == 'bold') return BOLD_MARK
- }
-
- onChange(state) {
- this.setState({ state })
- }
-
- onKeyDown(event, state) {
- if (event.which != 66 || !event.metaKey) return
-
- const newState = state
- .transform()
- .mark('bold')
- .apply()
-
- return newState
- }
-
-}
-```
-
-Now, if you try selecting a piece of text and hitting **⌘-B** you should see it turn bold! Magic!
-
-
-
-Next:
Adding Custom Block Types
-
diff --git a/docs/guides/adding-event-handlers.md b/docs/guides/adding-event-handlers.md
index 6b3235eae..82b084e1a 100644
--- a/docs/guides/adding-event-handlers.md
+++ b/docs/guides/adding-event-handlers.md
@@ -27,11 +27,16 @@ class App extends React.Component {
return (
this.renderNode(node)}
onChange={state => this.onChange(state)}
/>
)
}
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
onChange(state) {
this.setState({ state })
}
@@ -55,12 +60,17 @@ class App extends React.Component {
return (
this.renderNode(node)}
onChange={state => this.onChange(state)}
- onKeyDown={e, state => this.onKeyDown(e, state)}
+ onKeyDown={(e, state) => this.onKeyDown(e, state)}
/>
)
}
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
onChange(state) {
this.setState({ state })
}
@@ -93,12 +103,17 @@ class App extends React.Component {
return (
this.renderNode(node)}
onChange={state => this.onChange(state)}
- onKeyDown={e, state => this.onKeyDown(e, state)}
+ onKeyDown={(e, state) => this.onKeyDown(e, state)}
/>
)
}
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
onChange(state) {
this.setState({ state })
}
@@ -125,5 +140,5 @@ With that added, try typing `&`, and you should see it automatically become `and
That gives you a sense for what you can do with Slate's event handlers. Each one will be called with the `event` object, and the current `state` of the editor.
-Next:
Adding Custom Formatting
+Next:
Adding Custom Block Nodes
diff --git a/docs/guides/applying-custom-formatting.md b/docs/guides/applying-custom-formatting.md
new file mode 100644
index 000000000..7c1df477f
--- /dev/null
+++ b/docs/guides/applying-custom-formatting.md
@@ -0,0 +1,276 @@
+
+
+Previous:
Defining Custom Block Nodes
+
+
+### Applying Custom Formatting
+
+In the previous guide we learned how to create custom block types that render chunks of text inside different containers. But Slate allows for more than just "blocks".
+
+In this guide, we'll show you how to add custom formatting options, like **bold**, _italic_, `code` or ~~strikethrough~~.
+
+So we start with our app from earlier:
+
+```js
+const CodeNode = (props) => {
+ return {props.children}
+}
+
+const ParagraphNode = (props) => {
+ return {props.children}
+}
+
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={e, state => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ renderNode(node) {
+ switch (node.type) {
+ case 'code': return CodeNode
+ case 'paragraph': return ParagraphNode
+ }
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (event.which != 192 || !event.metaKey) return
+ const isCode = state.blocks.some(block => block.type == 'code')
+
+ return state
+ .transform()
+ .setBlock(isCode ? 'paragraph' : 'code')
+ .apply()
+ }
+ }
+
+}
+```
+
+And now, we'll edit the `onKeyDown` handler to make it so that when you press **⌘-B**, it will add a "bold" mark to the currently selected text:
+
+```js
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={(e, state) => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (!event.metaKey) return
+
+ // Decide what to do based on the key code...
+ switch (event.which) {
+ // When "B" is pressed, add a "bold" mark to the text.
+ case 66: {
+ return state
+ .transform()
+ .mark('bold')
+ .apply()
+ }
+ // When "`" is pressed, keep our existing code block logic.
+ case 192: {
+ const isCode = state.blocks.some(block => block.type == 'code')
+ return state
+ .transform()
+ .setBlock(isCode ? 'paragraph' : 'code')
+ .apply()
+ }
+ }
+ }
+
+}
+```
+
+Okay, so we've got the hotkey handler setup... but! If you happen to now try selecting text and hitting **⌘-B**, you'll get an error in your console. That's because we haven't told Slate how to render a "bold" mark.
+
+For every mark type you want to add to your schema, you need to give Slate a "renderer" for that mark, just like nodes. Except unlike nodes, mark renderers are just simple objects of styles that will be passed directly to React's `style=` property.
+
+So let's define our `bold` mark:
+
+```js
+// Define a set of styles that make text bold.
+const BOLD_MARK = {
+ fontWeight: 'bold'
+}
+```
+
+Pretty simple, right?
+
+And now, let's tell Slate about that mark. To do that, we'll need to pass in a `renderMark` function to the `Editor`, which it will call with any mark it finds. And when it calls it with a bold mark, we'll return our `BOLD_MARK` styles. Like so:
+
+```js
+const BOLD_MARK = {
+ fontWeight: 'bold'
+}
+
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ // Add the `renderMark` handler to the editor.
+ render() {
+ return (
+ this.renderMark(mark)}
+ renderNode={node => this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={(e, state) => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ // Define a mark rendering function that knows about "bold" marks.
+ renderMark(mark) {
+ if (mark.type == 'bold') return BOLD_MARK
+ }
+
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (!event.metaKey) return
+
+ switch (event.which) {
+ case 66: {
+ return state
+ .transform()
+ .mark('bold')
+ .apply()
+ }
+ case 192: {
+ const isCode = state.blocks.some(block => block.type == 'code')
+ return state
+ .transform()
+ .setBlock(isCode ? 'paragraph' : 'code')
+ .apply()
+ }
+ }
+ }
+
+}
+```
+
+Now, if you try selecting a piece of text and hitting **⌘-B** you should see it turn bold! Magic!
+
+But we forgot one thing. When you hit **⌘-B** again, it should remove the bold formatting. To do that, we'll need to add a bit of logic to either add or remove the `bold` mark depending on what the currently selected marks on the text are:
+
+```js
+const BOLD_MARK = {
+ fontWeight: 'bold'
+}
+
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderMark(mark)}
+ renderNode={node => this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={(e, state) => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ renderMark(mark) {
+ if (mark.type == 'bold') return BOLD_MARK
+ }
+
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (!event.metaKey) return
+
+ switch (event.which) {
+ case 66: {
+ // Loop through the current marks, check to see if any are bold.
+ const isBold = state.marks.some(mark => mark.type == 'bold')
+ return state
+ .transform()
+ [isBold ? 'mark' : 'unmark']('bold')
+ .apply()
+ }
+ case 192: {
+ const isCode = state.blocks.some(block => block.type == 'code')
+ return state
+ .transform()
+ .setBlock(isCode ? 'paragraph' : 'code')
+ .apply()
+ }
+ }
+ }
+
+}
+```
+
+Now when you repeatedly press **⌘-B** you should see the bold formatting be added and removed!
+
+
+Next:
Using Plugins
+
diff --git a/docs/guides/defining-custom-block-nodes.md b/docs/guides/defining-custom-block-nodes.md
new file mode 100644
index 000000000..68b292011
--- /dev/null
+++ b/docs/guides/defining-custom-block-nodes.md
@@ -0,0 +1,249 @@
+
+
+Previous:
Adding Event Handlers
+
+
+### Defining Custom Block Nodes
+
+In our previous example, we started with a `paragraph` block node, but that's not all you can do. Slate lets you define any type of custom blocks you want, like block quotes, code blocks, list items, etc.
+
+We'll show you how. Let's start with our app from earlier:
+
+```js
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={(e, state) => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (event.which != 55 || !event.shiftKey) return
+
+ const newState = state
+ .transform()
+ .insertText('and')
+ .apply()
+
+ return newState
+ }
+
+}
+```
+
+Now let's add "code blocks" to our editor.
+
+Just like when we defined our `paragraph` block, we'll do the same except this time for code blocks:
+
+```js
+// Define a React component renderer for our code blocks.
+const CodeNode = (props) => {
+ return {props.children}
+}
+```
+
+Pretty simple.
+
+See that `props.children` reference? We glossed over it earlier. Slate will automatically render all of the children of a block for you, and then pass them to you just like any other React component would, via `props.children`. That way you don't have to muck around with rendering the proper text nodes or anything like that.
+
+Now, let's add that renderer to our `Editor`:
+
+```js
+const CodeNode = (props) => {
+ return {props.children}
+}
+
+const ParagraphNode = (props) => {
+ return {props.children}
+}
+
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={e, state => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ // Render the right component depending on the node `type`.
+ renderNode(node) {
+ switch (node.type) {
+ case 'code': return CodeNode
+ case 'paragraph': return ParagraphNode
+ }
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (event.which != 55 || !event.shiftKey) return
+
+ const newState = state
+ .transform()
+ .insertText('and')
+ .apply()
+
+ return newState
+ }
+
+}
+```
+
+Okay, but now we'll need a way for the user to actually turn a block into a code block. So let's change our `onKeyDown` function to add a **⌘-`** shortcut that does just that:
+
+```js
+const CodeNode = (props) => {
+ return {props.children}
+}
+
+const ParagraphNode = (props) => {
+ return {props.children}
+}
+
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={e, state => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ renderNode(node) {
+ switch (node.type) {
+ case 'code': return CodeNode
+ case 'paragraph': return ParagraphNode
+ }
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ // Return with no changes if it's not the "`" key with cmd/ctrl pressed.
+ if (event.which != 192 || !event.metaKey) return
+
+ // Otherwise, set the currently selected blocks type to "code".
+ return state
+ .transform()
+ .setBlock('code')
+ .apply()
+ }
+ }
+
+}
+```
+
+Now, if you press **⌘-`**, the block your cursor is in should turn into a code block! Magic!
+
+But we forgot one thing. When you hit **⌘-`** again, it should change the code block back into a paragraph. To do that, we'll need to add a bit of logic to change the type we set based on whether any of the currently selected blocks are already a code block:
+
+```js
+const CodeNode = (props) => {
+ return {props.children}
+}
+
+const ParagraphNode = (props) => {
+ return {props.children}
+}
+
+class App extends React.Component {
+
+ constructor(props) {
+ super(props)
+ this.state = {
+ state: initialState
+ }
+ }
+
+ render() {
+ return (
+ this.renderNode(node)}
+ onChange={state => this.onChange(state)}
+ onKeyDown={e, state => this.onKeyDown(e, state)}
+ />
+ )
+ }
+
+ renderNode(node) {
+ switch (node.type) {
+ case 'code': return CodeNode
+ case 'paragraph': return ParagraphNode
+ }
+ }
+
+ onChange(state) {
+ this.setState({ state })
+ }
+
+ onKeyDown(event, state) {
+ if (event.which != 192 || !event.metaKey) return
+
+ // Determine whether any of the currently selected blocks are code blocks.
+ const isCode = state.blocks.some(block => block.type == 'code')
+
+ // Toggle the block type depending on `isCode`.
+ return state
+ .transform()
+ .setBlock(isCode ? 'paragraph' : 'code')
+ .apply()
+ }
+ }
+
+}
+```
+
+And there you have it! If you press **⌘-`** while inside a code block, it should turn back into a paragraph!
+
+
+Next:
Applying Custom Formatting
+
diff --git a/docs/guides/installing-slate.md b/docs/guides/installing-slate.md
index c70796618..94846c5ce 100644
--- a/docs/guides/installing-slate.md
+++ b/docs/guides/installing-slate.md
@@ -47,7 +47,18 @@ const initialState = Raw.deserialize([
])
```
-Once you've got a `State` object create, via the `Raw` serializer, or any other serialization method you want, you can pass it into the `Editor` component inside your application:
+Okay, now we've got our initial state in a format that Slate understands. But Slate doesn't know anything about our schema, specifically how to render `paragraph` block nodes.
+
+So we need to define a paragraph node renderer, which is just a simple React component, like so:
+
+```js
+// A simple React component that wraps text in a `` element.
+const ParagraphNode = (props) => {
+ return
{props.children}
+}
+```
+
+And now that we've our initial state and our paragraph renderer, we define our `App` and pass them into Slate's `Editor` component, like so:
```js
import React from 'react'
@@ -70,6 +81,10 @@ const initialState = Raw.deserialize([
}
])
+const ParagraphNode = (props) => {
+ return {props.children}
+}
+
// Define our app...
class App extends React.Component {
@@ -86,11 +101,16 @@ class App extends React.Component {
return (
this.renderNode(node)}
onChange={state => this.onChange(state)}
/>
)
}
+ renderNode(node) {
+ if (node.type == 'paragraph') return ParagraphNode
+ }
+
onChange(state) {
// Update the app's React state with the new editor state.
this.setState({ state })