1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-28 09:29:49 +02:00

refactor docs

This commit is contained in:
Ian Storm Taylor
2016-07-12 21:34:31 -07:00
parent 510eb63d8d
commit 0b8498e83a
14 changed files with 121 additions and 169 deletions

View File

@@ -1,6 +1,6 @@
<p align="center"><img src="docs/banner.png" /></p>
<p align="center"><img src="./docs/banner.png" /></p>
<p align="center">A <em>completely</em> customizable framework <br/>for building rich text editors in the browser.</p>
<br/>
@@ -36,15 +36,15 @@ _Slate is currently in **beta**, while work is being done on: cross-browser supp
To get a sense for how you might use Slate, check out a few of the examples:
- [**Plain text**](examples/plain-text) — showing the most basic case: a glorified `<textarea>`.
- [**Rich text**](examples/rich-text) — showing the features you'd expect from a basic editor.
- [**Auto-markdown**](examples/auto-markdown) — showing how to add key handlers for Markdown-like shortcuts.
- [**Links**](examples/links) — showing how wrap text in inline nodes with associated data.
- [**Images**](examples/images) — showing how to use void (text-less) nodes to add images.
- [**Hovering menu**](examples/hovering-menu) — showing how a contextual hovering menu can be implemented.
- [**Tables**](examples/tables) — showing how to nest blocks to render more advanced components.
- [**Paste HTML**](examples/paste-html) — showing how to use an HTML serializer to handle pasted HTML.
- [**Code Highlighting**](examples/code-highlighting) — showing how to use decorators to dynamically mark text.
- [**Plain text**](./examples/plain-text) — showing the most basic case: a glorified `<textarea>`.
- [**Rich text**](./examples/rich-text) — showing the features you'd expect from a basic editor.
- [**Auto-markdown**](./examples/auto-markdown) — showing how to add key handlers for Markdown-like shortcuts.
- [**Links**](./examples/links) — showing how wrap text in inline nodes with associated data.
- [**Images**](./examples/images) — showing how to use void (text-less) nodes to add images.
- [**Hovering menu**](./examples/hovering-menu) — showing how a contextual hovering menu can be implemented.
- [**Tables**](./examples/tables) — showing how to nest blocks to render more advanced components.
- [**Paste HTML**](./examples/paste-html) — showing how to use an HTML serializer to handle pasted HTML.
- [**Code Highlighting**](./examples/code-highlighting) — showing how to use decorators to dynamically mark text.
If you have an idea for an example that shows a common use case, pull request it!
@@ -54,8 +54,8 @@ If you have an idea for an example that shows a common use case, pull request it
Slate encourages you to write small, reusable modules. Check out the public ones you can use in your project!
- [**Plugins**](wiki#plugins)
- [**Serializers**](wiki#serializers)
- [**Plugins**](./wiki#plugins)
- [**Serializers**](./wiki#serializers)
<br/>
@@ -63,39 +63,41 @@ Slate encourages you to write small, reusable modules. Check out the public ones
If you're using Slate for the first time, check out the [Getting Started](./docs/guides/installing-slate.md) guides and the [Core Concepts](./docs/concepts) to familiarize yourself with Slate's architecture and mental models. Once you've gotten familiar with those, you'll probably want to check out the full [API Reference](./docs/reference).
- [**Guides**](docs/guides)
- [Installing Slate](docs/guides/installing-slate.md)
- [Adding Event Handlers](docs/guides/adding-event-handlers.md)
- [Defining Custom Block Nodes](docs/guides/defining-custom-block-nodes.md)
- [Applying Custom Formatting](docs/guides/applying-custom-formatting.md)
- [Using Plugins](docs/guides/using-plugins.md)
- [**Guides**](./docs/guides)
- [Installing Slate](./docs/guides/installing-slate.md)
- [Adding Event Handlers](./docs/guides/adding-event-handlers.md)
- [Defining Custom Block Nodes](./docs/guides/defining-custom-block-nodes.md)
- [Applying Custom Formatting](./docs/guides/applying-custom-formatting.md)
- [Using Plugins](./docs/guides/using-plugins.md)
- Saving to a Database
- Adding a Hovering Menu
- Rendering Adjacent Elements in Components
- **Concepts**
- [**Concepts**](./docs/concepts)
- Statelessness & Immutability
- The Document Model
- The Selection Model
- Plugins
- **Reference**
- Components
- [Editor](docs/reference/components/editor.md)
- [Placeholder](docs/reference/components/placeholder.md)
- Models
- [Block](docs/reference/models/block.md)
- [Character](docs/reference/models/character.md)
- [Data](docs/reference/data.md)
- [Document](docs/reference/models/document.md)
- [Inline](docs/reference/models/inline.md)
- [Mark](docs/reference/mark.md)
- [Node](docs/reference/models/node.md)
- [Selection](docs/reference/models/selection.md)
- [State](docs/reference/models/state.md)
- [Text](docs/reference/text.md)
- [Transform](docs/reference/models/transform.md)
- Plugins
- [Plugins](docs/reference/plugins/plugins.md)
- [Core](docs/reference/plugins/core.md)
- [**Reference**](./docs/reference)
- **Components**
- [Editor](./docs/reference/components/editor.md)
- [Placeholder](./docs/reference/components/placeholder.md)
- **Models**
- [Block](./docs/reference/models/block.md)
- [Character](./docs/reference/models/character.md)
- [Data](./docs/reference/data.md)
- [Document](./docs/reference/models/document.md)
- [Inline](./docs/reference/models/inline.md)
- [Mark](./docs/reference/mark.md)
- [Node](./docs/reference/models/node.md)
- [Selection](./docs/reference/models/selection.md)
- [State](./docs/reference/models/state.md)
- [Text](./docs/reference/text.md)
- [Transform](./docs/reference/models/transform.md)
- **Plugins**
- [Plugins](./docs/reference/plugins/plugins.md)
- [Core](./docs/reference/plugins/core.md)
If even that's not enough, you can always [read the source itself](./lib), which is explained along with a handful of readme's.

View File

@@ -1,44 +1,16 @@
# Concepts
This document explain the core concepts that Slate is built on around. It is helpful to read it through in it's entirety to get a good mental model for how Slate works.
- [Statelessness & Immutability](#statelessness-immutability)
- [The Document Model](#the-document-model)
- [The Selection Mode](#the-selection-model)
- [Transforms](#transforms)
- [Plugins](#plugins)
- [Statelessness & Immutability](./statelessness-and-immutability.md)
- [The Document Model](./the-document-model.md)
- [The Selection Model](./the-selection-model.md)
- [Transforms](./transforms.md)
- [Plugins](./plugins.md)
### Statelessness & Immutability
- all the data is immutable, for performance
- changes propagated up through the single `onChange` handler
### The Document Model
- recursive, nested tree
- document, blocks, and inlines implement node interface
- blocks and inlines can be nested to any depth
- blocks contain inlines and text
- inlines contain text
- always a text node at the leaves, for selection handling
- void nodes can't have content, but still have an empty text node
### The Selection Model
- selection is always relative to text nodes (is normalized)
- "blocks" always refers to the closest block parent
### Transforms
- no updating of document/selection outside of transforms
- wrap blocks wraps close to the text
- wrap inline wraps far from the text
### Plugins
- everything is a plugin, even core is one
- the editor's props become the highest-priority plugin

5
docs/concepts/plugins.md Normal file
View File

@@ -0,0 +1,5 @@
### Plugins
- everything is a plugin, even core is one
- the editor's props become the highest-priority plugin

View File

@@ -1,5 +1,5 @@
# Statelessness & Immutability
- all the data is immutable, for performance
- changes propagated up through the single `onChange` handler

View File

@@ -1,4 +1,13 @@
# The Document Model
- recursive, nested tree
- document, blocks, and inlines implement node interface
- blocks and inlines can be nested to any depth
- blocks contain inlines and text
- inlines contain text
- always a text node at the leaves, for selection handling
- void nodes can't have content, but still have an empty text node

View File

@@ -0,0 +1,5 @@
# The Selection Model
- selection is always relative to text nodes (is normalized)
- "blocks" always refers to the closest block parent

View File

@@ -0,0 +1,6 @@
# Transforms
- no updating of document/selection outside of transforms
- wrap blocks wraps close to the text
- wrap inline wraps far from the text

View File

@@ -1,5 +1,5 @@
### Guides
# Guides
These guides introduce you to the different parts of Slate in a step-by-step way that build on each other, perfect for getting started. We recommend reading them in order, start to finish!

View File

@@ -3,7 +3,7 @@
<p align="center"><strong>Previous:</strong><br/><a href="./installing-slate.md">Installing Slate</a></p>
<br/>
### Adding Event Handlers
# Adding Event Handlers
Okay, so you've got Slate installed and rendered on the page, and when you type in it, you can see the changes reflected. But you want to do more than just type a plaintext string.

View File

@@ -3,7 +3,7 @@
<p align="center"><strong>Previous:</strong><br/><a href="./defining-custom-block-nodes.md">Defining Custom Block Nodes</a></p>
<br/>
### Applying Custom Formatting
# 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".
@@ -12,14 +12,6 @@ In this guide, we'll show you how to add custom formatting options, like **bold*
So we start with our app from earlier:
```js
const CodeNode = (props) => {
return <pre><code>{props.children}</code></pre>
}
const ParagraphNode = (props) => {
return <p>{props.children}</p>
}
class App extends React.Component {
constructor(props) {
@@ -33,20 +25,12 @@ class App extends React.Component {
return (
<Editor
state={this.state.state}
renderNode={node => 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 })
}
@@ -81,17 +65,12 @@ class App extends React.Component {
return (
<Editor
state={this.state.state}
renderNode={node => 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 })
}
@@ -159,7 +138,6 @@ class App extends React.Component {
<Editor
state={this.state.state}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
onChange={state => this.onChange(state)}
onKeyDown={(e, state) => this.onKeyDown(e, state)}
/>
@@ -171,10 +149,6 @@ class App extends React.Component {
if (mark.type == 'bold') return BOLD_MARK
}
renderNode(node) {
if (node.type == 'paragraph') return ParagraphNode
}
onChange(state) {
this.setState({ state })
}
@@ -225,7 +199,6 @@ class App extends React.Component {
<Editor
state={this.state.state}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
onChange={state => this.onChange(state)}
onKeyDown={(e, state) => this.onKeyDown(e, state)}
/>
@@ -236,10 +209,6 @@ class App extends React.Component {
if (mark.type == 'bold') return BOLD_MARK
}
renderNode(node) {
if (node.type == 'paragraph') return ParagraphNode
}
onChange(state) {
this.setState({ state })
}

View File

@@ -3,9 +3,11 @@
<p align="center"><strong>Previous:</strong><br/><a href="./adding-event-handlers.md">Adding Event Handlers</a></p>
<br/>
### Defining Custom Block Nodes
# 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.
In our previous example, we started with a paragraph, but we never actually told Slate anything about the `paragraph` block type. We just let it use its internal default renderer.
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:
@@ -54,18 +56,22 @@ class App extends React.Component {
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:
The problem is, code blocks won't just be rendered as a plain paragraph, they'll need to be renderer differently. To make that happen, we need to define a "renderer" for `code` nodes
Node renderers are just simple React components, like so:
```js
// Define a React component renderer for our code blocks.
const CodeNode = (props) => {
return <pre><code>{props.children}</code></pre>
return <pre {...props.attributes}><code>{props.children}</code></pre>
}
```
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.
See the `props.attributes` reference? Slate passes attributes that should be rendered on the top-most element of your blocks, so that you don't have to build them up yourself. You **must** mix the attributes into your component.
And see that `props.children` reference? 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. You **must** render the children as the lowest leaf in your component.
Now, let's add that renderer to our `Editor`:
@@ -100,10 +106,8 @@ class App extends React.Component {
// Render the right component depending on the node `type`.
renderNode(node) {
switch (node.type) {
case 'code': return CodeNode
case 'paragraph': return ParagraphNode
}
if (node.type == 'code') return CodeNode
// Any nodes that fall through here will still use the default renderer.
}
onChange(state) {
@@ -156,10 +160,7 @@ class App extends React.Component {
}
renderNode(node) {
switch (node.type) {
case 'code': return CodeNode
case 'paragraph': return ParagraphNode
}
if (node.type == 'code') return CodeNode
}
onChange(state) {
@@ -215,10 +216,7 @@ class App extends React.Component {
}
renderNode(node) {
switch (node.type) {
case 'code': return CodeNode
case 'paragraph': return ParagraphNode
}
if (node.type == 'code') return CodeNode
}
onChange(state) {

View File

@@ -1,5 +1,5 @@
### Installing Slate
# Installing Slate
Slate is an npm module, so to install it you do:
@@ -18,6 +18,7 @@ Once you've install it, you'll need to import it.
Slate exposes a set of modules that you'll use to build your editor. The most important of which is an `Editor` component.
```js
// Import the Slate editor.
import { Editor } from 'slate'
```
@@ -26,6 +27,7 @@ In addition to loading the editor, you need to give Slate a "initial state" to w
To keep things simple, we'll use the `Raw` serializer that ships with Slate to create a new initial state that just contains a single paragraph block with some text in it:
```js
// Import the "raw" serializer that ships with Slate.
import { Editor, Raw } from 'slate'
// Create our initial state...
@@ -47,20 +49,10 @@ const initialState = Raw.deserialize([
])
```
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 `<p>` element.
const ParagraphNode = (props) => {
return <p>{props.children}</p>
}
```
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:
And now that we've our initial state, we define our `App` and pass it into Slate's `Editor` component, like so:
```js
// Import React!
import React from 'react'
import { Editor, Raw } from 'state'
@@ -81,10 +73,6 @@ const initialState = Raw.deserialize([
}
])
const ParagraphNode = (props) => {
return <p>{props.children}</p>
}
// Define our app...
class App extends React.Component {
@@ -101,16 +89,11 @@ class App extends React.Component {
return (
<Editor
state={this.state.state}
renderNode={node => 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 })

View File

@@ -3,7 +3,7 @@
<p align="center"><strong>Previous:</strong><br/><a href="./applying-custom-formatting.md">Applying Custom Formatting</a></p>
<br/>
### Using Formatting
# Using Plugins
Up to now, everything we've learned has been about how to write one-off logic for your specific Slate editor. But one of the most beautiful things about Slate is actually its plugin system, and how it lets you write less one-off code.
@@ -32,7 +32,6 @@ class App extends React.Component {
<Editor
state={this.state.state}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
onChange={state => this.onChange(state)}
onKeyDown={(e, state) => this.onKeyDown(e, state)}
/>
@@ -43,10 +42,6 @@ class App extends React.Component {
if (mark.type == 'bold') return BOLD_MARK
}
renderNode(node) {
if (node.type == 'paragraph') return ParagraphNode
}
onChange(state) {
this.setState({ state })
}
@@ -138,7 +133,6 @@ class App extends React.Component {
state={this.state.state}
plugins={plugins}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
onChange={state => this.onChange(state)}
/>
)
@@ -148,10 +142,6 @@ class App extends React.Component {
if (mark.type == 'bold') return BOLD_MARK
}
renderNode(node) {
if (node.type == 'paragraph') return ParagraphNode
}
onChange(state) {
this.setState({ state })
}
@@ -207,7 +197,6 @@ class App extends React.Component {
state={this.state.state}
plugins={plugins}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
onChange={state => this.onChange(state)}
/>
)
@@ -218,10 +207,6 @@ class App extends React.Component {
return MARKS[mark.type]
}
renderNode(node) {
if (node.type == 'paragraph') return ParagraphNode
}
onChange(state) {
this.setState({ state })
}
@@ -315,7 +300,6 @@ class App extends React.Component {
state={this.state.state}
plugins={plugins}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
onChange={state => this.onChange(state)}
/>
)
@@ -325,10 +309,6 @@ class App extends React.Component {
return MARKS[mark.type]
}
renderNode(node) {
if (node.type == 'paragraph') return ParagraphNode
}
onChange(state) {
this.setState({ state })
}

View File

@@ -0,0 +1,23 @@
# Reference
This is the full reference documentation for all of the pieces of Slate, broken up into sections by type:
- **Components**
- [Editor](./components/editor.md)
- [Placeholder](./components/placeholder.md)
- **Models**
- [Block](./models/block.md)
- [Character](./models/character.md)
- [Data](./data.md)
- [Document](./models/document.md)
- [Inline](./models/inline.md)
- [Mark](./mark.md)
- [Node](./models/node.md)
- [Selection](./models/selection.md)
- [State](./models/state.md)
- [Text](./text.md)
- [Transform](./models/transform.md)
- **Plugins**
- [Plugins](./plugins/plugins.md)
- [Core](./plugins/core.md)