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

fix some typos in docs/guides (#1412)

This commit is contained in:
Tobias Andersen
2017-11-17 02:14:38 +07:00
committed by Ian Storm Taylor
parent 237ae9fc2f
commit 1abc7e74b8
5 changed files with 41 additions and 42 deletions

View File

@@ -14,7 +14,7 @@ Changes in Slate are designed to prioritize expressiveness above almost all else
If you're building a powerful editor, it's going to be somewhat complex, and you're going to be writing code to perform all different kinds of programmatic changes. You'll be removing nodes, inserting fragments, moving the selection around, etc. If you're building a powerful editor, it's going to be somewhat complex, and you're going to be writing code to perform all different kinds of programmatic changes. You'll be removing nodes, inserting fragments, moving the selection around, etc.
And if the API for changes was verbose, or if required lots of in between steps to be continually performed, your code would balloon to be impossible to understand very quickly. And if the API for changes was verbose, or if it required lots of in between steps to be continually performed, your code would balloon to be impossible to understand very quickly.
To solve this, Slate has very expressive, chainable changes. Like this: To solve this, Slate has very expressive, chainable changes. Like this:
@@ -178,7 +178,7 @@ function insertImage(change, src) {
} }
``` ```
Notice how rewriting that image inserting logic multiple times without having it encapsulated in a single function would get tedious. Now with those change functions define, you can reuse them! Notice how rewriting that image inserting logic multiple times without having it encapsulated in a single function would get tedious. Now with those change functions defined, you can reuse them!
But sadly you can't chain with those functions directly, since `change` objects don't actually know about them. Instead, you use the `.call()` method: But sadly you can't chain with those functions directly, since `change` objects don't actually know about them. Instead, you use the `.call()` method:

View File

@@ -30,7 +30,7 @@ But for updating values, you'll need to use the [`Immutable.Record` API](https:/
Collections of Slate objects are represented as immutable `Lists`, `Sets`, `Stacks`, etc. Which means we get nice support for expressive methods like `filter`, `includes`, `take`, `skip`, `rest`, `last`, etc. Collections of Slate objects are represented as immutable `Lists`, `Sets`, `Stacks`, etc. Which means we get nice support for expressive methods like `filter`, `includes`, `take`, `skip`, `rest`, `last`, etc.
If you haven't used Immutable.js before, there is definitely a learning curve. Before you give into Slate, you should check out the [Immutable.js docs](https://facebook.github.io/immutable-js/docs/#/). Once you get the hang of it won't slow you down at all, but it will take a few days to get used to, and you might write things a little "un-performantly" to start. If you haven't used Immutable.js before, there is definitely a learning curve. Before you give into Slate, you should check out the [Immutable.js docs](https://facebook.github.io/immutable-js/docs/#/). Once you get the hang of it, it won't slow you down at all, but it will take a few days to get used to, and you might write things a little "un-performantly" to start.
## The "Value" ## The "Value"
@@ -48,7 +48,7 @@ Slate documents are nested and recursive. This means that a document has block n
Unlike the DOM though, Slate enforces a few more restrictions on its documents, to reduce the complexity involved in manipulating them, and to prevent "impossible" situations from arising. These restrictions are: Unlike the DOM though, Slate enforces a few more restrictions on its documents, to reduce the complexity involved in manipulating them, and to prevent "impossible" situations from arising. These restrictions are:
- **Documents can only contain block nodes as direct children.** This restriction mirrors how rich-text editors work, with the top-most elements being blocks that can be split when pressing enter <kbd>enter</kbd>. - **Documents can only contain block nodes as direct children.** This restriction mirrors how rich-text editors work, with the top-most elements being blocks that can be split when pressing <kbd>enter</kbd>.
- **Blocks can only contain either other block nodes, or inlines and text nodes.** This is another "sane" restriction that allows you to avoid lots of boilerplate `if` statements in your code. Blocks either wrap other blocks, or contain actual content. - **Blocks can only contain either other block nodes, or inlines and text nodes.** This is another "sane" restriction that allows you to avoid lots of boilerplate `if` statements in your code. Blocks either wrap other blocks, or contain actual content.
@@ -56,7 +56,7 @@ Unlike the DOM though, Slate enforces a few more restrictions on its documents,
- **Inlines can't contain no text.** Any inline node whose text is an empty string (`''`) will be automatically removed. This makes sense when you think about a user backspacing through an inline. When they delete that last character, they'd expect the inline to be removed. And when there are no characters, you can't really put your selection into the inline anymore. So Slate removes them from the document automatically, to simplify things. - **Inlines can't contain no text.** Any inline node whose text is an empty string (`''`) will be automatically removed. This makes sense when you think about a user backspacing through an inline. When they delete that last character, they'd expect the inline to be removed. And when there are no characters, you can't really put your selection into the inline anymore. So Slate removes them from the document automatically, to simplify things.
- **Text nodes can't be adjacent to other text nodes.** Any two adjacent text nodes will automatically be merged into one. This prevents ambiguous case where a cursor could be at the end of one text node or at the start of the next. However, you can have an inline node surrounded by two texts. - **Text nodes can't be adjacent to other text nodes.** Any two adjacent text nodes will automatically be merged into one. This prevents ambiguous cases where a cursor could be at the end of one text node or at the start of the next. However, you can have an inline node surrounded by two texts.
- **Blocks and inlines must always contain at least one text node.** This is to ensure that the user's cursor can always "enter" the nodes, and to make sure that ranges can be created referencing them. - **Blocks and inlines must always contain at least one text node.** This is to ensure that the user's cursor can always "enter" the nodes, and to make sure that ranges can be created referencing them.
@@ -71,7 +71,7 @@ In addition to documents, blocks and inlines, Slate introduces one other type of
Marks are how Slate represents formatting data that is attached to the characters in the text itself—things like **bold**, _italic_, `code`, or even more complex formatting like comments. Marks are how Slate represents formatting data that is attached to the characters in the text itself—things like **bold**, _italic_, `code`, or even more complex formatting like comments.
Although you can change styling based on either inlines or marks, marks differ form inlines in that they don't affect the structure of the nodes in the document, they simply attach themselves to the characters. Although you can change styling based on either inlines or marks, marks differ from inlines in that they don't affect the structure of the nodes in the document, they simply attach themselves to the characters.
This makes marks easier to reason about and easier to manipulate. Because inlines involve editing the document's structure, you have to worry about things like splitting any existing nodes, what their order in the hierarchy is, etc. Marks on the other hand can be applied to characters no matter how the characters are nested in the document. If you can express it as a `Range`, you can add marks to it. This makes marks easier to reason about and easier to manipulate. Because inlines involve editing the document's structure, you have to worry about things like splitting any existing nodes, what their order in the hierarchy is, etc. Marks on the other hand can be applied to characters no matter how the characters are nested in the document. If you can express it as a `Range`, you can add marks to it.
@@ -89,7 +89,7 @@ Because the elements don't properly close themselves. Instead you have to write
<em>t</em><strong><em>e</em>x</strong>t <em>t</em><strong><em>e</em>x</strong>t
``` ```
And if you happened to another overlapping section of `<strike>` to that text, you might have to rearrange the closing tags again. Rendering marks in Slate is similar—you can't guarantee that even though a word has one mark applied that that mark will be contiguous, because it depends on how it overlaps with other marks. And if you happened to add another overlapping section of `<strike>` to that text, you might have to rearrange the closing tags again. Rendering marks in Slate is similar—you can't guarantee that even though a word has one mark applied that that mark will be contiguous, because it depends on how it overlaps with other marks.
That all sounds pretty complex, but you don't have to think about it much, as long as you use marks and inlines for their intended purposes... That all sounds pretty complex, but you don't have to think about it much, as long as you use marks and inlines for their intended purposes...
@@ -101,7 +101,7 @@ That all sounds pretty complex, but you don't have to think about it much, as lo
Just like in the DOM, you can reference a part of the document using a `Range`. And there's one special range that Slate keeps track of called the "selection" that refers to the user's current cursor selection. Just like in the DOM, you can reference a part of the document using a `Range`. And there's one special range that Slate keeps track of called the "selection" that refers to the user's current cursor selection.
Ranges are defined by an "anchor" and "focus" point. The anchor is where the range starts, and the focus is where it ends. And each point is a combination of an "key" referencing a specific node, and an "offset". This ends up looking like this: Ranges are defined by an "anchor" and "focus" point. The anchor is where the range starts, and the focus is where it ends. And each point is a combination of a "key" referencing a specific node, and an "offset". This ends up looking like this:
```js ```js
const range = Range.create({ const range = Range.create({
@@ -115,14 +115,14 @@ const range = Range.create({
The more readable `node-a` name is just pseudocode, because Slate uses auto-incrementing numerical strings by default—`'1', '2', '3', ...` But the important part is that every node has a unique `key` property, and a range references nodes by their keys. The more readable `node-a` name is just pseudocode, because Slate uses auto-incrementing numerical strings by default—`'1', '2', '3', ...` But the important part is that every node has a unique `key` property, and a range references nodes by their keys.
The terms "anchor" and "focus" are borrowed from the DOM, where they mean the same thing. The anchor is where a range starts, and the focus is where it ends. However, be careful because the anchor point doesnt't always _before_ the focus point in the document. Just like in the DOM, it depends on whether the range is backwards or forwards. The terms "anchor" and "focus" are borrowed from the DOM, where they mean the same thing. The anchor is where a range starts, and the focus is where it ends. However, be careful because the anchor point isn't always _before_ the focus point in the document. Just like in the DOM, it depends on whether the range is backwards or forwards.
Here's how MDN explains it: Here's how MDN explains it:
> A user may make a selection from left to right (in document order) or right to left (reverse of document order). The anchor is where the user began the selection and the focus is where the user ends the selection. If you make a selection with a desktop mouse, the anchor is placed where you pressed the mouse button and the focus is placed where you released the mouse button. Anchor and focus should not be confused with the start and end positions of a selection, since anchor can be placed before the focus or vice versa, depending on the direction you made your selection. > A user may make a selection from left to right (in document order) or right to left (reverse of document order). The anchor is where the user began the selection and the focus is where the user ends the selection. If you make a selection with a desktop mouse, the anchor is placed where you pressed the mouse button and the focus is placed where you released the mouse button. Anchor and focus should not be confused with the start and end positions of a selection, since anchor can be placed before the focus or vice versa, depending on the direction you made your selection.
> — [`Selection`, MDN](https://developer.mozilla.org/en-US/docs/Web/API/Selection) > — [`Selection`, MDN](https://developer.mozilla.org/en-US/docs/Web/API/Selection)
To make dealing with ranges easier though, they also provide "start" and "end" properties that take whether the range is forward or backward into account. The `startKey` and `startOffset` will always before the `endKey` and `endOffset` in the document. To make dealing with ranges easier though, they also provide "start" and "end" properties that take whether the range is forward or backward into account. The `startKey` and `startOffset` will always be before the `endKey` and `endOffset` in the document.
One important thing to note is that the anchor and focus points of ranges **always reference the "leaf-most" text nodes**. They never reference blocks or inlines, always their child text nodes. This makes dealing with ranges a _lot_ easier. One important thing to note is that the anchor and focus points of ranges **always reference the "leaf-most" text nodes**. They never reference blocks or inlines, always their child text nodes. This makes dealing with ranges a _lot_ easier.

View File

@@ -29,7 +29,7 @@ Here's a really simple plugin:
} }
``` ```
It focuses the editor and selects everything when it is clicked, and it blurs the editor what <kbd>esc</kbd> is pressed. It focuses the editor and selects everything when it is clicked, and it blurs the editor when <kbd>esc</kbd> is pressed.
Notice how it's able to define a set of behaviors that work together to form a single "feature" in the editor. That's what makes Slate's plugins a powerful form of encapsulation. Notice how it's able to define a set of behaviors that work together to form a single "feature" in the editor. That's what makes Slate's plugins a powerful form of encapsulation.
@@ -49,7 +49,7 @@ const plugins = [
/> />
``` ```
When the editor needs to handle a DOM event, or to decide what to render, it will loop through the plugins stack, invoking each plugin in turn. Plugins can choose to handle the request, in which case the editor will break out of the loop. Or they can ignore it, and they will be skipped as the editor proceeds to the next plugin in the stack. When the editor needs to handle a DOM event, or decide what to render, it will loop through the plugins stack, invoking each plugin in turn. Plugins can choose to handle the request, in which case the editor will break out of the loop. Or they can ignore it, and they will be skipped as the editor proceeds to the next plugin in the stack.
Because of this looping, plugins are **order-sensitive**! This is very important. The earlier in the stack, the more preference the plugin has, since it can react before the others after it. If two plugins both try to handle the same event, the earlier plugin will "win". Because of this looping, plugins are **order-sensitive**! This is very important. The earlier in the stack, the more preference the plugin has, since it can react before the others after it. If two plugins both try to handle the same event, the earlier plugin will "win".
@@ -58,7 +58,7 @@ Because of this looping, plugins are **order-sensitive**! This is very important
If you put Slate on the page without adding any of your own plugins, it will still behave like you'd expect a rich-text editor to. That's because it has its own "core" logic. And that core logic is implemented with its own core plugins. If you put Slate on the page without adding any of your own plugins, it will still behave like you'd expect a rich-text editor to. That's because it has its own "core" logic. And that core logic is implemented with its own core plugins.
The core plugins doesn't have any assumptions about your schema, or what types of formatting you want to allow. But they do define the common editing behaviors like splitting the current block when <kbd>enter</kbd> is pressed, or inserting a string of text when the user pastes from their clipboard. The core plugins doesn't have any assumptions about your schema, or what types of formatting you want to allow. But they do define common editing behaviors like splitting the current block when <kbd>enter</kbd> is pressed, or inserting a string of text when the user pastes from their clipboard.
These are behaviors that all rich-text editors exhibit, and that don't make sense for userland to have to re-invent for every new editor. These are behaviors that all rich-text editors exhibit, and that don't make sense for userland to have to re-invent for every new editor.
@@ -71,7 +71,7 @@ _To learn more, check out the [Core Plugin reference](../reference/slate-react/c
## The "Editor" Plugin ## The "Editor" Plugin
If you've read through the [`<Editor>` reference](../reference/slate-react/editor.md) you'll notice that the editor itself has handler like `onKeyDown`, `onClick`, etc. just like plugins. If you've read through the [`<Editor>` reference](../reference/slate-react/editor.md) you'll notice that the editor itself has handlers like `onKeyDown`, `onClick`, etc. just like plugins.
```js ```js
const plugins = [ const plugins = [
@@ -146,7 +146,7 @@ But hotkey binding logic by itself isn't a "feature". It's just a small helper t
### Feature Plugins ### Feature Plugins
Feature plugins are much larger in scope, and serve to define an entire series of behaviors that make up a single "feature" in your editor. They're not as concrete as util plugins, but they make reasoning about complex editors much simple. Feature plugins are much larger in scope, and serve to define an entire series of behaviors that make up a single "feature" in your editor. They're not as concrete as util plugins, but they make reasoning about complex editors much simpler.
For example, you maybe decide you want to allow **bold** formatting in your editor. To do that, you need a handful of different behaviors. For example, you maybe decide you want to allow **bold** formatting in your editor. To do that, you need a handful of different behaviors.
@@ -223,7 +223,7 @@ That said, there might be another type of plugins that kind of straddle the line
These are plugins that bundle up a set of logic, similar to how a feature might, but in a way that is re-usable across codebases. Some examples of these would be [`slate-edit-code`](https://github.com/GitbookIO/slate-edit-code), [`slate-edit-list`](https://github.com/GitbookIO/slate-edit-list), [`slate-edit-table`](https://github.com/GitbookIO/slate-edit-table), etc. These are plugins that bundle up a set of logic, similar to how a feature might, but in a way that is re-usable across codebases. Some examples of these would be [`slate-edit-code`](https://github.com/GitbookIO/slate-edit-code), [`slate-edit-list`](https://github.com/GitbookIO/slate-edit-list), [`slate-edit-table`](https://github.com/GitbookIO/slate-edit-table), etc.
Framework plugins will often expose objects with `changes`, `helpers` and `plugins` instead of simple array. Or, they may choose to just augment a single returned plugin object with some of the other exports. Framework plugins will often expose objects with `changes`, `helpers` and `plugins` instead of a simple array. Or, they may choose to just augment a single returned plugin object with some of the other exports.
You'll often want to encapsulate framework plugins in your own feature plugins, but they can go a long way in terms of reducing your codebase size. You'll often want to encapsulate framework plugins in your own feature plugins, but they can go a long way in terms of reducing your codebase size.
@@ -272,7 +272,7 @@ function YourBoldPlugin(options) {
### Accept Change Functions ### Accept Change Functions
It's common for a helper plugins to want to make some change based on an event that is triggered by the user. For example, when you want to write a plugin that adds a mark when a hotkey is pressed. It's common for helper plugins to want to make some change based on an event that is triggered by the user. For example, when you want to write a plugin that adds a mark when a hotkey is pressed.
If you write this in the naive way as taking a mark `type` string, users won't be able to add data associated with the mark in more complex cases. And if you accept a string or an object, what happens if the user wants to actually add two marks at once, or perform some other piece of logic. You'll have to keep adding esoteric options which make the plugin hard to maintain. If you write this in the naive way as taking a mark `type` string, users won't be able to add data associated with the mark in more complex cases. And if you accept a string or an object, what happens if the user wants to actually add two marks at once, or perform some other piece of logic. You'll have to keep adding esoteric options which make the plugin hard to maintain.
@@ -313,4 +313,3 @@ const plugins = [
}) })
] ]
``` ```

View File

@@ -29,9 +29,9 @@ function renderNode(props) {
} }
``` ```
> 🤖 Be sure to mix in `props.attributes` and render `props.children` in your node components! The attributes required for utilities like Slate's `findDOMNode`, and the children are the actual text content of your nodes. > 🤖 Be sure to mix in `props.attributes` and render `props.children` in your node components! The attributes are required for utilities like Slate's `findDOMNode`, and the children are the actual text content of your nodes.
Or course, you don't have to use simple HTML elements, you can use your own custom React components too: You don't have to use simple HTML elements, you can use your own custom React components too:
```js ```js
function renderNode(props) { function renderNode(props) {
@@ -143,6 +143,6 @@ function renderEditor(props) {
Here we're rendering a small word count number underneath all of the content of the editor. Whenever you change the content of the editor, `renderEditor` will be called, and the word count will be updated. Here we're rendering a small word count number underneath all of the content of the editor. Whenever you change the content of the editor, `renderEditor` will be called, and the word count will be updated.
This is very similar to how higher-order components work! Except it allows each plugin in Slate's plugin stack to add to wrap the editor's children. This is very similar to how higher-order components work! Except it allows each plugin in Slate's plugin stack to wrap the editor's children.
> 🤖 Be sure to remember to render `children` in your `renderEditor` functions, because that contains the editor's own elements! > 🤖 Be sure to remember to render `children` in your `renderEditor` functions, because that contains the editor's own elements!

View File

@@ -76,7 +76,7 @@ const schema = {
That's an example of defining your own custom `normalize` option for the document validation. If the invalid reason is `child_type_invalid`, it will set the child to be a `paragraph`. That's an example of defining your own custom `normalize` option for the document validation. If the invalid reason is `child_type_invalid`, it will set the child to be a `paragraph`.
When Slate discovers and invalid child, it will first check to see if your custom normalizer handles that case, and if it does Slate won't do any of its default behavior. That way you can opt-in to customizing the normalization logic for specific cases, without having to re-implement all of the defaults yourself. When Slate discovers an invalid child, it will first check to see if your custom normalizer handles that case, and if it does Slate won't do any of its default behavior. That way you can opt-in to customizing the normalization logic for specific cases, without having to re-implement all of the defaults yourself.
This gives you the best of both worlds. You can write simple, terse, declarative validation rules that can be highly optimized. But you can still define fine-grained, imperative normalization logic for when invalid states occur. This gives you the best of both worlds. You can write simple, terse, declarative validation rules that can be highly optimized. But you can still define fine-grained, imperative normalization logic for when invalid states occur.
@@ -89,7 +89,7 @@ Sometimes though, the declarative validation syntax isn't fine-grained enough to
> 🤖 Actually, under the covers the declarative schemas are all translated into `validateNode` functions too! > 🤖 Actually, under the covers the declarative schemas are all translated into `validateNode` functions too!
When you define a `validateNode` function, you either return nothing if ths node's already valid, or you return a normalizer function that will make the node valid if it isn't. Here's an example: When you define a `validateNode` function, you either return nothing if the node's already valid, or you return a normalizer function that will make the node valid if it isn't. Here's an example:
```js ```js
function validateNode(node) { function validateNode(node) {