mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-01-17 13:38:37 +01:00
Lint JSON, CSS and Markdown files with Prettier (#1612)
* Process and Lint CSS, Markdown and JSON files with Prettier * Run `yarn prettier` to re-format Markdown, CSS and JSON files
This commit is contained in:
parent
fc264841b6
commit
de4c9e478a
3
.github/ISSUE_TEMPLATE.md
vendored
3
.github/ISSUE_TEMPLATE.md
vendored
@ -1,5 +1,4 @@
|
||||
|
||||
#### Do you want to request a *feature* or report a *bug*?
|
||||
#### Do you want to request a _feature_ or report a _bug_?
|
||||
|
||||
<!--
|
||||
If you have a question, ask it in our Slack channel instead:
|
||||
|
21
Changelog.md
21
Changelog.md
@ -1,15 +1,14 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
Since Slate is a monorepo with many packages that are versioned separately, we maintain a changelog for each individual package:
|
||||
|
||||
- [`slate`](./packages/slate/Changelog.md)
|
||||
- [`slate-base64-serializer`](./packages/slate-base64-serializer/Changelog.md)
|
||||
- [`slate-dev-logger`](./packages/slate-dev-logger/Changelog.md)
|
||||
- [`slate-html-serializer`](./packages/slate-html-serializer/Changelog.md)
|
||||
- [`slate-hyperscript`](./packages/slate-hyperscript/Changelog.md)
|
||||
- [`slate-plain-serializer`](./packages/slate-plain-serializer/Changelog.md)
|
||||
- [`slate-prop-types`](./packages/slate-prop-types/Changelog.md)
|
||||
- [`slate-react`](./packages/slate-react/Changelog.md)
|
||||
- [`slate-schema-violations`](./packages/slate-schema-violations/Changelog.md)
|
||||
- [`slate-simulator`](./packages/slate-simulator/Changelog.md)
|
||||
* [`slate`](./packages/slate/Changelog.md)
|
||||
* [`slate-base64-serializer`](./packages/slate-base64-serializer/Changelog.md)
|
||||
* [`slate-dev-logger`](./packages/slate-dev-logger/Changelog.md)
|
||||
* [`slate-html-serializer`](./packages/slate-html-serializer/Changelog.md)
|
||||
* [`slate-hyperscript`](./packages/slate-hyperscript/Changelog.md)
|
||||
* [`slate-plain-serializer`](./packages/slate-plain-serializer/Changelog.md)
|
||||
* [`slate-prop-types`](./packages/slate-prop-types/Changelog.md)
|
||||
* [`slate-react`](./packages/slate-react/Changelog.md)
|
||||
* [`slate-schema-violations`](./packages/slate-schema-violations/Changelog.md)
|
||||
* [`slate-simulator`](./packages/slate-simulator/Changelog.md)
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright © 2016–2017, [Ian Storm Taylor](https://ianstormtaylor.com)
|
||||
|
88
Readme.md
88
Readme.md
@ -1,4 +1,3 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="#"><img src="./docs/images/banner.png" /></a>
|
||||
</p>
|
||||
@ -58,7 +57,6 @@ It can do this because all of its logic is implemented with a series of plugins,
|
||||
|
||||
_**Slate is currently in beta**. It's useable now, but you might need to pull request a fix or two for advanced use cases._
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
### Why?
|
||||
@ -67,27 +65,26 @@ Why create Slate? Well... _(Beware: this section has a few of [my](https://githu
|
||||
|
||||
Before creating Slate, I tried a lot of the other rich text libraries out there—[**Draft.js**](https://facebook.github.io/draft-js/), [**Prosemirror**](http://prosemirror.net/), [**Quill**](http://quilljs.com/), etc. What I found was that while getting simple examples to work was easy enough, once you started trying to build something like [Medium](https://medium.com/), [Dropbox Paper](https://www.dropbox.com/paper) or [Google Docs](https://www.google.com/docs/about/), you ran into deeper issues...
|
||||
|
||||
- **The editor's "schema" was hardcoded and hard to customize.** Things like bold and italic were supported out of the box, but what about comments, or embeds, or even more domain-specific needs?
|
||||
* **The editor's "schema" was hardcoded and hard to customize.** Things like bold and italic were supported out of the box, but what about comments, or embeds, or even more domain-specific needs?
|
||||
|
||||
- **Transforming the documents programmatically was very convoluted.** Writing as a user may have worked, but making programmatic changes, which is critical for building advanced behaviors, was needlessly complex.
|
||||
* **Transforming the documents programmatically was very convoluted.** Writing as a user may have worked, but making programmatic changes, which is critical for building advanced behaviors, was needlessly complex.
|
||||
|
||||
- **Serializing to HTML, Markdown, etc. seemed like an afterthought.** Simple things like transforming a document to HTML or Markdown involved writing lots of boilerplate code, for what seemed like very common use cases.
|
||||
* **Serializing to HTML, Markdown, etc. seemed like an afterthought.** Simple things like transforming a document to HTML or Markdown involved writing lots of boilerplate code, for what seemed like very common use cases.
|
||||
|
||||
- **Re-inventing the view layer seemed inefficient and limiting.** Most editors rolled their own views, instead of using existing technologies like React, so you have to learn a whole new system with new "gotchas".
|
||||
* **Re-inventing the view layer seemed inefficient and limiting.** Most editors rolled their own views, instead of using existing technologies like React, so you have to learn a whole new system with new "gotchas".
|
||||
|
||||
- **Collaborative editing wasn't designed for in advance.** Often the editor's internal representation of data made it impossible to use to for a realtime, collaborative editing use case without basically rewriting the editor.
|
||||
* **Collaborative editing wasn't designed for in advance.** Often the editor's internal representation of data made it impossible to use to for a realtime, collaborative editing use case without basically rewriting the editor.
|
||||
|
||||
- **The repostories were monolithic, not small and reusable.** The code bases for many of the editors often didn't expose the internal tooling that could have been re-used by developers, leading to having to reinvent the wheel.
|
||||
* **The repostories were monolithic, not small and reusable.** The code bases for many of the editors often didn't expose the internal tooling that could have been re-used by developers, leading to having to reinvent the wheel.
|
||||
|
||||
- **Building complex, nested documents was impossible.** Many editors were designed around simplistic "flat" documents, making things like tables, embeds and captions difficult to reason about and sometimes impossible.
|
||||
* **Building complex, nested documents was impossible.** Many editors were designed around simplistic "flat" documents, making things like tables, embeds and captions difficult to reason about and sometimes impossible.
|
||||
|
||||
Of course not every editor exhibits all of these issues, but if you've tried using another editor you might have run into similar problems. To get around the limitations of their API's and achieve the user experience you're after, you have to resort to very hacky things. And some experiences are just plain impossible to achieve.
|
||||
Of course not every editor exhibits all of these issues, but if you've tried using another editor you might have run into similar problems. To get around the limitations of their API's and achieve the user experience you're after, you have to resort to very hacky things. And some experiences are just plain impossible to achieve.
|
||||
|
||||
If that sounds familiar, you might like Slate.
|
||||
If that sounds familiar, you might like Slate.
|
||||
|
||||
Which brings me to how Slate solves all of that...
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
### Principles
|
||||
@ -100,16 +97,15 @@ Slate tries to solve the question of "[Why?](#why)" with a few principles:
|
||||
|
||||
3. **Nested document model.** The document model used for Slate is a nested, recursive tree, just like the DOM itself. This means that creating complex components like tables or nested block quotes are possible for advanced use cases. But it's also easy to keep it simple by only using a single level of hierarchy.
|
||||
|
||||
3. **Parallel to the DOM.** Slate's data model is based on the DOM—the document is a nested tree, it uses selections and ranges, and it exposes all the standard event handlers. This means that advanced behaviors like tables or nested block quotes are possible. Pretty much anything you can do in the DOM, you can do in Slate.
|
||||
4. **Parallel to the DOM.** Slate's data model is based on the DOM—the document is a nested tree, it uses selections and ranges, and it exposes all the standard event handlers. This means that advanced behaviors like tables or nested block quotes are possible. Pretty much anything you can do in the DOM, you can do in Slate.
|
||||
|
||||
4. **Stateless views and immutable data.** By using React and Immutable.js, the Slate editor is built in a stateless fashion using immutable data structures, which leads to much easier to reason about code, and a much easier time writing plugins.
|
||||
5. **Stateless views and immutable data.** By using React and Immutable.js, the Slate editor is built in a stateless fashion using immutable data structures, which leads to much easier to reason about code, and a much easier time writing plugins.
|
||||
|
||||
5. **Intuitive changes.** Slate documents are edited using "changes", that are designed to be high-level and extremely intuitive to write and read, so that custom functionality is as expressive as possible. This greatly increases your ability to reason about your code.
|
||||
6. **Intuitive changes.** Slate documents are edited using "changes", that are designed to be high-level and extremely intuitive to write and read, so that custom functionality is as expressive as possible. This greatly increases your ability to reason about your code.
|
||||
|
||||
6. **Collaboration-ready data model.** The data model Slate uses—specifically how changes are applied to the document—has been designed to allow for collaborative editing to be layered on top, so you won't need to rethink everything if you decide to make your editor collaborative.
|
||||
|
||||
7. **Clear "core" boundaries.** With a plugin-first architecture, and a schema-less core, it becomes a lot clearer where the boundary is between "core" and "custom", which means that the core experience doesn't get bogged down in edge cases.
|
||||
7. **Collaboration-ready data model.** The data model Slate uses—specifically how changes are applied to the document—has been designed to allow for collaborative editing to be layered on top, so you won't need to rethink everything if you decide to make your editor collaborative.
|
||||
|
||||
8. **Clear "core" boundaries.** With a plugin-first architecture, and a schema-less core, it becomes a lot clearer where the boundary is between "core" and "custom", which means that the core experience doesn't get bogged down in edge cases.
|
||||
|
||||
<br/>
|
||||
|
||||
@ -117,44 +113,41 @@ Slate tries to solve the question of "[Why?](#why)" with a few principles:
|
||||
|
||||
Check out the [**live demo**](http://slatejs.org) of all of the examples!
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
### Examples
|
||||
|
||||
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.
|
||||
- [**See all the examples...**](./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.
|
||||
* [**See all the examples...**](./examples)
|
||||
|
||||
If you have an idea for an example that shows a common use case, pull request it!
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
### Plugins
|
||||
|
||||
Slate encourages you to write small, reusable modules. Check out the public ones you can use in your project!
|
||||
|
||||
- [`slate-auto-replace`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-auto-replace) auto-replaces text as the user types. Useful for "smart" typography!
|
||||
- [`slate-collapse-on-escape`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-collapse-on-escape) simply collapses the selection when `escape` is pressed.
|
||||
- [`slate-edit-code`](https://github.com/GitbookIO/slate-edit-code) adds code editing behavior like tab-to-indent, and enter-to-soft-break.
|
||||
- [`slate-edit-list`](https://github.com/GitbookIO/slate-edit-list) adds rich, nested list editing behavior.
|
||||
- [`slate-edit-table`](https://github.com/GitbookIO/slate-edit-table) adds complex table editing behavior!
|
||||
- [`slate-paste-linkify`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-paste-linkify) wraps the selected text in a link when a URL is pasted from the clipboard.
|
||||
- [`slate-prism`](https://github.com/GitbookIO/slate-prism) highlights code blocks with [Prism.js](http://prismjs.com/)!
|
||||
- [`slate-soft-break`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-soft-break) adds a soft break when `enter` is pressed.
|
||||
- [`slate-drop-or-paste-images`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-drop-or-paste-images) lets users drop or paste images to insert them!
|
||||
- [**See all the plugins...**](./docs/general/plugins.md)
|
||||
|
||||
* [`slate-auto-replace`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-auto-replace) auto-replaces text as the user types. Useful for "smart" typography!
|
||||
* [`slate-collapse-on-escape`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-collapse-on-escape) simply collapses the selection when `escape` is pressed.
|
||||
* [`slate-edit-code`](https://github.com/GitbookIO/slate-edit-code) adds code editing behavior like tab-to-indent, and enter-to-soft-break.
|
||||
* [`slate-edit-list`](https://github.com/GitbookIO/slate-edit-list) adds rich, nested list editing behavior.
|
||||
* [`slate-edit-table`](https://github.com/GitbookIO/slate-edit-table) adds complex table editing behavior!
|
||||
* [`slate-paste-linkify`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-paste-linkify) wraps the selected text in a link when a URL is pasted from the clipboard.
|
||||
* [`slate-prism`](https://github.com/GitbookIO/slate-prism) highlights code blocks with [Prism.js](http://prismjs.com/)!
|
||||
* [`slate-soft-break`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-soft-break) adds a soft break when `enter` is pressed.
|
||||
* [`slate-drop-or-paste-images`](https://github.com/ianstormtaylor/slate-plugins/tree/master/packages/slate-drop-or-paste-images) lets users drop or paste images to insert them!
|
||||
* [**See all the plugins...**](./docs/general/plugins.md)
|
||||
|
||||
<br/>
|
||||
|
||||
@ -162,21 +155,20 @@ 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](http://docs.slatejs.org/walkthroughs/installing-slate) walkthroughs and the [Guides](http://docs.slatejs.org/guides) 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](http://docs.slatejs.org/slate-core).
|
||||
|
||||
- [**Walkthroughs**](http://docs.slatejs.org/walkthroughs/installing-slate)
|
||||
- [**Guides**](http://docs.slatejs.org/guides)
|
||||
- [**Reference**](http://docs.slatejs.org/slate-core)
|
||||
- [**FAQ**](http://docs.slatejs.org/general/faq)
|
||||
- [**Resources**](http://docs.slatejs.org/general/resources)
|
||||
* [**Walkthroughs**](http://docs.slatejs.org/walkthroughs/installing-slate)
|
||||
* [**Guides**](http://docs.slatejs.org/guides)
|
||||
* [**Reference**](http://docs.slatejs.org/slate-core)
|
||||
* [**FAQ**](http://docs.slatejs.org/general/faq)
|
||||
* [**Resources**](http://docs.slatejs.org/general/resources)
|
||||
|
||||
If even that's not enough, you can always [read the source itself](./src), which is heavily commented.
|
||||
|
||||
There are also translations of the documentation into other languages:
|
||||
|
||||
- [中文](https://doodlewind.github.io/slate-doc-cn/)
|
||||
* [中文](https://doodlewind.github.io/slate-doc-cn/)
|
||||
|
||||
If you're maintaining a translation, feel free to pull request it here!
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
### Contributing!
|
||||
|
@ -5,11 +5,7 @@
|
||||
"readme": "Introduction.md",
|
||||
"summary": "Readme.md"
|
||||
},
|
||||
"plugins": [
|
||||
"-highlight",
|
||||
"prism",
|
||||
"github"
|
||||
],
|
||||
"plugins": ["-highlight", "prism", "github"],
|
||||
"pluginsConfig": {
|
||||
"github": {
|
||||
"url": "https://github.com/ianstormtaylor/slate"
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Slate
|
||||
|
||||
[Slate](http://slatejs.org) is a _completely_ customizable framework for building rich text editors.
|
||||
@ -9,34 +8,32 @@ It can do this because all of its logic is implemented with a series of plugins,
|
||||
|
||||
_**Slate is currently in beta**. It's useable now, but you might need to pull request a fix or two for advanced use cases._
|
||||
|
||||
|
||||
## Why?
|
||||
|
||||
Why create Slate? Well... _(Beware: this section has a few of [my](https://github.com/ianstormtaylor) opinions!)_
|
||||
|
||||
Before creating Slate, I tried a lot of the other rich text libraries out there—[**Draft.js**](https://facebook.github.io/draft-js/), [**Prosemirror**](http://prosemirror.net/), [**Quill**](http://quilljs.com/), etc. What I found was that while getting simple examples to work was easy enough, once you started trying to build something like [Medium](https://medium.com/), [Dropbox Paper](https://www.dropbox.com/paper) or [Google Docs](https://www.google.com/docs/about/), you ran into deeper issues...
|
||||
|
||||
- **The editor's "schema" was hardcoded and hard to customize.** Things like bold and italic were supported out of the box, but what about comments, or embeds, or even more domain-specific needs?
|
||||
* **The editor's "schema" was hardcoded and hard to customize.** Things like bold and italic were supported out of the box, but what about comments, or embeds, or even more domain-specific needs?
|
||||
|
||||
- **Transforming the documents programmatically was very convoluted.** Writing as a user may have worked, but making programmatic changes, which is critical for building advanced behaviors, was needlessly complex.
|
||||
* **Transforming the documents programmatically was very convoluted.** Writing as a user may have worked, but making programmatic changes, which is critical for building advanced behaviors, was needlessly complex.
|
||||
|
||||
- **Serializing to HTML, Markdown, etc. seemed like an afterthought.** Simple things like transforming a document to HTML or Markdown involved writing lots of boilerplate code, for what seemed like very common use cases.
|
||||
* **Serializing to HTML, Markdown, etc. seemed like an afterthought.** Simple things like transforming a document to HTML or Markdown involved writing lots of boilerplate code, for what seemed like very common use cases.
|
||||
|
||||
- **Re-inventing the view layer seemed inefficient and limiting.** Most editors rolled their own views, instead of using existing technologies like React, so you have to learn a whole new system with new "gotchas".
|
||||
* **Re-inventing the view layer seemed inefficient and limiting.** Most editors rolled their own views, instead of using existing technologies like React, so you have to learn a whole new system with new "gotchas".
|
||||
|
||||
- **Collaborative editing wasn't designed for in advance.** Often the editor's internal representation of data made it impossible to use to for a realtime, collaborative editing use case without basically rewriting the editor.
|
||||
* **Collaborative editing wasn't designed for in advance.** Often the editor's internal representation of data made it impossible to use to for a realtime, collaborative editing use case without basically rewriting the editor.
|
||||
|
||||
- **The repostories were monolithic, not small and reusable.** The code bases for many of the editors often didn't expose the internal tooling that could have been re-used by developers, leading to having to reinvent the wheel.
|
||||
* **The repostories were monolithic, not small and reusable.** The code bases for many of the editors often didn't expose the internal tooling that could have been re-used by developers, leading to having to reinvent the wheel.
|
||||
|
||||
- **Building complex, nested documents was impossible.** Many editors were designed around simplistic "flat" documents, making things like tables, embeds and captions difficult to reason about and sometimes impossible.
|
||||
* **Building complex, nested documents was impossible.** Many editors were designed around simplistic "flat" documents, making things like tables, embeds and captions difficult to reason about and sometimes impossible.
|
||||
|
||||
Of course not every editor exhibits all of these issues, but if you've tried using another editor you might have run into similar problems. To get around the limitations of their API's and achieve the user experience you're after, you have to resort to very hacky things. And some experiences are just plain impossible to achieve.
|
||||
Of course not every editor exhibits all of these issues, but if you've tried using another editor you might have run into similar problems. To get around the limitations of their API's and achieve the user experience you're after, you have to resort to very hacky things. And some experiences are just plain impossible to achieve.
|
||||
|
||||
If that sounds familiar, you might like Slate.
|
||||
If that sounds familiar, you might like Slate.
|
||||
|
||||
Which brings me to how Slate solves all of that...
|
||||
|
||||
|
||||
## Principles
|
||||
|
||||
Slate tries to solve the question of "[Why?](#why)" with a few principles:
|
||||
@ -47,74 +44,69 @@ Slate tries to solve the question of "[Why?](#why)" with a few principles:
|
||||
|
||||
3. **Nested document model.** The document model used for Slate is a nested, recursive tree, just like the DOM itself. This means that creating complex components like tables or nested block quotes are possible for advanced use cases. But it's also easy to keep it simple by only using a single level of hierarchy.
|
||||
|
||||
3. **Parallel to the DOM.** Slate's data model is based on the DOM—the document is a nested tree, it uses selections and ranges, and it exposes all the standard event handlers. This means that advanced behaviors like tables or nested block quotes are possible. Pretty much anything you can do in the DOM, you can do in Slate.
|
||||
4. **Parallel to the DOM.** Slate's data model is based on the DOM—the document is a nested tree, it uses selections and ranges, and it exposes all the standard event handlers. This means that advanced behaviors like tables or nested block quotes are possible. Pretty much anything you can do in the DOM, you can do in Slate.
|
||||
|
||||
4. **Stateless views and immutable data.** By using React and Immutable.js, the Slate editor is built in a stateless fashion using immutable data structures, which leads to much easier to reason about code, and a much easier time writing plugins.
|
||||
5. **Stateless views and immutable data.** By using React and Immutable.js, the Slate editor is built in a stateless fashion using immutable data structures, which leads to much easier to reason about code, and a much easier time writing plugins.
|
||||
|
||||
5. **Intuitive changes.** Slate documents are edited using "changes", that are designed to be high-level and extremely intuitive to write and read, so that custom functionality is as expressive as possible. This greatly increases your ability to reason about your code.
|
||||
6. **Intuitive changes.** Slate documents are edited using "changes", that are designed to be high-level and extremely intuitive to write and read, so that custom functionality is as expressive as possible. This greatly increases your ability to reason about your code.
|
||||
|
||||
6. **Collaboration-ready data model.** The data model Slate uses—specifically how changes are applied to the document—has been designed to allow for collaborative editing to be layered on top, so you won't need to rethink everything if you decide to make your editor collaborative.
|
||||
|
||||
7. **Clear "core" boundaries.** With a plugin-first architecture, and a schema-less core, it becomes a lot clearer where the boundary is between "core" and "custom", which means that the core experience doesn't get bogged down in edge cases.
|
||||
7. **Collaboration-ready data model.** The data model Slate uses—specifically how changes are applied to the document—has been designed to allow for collaborative editing to be layered on top, so you won't need to rethink everything if you decide to make your editor collaborative.
|
||||
|
||||
8. **Clear "core" boundaries.** With a plugin-first architecture, and a schema-less core, it becomes a lot clearer where the boundary is between "core" and "custom", which means that the core experience doesn't get bogged down in edge cases.
|
||||
|
||||
## Demo
|
||||
|
||||
Check out the [**live demo**](http://slatejs.org) of all of the examples!
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
To get a sense for how you might use Slate, check out a few of the examples:
|
||||
|
||||
- [**Plain text**](https://github.com/ianstormtaylor/slate/tree/master/examples/plain-text) — showing the most basic case: a glorified `<textarea>`.
|
||||
- [**Rich text**](https://github.com/ianstormtaylor/slate/tree/master/examples/rich-text) — showing the features you'd expect from a basic editor.
|
||||
- [**Auto-markdown**](https://github.com/ianstormtaylor/slate/tree/master/examples/markdown-preview) — showing how to add key handlers for Markdown-like shortcuts.
|
||||
- [**Links**](https://github.com/ianstormtaylor/slate/tree/master/examples/links) — showing how wrap text in inline nodes with associated data.
|
||||
- [**Images**](https://github.com/ianstormtaylor/slate/tree/master/examples/images) — showing how to use void (text-less) nodes to add images.
|
||||
- [**Hovering menu**](https://github.com/ianstormtaylor/slate/tree/master/examples/hovering-menu) — showing how a contextual hovering menu can be implemented.
|
||||
- [**Tables**](https://github.com/ianstormtaylor/slate/tree/master/examples/tables) — showing how to nest blocks to render more advanced components.
|
||||
- [**Paste HTML**](https://github.com/ianstormtaylor/slate/tree/master/examples/paste-html) — showing how to use an HTML serializer to handle pasted HTML.
|
||||
- [**Code Highlighting**](https://github.com/ianstormtaylor/slate/tree/master/examples/code-highlighting) — showing how to use decorators to dynamically mark text.
|
||||
* [**Plain text**](https://github.com/ianstormtaylor/slate/tree/master/examples/plain-text) — showing the most basic case: a glorified `<textarea>`.
|
||||
* [**Rich text**](https://github.com/ianstormtaylor/slate/tree/master/examples/rich-text) — showing the features you'd expect from a basic editor.
|
||||
* [**Auto-markdown**](https://github.com/ianstormtaylor/slate/tree/master/examples/markdown-preview) — showing how to add key handlers for Markdown-like shortcuts.
|
||||
* [**Links**](https://github.com/ianstormtaylor/slate/tree/master/examples/links) — showing how wrap text in inline nodes with associated data.
|
||||
* [**Images**](https://github.com/ianstormtaylor/slate/tree/master/examples/images) — showing how to use void (text-less) nodes to add images.
|
||||
* [**Hovering menu**](https://github.com/ianstormtaylor/slate/tree/master/examples/hovering-menu) — showing how a contextual hovering menu can be implemented.
|
||||
* [**Tables**](https://github.com/ianstormtaylor/slate/tree/master/examples/tables) — showing how to nest blocks to render more advanced components.
|
||||
* [**Paste HTML**](https://github.com/ianstormtaylor/slate/tree/master/examples/paste-html) — showing how to use an HTML serializer to handle pasted HTML.
|
||||
* [**Code Highlighting**](https://github.com/ianstormtaylor/slate/tree/master/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!
|
||||
|
||||
|
||||
## Plugins
|
||||
|
||||
Slate encourages you to write small, reusable modules. Check out the public ones you can use in your project!
|
||||
|
||||
- [`slate-auto-replace`](https://github.com/ianstormtaylor/slate-auto-replace) auto-replaces text as the user types. Useful for "smart" typography!
|
||||
- [`slate-collapse-on-escape`](https://github.com/ianstormtaylor/slate-collapse-on-escape) simply collapses the selection when `escape` is pressed.
|
||||
- [`slate-edit-code`](https://github.com/GitbookIO/slate-edit-code) adds code editing behavior like tab-to-indent, and enter-to-soft-break.
|
||||
- [`slate-edit-list`](https://github.com/GitbookIO/slate-edit-list) adds rich, nested list editing behavior.
|
||||
- [`slate-edit-table`](https://github.com/GitbookIO/slate-edit-table) adds complex table editing behavior!
|
||||
- [`slate-paste-linkify`](https://github.com/ianstormtaylor/slate-paste-linkify) wraps the selected text in a link when a URL is pasted from the clipboard.
|
||||
- [`slate-prism`](https://github.com/GitbookIO/slate-prism) highlights code blocks with [Prism.js](http://prismjs.com/)!
|
||||
- [`slate-soft-break`](https://github.com/ianstormtaylor/slate-soft-break) adds a soft break when `enter` is pressed.
|
||||
- [`slate-drop-or-paste-images`](https://github.com/ianstormtaylor/slate-drop-or-paste-images) lets users drop or paste images to insert them!
|
||||
- [**View all plugins...**](https://github.com/ianstormtaylor/slate/blob/master/docs/general/plugins.md)
|
||||
|
||||
* [`slate-auto-replace`](https://github.com/ianstormtaylor/slate-auto-replace) auto-replaces text as the user types. Useful for "smart" typography!
|
||||
* [`slate-collapse-on-escape`](https://github.com/ianstormtaylor/slate-collapse-on-escape) simply collapses the selection when `escape` is pressed.
|
||||
* [`slate-edit-code`](https://github.com/GitbookIO/slate-edit-code) adds code editing behavior like tab-to-indent, and enter-to-soft-break.
|
||||
* [`slate-edit-list`](https://github.com/GitbookIO/slate-edit-list) adds rich, nested list editing behavior.
|
||||
* [`slate-edit-table`](https://github.com/GitbookIO/slate-edit-table) adds complex table editing behavior!
|
||||
* [`slate-paste-linkify`](https://github.com/ianstormtaylor/slate-paste-linkify) wraps the selected text in a link when a URL is pasted from the clipboard.
|
||||
* [`slate-prism`](https://github.com/GitbookIO/slate-prism) highlights code blocks with [Prism.js](http://prismjs.com/)!
|
||||
* [`slate-soft-break`](https://github.com/ianstormtaylor/slate-soft-break) adds a soft break when `enter` is pressed.
|
||||
* [`slate-drop-or-paste-images`](https://github.com/ianstormtaylor/slate-drop-or-paste-images) lets users drop or paste images to insert them!
|
||||
* [**View all plugins...**](https://github.com/ianstormtaylor/slate/blob/master/docs/general/plugins.md)
|
||||
|
||||
## Documentation
|
||||
|
||||
If you're using Slate for the first time, check out the [Getting Started](http://docs.slatejs.org/walkthroughs/installing-slate) walkthroughs and the [Guides](http://docs.slatejs.org/guides) 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](http://docs.slatejs.org/slate-core).
|
||||
|
||||
- [**Walkthroughs**](http://docs.slatejs.org/walkthroughs/installing-slate)
|
||||
- [**Guides**](http://docs.slatejs.org/guides)
|
||||
- [**Reference**](http://docs.slatejs.org/slate-core)
|
||||
- [**FAQ**](http://docs.slatejs.org/general/faq)
|
||||
- [**Resources**](http://docs.slatejs.org/general/resources)
|
||||
* [**Walkthroughs**](http://docs.slatejs.org/walkthroughs/installing-slate)
|
||||
* [**Guides**](http://docs.slatejs.org/guides)
|
||||
* [**Reference**](http://docs.slatejs.org/slate-core)
|
||||
* [**FAQ**](http://docs.slatejs.org/general/faq)
|
||||
* [**Resources**](http://docs.slatejs.org/general/resources)
|
||||
|
||||
If even that's not enough, you can always [read the source itself](./src), which is heavily commented.
|
||||
|
||||
There are also translations of the documentation into other languages:
|
||||
|
||||
- [中文](https://doodlewind.github.io/slate-doc-cn/)
|
||||
* [中文](https://doodlewind.github.io/slate-doc-cn/)
|
||||
|
||||
If you're maintaining a translation, feel free to pull request it here!
|
||||
|
||||
|
||||
## Contributing!
|
||||
|
||||
All contributions are super welcome! Check out the [Contributing instructions](./Contributing.md) for more info!
|
||||
|
110
docs/Readme.md
110
docs/Readme.md
@ -1,77 +1,69 @@
|
||||
|
||||
- [Introduction](./Introduction.md)
|
||||
|
||||
* [Introduction](./Introduction.md)
|
||||
|
||||
## Walkthroughs
|
||||
|
||||
- [Installing Slate](./walkthroughs/installing-slate.md)
|
||||
- [Adding Event Handlers](./walkthroughs/adding-event-handlers.md)
|
||||
- [Defining Custom Block Nodes](./walkthroughs/defining-custom-block-nodes.md)
|
||||
- [Applying Custom Formatting](./walkthroughs/applying-custom-formatting.md)
|
||||
- [Using Plugins](./walkthroughs/using-plugins.md)
|
||||
- [Saving to a Database](./walkthroughs/saving-to-a-database.md)
|
||||
- [Saving and Loading HTML Content](./walkthroughs/saving-and-loading-html-content.md)
|
||||
|
||||
* [Installing Slate](./walkthroughs/installing-slate.md)
|
||||
* [Adding Event Handlers](./walkthroughs/adding-event-handlers.md)
|
||||
* [Defining Custom Block Nodes](./walkthroughs/defining-custom-block-nodes.md)
|
||||
* [Applying Custom Formatting](./walkthroughs/applying-custom-formatting.md)
|
||||
* [Using Plugins](./walkthroughs/using-plugins.md)
|
||||
* [Saving to a Database](./walkthroughs/saving-to-a-database.md)
|
||||
* [Saving and Loading HTML Content](./walkthroughs/saving-and-loading-html-content.md)
|
||||
|
||||
## Guides
|
||||
|
||||
- [Changes](./guides/changes.md)
|
||||
- [Data Model](./guides/data-model.md)
|
||||
- [Plugins](./guides/plugins.md)
|
||||
- [Rendering](./guides/rendering.md)
|
||||
- [Schemas](./guides/schemas.md)
|
||||
|
||||
* [Changes](./guides/changes.md)
|
||||
* [Data Model](./guides/data-model.md)
|
||||
* [Plugins](./guides/plugins.md)
|
||||
* [Rendering](./guides/rendering.md)
|
||||
* [Schemas](./guides/schemas.md)
|
||||
|
||||
## General
|
||||
|
||||
- [Plugins](./general/plugins.md)
|
||||
- [Resources](./general/resources.md)
|
||||
- [Contributing](../Contributing.md)
|
||||
- [Changelog](./general/changelog.md)
|
||||
- [FAQ](./general/faq.md)
|
||||
|
||||
* [Plugins](./general/plugins.md)
|
||||
* [Resources](./general/resources.md)
|
||||
* [Contributing](../Contributing.md)
|
||||
* [Changelog](./general/changelog.md)
|
||||
* [FAQ](./general/faq.md)
|
||||
|
||||
## Slate Core
|
||||
|
||||
- [Block](./reference/slate/block.md)
|
||||
- [Change](./reference/slate/change.md)
|
||||
- [Character](./reference/slate/character.md)
|
||||
- [Data](./reference/slate/data.md)
|
||||
- [Document](./reference/slate/document.md)
|
||||
- [Inline](./reference/slate/inline.md)
|
||||
- [Mark](./reference//slate/mark.md)
|
||||
- [Node](./reference/slate/node.md)
|
||||
- [Operation](./reference/slate/operation.md)
|
||||
- [Range](./reference/slate/range.md)
|
||||
- [Schema](./reference/slate/schema.md)
|
||||
- [Text](./reference/slate/text.md)
|
||||
- [Value](./reference/slate/value.md)
|
||||
- [setKeyGenerator](./reference/slate/utils.md)
|
||||
- [resetKeyGenerator](./reference/slate/utils.md)
|
||||
|
||||
* [Block](./reference/slate/block.md)
|
||||
* [Change](./reference/slate/change.md)
|
||||
* [Character](./reference/slate/character.md)
|
||||
* [Data](./reference/slate/data.md)
|
||||
* [Document](./reference/slate/document.md)
|
||||
* [Inline](./reference/slate/inline.md)
|
||||
* [Mark](./reference//slate/mark.md)
|
||||
* [Node](./reference/slate/node.md)
|
||||
* [Operation](./reference/slate/operation.md)
|
||||
* [Range](./reference/slate/range.md)
|
||||
* [Schema](./reference/slate/schema.md)
|
||||
* [Text](./reference/slate/text.md)
|
||||
* [Value](./reference/slate/value.md)
|
||||
* [setKeyGenerator](./reference/slate/utils.md)
|
||||
* [resetKeyGenerator](./reference/slate/utils.md)
|
||||
|
||||
## Slate React
|
||||
|
||||
- [Editor](./reference/slate-react/editor.md)
|
||||
- [Plugins](./reference/slate-react/plugins.md)
|
||||
- [Custom Nodes](./reference/slate-react/custom-nodes.md)
|
||||
- [Core Plugins](./reference/slate-react/core-plugins.md)
|
||||
- [cloneFragment](./reference/slate-react/utils.md)
|
||||
- [findDOMNode](./reference/slate-react/utils.md)
|
||||
- [findDOMRange](./reference/slate-react/utils.md)
|
||||
- [findNode](./reference/slate-react/utils.md)
|
||||
- [findRange](./reference/slate-react/utils.md)
|
||||
- [getEventRange](./reference/slate-react/utils.md)
|
||||
- [getEventTransfer](./reference/slate-react/utils.md)
|
||||
- [setEventTransfer](./reference/slate-react/utils.md)
|
||||
|
||||
* [Editor](./reference/slate-react/editor.md)
|
||||
* [Plugins](./reference/slate-react/plugins.md)
|
||||
* [Custom Nodes](./reference/slate-react/custom-nodes.md)
|
||||
* [Core Plugins](./reference/slate-react/core-plugins.md)
|
||||
* [cloneFragment](./reference/slate-react/utils.md)
|
||||
* [findDOMNode](./reference/slate-react/utils.md)
|
||||
* [findDOMRange](./reference/slate-react/utils.md)
|
||||
* [findNode](./reference/slate-react/utils.md)
|
||||
* [findRange](./reference/slate-react/utils.md)
|
||||
* [getEventRange](./reference/slate-react/utils.md)
|
||||
* [getEventTransfer](./reference/slate-react/utils.md)
|
||||
* [setEventTransfer](./reference/slate-react/utils.md)
|
||||
|
||||
## Other Packages
|
||||
|
||||
- [`slate-html-serializer`](./reference/slate-html-serializer/index.md)
|
||||
- [`slate-hyperscript`](./reference/slate-hyperscript/index.md)
|
||||
- [`slate-plain-serializer`](./reference/slate-plain-serializer/index.md)
|
||||
- [`slate-prop-types`](./reference/slate-prop-types/index.md)
|
||||
- [`slate-schema-violations`](./reference/slate-schema-violations/index.md)
|
||||
- [`slate-simulator`](./reference/slate-simulator/index.md)
|
||||
|
||||
* [`slate-html-serializer`](./reference/slate-html-serializer/index.md)
|
||||
* [`slate-hyperscript`](./reference/slate-hyperscript/index.md)
|
||||
* [`slate-plain-serializer`](./reference/slate-plain-serializer/index.md)
|
||||
* [`slate-prop-types`](./reference/slate-prop-types/index.md)
|
||||
* [`slate-schema-violations`](./reference/slate-schema-violations/index.md)
|
||||
* [`slate-simulator`](./reference/slate-simulator/index.md)
|
||||
|
@ -1,15 +1,14 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
Since Slate is a monorepo with many packages that are versioned separately, we maintain a changelog for each individual package:
|
||||
|
||||
- [`slate`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate/Changelog.md)
|
||||
- [`slate-base64-serializer`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-base64-serializer/Changelog.md)
|
||||
- [`slate-dev-logger`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-dev-logger/Changelog.md)
|
||||
- [`slate-html-serializer`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-html-serializer/Changelog.md)
|
||||
- [`slate-hyperscript`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-hyperscript/Changelog.md)
|
||||
- [`slate-plain-serializer`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-plain-serializer/Changelog.md)
|
||||
- [`slate-prop-types`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-prop-types/Changelog.md)
|
||||
- [`slate-react`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-react/Changelog.md)
|
||||
- [`slate-schema-violations`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-schema-violations/Changelog.md)
|
||||
- [`slate-simulator`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-simulator/Changelog.md)
|
||||
* [`slate`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate/Changelog.md)
|
||||
* [`slate-base64-serializer`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-base64-serializer/Changelog.md)
|
||||
* [`slate-dev-logger`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-dev-logger/Changelog.md)
|
||||
* [`slate-html-serializer`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-html-serializer/Changelog.md)
|
||||
* [`slate-hyperscript`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-hyperscript/Changelog.md)
|
||||
* [`slate-plain-serializer`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-plain-serializer/Changelog.md)
|
||||
* [`slate-prop-types`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-prop-types/Changelog.md)
|
||||
* [`slate-react`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-react/Changelog.md)
|
||||
* [`slate-schema-violations`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-schema-violations/Changelog.md)
|
||||
* [`slate-simulator`](https://github.com/ianstormtaylor/slate/tree/master/packages/slate-simulator/Changelog.md)
|
||||
|
@ -1,12 +1,10 @@
|
||||
|
||||
# FAQ
|
||||
|
||||
A series of common questions people have about Slate:
|
||||
|
||||
- [Why is content pasted as plain text?](#why-is-content-is-pasted-as-plain-text)
|
||||
- [What can a `Block` node have as its children?](#what-can-a-block-node-have-as-its-children)
|
||||
- [What browsers and devices does Slate support?](#what-browsers-and-devices-does-slate-support)
|
||||
|
||||
* [Why is content pasted as plain text?](#why-is-content-is-pasted-as-plain-text)
|
||||
* [What can a `Block` node have as its children?](#what-can-a-block-node-have-as-its-children)
|
||||
* [What browsers and devices does Slate support?](#what-browsers-and-devices-does-slate-support)
|
||||
|
||||
### Why is content pasted as plain text?
|
||||
|
||||
@ -16,14 +14,12 @@ For this most part, this leads to increased flexbility without many downsides, b
|
||||
|
||||
Since Slate knows nothing about your schema, it can't know how to parse pasted HTML content (or other content). So, by default whenever a user pastes content into a Slate editor, it will parse it as plain text. If you want it to be smarter about pasted content, you need to define an [`onPaste`](../reference/slate-react/editor.md#onpaste) handler that parses the content as you wish.
|
||||
|
||||
|
||||
### What can a `Block` node have as its children?
|
||||
|
||||
With Slate, you can use `Block` node to created complex nested structures. Block nodes may contain nested block nodes (both void and non-void), inline nodes, text nodes and just regular DOM elements (with `contentEditable = {false}`).
|
||||
|
||||
If you have an element that is not going to be editable, you can choose between a `void` node or just a DOM element with `contentEditable = {false}`. Opt for the `void` node if you would like it represented in the Slate schema, and for Slate to be aware of it.
|
||||
|
||||
|
||||
### What browsers and devices does Slate support?
|
||||
|
||||
Slate's goal is to support all the modern browsers on both desktop and mobile devices.
|
||||
|
@ -1,57 +1,52 @@
|
||||
|
||||
# Plugins
|
||||
|
||||
Here's a list of Slate plugins, organized by category, so that they're easier to find than searching NPM or Yarn.
|
||||
|
||||
|
||||
### Behavior
|
||||
|
||||
Plugins that add specific behaviors to your editor.
|
||||
|
||||
|**Plugin**|**Description**|**Downloads**|
|
||||
|---|---|---|
|
||||
|[`slate-auto-replace`](https://yarnpkg.com/en/package/slate-auto-replace)|Automatically transform certain input as a user types.|![](https://img.shields.io/npm/dm/slate-auto-replace.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-collapse-on-escape`](https://yarnpkg.com/en/package/slate-collapse-on-escape)|Collapse the selection when users hit <kbd>esc</kbd>.|![](https://img.shields.io/npm/dm/slate-collapse-on-escape.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-drop-or-paste-images`](https://yarnpkg.com/en/package/slate-drop-or-paste-images)|Allows users to insert images by drag-dropping or copy-pasting.|![](https://img.shields.io/npm/dm/slate-drop-or-paste-images.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-edit-blockquote`](https://yarnpkg.com/en/package/slate-edit-blockquote)|Adds blockquote editing behaviors to an editor.|![](https://img.shields.io/npm/dm/slate-edit-blockquote.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-edit-code`](https://yarnpkg.com/en/package/slate-edit-code)|Adds code block editing behaviors to an editor.|![](https://img.shields.io/npm/dm/slate-edit-code.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-edit-footnote`](https://yarnpkg.com/en/package/slate-edit-footnote)|Adds footnote editing behaviors to an editor.|![](https://img.shields.io/npm/dm/slate-edit-footnote.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-edit-list`](https://yarnpkg.com/en/package/slate-edit-list)|Adds list editing behaviors to an editor.|![](https://img.shields.io/npm/dm/slate-edit-list.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-edit-table`](https://yarnpkg.com/en/package/slate-edit-table)|Adds common table editing behaviors to an editor.|![](https://img.shields.io/npm/dm/slate-edit-table.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-no-empty`](https://yarnpkg.com/en/package/slate-no-empty)|Prevents documents from being empty.|![](https://img.shields.io/npm/dm/slate-no-empty.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-paste-linkify`](https://yarnpkg.com/en/package/slate-paste-linkify)|Automatically linkify URLs when they are pasted.|![](https://img.shields.io/npm/dm/slate-paste-linkify.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-soft-break`](https://yarnpkg.com/en/package/slate-soft-break)|Adds soft breaks when users hit <kbd>enter</kbd>.|![](https://img.shields.io/npm/dm/slate-soft-break.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-sticky-inlines`](https://yarnpkg.com/en/package/slate-sticky-inlines)|Changes the inline node behavior to allow editing at the edges.|![](https://img.shields.io/npm/dm/slate-sticky-inlines.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-suggestions`](https://yarnpkg.com/en/package/slate-suggestions)|Displays inline auto-completed suggestions.|![](https://img.shields.io/npm/dm/slate-suggestions.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-trailing-block`](https://yarnpkg.com/en/package/slate-trailing-block)|Ensure that documents end in a specific kind of block.|![](https://img.shields.io/npm/dm/slate-trailing-block.svg?maxAge=3600&label=⬇)|
|
||||
|
||||
| **Plugin** | **Description** | **Downloads** |
|
||||
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| [`slate-auto-replace`](https://yarnpkg.com/en/package/slate-auto-replace) | Automatically transform certain input as a user types. | ![](https://img.shields.io/npm/dm/slate-auto-replace.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-collapse-on-escape`](https://yarnpkg.com/en/package/slate-collapse-on-escape) | Collapse the selection when users hit <kbd>esc</kbd>. | ![](https://img.shields.io/npm/dm/slate-collapse-on-escape.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-drop-or-paste-images`](https://yarnpkg.com/en/package/slate-drop-or-paste-images) | Allows users to insert images by drag-dropping or copy-pasting. | ![](https://img.shields.io/npm/dm/slate-drop-or-paste-images.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-edit-blockquote`](https://yarnpkg.com/en/package/slate-edit-blockquote) | Adds blockquote editing behaviors to an editor. | ![](https://img.shields.io/npm/dm/slate-edit-blockquote.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-edit-code`](https://yarnpkg.com/en/package/slate-edit-code) | Adds code block editing behaviors to an editor. | ![](https://img.shields.io/npm/dm/slate-edit-code.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-edit-footnote`](https://yarnpkg.com/en/package/slate-edit-footnote) | Adds footnote editing behaviors to an editor. | ![](https://img.shields.io/npm/dm/slate-edit-footnote.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-edit-list`](https://yarnpkg.com/en/package/slate-edit-list) | Adds list editing behaviors to an editor. | ![](https://img.shields.io/npm/dm/slate-edit-list.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-edit-table`](https://yarnpkg.com/en/package/slate-edit-table) | Adds common table editing behaviors to an editor. | ![](https://img.shields.io/npm/dm/slate-edit-table.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-no-empty`](https://yarnpkg.com/en/package/slate-no-empty) | Prevents documents from being empty. | ![](https://img.shields.io/npm/dm/slate-no-empty.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-paste-linkify`](https://yarnpkg.com/en/package/slate-paste-linkify) | Automatically linkify URLs when they are pasted. | ![](https://img.shields.io/npm/dm/slate-paste-linkify.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-soft-break`](https://yarnpkg.com/en/package/slate-soft-break) | Adds soft breaks when users hit <kbd>enter</kbd>. | ![](https://img.shields.io/npm/dm/slate-soft-break.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-sticky-inlines`](https://yarnpkg.com/en/package/slate-sticky-inlines) | Changes the inline node behavior to allow editing at the edges. | ![](https://img.shields.io/npm/dm/slate-sticky-inlines.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-suggestions`](https://yarnpkg.com/en/package/slate-suggestions) | Displays inline auto-completed suggestions. | ![](https://img.shields.io/npm/dm/slate-suggestions.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-trailing-block`](https://yarnpkg.com/en/package/slate-trailing-block) | Ensure that documents end in a specific kind of block. | ![](https://img.shields.io/npm/dm/slate-trailing-block.svg?maxAge=3600&label=⬇) |
|
||||
|
||||
### Components
|
||||
|
||||
Components for building Slate editors.
|
||||
|
||||
|**Plugin**|**Description**|**Downloads**|
|
||||
|---|---|---|
|
||||
|[`slate-editor-icons`](https://yarnpkg.com/en/package/slate-editor-icons)|A set of icons for using in toolbars, etc.|![](https://img.shields.io/npm/dm/slate-editor-icons.svg?maxAge=3600&label=⬇)|
|
||||
|
||||
| **Plugin** | **Description** | **Downloads** |
|
||||
| ------------------------------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- |
|
||||
| [`slate-editor-icons`](https://yarnpkg.com/en/package/slate-editor-icons) | A set of icons for using in toolbars, etc. | ![](https://img.shields.io/npm/dm/slate-editor-icons.svg?maxAge=3600&label=⬇) |
|
||||
|
||||
### Serializers
|
||||
|
||||
Serializers for handling Slate data.
|
||||
|
||||
|**Plugin**|**Description**|**Downloads**|
|
||||
|---|---|---|
|
||||
|[`slate-base64-serializer`](https://yarnpkg.com/en/package/slate-base64-serializer)|A base64 string serializer for Slate documents.|![](https://img.shields.io/npm/dm/slate-base64-serializer.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-html-serializer`](https://yarnpkg.com/en/package/slate-html-serializer)|An HTML serializer for Slate documents.|![](https://img.shields.io/npm/dm/slate-html-serializer.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-plain-serializer`](https://yarnpkg.com/en/package/slate-plain-serializer)|A plain text serializer for Slate documents.|![](https://img.shields.io/npm/dm/slate-plain-serializer.svg?maxAge=3600&label=⬇)|
|
||||
|
||||
| **Plugin** | **Description** | **Downloads** |
|
||||
| ----------------------------------------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| [`slate-base64-serializer`](https://yarnpkg.com/en/package/slate-base64-serializer) | A base64 string serializer for Slate documents. | ![](https://img.shields.io/npm/dm/slate-base64-serializer.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-html-serializer`](https://yarnpkg.com/en/package/slate-html-serializer) | An HTML serializer for Slate documents. | ![](https://img.shields.io/npm/dm/slate-html-serializer.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-plain-serializer`](https://yarnpkg.com/en/package/slate-plain-serializer) | A plain text serializer for Slate documents. | ![](https://img.shields.io/npm/dm/slate-plain-serializer.svg?maxAge=3600&label=⬇) |
|
||||
|
||||
### Utils
|
||||
|
||||
Useful utilities when working with Slate documents and components.
|
||||
|
||||
|**Plugin**|**Description**|**Downloads**|
|
||||
|---|---|---|
|
||||
|[`slate-hyperprint`](https://yarnpkg.com/en/package/slate-hyperprint)|Prints Slate documents in their `slate-hyperscript` format.|![](https://img.shields.io/npm/dm/slate-hyperprint.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-hyperscript`](https://yarnpkg.com/en/package/slate-hyperscript)|Allows you to express Slate documents in JSX.|![](https://img.shields.io/npm/dm/slate-hyperscript.svg?maxAge=3600&label=⬇)|
|
||||
|[`slate-prop-types`](https://yarnpkg.com/en/package/slate-prop-types)|A set of prop types to use in your Slate components.|![](https://img.shields.io/npm/dm/slate-prop-types.svg?maxAge=3600&label=⬇)|
|
||||
| **Plugin** | **Description** | **Downloads** |
|
||||
| ----------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| [`slate-hyperprint`](https://yarnpkg.com/en/package/slate-hyperprint) | Prints Slate documents in their `slate-hyperscript` format. | ![](https://img.shields.io/npm/dm/slate-hyperprint.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-hyperscript`](https://yarnpkg.com/en/package/slate-hyperscript) | Allows you to express Slate documents in JSX. | ![](https://img.shields.io/npm/dm/slate-hyperscript.svg?maxAge=3600&label=⬇) |
|
||||
| [`slate-prop-types`](https://yarnpkg.com/en/package/slate-prop-types) | A set of prop types to use in your Slate components. | ![](https://img.shields.io/npm/dm/slate-prop-types.svg?maxAge=3600&label=⬇) |
|
||||
|
@ -1,21 +1,17 @@
|
||||
|
||||
# Resources
|
||||
|
||||
A few resources that are helpful for building with Slate.
|
||||
|
||||
|
||||
## Libraries
|
||||
|
||||
- [`is-hotkey`](https://github.com/ianstormtaylor/is-hotkey) is a simple way to check whether an `onKeyDown` handler should fire for a given hotkey, handling cross-platform concerns like <kbd>cmd</kbd> vs. <kbd>ctrl</kbd> keys for you automatically.
|
||||
- [`react-broadcast`](https://github.com/ReactTraining/react-broadcast) works well when you need to have your custom node components re-render based on state that lives outside the `document`. It's the same pattern that `react-router` uses to update `<Link>` components.
|
||||
|
||||
* [`is-hotkey`](https://github.com/ianstormtaylor/is-hotkey) is a simple way to check whether an `onKeyDown` handler should fire for a given hotkey, handling cross-platform concerns like <kbd>cmd</kbd> vs. <kbd>ctrl</kbd> keys for you automatically.
|
||||
* [`react-broadcast`](https://github.com/ReactTraining/react-broadcast) works well when you need to have your custom node components re-render based on state that lives outside the `document`. It's the same pattern that `react-router` uses to update `<Link>` components.
|
||||
|
||||
## Tooling
|
||||
|
||||
- [Immutable.js Console Extension](https://github.com/mattzeunert/immutable-object-formatter-extension) — this greatly improves the `console.log` output when working with [Immutable.js](https://facebook.github.io/immutable-js/) objects, which Slate's data model is based on.
|
||||
|
||||
* [Immutable.js Console Extension](https://github.com/mattzeunert/immutable-object-formatter-extension) — this greatly improves the `console.log` output when working with [Immutable.js](https://facebook.github.io/immutable-js/) objects, which Slate's data model is based on.
|
||||
|
||||
## Showcase
|
||||
|
||||
- [ORY Editor](https://editor.ory.am/) — a self-contained, inline WYSIWYG editor library built on top of Slate.
|
||||
- [Nossas Editor](http://slate-editor.bonde.org/) — a drop-in WYSIWYG editor built with Slate.
|
||||
* [ORY Editor](https://editor.ory.am/) — a self-contained, inline WYSIWYG editor library built on top of Slate.
|
||||
* [Nossas Editor](http://slate-editor.bonde.org/) — a drop-in WYSIWYG editor built with Slate.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Changes
|
||||
|
||||
All changes to a Slate editor's value, whether it's the `selection`, `document`, `history`, etc. happen via "changes"—specifically, via the [`Change`](../reference/slate/change.md) model.
|
||||
@ -7,7 +6,6 @@ This is important because the `Change` model is responsible for ensuring that ev
|
||||
|
||||
You just need to understand changes...
|
||||
|
||||
|
||||
## Expressiveness is Key
|
||||
|
||||
Changes in Slate are designed to prioritize expressiveness above almost all else.
|
||||
@ -43,7 +41,6 @@ To that end, Slate defines _lots_ of change methods.
|
||||
|
||||
The change methods are the one place in Slate where overlap and near-duplication isn't stomped out. Because sometimes the exact-right change method is the difference between one line of code and ten. And not just ten once, but ten repeated everywhere throughout your codebase.
|
||||
|
||||
|
||||
## Change Categories
|
||||
|
||||
There are a handful of different categories of changes that ship with Slate by default, and understanding them may help you understand which methods to reach for when trying to write your editor's logic...
|
||||
@ -72,7 +69,6 @@ These are changes like `setData()`, `setDecorations()`, etc. that act on the oth
|
||||
|
||||
These are changes like `undo()`, `redo()`, etc. that use the operation history and redo or undo changes that have already happened. You generally don't need to worry about these, because they're already bound to the keyboard shortcuts you'd expect, and the user can use them.
|
||||
|
||||
|
||||
## Making Changes
|
||||
|
||||
When you decide you want to make a change to the Slate value, you're almost always in one of four places...
|
||||
@ -99,20 +95,15 @@ In that case, you'll need to use the `change()` method on the Slate [`<Editor>`]
|
||||
|
||||
```js
|
||||
class Image extends React.Component {
|
||||
|
||||
onClick = (event) => {
|
||||
this.props.editor.change((change) => {
|
||||
onClick = event => {
|
||||
this.props.editor.change(change => {
|
||||
change.removeNodeByKey(this.props.node.key)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
<img
|
||||
{...this.props.attributes}
|
||||
onClick={this.onClick}
|
||||
/>
|
||||
;<img {...this.props.attributes} onClick={this.onClick} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -146,7 +137,8 @@ This is the fourth place you might want to make changes, and also the most dange
|
||||
That said, if that's okay with you, you can make changes manually by using the `change()` method on a Slate [`Value`](../reference/slate/value.md). For example:
|
||||
|
||||
```js
|
||||
const change = value.change()
|
||||
const change = value
|
||||
.change()
|
||||
.selectAll()
|
||||
.delete()
|
||||
|
||||
@ -155,7 +147,6 @@ const newValue = change.value
|
||||
|
||||
Note that you'll need to then grab the new value by accessing the `change.value` property directly.
|
||||
|
||||
|
||||
## Reusing Changes
|
||||
|
||||
In addition to using the built-in changes, if your editor is of any complexity you'll want to write your own reusable changes. That way, you can reuse a single `insertImage` change instead of constantly writing `insertBlock(...args)`.
|
||||
@ -183,9 +174,7 @@ Notice how rewriting that image inserting logic multiple times without having it
|
||||
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:
|
||||
|
||||
```js
|
||||
change
|
||||
.call(insertParagraph)
|
||||
.call(insertImage, 'https://google.com/logo')
|
||||
change.call(insertParagraph).call(insertImage, 'https://google.com/logo')
|
||||
```
|
||||
|
||||
Not only can you use them with `.call()`, but if you're making one-off changes to the `editor`, you can use them with `editor.change()` as well. For example:
|
||||
|
@ -1,9 +1,7 @@
|
||||
|
||||
# Data Model
|
||||
|
||||
Slate is based on an immutable data model that closely resembles the DOM. When you start using Slate, one of the most important things to do is familiarize yourself with this data model. This guide will help you do just that!
|
||||
|
||||
|
||||
## Mirror the DOM
|
||||
|
||||
One of the main principles of Slate is that it tries to mirror the native DOM API's as much as possible.
|
||||
@ -12,7 +10,6 @@ If you think about it, this makes sense. Slate is kind of like a nicer implement
|
||||
|
||||
Because it mirrors the DOM, Slate's data model features a [`Document`](../reference/slate/document.md) with [`Block`](../reference/slate/block.md), [`Inline`](../reference/slate/inline.md) and [`Text`](../reference/slate/text.md) nodes. You can reference parts of the document with a [`Range`](../reference/slate/range.md). And there is a special range called a "selection" that represents the user's current cursor selection.
|
||||
|
||||
|
||||
## Immutable Objects
|
||||
|
||||
Slate's data model is built out of [`Immutable.js`](https://facebook.github.io/immutable-js/) objects. This allows us to make rendering much more performant, and it ensures that we don't end up with hard to track down bugs.
|
||||
@ -23,7 +20,7 @@ Specifically, Slate's models are [`Immutable.Record`](https://facebook.github.io
|
||||
const block = Block.create({ type: 'paragraph' })
|
||||
|
||||
block.object // "block"
|
||||
block.type // "paragraph"
|
||||
block.type // "paragraph"
|
||||
```
|
||||
|
||||
But for updating values, you'll need to use the [`Immutable.Record` API](https://facebook.github.io/immutable-js/docs/#/Record/set).
|
||||
@ -32,7 +29,6 @@ Collections of Slate objects are represented as immutable `Lists`, `Sets`, `Stac
|
||||
|
||||
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 top-level object in Slate—the object encapsulates the entire value of an Slate editor—is called a [`Value`](../reference/slate/value.md).
|
||||
@ -41,31 +37,29 @@ It is made up of a document filled with content, and a selection representing th
|
||||
|
||||
> 📋 For more info, check out the [`Value` reference](../reference/slate/value.md).
|
||||
|
||||
|
||||
## Documents and Nodes
|
||||
|
||||
Slate documents are nested and recursive. This means that a document has block nodes, and those block nodes can have child block nodes—all the way down. This lets you model more complex nested behaviors like tables, or figures with captions.
|
||||
|
||||
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 <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.
|
||||
|
||||
- **Inlines can only contain inline or text nodes.** This one is also for sanity and avoiding boilerplate. Once you've descended into an "inline" context, you can't have block nodes inside them.
|
||||
* **Inlines can only contain inline or text nodes.** This one is also for sanity and avoiding boilerplate. Once you've descended into an "inline" context, you can't have block nodes inside them.
|
||||
|
||||
- **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 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.
|
||||
* **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.
|
||||
|
||||
Slate enforces all of these restrictions for you automatically. Any time you [perform changes](./changes.md) to the document, Slate will check if the document is invalid, and if so it will return it to a "normalized" value.
|
||||
|
||||
> 🙃 Fun fact: normalizing is actually based on the DOM's [`Node.normalize()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/normalize)!
|
||||
|
||||
In addition to documents, blocks and inlines, Slate introduces one other type of markup that the DOM doesn't have natively: the [`Mark`](../reference/slate/mark.md).
|
||||
|
||||
In addition to documents, blocks and inlines, Slate introduces one other type of markup that the DOM doesn't have natively: the [`Mark`](../reference/slate/mark.md).
|
||||
|
||||
## Marks
|
||||
|
||||
@ -93,9 +87,8 @@ And if you happened to add another overlapping section of `<strike>` to that tex
|
||||
|
||||
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...
|
||||
|
||||
- Marks represent **unordered**, character-level formatting.
|
||||
- Inlines represent **contiguous**, semantic elements in the document.
|
||||
|
||||
* Marks represent **unordered**, character-level formatting.
|
||||
* Inlines represent **contiguous**, semantic elements in the document.
|
||||
|
||||
## Ranges and "The Selection"
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Plugins
|
||||
|
||||
With Slate, _all_ of your editor's logic is controlled by "plugins".
|
||||
@ -7,7 +6,6 @@ Plugins have complete control over the schema, the behaviors, and the rendering
|
||||
|
||||
Slate encourages you to break up code into small, reusable modules that can be shared with others, and easily reasoned about.
|
||||
|
||||
|
||||
## What Are Plugins?
|
||||
|
||||
Slate's plugins are simply a collection of functions that all contribute to a shared behavior—each with a specific name and set of arguments. For a full list of the arguments, check out the [`Plugins` reference](../reference/slate-react/plugins.md).
|
||||
@ -33,7 +31,6 @@ It focuses the editor and selects everything when it is clicked, and it blurs th
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## The Plugins "Stack"
|
||||
|
||||
Slate's editor takes a list of plugins as one of its arguments. We refer to this list as the plugins "stack". It is very similar to "middleware" from Express or Koa.
|
||||
@ -53,7 +50,6 @@ When the editor needs to handle a DOM event, or decide what to render, it will l
|
||||
|
||||
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".
|
||||
|
||||
|
||||
## "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.
|
||||
@ -68,7 +64,6 @@ For the most part you don't need to worry about the core plugins. The before plu
|
||||
|
||||
_To learn more, check out the [Core Plugin reference](../reference/slate-react/core-plugins.md)._
|
||||
|
||||
|
||||
## The "Editor" Plugin
|
||||
|
||||
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.
|
||||
@ -102,7 +97,6 @@ const plugins = [
|
||||
|
||||
This isn't something you need to remember, but it's helpful to know that even the top-level editor props are just another plugin!
|
||||
|
||||
|
||||
## Helper Plugins vs. Feature Plugins
|
||||
|
||||
Plugins _can_ do anything and everything. But that doesn't mean you should build plugins that are thousands of lines long that implement every single feature in your editor—your codebase would become hell to maintain. Instead, just like all modules, you should split them up into pieces with separate concerns.
|
||||
@ -124,7 +118,7 @@ function Hotkey(hotkey, fn) {
|
||||
if (isHotkey(hotkey, event)) {
|
||||
change.call(fn)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -227,7 +221,6 @@ Framework plugins will often expose objects with `changes`, `helpers` and `plugi
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
When you're writing plugins, there are a few patterns to follow that will make your plugins more flexible, and more familiar for others.
|
||||
@ -283,7 +276,7 @@ const plugins = [
|
||||
AddMark({
|
||||
hotkey: 'cmd+b',
|
||||
change: change => change.addMark('bold'),
|
||||
})
|
||||
}),
|
||||
]
|
||||
```
|
||||
|
||||
@ -294,22 +287,19 @@ const plugins = [
|
||||
AddMark({
|
||||
hotkey: 'cmd+opt+c',
|
||||
change: change => {
|
||||
change
|
||||
.addMark({ type: 'comment', data: { id: userId }})
|
||||
.selectAll()
|
||||
}
|
||||
})
|
||||
change.addMark({ type: 'comment', data: { id: userId } }).selectAll()
|
||||
},
|
||||
}),
|
||||
]
|
||||
```
|
||||
|
||||
And what's even better, since it's a common practice to write change function helpers in your codebase to reuse, users can usually just pass in one of the functions they've already defined:
|
||||
|
||||
```js
|
||||
|
||||
const plugins = [
|
||||
AddMark({
|
||||
hotkey: 'cmd+b',
|
||||
change: addBoldMark,
|
||||
})
|
||||
}),
|
||||
]
|
||||
```
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Rendering
|
||||
|
||||
One of the best parts of Slate is that it's built with React, so it fits right into your existing application. It doesn't re-invent its own view layer that you have to learn. It tries to keep everything as React-y as possible.
|
||||
@ -7,7 +6,6 @@ To that end, Slate gives you control over the rendering behavior of every node a
|
||||
|
||||
You can define these behaviors by passing `props` into the editor, or you can define them in Slate plugins.
|
||||
|
||||
|
||||
## Nodes & Marks
|
||||
|
||||
Using custom components for the nodes and marks is the most common rendering need. Slate makes this easy to do, you just define a `renderNode` function.
|
||||
@ -19,8 +17,10 @@ function renderNode(props) {
|
||||
const { node, attributes, children } = props
|
||||
|
||||
switch (node.type) {
|
||||
case 'paragraph': return <p {...attributes}>{children}</p>
|
||||
case 'quote': return <blockquote {...attributes}>{children}</blockquote>
|
||||
case 'paragraph':
|
||||
return <p {...attributes}>{children}</p>
|
||||
case 'quote':
|
||||
return <blockquote {...attributes}>{children}</blockquote>
|
||||
case 'image': {
|
||||
const src = node.data.get('src')
|
||||
return <img {...attributes} src={src} />
|
||||
@ -71,11 +71,16 @@ Marks work the same way, except they invoke the `renderMark` function. Like so:
|
||||
function renderMark(props) {
|
||||
const { children, mark } = props
|
||||
switch (mark.type) {
|
||||
case 'bold': return <strong>{children}</strong>
|
||||
case 'italic': return <em>{children}</em>
|
||||
case 'code': return <code>{children}</code>
|
||||
case 'underline': return <u>{children}</u>
|
||||
case 'strikethrough': return <strike>{children}</strike>
|
||||
case 'bold':
|
||||
return <strong>{children}</strong>
|
||||
case 'italic':
|
||||
return <em>{children}</em>
|
||||
case 'code':
|
||||
return <code>{children}</code>
|
||||
case 'underline':
|
||||
return <u>{children}</u>
|
||||
case 'strikethrough':
|
||||
return <strike>{children}</strike>
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -84,7 +89,6 @@ That way, if you happen to have a global stylesheet that defines `strong`, `em`,
|
||||
|
||||
> 🤖 Be aware though that marks aren't guaranteed to be "contiguous". Which means even though a **word** is bolded, it's not guaranteed to render as a single `<strong>` element. If some of its characters are also italic, it might be split up into multiple elements—one `<strong>wo</strong>` and one `<em><strong>rd</strong></em>`.
|
||||
|
||||
|
||||
## Placeholders
|
||||
|
||||
By default Slate will render a placeholder for you which mimics the native DOM `placeholder` attribute of `<input>` and `<textarea>` elements—it's in the same typeface as the editor, and it's slightly translucent. And as soon as the document has any content, the placeholder disappears.
|
||||
@ -116,7 +120,6 @@ function renderPlaceholder(props) {
|
||||
|
||||
That will render a simple placeholder element inside all of the your `caption` blocks until someone decides to write in a caption.
|
||||
|
||||
|
||||
## The Editor Itself
|
||||
|
||||
Not only can you control the rendering behavior of the components inside the editor, but you can also control the rendering of the editor itself.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Schemas
|
||||
|
||||
One of Slate's principles is that it doesn't assume anything about the type of content you're building an editor for. Some editors will want **bold**, _italic_, ~~strikethrough~~, and some won't. Some will want comments and highlighting, some won't. You _can_ build all of these things with Slate, but Slate doesn't assume anything out of the box.
|
||||
@ -9,7 +8,6 @@ That said, just because Slate is agnostic doesn't mean you aren't going to need
|
||||
|
||||
To that end, Slate provides a `Schema` model, which allows you to easily define validations for the structure of your documents, and to fix them if the document ever becomes invalid. This guide will show you how they work.
|
||||
|
||||
|
||||
## Basic Schemas
|
||||
|
||||
Slate schemas are defined as Javascript objects, with properties that describe the document, block nodes, and inlines nodes in your editor. Here's a simple schema:
|
||||
@ -17,23 +15,19 @@ Slate schemas are defined as Javascript objects, with properties that describe t
|
||||
```js
|
||||
const schema = {
|
||||
document: {
|
||||
nodes: [
|
||||
{ types: ['paragraph', 'image'] }
|
||||
]
|
||||
nodes: [{ types: ['paragraph', 'image'] }],
|
||||
},
|
||||
blocks: {
|
||||
paragraph: {
|
||||
nodes: [
|
||||
{ objects: ['text'] }
|
||||
]
|
||||
nodes: [{ objects: ['text'] }],
|
||||
},
|
||||
image: {
|
||||
isVoid: true,
|
||||
data: {
|
||||
src: v => v && isUrl(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
src: v => v && isUrl(v),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
@ -47,7 +41,6 @@ That magic is that by passing a schema like this into your editor, it will autom
|
||||
|
||||
This way you can guarantee that the data is in a format that you expect, so you don't have to handle tons of edge-cases or invalid states in your own code.
|
||||
|
||||
|
||||
## Custom Normalizers
|
||||
|
||||
By default, Slate will normalize any invalid states to ensure that the document is valid again. However, since Slate doesn't have that much information about your schema, its default normalization techniques might not always be what you want.
|
||||
@ -82,7 +75,6 @@ This gives you the best of both worlds. You can write simple, terse, declarative
|
||||
|
||||
> 🤖 For a full list of validation `reason` arguments, check out the [`Schema` reference](../reference/slate/schema.md).
|
||||
|
||||
|
||||
## Custom Validations
|
||||
|
||||
Sometimes though, the declarative validation syntax isn't fine-grained enough to handle a specific piece of validation. That's okay, because you can actually define schema validations in Slate as regular functions when you need more control, using the `validateNode` property of plugins and editors.
|
||||
@ -101,7 +93,7 @@ function validateNode(node) {
|
||||
if (nodes.first().object != 'text') return
|
||||
if (nodes.last().object != 'text') return
|
||||
|
||||
return (change) => {
|
||||
return change => {
|
||||
change.removeNodeByKey(node.key)
|
||||
}
|
||||
}
|
||||
@ -117,7 +109,7 @@ However, only use it when you absolutely have to. And when you do, you need to b
|
||||
|
||||
Some normalizations will require multiple `change` function calls in order to complete. But after calling the first change function, the resulting document will be normalized, changing it out from under you. This can cause unintended behaviors.
|
||||
|
||||
Consider the following validation function that merges adjacent text nodes together.
|
||||
Consider the following validation function that merges adjacent text nodes together.
|
||||
|
||||
Note: This functionality is already correctly implemented in slate-core so you don't need to put it in yourself!
|
||||
|
||||
@ -164,7 +156,7 @@ The above validation function can then be written as below
|
||||
* @type {Object}
|
||||
*/
|
||||
validateNode(node) {
|
||||
...
|
||||
...
|
||||
return (change) => {
|
||||
change.withoutNormalization((c) => {
|
||||
// Reverse the list to handle consecutive merges, since the earlier nodes
|
||||
@ -175,4 +167,4 @@ validateNode(node) {
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `slate-html-serializer`
|
||||
|
||||
```js
|
||||
@ -9,7 +8,6 @@ The HTML serializer lets you parse and stringify arbitrary HTML content, based o
|
||||
|
||||
For an example of the HTML serializer in action, check out the [`paste-html` example](../../../examples/paste-html).
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```txt
|
||||
@ -18,28 +16,30 @@ For an example of the HTML serializer in action, check out the [`paste-html` exa
|
||||
<p>Check out <a href="http://slatejs.org">http://slatejs.org</a> for examples!</p>
|
||||
```
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
new Html({
|
||||
rules: Array,
|
||||
defaultBlock: String|Object|Block,
|
||||
defaultBlock: String | Object | Block,
|
||||
parseHtml: Function,
|
||||
})
|
||||
```
|
||||
|
||||
### `rules`
|
||||
|
||||
`Array`
|
||||
|
||||
An array of rules to initialize the HTML serializer with, defining your schema.
|
||||
|
||||
### `defaultBlock`
|
||||
|
||||
`String|Object|Block`
|
||||
|
||||
A set of properties to use for blocks which do not match any rule. Can be a string such as `'paragraph'` or an object with a `type` attribute such as `{ type: 'paragraph' }`, or even a [`Block`](../slate/block.md).
|
||||
|
||||
### `parseHtml`
|
||||
|
||||
`Function`
|
||||
|
||||
A function to parse an HTML string and return a DOM object. Defaults to using the native `DOMParser` in browser environments that support it. For older browsers or server-side rendering, you can include the [jsdom](https://www.npmjs.com/package/jsdom) package and pass `JSDOM.fragment` as the `parseHtml` option.
|
||||
@ -49,6 +49,7 @@ This parse function should return the `<body>` node of the DOM.
|
||||
## Methods
|
||||
|
||||
### `Html.deserialize`
|
||||
|
||||
`Html.deserialize(html: String, [options: Object]) => Value`
|
||||
|
||||
Deserialize an HTML `string` into a [`Value`](../slate/value.md). How the string is deserialized will be determined by the rules that the HTML serializer was constructed with.
|
||||
@ -56,13 +57,13 @@ Deserialize an HTML `string` into a [`Value`](../slate/value.md). How the string
|
||||
If you pass `toJSON: true` as an option, the return value will be a JSON object instead of a [`Value`](../slate/value.md) object.
|
||||
|
||||
### `Html.serialize`
|
||||
|
||||
`Html.serialize(value: Value, [options: Object]) => String || Array`
|
||||
|
||||
Serialize a `value` into an HTML string. How the string is serialized will be determined by the rules that the HTML serializer was constructed with.
|
||||
|
||||
If you pass `render: false` as an option, the return value will instead be an iterable list of the top-level React elements, to be rendered as children in your own React component.
|
||||
|
||||
|
||||
## Rules
|
||||
|
||||
To initialize an HTML serializer, you must pass it an array of rules, defining your schema. Each rule defines how to deserialize and serialize a node or mark, by implementing two functions.
|
||||
@ -76,8 +77,8 @@ Each rule must define two properties:
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `rule.deserialize`
|
||||
|
||||
`rule.deserialize(el: Element, next: Function) => Object || Void`
|
||||
|
||||
The `deserialize` function receives a DOM element and should return a plain Javascript object representing the deserialized value, or nothing if the rule in question doesn't know how to deserialize the object, in which case the next rule in the stack will be attempted.
|
||||
@ -112,8 +113,8 @@ The object should be one of:
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `rule.serialize`
|
||||
|
||||
`rule.serialize(object: Node || Mark || String, children: String || Element || Array) => Element || Void`
|
||||
|
||||
The `serialize` function should return a React element representing the serialized HTML, or nothing if the rule in question doesn't know how to serialize the object, in which case the next rule in the stack will be attempted.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `slate-hyperscript`
|
||||
|
||||
```js
|
||||
@ -8,7 +7,6 @@ import { createHyperscript } from 'slate-hyperscript'
|
||||
|
||||
A hyperscript helper for writing Slate documents with JSX!
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
@ -20,7 +18,11 @@ const value = (
|
||||
<value>
|
||||
<document>
|
||||
<block type="paragraph">
|
||||
A string of <mark type="bold">bold</mark> in a <inline type="link" data={{ src: 'http://slatejs.org' }}>Slate</inline> editor!
|
||||
A string of <mark type="bold">bold</mark> in a{' '}
|
||||
<inline type="link" data={{ src: 'http://slatejs.org' }}>
|
||||
Slate
|
||||
</inline>{' '}
|
||||
editor!
|
||||
</block>
|
||||
<block type="image" data={{ src: 'https://...' }} isVoid />
|
||||
</document>
|
||||
@ -39,7 +41,7 @@ const h = createHyperscript({
|
||||
image: {
|
||||
type: 'image',
|
||||
isVoid: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
inlines: {
|
||||
link: 'link',
|
||||
@ -53,7 +55,8 @@ const value = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
A string of <b>bold</b> in a <link src="http://slatejs.org">Slate</link> editor!
|
||||
A string of <b>bold</b> in a <link src="http://slatejs.org">Slate</link>{' '}
|
||||
editor!
|
||||
</paragraph>
|
||||
<image src="https://..." />
|
||||
</document>
|
||||
@ -61,15 +64,16 @@ const value = (
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
## Exports
|
||||
|
||||
### `h`
|
||||
|
||||
`Function`
|
||||
|
||||
The default export of `slate-hyperscript` is a barebones hyperscript helper that you can immediately start using to create Slate objects.
|
||||
|
||||
### `createHyperscript`
|
||||
|
||||
`createHyperscript(options: Object) => Function`
|
||||
|
||||
The other export is a `createHyperscript` helper that you can use to create your own, smarter, schema-aware hyperscript helper. You can pass it `options` that tell it about your schema to make creating objects much terser.
|
||||
@ -82,4 +86,3 @@ The other export is a `createHyperscript` helper that you can use to create your
|
||||
creators: Object,
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `slate-plain-serializer`
|
||||
|
||||
```js
|
||||
@ -7,7 +6,6 @@ import Plain from 'slate-plain-serializer'
|
||||
|
||||
A serializer that converts a Slate [`Value`](../slate/value.md) to and from a plain text string.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```txt
|
||||
@ -16,10 +14,10 @@ In its simplest form, when representing plain text, Slate is a glorified <textar
|
||||
Check out http://slatejs.org for examples!
|
||||
```
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
### `Plain.deserialize`
|
||||
|
||||
`Plain.deserialize(string: String, [options: Object]) => Value`
|
||||
|
||||
Deserialize a plain text `string` into a [`Value`](../slate/value.md). A series of blocks will be created by splitting the input string on `\n` characters. Each block is given a type of `'line'`.
|
||||
@ -27,6 +25,7 @@ Deserialize a plain text `string` into a [`Value`](../slate/value.md). A series
|
||||
If you pass `toJSON: true` as an option, the return value will be a JSON object instead of a [`Value`](../slate/value.md) object.
|
||||
|
||||
### `Plain.serialize`
|
||||
|
||||
`Plain.serialize(value: Value) => String`
|
||||
|
||||
Serialize a `value` into a plain text string. Each direct child block of the document will be separated by a `\n` character.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `slate-prop-types`
|
||||
|
||||
```js
|
||||
@ -7,7 +6,6 @@ import Types from 'slate-prop-types'
|
||||
|
||||
A set of React prop types for Slate editors and plugins.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
@ -27,7 +25,6 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Exports
|
||||
|
||||
### `block`
|
||||
|
@ -1,9 +1,7 @@
|
||||
|
||||
# Core Plugin
|
||||
|
||||
Slate's editor is very unopinionated. The only logic it handles by default is logic associated with the `contenteditable` functionality itself—managing text, selections, etc. That logic is contained in two plugins, called the "core" plugins. One runs before all other plugins, and one runs after.
|
||||
|
||||
|
||||
## Default Behavior
|
||||
|
||||
The default behavior of the core plugin performs the following logic:
|
||||
@ -42,7 +40,7 @@ When the user pastes content into the editor, the core plugin handles all pastes
|
||||
|
||||
### `onSelect`
|
||||
|
||||
When the user makes a new selection in the DOM, the core plugin updates that selection in Slate's internal data model, re-rendering if it needs to.
|
||||
When the user makes a new selection in the DOM, the core plugin updates that selection in Slate's internal data model, re-rendering if it needs to.
|
||||
|
||||
### `render`
|
||||
|
||||
@ -54,12 +52,11 @@ The core plugin defines a schema that enforces a few constraints on the content
|
||||
|
||||
The default block component also controls its own placeholder logic, which is controlled via the [`<Editor>`](../slate-react/editor.md)'s placeholder options.
|
||||
|
||||
|
||||
## Overriding Defaults
|
||||
|
||||
Any plugin you add to the editor will override the default behavior of the core plugin, because it is always resolved last.
|
||||
|
||||
However, sometimes you might want to disable the logic of the core plugin without actually adding any logic yourself. For example, you might want to prevent the `enter` key from performing any action. In those cases, you'll need to define a "noop" handler.
|
||||
However, sometimes you might want to disable the logic of the core plugin without actually adding any logic yourself. For example, you might want to prevent the `enter` key from performing any action. In those cases, you'll need to define a "noop" handler.
|
||||
|
||||
A noop `onBeforeInput` handler looks like:
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
|
||||
# Custom Nodes
|
||||
|
||||
Slate will render custom nodes for [`Block`](../slate/block.md) and [`Inline`](../slate/inline.md) models, based on what you pass in as your schema. This allows you to completely customize the rendering behavior of your Slate editor.
|
||||
|
||||
|
||||
## Props
|
||||
|
||||
```js
|
||||
@ -19,15 +17,15 @@ Slate will render custom nodes for [`Block`](../slate/block.md) and [`Inline`](.
|
||||
```
|
||||
|
||||
### `attributes`
|
||||
|
||||
`Object`
|
||||
|
||||
A dictionary of DOM attributes that you must attach to the main DOM element of the node you render. For example:
|
||||
|
||||
```js
|
||||
return (
|
||||
<p {...props.attributes}>{props.children}</p>
|
||||
)
|
||||
return <p {...props.attributes}>{props.children}</p>
|
||||
```
|
||||
|
||||
```js
|
||||
return (
|
||||
<figure {...props.attributes}>
|
||||
@ -37,19 +35,17 @@ return (
|
||||
```
|
||||
|
||||
### `children`
|
||||
|
||||
`Object`
|
||||
|
||||
A set of React children elements that are composed of internal Slate components that handle all of the editing logic of the editor for you. You must render these as the children of your non-void nodes. For example:
|
||||
|
||||
```js
|
||||
return (
|
||||
<p {...props.attributes}>
|
||||
{props.children}
|
||||
</p>
|
||||
)
|
||||
return <p {...props.attributes}>{props.children}</p>
|
||||
```
|
||||
|
||||
### `editor`
|
||||
|
||||
`Editor`
|
||||
|
||||
A reference to the Slate [`<Editor>`](./editor.md) instance. This allows you to retrieve the current `value` of the editor, or perform a `change` on the value. For example:
|
||||
@ -57,28 +53,33 @@ A reference to the Slate [`<Editor>`](./editor.md) instance. This allows you to
|
||||
```js
|
||||
const value = editor.value
|
||||
```
|
||||
|
||||
```js
|
||||
editor.change((change) => {
|
||||
editor.change(change => {
|
||||
change.selectAll().delete()
|
||||
})
|
||||
```
|
||||
|
||||
### `isSelected`
|
||||
|
||||
`Boolean`
|
||||
|
||||
A boolean representing whether the node you are rendering is currently selected. You can use this to render a visual representation of the selection.
|
||||
|
||||
### `node`
|
||||
|
||||
`Node`
|
||||
|
||||
A reference to the [`Node`](../slate/node.md) being rendered.
|
||||
|
||||
### `parent`
|
||||
|
||||
`Node`
|
||||
|
||||
A reference to the parent of the current [`Node`](../slate/node.md) being rendered.
|
||||
|
||||
### `readOnly`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the editor is in "read-only" mode, where all of the rendering is the same, but the user is prevented from editing the editor's content.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `<Editor>`
|
||||
|
||||
```js
|
||||
@ -7,7 +6,6 @@ import { Editor } from 'slate-react'
|
||||
|
||||
The top-level React component that renders the Slate editor itself.
|
||||
|
||||
|
||||
## Props
|
||||
|
||||
```js
|
||||
@ -28,66 +26,77 @@ The top-level React component that renders the Slate editor itself.
|
||||
```
|
||||
|
||||
### `autoCorrect`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the editor should attempt to autocorrect spellcheck errors.
|
||||
|
||||
### `autoFocus`
|
||||
|
||||
`Boolean`
|
||||
|
||||
An optional attribute that, when set to true, attempts to give the content editable element focus when it's loaded onto the page.
|
||||
|
||||
### `className`
|
||||
|
||||
`String`
|
||||
|
||||
An optional class name to apply to the content editable element.
|
||||
|
||||
### `onChange`
|
||||
|
||||
`Function onChange(change: Change)`
|
||||
|
||||
A change handler that will be called with the `change` that applied the change. You should usually pass the newly changed `change.value` back into the editor through its `value` property. This hook allows you to add persistence logic to your editor.
|
||||
|
||||
### `placeholder`
|
||||
|
||||
`String || Element`
|
||||
|
||||
A placeholder string (or React element) that will be rendered as the default block type's placeholder.
|
||||
|
||||
### `plugins`
|
||||
|
||||
`Array`
|
||||
|
||||
An array of [`Plugins`](./plugins.md) that define the editor's behavior.
|
||||
|
||||
### `readOnly`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the editor should be in "read-only" mode, where all of the rendering is the same, but the user is prevented from editing the editor's content.
|
||||
|
||||
### `role`
|
||||
|
||||
`String`
|
||||
|
||||
ARIA property to define the role of the editor, it defaults to `textbox` when editable.
|
||||
|
||||
### `spellCheck`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether spellcheck is turned on for the editor.
|
||||
|
||||
### `style`
|
||||
|
||||
`Object`
|
||||
|
||||
An optional dictionary of styles to apply to the content editable element.
|
||||
|
||||
### `tabIndex`
|
||||
|
||||
`Number`
|
||||
|
||||
Indicates if it should participate to [sequential keyboard navigation](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex).
|
||||
|
||||
### `value`
|
||||
|
||||
`Value`
|
||||
|
||||
A [`Value`](../slate/value.md) object representing the current value of the editor.
|
||||
|
||||
|
||||
## Plugin-like Props
|
||||
|
||||
In addition to its own properties, the editor allows passing any of the properties that a [plugin](./plugins.md) defines as well.
|
||||
@ -125,28 +134,39 @@ const plugins = [
|
||||
```
|
||||
|
||||
### `onBeforeInput`
|
||||
|
||||
### `onBlur`
|
||||
|
||||
### `onFocus`
|
||||
|
||||
### `onCopy`
|
||||
|
||||
### `onCut`
|
||||
|
||||
### `onDrop`
|
||||
|
||||
### `onKeyDown`
|
||||
|
||||
### `onKeyUp`
|
||||
|
||||
### `onPaste`
|
||||
|
||||
### `onSelect`
|
||||
|
||||
### `schema`
|
||||
|
||||
To see how these properties behave, check out the [Plugins reference](./plugins.md).
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `blur`
|
||||
|
||||
`blur() => Void`
|
||||
|
||||
Programmatically blur the editor.
|
||||
|
||||
### `change`
|
||||
|
||||
`change(fn) => Void`
|
||||
`change(fn, ...args) => Void`
|
||||
|
||||
@ -155,24 +175,27 @@ Programmatically invoke a change `fn` on the editor. The function will be invokv
|
||||
If extra `...args` are passed in, the change `fn` will be invoked with `(change, ...args)`, so you can use this as a shorthand for performing single-function changes.
|
||||
|
||||
### `focus`
|
||||
|
||||
`focus() => Void`
|
||||
|
||||
Programmatically focus the editor.
|
||||
|
||||
|
||||
## Instance Properties
|
||||
|
||||
### `schema`
|
||||
|
||||
`Schema`
|
||||
|
||||
The editor's current schema.
|
||||
|
||||
### `stack`
|
||||
|
||||
`Stack`
|
||||
|
||||
The editor's current stack.
|
||||
|
||||
### `value`
|
||||
|
||||
`Value`
|
||||
|
||||
The editor's current value.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Plugins
|
||||
|
||||
Plugins can be attached to an editor to alter its behavior in different ways. Plugins are just simple Javascript objects, containing a set of properties that control different behaviors—event handling, change handling, rendering, etc.
|
||||
@ -7,7 +6,6 @@ Each editor has a "middleware stack" of plugins, which has a specific order.
|
||||
|
||||
When the editor needs to resolve a plugin-related handler, it will loop through its plugin stack, searching for the first plugin that successfully returns a value. After receiving that value, the editor will **not** continue to search the remaining plugins; it returns early. If you'd like for the stack to continue, a plugin handler should return `undefined`.
|
||||
|
||||
|
||||
## Conventions
|
||||
|
||||
A plugin should always export a function that takes options. This way even if it doesn't take any options now, it won't be a breaking API change to take more options in the future. So a basic plugin might look like this:
|
||||
@ -20,7 +18,6 @@ export default function MySlatePlugin(options) {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Event Handler Properties
|
||||
|
||||
```js
|
||||
@ -40,11 +37,12 @@ export default function MySlatePlugin(options) {
|
||||
|
||||
All of the event handler properties are passed the same React `event` object you are used to from React's event handlers. They are also passed a `change` object representing any changes that have resulted from the event, and the `editor` instance itself.
|
||||
|
||||
Each event handler can choose to call methods on the `change` object, in which case the editor's value will be updated.
|
||||
Each event handler can choose to call methods on the `change` object, in which case the editor's value will be updated.
|
||||
|
||||
If the return value of a plugin handler is `null`, the editor will simply continue resolving the plugin stack. However, if you return a non-null value, the editor will break out of the loop.
|
||||
|
||||
### `onBeforeInput`
|
||||
|
||||
`Function onBeforeInput(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called right before a string of text is inserted into the `contenteditable` element.
|
||||
@ -52,31 +50,37 @@ This handler is called right before a string of text is inserted into the `conte
|
||||
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
|
||||
|
||||
### `onBlur`
|
||||
|
||||
`Function onBlur(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when the editor's `contenteditable` element is blurred.
|
||||
This handler is called when the editor's `contenteditable` element is blurred.
|
||||
|
||||
### `onFocus`
|
||||
|
||||
`Function onFocus(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when the editor's `contenteditable` element is focused.
|
||||
|
||||
### `onCopy`
|
||||
|
||||
`Function onCopy(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when there is a copy event in the editor's `contenteditable` element.
|
||||
|
||||
### `onCut`
|
||||
|
||||
`Function onCut(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is equivalent to the `onCopy` handler.
|
||||
|
||||
### `onDrop`
|
||||
|
||||
`Function onDrop(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when the user drops content into the `contenteditable` element. The event is already prevented by default, so you must define a value change to have any affect occur.
|
||||
|
||||
### `onKeyDown`
|
||||
|
||||
`Function onKeyDown(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when any key is pressed in the `contenteditable` element, before any action is taken.
|
||||
@ -84,23 +88,25 @@ This handler is called when any key is pressed in the `contenteditable` element,
|
||||
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
|
||||
|
||||
### `onKeyUp`
|
||||
|
||||
`Function onKeyUp(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when any key is released in the `contenteditable` element.
|
||||
|
||||
### `onPaste`
|
||||
|
||||
`Function onPaste(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called when the user pastes content into the `contenteditable` element. The event is already prevented by default, so you must define a value change to have any affect occur.
|
||||
|
||||
### `onSelect`
|
||||
|
||||
`Function onSelect(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||
|
||||
This handler is called whenever the native DOM selection changes.
|
||||
This handler is called whenever the native DOM selection changes.
|
||||
|
||||
_Note: This is **not** Slate's internal selection representation (although it mirrors it). If you want to get notified when Slate's selection changes, use the [`onChange`](../slate-react/editor.md#onchange) property of the `<Editor>`. This handler is instead meant to give you lower-level access to the DOM selection handling, which **is not always triggered** as you'd expect._
|
||||
|
||||
|
||||
## Other Properties
|
||||
|
||||
```js
|
||||
@ -110,16 +116,19 @@ _Note: This is **not** Slate's internal selection representation (although it mi
|
||||
```
|
||||
|
||||
### `onChange`
|
||||
|
||||
`Function onChange(change: Change) => Any || Void`
|
||||
|
||||
The `onChange` handler isn't a native browser event handler. Instead, it is invoked whenever the editor value changes. This allows plugins to augment a change however they want.
|
||||
|
||||
### `renderEditor`
|
||||
|
||||
`Function renderEditor(props: Object, editor: Editor) => Object || Void`
|
||||
|
||||
The `renderEditor` property allows you to define higher-order-component-like behavior. It is passed all of the properties of the editor, including `props.children`. You can then choose to wrap the existing `children` in any custom elements or proxy the properties however you choose. This can be useful for rendering toolbars, styling the editor, rendering validation, etc. Remember that the `renderEditor` function has to render `props.children` for editor's children to render.
|
||||
|
||||
### `schema`
|
||||
|
||||
`Object`
|
||||
|
||||
The `schema` property allows you to define a set of rules that will be added to the editor's schema. The rules from each of the schemas returned by the plugins are collected into a single schema for the editor.
|
||||
|
@ -1,8 +1,7 @@
|
||||
|
||||
# Utils
|
||||
|
||||
```js
|
||||
import {
|
||||
import {
|
||||
cloneFragment,
|
||||
findDOMNode,
|
||||
findDOMRange,
|
||||
@ -16,10 +15,10 @@ import {
|
||||
|
||||
React-specific utility functions for Slate that may be useful in certain use cases.
|
||||
|
||||
|
||||
## Functions
|
||||
|
||||
### `cloneFragment`
|
||||
|
||||
`cloneFragment(event: DOMEvent|ReactEvent, value: Value, fragment: Document)`
|
||||
|
||||
During a cut or copy event, sets `fragment` as the Slate document fragment to be copied.
|
||||
@ -54,6 +53,7 @@ function onCut(event, change, editor) {
|
||||
```
|
||||
|
||||
### `findDOMNode`
|
||||
|
||||
`findDOMNode(node: Node) => DOMElement`
|
||||
|
||||
Find the DOM node from a Slate [`Node`](../slate/node.md). Modelled after React's built-in `findDOMNode` helper.
|
||||
@ -67,11 +67,12 @@ function componentDidUpdate() {
|
||||
```
|
||||
|
||||
### `findDOMRange`
|
||||
|
||||
`findDOMRange(range: Range) => DOMRange`
|
||||
|
||||
Find the DOM range from a Slate [`Range`](../slate/range.md).
|
||||
|
||||
```js
|
||||
```js
|
||||
function onChange(change) {
|
||||
const { value } = change
|
||||
const range = findDOMRange(value.selection)
|
||||
@ -80,6 +81,7 @@ function onChange(change) {
|
||||
```
|
||||
|
||||
### `findNode`
|
||||
|
||||
`findNode(element: DOMElement, value: Value) => Node`
|
||||
|
||||
Find the Slate node from a DOM `element` and Slate `value`.
|
||||
@ -92,6 +94,7 @@ function onSomeNativeEvent(event) {
|
||||
```
|
||||
|
||||
### `findRange`
|
||||
|
||||
`findRange(selection: DOMSelection, value: Value) => Range`
|
||||
`findRange(range: DOMRange, value: Value) => Range`
|
||||
|
||||
@ -110,6 +113,7 @@ function onSomeNativeEvent() {
|
||||
```
|
||||
|
||||
### `getEventRange`
|
||||
|
||||
`getEventRange(event: DOMEvent|ReactEvent, value: Value) => Range`
|
||||
|
||||
Get the affected Slate range from a DOM `event` and Slate `value`.
|
||||
@ -122,6 +126,7 @@ function onDrop(event, change, editor) {
|
||||
```
|
||||
|
||||
### `getEventTransfer`
|
||||
|
||||
`getEventTransfer(event: DOMEvent|ReactEvent) => Object`
|
||||
|
||||
Get the Slate-related data from a DOM `event` and Slate `value`.
|
||||
@ -138,6 +143,7 @@ function onDrop(event, change, editor) {
|
||||
```
|
||||
|
||||
### `setEventTransfer`
|
||||
|
||||
`setEventTransfer(event: DOMEvent|ReactEvent, type: String, data: Any)`
|
||||
|
||||
Sets the Slate-related `data` with `type` on an `event`. The `type` must be one of the types Slate recognizes: `'fragment'`, `'html'`, `'node'`, `'rich'`, or `'text'`.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `slate-schema-violations`
|
||||
|
||||
```js
|
||||
@ -22,7 +21,6 @@ import {
|
||||
|
||||
A set of constants for the built-in violations in a Slate schema.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
@ -42,7 +40,6 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Exports
|
||||
|
||||
### `CHILD_OBJECT_INVALID`
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `slate-simulator`
|
||||
|
||||
```js
|
||||
@ -7,7 +6,6 @@ import Simulator from 'slate-simulator'
|
||||
|
||||
A simulator to help writing tests for Slate editors and plugins. By default the simulator does not include the core plugins as they have a lot of dependencies on browser-specific globals, so running them in CI environments is very hard. If you need the core plugins for your use case you need to import them manually.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
@ -44,42 +42,49 @@ const simulator = new Simulator({ value, plugins })
|
||||
## Methods
|
||||
|
||||
### `beforeInput`
|
||||
|
||||
`beforeInput(event: Object) => Simulator`
|
||||
|
||||
Simulator a `beforeinput` event with an `event` object.
|
||||
|
||||
### `blur`
|
||||
|
||||
`blur(event: Object) => Simulator`
|
||||
|
||||
Simulator a `blur` event with an `event` object.
|
||||
|
||||
### `copy`
|
||||
|
||||
`copy(event: Object) => Simulator`
|
||||
|
||||
Simulator a `copy` event with an `event` object.
|
||||
|
||||
### `cut`
|
||||
|
||||
`cut(event: Object) => Simulator`
|
||||
|
||||
Simulator a `cut` event with an `event` object.
|
||||
|
||||
### `drop`
|
||||
|
||||
`drop(event: Object) => Simulator`
|
||||
|
||||
Simulator a `drop` event with an `event` object.
|
||||
|
||||
### `focus`
|
||||
|
||||
`focus(event: Object) => Simulator`
|
||||
|
||||
Simulator a `focus` event with an `event` object.
|
||||
|
||||
### `keyDown`
|
||||
|
||||
`keyDown(event: Object) => Simulator`
|
||||
|
||||
Simulator a `keyDown` event with an `event` object.
|
||||
|
||||
### `select`
|
||||
|
||||
`select(event: Object) => Simulator`
|
||||
|
||||
Simulator a `select` event with an `event` object.
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Block`
|
||||
|
||||
```js
|
||||
@ -9,7 +8,6 @@ A block node in a Slate [`Document`](./document.md). Block nodes implement the [
|
||||
|
||||
Block nodes may contain nested block nodes, inline nodes, and text nodes—just like in the DOM. They always contain at least one text node child.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -23,11 +21,13 @@ Block({
|
||||
```
|
||||
|
||||
### `data`
|
||||
|
||||
`Immutable.Map`
|
||||
|
||||
Arbitrary data associated with the node. Defaults to an empty `Map`.
|
||||
|
||||
### `isVoid`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the node is a "void" node, meaning that it has no child content (eg. images, videos, etc.). Defaults to `false`.
|
||||
@ -35,65 +35,71 @@ Whether the node is a "void" node, meaning that it has no child content (eg. ima
|
||||
Note that even though a node may be "void", it will still contain a single, empty [`Text`](./text.md) node for consistency across other operations. However, when rendered by Slate that single [`Text`](./text.md) node will not be visible.
|
||||
|
||||
### `key`
|
||||
|
||||
`String`
|
||||
|
||||
A unique identifier for the node.
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
An immutable string value of `'block'` for easily separating this node from [`Inline`](./inline.md) or [`Text`](./text.md) nodes.
|
||||
|
||||
### `nodes`
|
||||
|
||||
`Immutable.List`
|
||||
|
||||
A list of child nodes. Defaults to a list with a single text node child.
|
||||
|
||||
### `type`
|
||||
|
||||
`String`
|
||||
|
||||
The custom type of the node (eg. `blockquote` or `list-item`).
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
### `text`
|
||||
|
||||
`String`
|
||||
|
||||
A concatenated string of all of the descendant [`Text`](./text.md) nodes of this node.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Block.create`
|
||||
|
||||
`Block.create(properties: Object) => Block`
|
||||
|
||||
Create a block from a plain Javascript object of `properties`.
|
||||
|
||||
### `Block.createList`
|
||||
|
||||
`Block.createList(array: Array) => List`
|
||||
|
||||
Create a list of block nodes from a plain Javascript `array`.
|
||||
|
||||
### `Block.fromJSON`
|
||||
|
||||
`Block.fromJSON(object: Object) => Block`
|
||||
|
||||
Create a block from a JSON `object`.
|
||||
|
||||
### `Block.isBlock`
|
||||
|
||||
`Block.isBlock(maybeBlock: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Block`.
|
||||
|
||||
|
||||
## Node Methods
|
||||
|
||||
Blocks implement the [`Node`](./node.md) interface. For information about all of the node methods, see the [`Node` reference](./node.md).
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the block.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Change`
|
||||
|
||||
```js
|
||||
@ -9,10 +8,10 @@ A change allows you to define a series of changes you'd like to make to the curr
|
||||
|
||||
All changes are performed through `Change` objects, so that a history of changes can be preserved for use in undo/redo operations, and to make collaborative editing possible.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
A string with a value of `'change'`.
|
||||
@ -21,10 +20,10 @@ A string with a value of `'change'`.
|
||||
|
||||
A [`Value`](./value.md) with the change's current operations applied. Each time you run a new change function this property will be updated.
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
### `call`
|
||||
|
||||
`call(customChange: Function, ...args) => Change`
|
||||
|
||||
This method calls the provided `customChange` function with the current instance of the `Change` object as the first argument and passes through the remaining `args`.
|
||||
@ -51,6 +50,7 @@ function onSomeEvent(event, change) {
|
||||
```
|
||||
|
||||
### `withoutNormalization`
|
||||
|
||||
`withoutNormalization(customChange: Function) => Change`
|
||||
|
||||
This method calls the provided `customChange` function with the current instance of the `Change` object as the first argument. While `customChange` is executing, normalization is temporarily suppressed, but normalization will be executed once the `customChange` function completes execution.
|
||||
@ -83,21 +83,25 @@ validateNode(node) {
|
||||
These changes act on the `document` based on the current `selection`. They are equivalent to calling the [Document Changes](#document-changes) with the current selection as the `range` argument, but they are there for convenience, since you often want to act with the current selection, as a user would.
|
||||
|
||||
### `deleteBackward`
|
||||
|
||||
`deleteBackward(n: Number) => Change`
|
||||
|
||||
Delete backward `n` characters at the current cursor. If the selection is expanded, this method is equivalent to a regular [`delete()`](#delete). `n` defaults to `1`.
|
||||
|
||||
### `deleteForward`
|
||||
|
||||
`deleteForward(n: Number) => Change`
|
||||
|
||||
Delete forward `n` characters at the current cursor. If the selection is expanded, this method is equivalent to a regular [`delete()`](#delete). `n` defaults to `1`.
|
||||
|
||||
### `delete`
|
||||
|
||||
`delete() => Change`
|
||||
|
||||
Delete everything in the current selection.
|
||||
|
||||
### `insertBlock`
|
||||
|
||||
`insertBlock(block: Block) => Change` <br/>
|
||||
`insertBlock(properties: Object) => Change` <br/>
|
||||
`insertBlock(type: String) => Change`
|
||||
@ -105,22 +109,26 @@ Delete everything in the current selection.
|
||||
Insert a new block at the same level as the current block, splitting the current block to make room if it is non-empty. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `insertFragment`
|
||||
|
||||
`insertFragment(fragment: Document) => Change`
|
||||
|
||||
Insert a [`fragment`](./document.md) at the current selection. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `insertInline`
|
||||
|
||||
`insertInline(inline: Inline) => Change` <br/>
|
||||
`insertInline(properties: Object) => Change`
|
||||
|
||||
Insert a new inline at the current cursor position, splitting the text to make room if it is non-empty. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `insertText`
|
||||
|
||||
`insertText(text: String) => Change`
|
||||
|
||||
Insert a string of `text` at the current selection. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `addMark`
|
||||
|
||||
`addMark(mark: Mark) => Change` <br/>
|
||||
`addMark(properties: Object) => Change` <br/>
|
||||
`addMark(type: String) => Change`
|
||||
@ -128,28 +136,33 @@ Insert a string of `text` at the current selection. If the selection is expanded
|
||||
Add a [`mark`](./mark.md) to the characters in the current selection. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
|
||||
|
||||
### `setBlock`
|
||||
|
||||
`setBlock(properties: Object) => Change` <br/>
|
||||
`setBlock(type: String) => Change`
|
||||
|
||||
Set the `properties` of the [`Block`](./block.md) in the current selection. For convenience, you can pass a `type` string to set the blocks's type only.
|
||||
|
||||
### `setInline`
|
||||
|
||||
`setInline(properties: Object) => Change` <br/>
|
||||
`setInline(type: String) => Change`
|
||||
|
||||
Set the `properties` of the [`Inline`](./inline.md) nodes in the current selection. For convenience, you can pass a `type` string to set the inline's type only.
|
||||
|
||||
### `splitBlock`
|
||||
|
||||
`splitBlock(depth: Number) => Change`
|
||||
|
||||
Split the [`Block`](./block.md) in the current selection by `depth` levels. If the selection is expanded, it will be deleted first. `depth` defaults to `1`.
|
||||
|
||||
### `splitInline`
|
||||
|
||||
`splitInline(depth: Number) => Change`
|
||||
|
||||
Split the [`Inline`](./inline.md) node in the current selection by `depth` levels. If the selection is expanded, it will be deleted first. `depth` defaults to `Infinity`.
|
||||
|
||||
### `removeMark`
|
||||
|
||||
`removeMark(mark: Mark) => Change` <br/>
|
||||
`removeMark(properties: Object) => Change` <br/>
|
||||
`removeMark(type: String) => Change`
|
||||
@ -157,6 +170,7 @@ Split the [`Inline`](./inline.md) node in the current selection by `depth` level
|
||||
Remove a [`mark`](./mark.md) from the characters in the current selection. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
|
||||
|
||||
### `toggleMark`
|
||||
|
||||
`toggleMark(mark: Mark) => Change` <br/>
|
||||
`toggleMark(properties: Object) => Change` <br/>
|
||||
`toggleMark(type: String) => Change`
|
||||
@ -164,140 +178,163 @@ Remove a [`mark`](./mark.md) from the characters in the current selection. For c
|
||||
Add or remove a [`mark`](./mark.md) from the characters in the current selection, depending on it already exists on any or not. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
|
||||
|
||||
### `unwrapBlock`
|
||||
|
||||
`unwrapBlock(type: String) => Change` <br/>
|
||||
`unwrapBlock(properties: Object) => Change` <br />
|
||||
|
||||
Unwrap all [`Block`](./block.md) nodes in the current selection that match a `type` and/or `data`.
|
||||
|
||||
### `unwrapInline`
|
||||
|
||||
`unwrapInline(type: String) => Change` <br/>
|
||||
`unwrapInline(properties: Object) => Change` <br/>
|
||||
|
||||
Unwrap all [`Inline`](./inline.md) nodes in the current selection that match a `type` and/or `data`.
|
||||
|
||||
### `wrapBlock`
|
||||
|
||||
`wrapBlock(type: String) => Change` <br/>
|
||||
`wrapBlock(properties: Object) => Change` <br/>
|
||||
|
||||
Wrap the [`Block`](./block.md) nodes in the current selection with a new [`Block`](./block.md) node of `type`, with optional `data`.
|
||||
|
||||
### `wrapInline`
|
||||
|
||||
`wrapInline(type: String) => Change` <br />
|
||||
`wrapInline(properties: Object) => Change` <br />
|
||||
|
||||
Wrap the [`Inline`](./inline.md) nodes in the current selection with a new [`Inline`](./inline.md) node of `type`, with optional `data`.
|
||||
|
||||
### `wrapText`
|
||||
|
||||
`wrapText(prefix: String, [suffix: String]) => Change`
|
||||
|
||||
Surround the text in the current selection with `prefix` and `suffix` strings. If the `suffix` is ommitted, the `prefix` will be used instead.
|
||||
|
||||
|
||||
## Selection Changes
|
||||
|
||||
These changes change the current `selection`, without touching the `document`.
|
||||
|
||||
### `blur`
|
||||
|
||||
`blur() => Change`
|
||||
|
||||
Blur the current selection.
|
||||
|
||||
### `collapseTo{Edge}`
|
||||
|
||||
`collapseTo{Edge}() => Change`
|
||||
|
||||
Collapse the current selection to its `{Edge}`. Where `{Edge}` is either `Anchor`, `Focus`, `Start` or `End`.
|
||||
|
||||
### `collapseTo{Edge}Of`
|
||||
|
||||
`collapseTo{Edge}Of(node: Node) => Change`
|
||||
|
||||
Collapse the current selection to the `{Edge}` of `node`. Where `{Edge}` is either `Start` or `End`.
|
||||
|
||||
### `collapseTo{Edge}Of{Direction}Block`
|
||||
|
||||
`collapseTo{Edge}Of{Direction}Block() => Change`
|
||||
|
||||
Collapse the current selection to the `{Edge}` of the next [`Block`](./block.md) node in `{Direction}`. Where `{Edge}` is either `Start` or `End` and `{Direction}` is either `Next` or `Previous`.
|
||||
|
||||
### `collapseTo{Edge}Of{Direction}Text`
|
||||
|
||||
`collapseTo{Edge}Of{Direction}Text() => Change`
|
||||
|
||||
Collapse the current selection to the `{Edge}` of the next [`Text`](./text.md) node in `{Direction}`. Where `{Edge}` is either `Start` or `End` and `{Direction}` is either `Next` or `Previous`.
|
||||
|
||||
### `extend`
|
||||
|
||||
`extend(n: Number) => Change`
|
||||
|
||||
Extend the current selection's points by `n` characters. `n` can be positive or negative to indicate direction.
|
||||
|
||||
### `extendTo{Edge}Of`
|
||||
|
||||
`extendTo{Edge}Of(node: Node) => Change`
|
||||
|
||||
Extend the current selection to the `{Edge}` of a `node`. Where `{Edge}` is either `Start` or `End`.
|
||||
|
||||
### `flip`
|
||||
|
||||
`flip() => Change`
|
||||
|
||||
Flip the selection.
|
||||
|
||||
### `focus`
|
||||
|
||||
`focus() => Change`
|
||||
|
||||
Focus the current selection.
|
||||
|
||||
### `move`
|
||||
|
||||
`move(n: Number) => Change`
|
||||
|
||||
Move the current selection's offsets by `n`.
|
||||
Move the current selection's offsets by `n`.
|
||||
|
||||
### `move{Edge}`
|
||||
|
||||
`move{Edge}(n: Number) => Change`
|
||||
|
||||
Move the current selection's `{Edge}` offset by `n`. `{Edge}` can be one of `Start`, `End`.
|
||||
Move the current selection's `{Edge}` offset by `n`. `{Edge}` can be one of `Start`, `End`.
|
||||
|
||||
### `moveOffsetsTo`
|
||||
|
||||
`moveOffsetsTo(anchorOffset: Number, focusOffset: Number) => Change`
|
||||
|
||||
Move the current selection's offsets to a new `anchorOffset` and `focusOffset`.
|
||||
|
||||
### `moveToRangeOf`
|
||||
|
||||
`moveToRangeOf(node: Node) => Change`
|
||||
|
||||
Move the current selection's anchor point to the start of a `node` and its focus point to the end of the `node`.
|
||||
|
||||
### `select`
|
||||
|
||||
`select(properties: Range || Object) => Change`
|
||||
|
||||
Set the current selection to a range with merged `properties`. The `properties` can either be a [`Range`](./range.md) object or a plain Javascript object of selection properties.
|
||||
|
||||
### `selectAll`
|
||||
|
||||
`selectAll() => Change`
|
||||
|
||||
Select the entire document and focus the selection.
|
||||
|
||||
### `deselect`
|
||||
|
||||
`deselect() => Change`
|
||||
|
||||
Unset the selection.
|
||||
|
||||
|
||||
## Document Changes
|
||||
|
||||
These changes act on a specific [`Range`](./range.md) of the document.
|
||||
|
||||
### `deleteBackwardAtRange`
|
||||
|
||||
`deleteBackwardAtRange(range: Range, n: Number) => Change`
|
||||
|
||||
Delete backward `n` characters at a `range`. If the `range` is expanded, this method is equivalent to a regular [`delete()`](#delete). `n` defaults to `1`.
|
||||
|
||||
### `deleteForwardAtRange`
|
||||
|
||||
`deleteForwardAtRange(range: Range, n: Number) => Change`
|
||||
|
||||
Delete forward `n` characters at a `range`. If the `range` is expanded, this method is equivalent to a regular [`delete()`](#delete). `n` defaults to `1`.
|
||||
|
||||
### `deleteAtRange`
|
||||
|
||||
`deleteAtRange(range: Range, ) => Change`
|
||||
|
||||
Delete everything in a `range`.
|
||||
|
||||
### `insertBlockAtRange`
|
||||
|
||||
`insertBlockAtRange(range: Range, block: Block) => Change` <br/>
|
||||
`insertBlockAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`insertBlockAtRange(range: Range, type: String) => Change`
|
||||
@ -305,22 +342,26 @@ Delete everything in a `range`.
|
||||
Insert a new block at the same level as the leaf block at a `range`, splitting the current block to make room if it is non-empty. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `insertFragmentAtRange`
|
||||
|
||||
`insertFragmentAtRange(range: Range, fragment: Document) => Change`
|
||||
|
||||
Insert a [`fragment`](./document.md) at a `range`. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `insertInlineAtRange`
|
||||
|
||||
`insertInlineAtRange(range: Range, inline: Inline) => Change` <br/>
|
||||
`insertInlineAtRange(range: Range, properties: Object) => Change`
|
||||
|
||||
Insert a new inline at a `range`, splitting the text to make room if it is non-empty. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `insertTextAtRange`
|
||||
|
||||
`insertTextAtRange(range: Range, text: String) => Change`
|
||||
|
||||
Insert a string of `text` at a `range`. If the selection is expanded, it will be deleted first.
|
||||
|
||||
### `addMarkAtRange`
|
||||
|
||||
`addMarkAtRange(range: Range, mark: Mark) => Change` <br/>
|
||||
`addMarkAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`addMarkAtRange(range: Range, type: String) => Change`
|
||||
@ -328,28 +369,33 @@ Insert a string of `text` at a `range`. If the selection is expanded, it will be
|
||||
Add a [`mark`](./mark.md) to the characters in a `range`. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
|
||||
|
||||
### `setBlockAtRange`
|
||||
|
||||
`setBlockAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`setBlock(range: Range, type: String) => Change`
|
||||
|
||||
Set the `properties` of the [`Block`](./block.md) in a `range`. For convenience, you can pass a `type` string to set the blocks's type only.
|
||||
|
||||
### `setInlineAtRange`
|
||||
|
||||
`setInlineAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`setInline(range: Range, type: String) => Change`
|
||||
|
||||
Set the `properties` of the [`Inline`](./inline.md) nodes in a `range`. For convenience, you can pass a `type` string to set the inline's type only.
|
||||
|
||||
### `splitBlockAtRange`
|
||||
|
||||
`splitBlockAtRange(range: Range, depth: Number) => Change`
|
||||
|
||||
Split the [`Block`](./block.md) in a `range` by `depth` levels. If the selection is expanded, it will be deleted first. `depth` defaults to `1`.
|
||||
|
||||
### `splitInlineAtRange`
|
||||
|
||||
`splitInlineAtRange(range: Range, depth: Number) => Change`
|
||||
|
||||
Split the [`Inline`](./inline.md) node in a `range` by `depth` levels. If the selection is expanded, it will be deleted first. `depth` defaults to `Infinity`.
|
||||
|
||||
### `removeMarkAtRange`
|
||||
|
||||
`removeMarkAtRange(range: Range, mark: Mark) => Change` <br/>
|
||||
`removeMarkAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`removeMarkAtRange(range: Range, type: String) => Change`
|
||||
@ -357,6 +403,7 @@ Split the [`Inline`](./inline.md) node in a `range` by `depth` levels. If the se
|
||||
Remove a [`mark`](./mark.md) from the characters in a `range`. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
|
||||
|
||||
### `toggleMarkAtRange`
|
||||
|
||||
`toggleMarkAtRange(range: Range, mark: Mark) => Change` <br/>
|
||||
`toggleMarkAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`toggleMarkAtRange(range: Range, type: String) => Change`
|
||||
@ -364,145 +411,168 @@ Remove a [`mark`](./mark.md) from the characters in a `range`. For convenience,
|
||||
Add or remove a [`mark`](./mark.md) from the characters in a `range`, depending on whether any of them already have the mark. For convenience, you can pass a `type` string or `properties` object to implicitly create a [`Mark`](./mark.md) of that type.
|
||||
|
||||
### `unwrapBlockAtRange`
|
||||
|
||||
`unwrapBlockAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`unwrapBlockAtRange(range: Range, type: String) => Change`
|
||||
|
||||
Unwrap all [`Block`](./block.md) nodes in a `range` that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `unwrapInlineAtRange`
|
||||
|
||||
`unwrapInlineAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`unwrapInlineAtRange(range: Range, type: String) => Change`
|
||||
|
||||
Unwrap all [`Inline`](./inline.md) nodes in a `range` that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `wrapBlockAtRange`
|
||||
|
||||
`wrapBlockAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`wrapBlockAtRange(range: Range, type: String) => Change`
|
||||
|
||||
Wrap the [`Block`](./block.md) nodes in a `range` with a new [`Block`](./block.md) node with `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `wrapInlineAtRange`
|
||||
|
||||
`wrapInlineAtRange(range: Range, properties: Object) => Change` <br/>
|
||||
`wrapInlineAtRange(range: Range, type: String) => Change`
|
||||
|
||||
Wrap the [`Inline`](./inline.md) nodes in a `range` with a new [`Inline`](./inline.md) node with `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `wrapTextAtRange`
|
||||
|
||||
`wrapTextAtRange(range: Range, prefix: String, [suffix: String]) => Change`
|
||||
|
||||
Surround the text in a `range` with `prefix` and `suffix` strings. If the `suffix` is ommitted, the `prefix` will be used instead.
|
||||
|
||||
|
||||
## Node Changes
|
||||
|
||||
These changes are lower-level, and act on a specific node by its `key`. They're often used in your custom components because you'll have access to `props.node`.
|
||||
|
||||
### `addMarkByKey`
|
||||
|
||||
`addMarkByKey(key: String, offset: Number, length: Number, mark: Mark) => Change`
|
||||
|
||||
Add a `mark` to `length` characters starting at an `offset` in a [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `insertNodeByKey`
|
||||
|
||||
`insertNodeByKey(key: String, index: Number, node: Node) => Change`
|
||||
|
||||
Insert a `node` at `index` inside a parent [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `insertFragmentByKey`
|
||||
|
||||
`insertFragmentByKey(key: String, index: Number, fragment: Fragment) => Transform`
|
||||
|
||||
Insert a [`Fragment`](./fragment.md) at `index` inside a parent [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `insertTextByKey`
|
||||
|
||||
`insertTextByKey(key: String, offset: Number, text: String, [marks: Set]) => Change`
|
||||
|
||||
Insert `text` at an `offset` in a [`Text Node`](./text.md) by its `key` with optional `marks`.
|
||||
|
||||
### `moveNodeByKey`
|
||||
|
||||
`moveNodeByKey(key: String, newKey: String, newIndex: Number) => Change`
|
||||
|
||||
Move a [`Node`](./node.md) by its `key` to a new parent node with its `newKey` and at a `newIndex`.
|
||||
|
||||
### `removeMarkByKey`
|
||||
|
||||
`removeMarkByKey(key: String, offset: Number, length: Number, mark: Mark) => Change`
|
||||
|
||||
Remove a `mark` from `length` characters starting at an `offset` in a [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `removeNodeByKey`
|
||||
|
||||
`removeNodeByKey(key: String) => Change`
|
||||
|
||||
Remove a [`Node`](./node.md) from the document by its `key`.
|
||||
|
||||
### `replaceNodeByKey`
|
||||
|
||||
`replaceNodeByKey(key: String, node: Node) => Change`
|
||||
|
||||
Replace a [`Node`](./node.md) in the document with a new [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `removeTextByKey`
|
||||
|
||||
`removeTextByKey(key: String, offset: Number, length: Number) => Change`
|
||||
|
||||
Remove `length` characters of text starting at an `offset` in a [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `setMarkByKey`
|
||||
|
||||
`setMarkByKey(key: String, offset: Number, length: Number, mark: Mark, properties: Object) => Change`
|
||||
|
||||
Set a dictionary of `properties` on a [`mark`](./mark.md) on a [`Node`](./node.md) by its `key`.
|
||||
|
||||
### `setNodeByKey`
|
||||
|
||||
`setNodeByKey(key: String, properties: Object) => Change` <br/>
|
||||
`setNodeByKey(key: String, type: String) => Change`
|
||||
|
||||
Set a dictionary of `properties` on a [`Node`](./node.md) by its `key`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `splitNodeByKey`
|
||||
|
||||
`splitNodeByKey(key: String, offset: Number) => Change`
|
||||
|
||||
Split a node by its `key` at an `offset`.
|
||||
|
||||
### `unwrapInlineByKey`
|
||||
|
||||
`unwrapInlineByKey(key: String, properties: Object) => Change` <br/>
|
||||
`unwrapInlineByKey(key: String, type: String) => Change`
|
||||
|
||||
Unwrap all inner content of an [`Inline`](./inline.md) node by its `key` that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `unwrapBlockByKey`
|
||||
|
||||
`unwrapBlockByKey(key: String, properties: Object) => Change` <br/>
|
||||
`unwrapBlockByKey(key: String, type: String) => Change`
|
||||
|
||||
Unwrap all inner content of a [`Block`](./block.md) node by its `key` that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `unwrapNodeByKey`
|
||||
|
||||
`unwrapNodeByKey(key: String) => Change`
|
||||
|
||||
Unwrap a single node from its parent. If the node is surrounded with siblings, its parent will be split. If the node is the only child, the parent is removed, and simply replaced by the node itself. Cannot unwrap a root node.
|
||||
|
||||
### `wrapBlockByKey`
|
||||
|
||||
`wrapBlockByKey(key: String, properties: Object) => Change` <br/>
|
||||
`wrapBlockByKey(key: String, type: String) => Change`
|
||||
|
||||
Wrap the given node in a [`Block`](./block.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
### `wrapInlineByKey`
|
||||
|
||||
`wrapInlineByKey(key: String, properties: Object) => Change` <br/>
|
||||
`wrapInlineByKey(key: String, type: String) => Change`
|
||||
|
||||
Wrap the given node in a [`Inline`](./inline.md) node that match `properties`. For convenience, you can pass a `type` string or `properties` object.
|
||||
|
||||
|
||||
## History Changes
|
||||
|
||||
These changes use the history to undo/redo previously made changes.
|
||||
|
||||
### `redo`
|
||||
|
||||
`redo() => Change`
|
||||
|
||||
Move forward one step in the history.
|
||||
|
||||
### `undo`
|
||||
|
||||
`undo() => Change`
|
||||
|
||||
Move backward one step in the history.
|
||||
|
||||
### `snapshotSelection`
|
||||
|
||||
`snapshotSelection() => Change`
|
||||
|
||||
Snapshot `value.selection` for `undo` purposes, useful with delete operations like `removeNodeByKey(focusBlock.key).undo()`
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Character`
|
||||
|
||||
```js
|
||||
@ -9,7 +8,6 @@ A character in a [`Text`](./text.md) node.
|
||||
|
||||
Characters are how Slate associates [`Marks`](./mark.md) with a range of text, for formatting.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -20,47 +18,53 @@ Character({
|
||||
```
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
A string with a value of `'character'`.
|
||||
|
||||
### `marks`
|
||||
|
||||
`Immutable.Set`
|
||||
|
||||
A set of [`Marks`](./mark.md) attached to the character.
|
||||
|
||||
### `text`
|
||||
|
||||
`String`
|
||||
|
||||
The text string of the character.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Character.create`
|
||||
|
||||
`Character.create(properties: Object) => Character`
|
||||
|
||||
Create a character from a plain Javascript object of `properties`.
|
||||
|
||||
### `Character.createList`
|
||||
|
||||
`Character.createList(array: Array) => List`
|
||||
|
||||
Create a list of characters from a plain Javascript `array`.
|
||||
|
||||
### `Character.fromJSON`
|
||||
|
||||
`Character.fromJSON(object: Object) => Character`
|
||||
|
||||
Create a character from a JSON `object`.
|
||||
|
||||
### `Character.isCharacter`
|
||||
|
||||
`Character.isCharacter(maybeCharacter: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Character`.
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the character.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Data`
|
||||
|
||||
```js
|
||||
@ -9,15 +8,16 @@ Data is simply a thin wrapper around [`Immutable.Map`](https://facebook.github.i
|
||||
|
||||
A data object can have any properties associated with it.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Data.create`
|
||||
|
||||
`Data.create(properties: Object) => Data`
|
||||
|
||||
Create a data object from a plain Javascript object of `properties`.
|
||||
|
||||
### `Data.fromJSON`
|
||||
|
||||
`Data.fromJSON(object: Object) => Data`
|
||||
|
||||
Create a data object from a JSON `object`.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Document`
|
||||
|
||||
```js
|
||||
@ -11,7 +10,6 @@ Documents are made up of block nodes, inline nodes, and text nodes—just like i
|
||||
|
||||
In some places, you'll see mention of "fragments", which are also `Document` objects, just that aren't attached to the main `Value`. For example, when cutting-and-pasting a selection of content, that content will be referred to as a document "fragment".
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -21,9 +19,11 @@ Document({
|
||||
```
|
||||
|
||||
### `data`
|
||||
|
||||
`Immutable.Map`
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
An immutable string value of `'document'` for easily separating this node from [`Block`](./block.md), [`Inline`](./inline.md) or [`Text`](./text.md) nodes.
|
||||
@ -31,45 +31,47 @@ An immutable string value of `'document'` for easily separating this node from [
|
||||
Arbitrary data associated with the document. Defaults to an empty `Map`.
|
||||
|
||||
### `nodes`
|
||||
|
||||
`Immutable.List`
|
||||
|
||||
A list of child nodes.
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
### `text`
|
||||
|
||||
`String`
|
||||
|
||||
A concatenated string of all of the descendant [`Text`](./text.md) nodes of this node.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Document.create`
|
||||
|
||||
`Document.create(properties: Object) => Document`
|
||||
|
||||
Create a document from a plain Javascript object of `properties`.
|
||||
|
||||
### `Document.fromJSON`
|
||||
|
||||
`Document.fromJSON(object: Object) => Document`
|
||||
|
||||
Create a document from a JSON `object`.
|
||||
|
||||
### `Document.isDocument`
|
||||
|
||||
`Document.isDocument(maybeDocument: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Document`.
|
||||
|
||||
|
||||
## Node Methods
|
||||
|
||||
Documents implement the [`Node`](./node.md) interface. For information about all of the node methods, see the [`Node` reference](./node.md).
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the document.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Inline`
|
||||
|
||||
```js
|
||||
@ -9,7 +8,6 @@ A inline node in a Slate [`Document`](./document.md). Inline nodes implement the
|
||||
|
||||
Inline nodes may contain nested inline nodes and text nodes—just like in the DOM. They always contain at least one text node child.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -23,11 +21,13 @@ Inline({
|
||||
```
|
||||
|
||||
### `data`
|
||||
|
||||
`Immutable.Map`
|
||||
|
||||
Arbitrary data associated with the node. Defaults to an empty `Map`.
|
||||
|
||||
### `isVoid`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the node is a "void" node, meaning that it has no child content (eg. emoji, icons, etc.). Defaults to `false`.
|
||||
@ -35,65 +35,71 @@ Whether the node is a "void" node, meaning that it has no child content (eg. emo
|
||||
Note that even though a node may be "void", it will still contain a single, empty [`Text`](./text.md) node for consistency across other operations. However, when rendered by Slate that single [`Text`](./text.md) node will not be visible.
|
||||
|
||||
### `key`
|
||||
|
||||
`String`
|
||||
|
||||
A unique identifier for the node.
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
An immutable string value of `'inline'` for easily separating this node from [`Block`](./block.md) or [`Text`](./text.md) nodes.
|
||||
|
||||
### `nodes`
|
||||
|
||||
`Immutable.List`
|
||||
|
||||
A list of child nodes. Defaults to a list with a single text node child.
|
||||
|
||||
### `type`
|
||||
|
||||
`String`
|
||||
|
||||
The custom type of the node (eg. `link` or `hashtag`).
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
### `text`
|
||||
|
||||
`String`
|
||||
|
||||
A concatenated string of all of the descendant [`Text`](./text.md) nodes of this node.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Inline.create`
|
||||
|
||||
`Inline.create(properties: Object) => Inline`
|
||||
|
||||
Create an inline from a plain Javascript object of `properties`.
|
||||
|
||||
### `Inline.createList`
|
||||
|
||||
`Inline.createList(array: Array) => List`
|
||||
|
||||
Create a list of inline nodes from a plain Javascript `array`.
|
||||
|
||||
### `Inline.fromJSON`
|
||||
|
||||
`Inline.fromJSON(object: Object) => Inline`
|
||||
|
||||
Create an inline from a JSON `object`.
|
||||
|
||||
### `Inline.isInline`
|
||||
|
||||
`Inline.isInline(maybeInline: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Inline`.
|
||||
|
||||
|
||||
## Node Methods
|
||||
|
||||
Inlines implement the [`Node`](./node.md) interface. For information about all of the node methods, see the [`Node` reference](./node.md).
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the inline.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Mark`
|
||||
|
||||
```js
|
||||
@ -7,58 +6,63 @@ import { Mark } from 'slate'
|
||||
|
||||
A formatting mark that can be associated with [`Characters`](./character.md). Marks are how Slate represents rich formatting like **bold** or _italic_.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
Mark({
|
||||
data: Data,
|
||||
type: String
|
||||
type: String,
|
||||
})
|
||||
```
|
||||
|
||||
### `data`
|
||||
|
||||
`Data`
|
||||
|
||||
A map of [`Data`](./data.md).
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
A string with a value of `'mark'`.
|
||||
|
||||
### `type`
|
||||
|
||||
`String`
|
||||
|
||||
The custom type of the mark (eg. `bold` or `italic`).
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Mark.create`
|
||||
|
||||
`Mark.create(properties: Object) => Mark`
|
||||
|
||||
Create a mark from a plain Javascript object of `properties`.
|
||||
|
||||
### `Mark.createSet`
|
||||
|
||||
`Mark.createSet(array: Array) => Set`
|
||||
|
||||
Create a set of marks from a plain Javascript `array`.
|
||||
|
||||
### `Mark.fromJSON`
|
||||
|
||||
`Mark.fromJSON(object: Object) => Mark`
|
||||
|
||||
Create a mark from a JSON `object`.
|
||||
|
||||
### `Mark.isMark`
|
||||
|
||||
`Mark.isMark(maybeMark: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Mark`.
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the mark.
|
||||
|
@ -1,197 +1,229 @@
|
||||
|
||||
# `Node`
|
||||
|
||||
`Node` is not a publicly accessible module, but instead an interface that [`Document`](./document.md), [`Block`](./block.md) and [`Inline`](./inline.md) all implement.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
### `key`
|
||||
|
||||
`String`
|
||||
|
||||
A short-lived, unique identifier for the node.
|
||||
|
||||
By default, keys are **not** meant to be long-lived unique identifiers for nodes that you might store in a database, or elsewhere. They are meant purely to identify a node inside of a single Slate instance. For that reason, they are simply auto-incrementing strings. (eg. `'0'`, `'1'`, `'2'`, ...)
|
||||
By default, keys are **not** meant to be long-lived unique identifiers for nodes that you might store in a database, or elsewhere. They are meant purely to identify a node inside of a single Slate instance. For that reason, they are simply auto-incrementing strings. (eg. `'0'`, `'1'`, `'2'`, ...)
|
||||
|
||||
If you want to make your keys uniqueness long-lived, you'll need to supply your own key generating function via the [`setKeyGenerator`](./utils.md#setkeygenerator) util.
|
||||
|
||||
### `nodes`
|
||||
|
||||
`Immutable.List`
|
||||
|
||||
A list of child nodes. Defaults to a list with a single text node child.
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
An immutable string value of `'document'`, `'block'`, `'inline'` or `'text'` for easily separating this node from [`Inline`](./inline.md) or [`Text`](./text.md) nodes.
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
### `text`
|
||||
|
||||
`String`
|
||||
|
||||
A concatenated string of all of the descendant [`Text`](./text.md) nodes of this node.
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
### `filterDescendants`
|
||||
|
||||
`filterDescendants(iterator: Function) => List`
|
||||
|
||||
Deeply filter the descendant nodes of a node by `iterator`.
|
||||
|
||||
### `findDescendant`
|
||||
|
||||
`findDescendant(iterator: Function) => Node || Void`
|
||||
|
||||
Deeply find a descendant node by `iterator`.
|
||||
|
||||
### `getBlocksAtRange`
|
||||
|
||||
`getBlocksAtRange(range: Range) => List`
|
||||
|
||||
Get all of the bottom-most [`Block`](./block.md) nodes in a `range`.
|
||||
|
||||
### `getBlocks`
|
||||
|
||||
`getBlocks() => List`
|
||||
|
||||
Get all of the bottom-most [`Block`](./block.md) node descendants.
|
||||
|
||||
### `getCharactersAtRange`
|
||||
|
||||
`getCharactersAtRange(range: Range) => List`
|
||||
|
||||
Get a list of all of the [`Characters`](./character.md) in a `range`.
|
||||
|
||||
### `getChild`
|
||||
|
||||
`getChild(key: String || Node) => Node || Void`
|
||||
|
||||
Get a child by `key`.
|
||||
|
||||
### `getClosestBlock`
|
||||
|
||||
`getClosestBlock(key: String || Node) => Node || Void`
|
||||
|
||||
Get the closest [`Block`](./block.md) node to a descendant node by `key`.
|
||||
|
||||
### `getClosestInline`
|
||||
|
||||
`getClosestInline(key: String || Node) => Node || Void`
|
||||
|
||||
Get the closest [`Inline`](./inline.md) node to a descendant node by `key`.
|
||||
|
||||
### `getClosest`
|
||||
|
||||
`getClosest(key: String || Node, match: Function) => Node || Void`
|
||||
|
||||
Get the closest parent node of a descendant node by `key` that matches a `match` function.
|
||||
|
||||
### `getDepth`
|
||||
|
||||
`getDepth(key: String || Node) => Number`
|
||||
|
||||
Get the depth of a descendant node by `key`.
|
||||
|
||||
### `getDescendant`
|
||||
|
||||
`getDescendant(key: String || Node) => Node || Void`
|
||||
|
||||
Get a descendant node by `key`.
|
||||
|
||||
### `getFirstText`
|
||||
|
||||
`getFirstText() => Node || Void`
|
||||
|
||||
Get the first child text node inside a node.
|
||||
|
||||
### `getFragmentAtRange`
|
||||
|
||||
`getFragmentAtRange(range: Range) => Document`
|
||||
|
||||
Get a document fragment of the nodes in a `range`.
|
||||
|
||||
### `getFurthest`
|
||||
|
||||
`getFurthest(key: String, iterator: Function) => Node || Null`
|
||||
|
||||
Get the furthest parent of a node by `key` that matches an `iterator`.
|
||||
|
||||
### `getFurthestAncestor`
|
||||
|
||||
`getFurthestAncestor(key: String) => Node || Null`
|
||||
|
||||
Get the furthest ancestor of a node by `key`.
|
||||
|
||||
### `getFurthestBlock`
|
||||
|
||||
`getFurthestBlock(key: String) => Node || Null`
|
||||
|
||||
Get the furthest block parent of a node by `key`.
|
||||
|
||||
### `getFurthestInline`
|
||||
|
||||
`getFurthestInline(key: String) => Node || Null`
|
||||
|
||||
Get the furthest inline parent of a node by `key`.
|
||||
|
||||
### `getFurthestOnlyChildAncestor`
|
||||
|
||||
`getFurthestOnlyChildAncestor(key: String) => Node || Null`
|
||||
|
||||
Get the furthest ancestor of a node by `key` that has only one child.
|
||||
|
||||
### `getInlinesAtRange`
|
||||
|
||||
`getInlinesAtRange(range: Range) => List`
|
||||
|
||||
Get all of the top-most [`Inline`](./inline.md) nodes in a `range`.
|
||||
|
||||
### `getLastText`
|
||||
|
||||
`getLastText() => Node || Void`
|
||||
|
||||
Get the last child text node inside a node.
|
||||
|
||||
### `getMarksAtRange`
|
||||
|
||||
`getMarksAtRange(range: Range) => Set`
|
||||
|
||||
Get a set of all of the marks in a `range`.
|
||||
|
||||
### `getNextBlock`
|
||||
|
||||
`getNextBlock(key: String || Node) => Node || Void`
|
||||
|
||||
Get the next, bottom-most [`Block`](./block.md) node after a descendant by `key`.
|
||||
|
||||
### `getNextSibling`
|
||||
|
||||
`getNextSibling(key: String || Node) => Node || Void`
|
||||
|
||||
Get the next sibling of a descendant by `key`.
|
||||
|
||||
### `getNextText`
|
||||
|
||||
`getNextText(key: String || Node) => Node || Void`
|
||||
|
||||
Get the next [`Text`](./text.md) node after a descendant by `key`.
|
||||
|
||||
### `getParent`
|
||||
|
||||
`getParent(key: String || Node) => Node || Void`
|
||||
|
||||
Get the parent node of a descendant by `key`.
|
||||
|
||||
### `getPreviousBlock`
|
||||
|
||||
`getPreviousBlock(key: String || Node) => Node || Void`
|
||||
|
||||
Get the previous, bottom-most [`Block`](./block.md) node before a descendant by `key`.
|
||||
|
||||
### `getPreviousSibling`
|
||||
|
||||
`getPreviousSibling(key: String || Node) => Node || Void`
|
||||
|
||||
Get the previous sibling of a descendant by `key`.
|
||||
|
||||
### `getPreviousText`
|
||||
|
||||
`getPreviousText(key: String || Node) => Node || Void`
|
||||
|
||||
Get the previous [`Text`](./text.md) node before a descendant by `key`.
|
||||
|
||||
### `getTextAtOffset`
|
||||
|
||||
`getTextAtOffset(offset: Number) => Text || Void`
|
||||
|
||||
Get the [`Text`](./text.md) node at an `offset`.
|
||||
|
||||
### `getTextsAtRange`
|
||||
|
||||
`getTextsAtRange(range: Range) => List`
|
||||
|
||||
Get all of the [`Text`](./text.md) nodes in a `range`.
|
||||
|
||||
### `hasChild`
|
||||
|
||||
`hasChild(key: String || Node) => Boolean`
|
||||
|
||||
Check whether the node has a child node by `key`.
|
||||
|
||||
### `hasDescendant`
|
||||
|
||||
`hasDescendant(key: String || Node) => Boolean`
|
||||
|
||||
Check whether the node has a descendant node by `key`.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Operation
|
||||
|
||||
An operation is the lowest-level description of a specific change to a part of Slate's value. They are designed to be collaborative-editing friendly.
|
||||
@ -7,7 +6,6 @@ All of the [`Change`](./change.md) methods result in operations being created an
|
||||
|
||||
There are a handful of Slate operation types. The goal is to have the fewest possible types, while still maintaining the necessary semantics for collaborative editing to work.
|
||||
|
||||
|
||||
## Text Operations
|
||||
|
||||
### `insert_text`
|
||||
@ -37,7 +35,6 @@ Inserts a `text` string at `offset` into a text node at `path`, with optional `m
|
||||
|
||||
Removes a string of `text` at `offset` into a text node at `path`.
|
||||
|
||||
|
||||
## Mark Operations
|
||||
|
||||
### `add_mark`
|
||||
@ -83,7 +80,6 @@ Removes a `mark` from a text node at `path` starting at an `offset` and spanning
|
||||
|
||||
Set new `properties` on any marks that match an existing `mark` in a text node at `path`, starting at an `offset` and spanning `length` characters.
|
||||
|
||||
|
||||
## Node Operations
|
||||
|
||||
### `insert_node`
|
||||
@ -162,7 +158,6 @@ Set new `properties` on the node at `path`.
|
||||
|
||||
Split the node at `path` at `position`. The `position` refers to either the index in the child nodes in the case of [`Block`](./block.md) or [`Inline`](./inline.md) nodes, and the index in the characters in the case of [`Text`](./text.md) nodes. In the case of nested splits, `target` refers to the target path of the child split operation. The `properties` object contains properties that should be assigned to the new node created after the split operation is complete.
|
||||
|
||||
|
||||
## Value Operations
|
||||
|
||||
### `set_selection`
|
||||
@ -189,15 +184,16 @@ Set new `properties` on the selection.
|
||||
|
||||
Set new `properties` on a value. Properties can contain `data` and `decorations`.
|
||||
|
||||
|
||||
## Helpers
|
||||
|
||||
### `apply`
|
||||
|
||||
`apply(value: Value, operation: Object) => Value`
|
||||
|
||||
Applies an `operation` to a `value` object.
|
||||
|
||||
### `invert`
|
||||
|
||||
`invert(operation: Object) => Object`
|
||||
|
||||
Create an inverse operation that will undo the changes made by the original.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Range`
|
||||
|
||||
```js
|
||||
@ -11,7 +10,6 @@ The "anchor" is the fixed point in a range, and the "focus" is the non-fixed poi
|
||||
|
||||
Often times, you don't need to specifically know which point is the "anchor" and which is the "focus", and you just need to know which comes first and last in the document. For these cases, there are many convenience equivalent properties and methods referring to the "start" and "end" points.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -21,132 +19,152 @@ Range({
|
||||
focusKey: String,
|
||||
focusOffset: Number,
|
||||
isFocused: Boolean,
|
||||
isBackward: Boolean
|
||||
isBackward: Boolean,
|
||||
})
|
||||
```
|
||||
|
||||
### `anchorKey`
|
||||
|
||||
`String`
|
||||
|
||||
The key of the text node at the range's anchor point.
|
||||
|
||||
### `anchorOffset`
|
||||
|
||||
`Number`
|
||||
|
||||
The number of characters from the start of the text node at the range's anchor point.
|
||||
|
||||
### `focusKey`
|
||||
|
||||
`String`
|
||||
|
||||
The key of the text node at the range's focus point.
|
||||
|
||||
### `focusOffset`
|
||||
|
||||
`Number`
|
||||
|
||||
The number of characters from the start of the text node at the range's focus point.
|
||||
|
||||
### `isBackward`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the range is backward. A range is considered "backward" when its focus point references a location earlier in the document than its anchor point.
|
||||
|
||||
### `isFocused`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the range currently has focus.
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
A string with a value of `'range'`.
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
These properties aren't supplied when creating a range, but are instead computed based on the real properties.
|
||||
|
||||
### `isBlurred`
|
||||
|
||||
`Boolean`
|
||||
|
||||
The opposite of `isFocused`, for convenience.
|
||||
|
||||
### `isCollapsed`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the range is collapsed. A range is considered "collapsed" when the anchor point and focus point of the range are the same.
|
||||
|
||||
### `isExpanded`
|
||||
|
||||
`Boolean`
|
||||
|
||||
The opposite of `isCollapsed`, for convenience.
|
||||
|
||||
### `isForward`
|
||||
|
||||
`Boolean`
|
||||
|
||||
The opposite of `isBackward`, for convenience.
|
||||
|
||||
### `startKey`
|
||||
|
||||
### `startOffset`
|
||||
|
||||
### `endKey`
|
||||
|
||||
### `endOffset`
|
||||
|
||||
A few convenience properties for accessing the first and last point of the range. When the range is forward, `start` refers to the `anchor` point and `end` refers to the `focus` point. And when it's backward they are reversed.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Range.create`
|
||||
|
||||
`Range.create(properties: Object) => Range`
|
||||
|
||||
Create a new `Range` instance with `properties`.
|
||||
|
||||
### `Range.fromJSON`
|
||||
|
||||
`Range.fromJSON(object: Object) => Range`
|
||||
|
||||
Create a range from a JSON `object`.
|
||||
|
||||
### `Range.isRange`
|
||||
|
||||
`Range.isRange(maybeRange: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Range`.
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the range.
|
||||
|
||||
|
||||
## Checking Methods
|
||||
|
||||
### `has{Edge}AtStartOf`
|
||||
|
||||
`has{Edge}AtStartOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether a range has an edge at the start of a `node`. Where `{Edge}` can be one of: `Anchor`, `Focus`, `Start`, `End` or `Edge` (referring to either point).
|
||||
|
||||
### `has{Edge}AtEndOf`
|
||||
|
||||
`has{Edge}AtEndOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether a range has an edge at the end of a `node`. Where `{Edge}` can be one of: `Anchor`, `Focus`, `Start`, `End` or `Edge` (referring to either point).
|
||||
|
||||
### `has{Edge}Between`
|
||||
|
||||
`has{Edge}Between(node: Node, start: Number, end: Number) => Boolean`
|
||||
|
||||
Determine whether a range has an edge in a `node` between its `start` and `end` offset. Where `{Edge}` can be one of: `Anchor`, `Focus`, `Start`, `End` or `Edge` (referring to either point).
|
||||
|
||||
### `has{Edge}In`
|
||||
|
||||
`has{Edge}In(node: Node) => Boolean`
|
||||
|
||||
Determine whether a range has an edge inside a `node`. Where `{Edge}` can be one of: `Anchor`, `Focus`, `Start`, `End` or `Edge` (referring to either point).
|
||||
|
||||
### `isAtStartOf`
|
||||
|
||||
`isAtStartOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether the range is at the start of a `node`.
|
||||
|
||||
### `isAtEndOf`
|
||||
|
||||
`isAtEndOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether the range is at the end of a `node`.
|
||||
|
@ -1,9 +1,7 @@
|
||||
|
||||
# `Schema`
|
||||
|
||||
Every Slate editor has a "schema" associated with it, which contains information about the structure of its content. For the most basic cases, you'll just rely on Slate's default core schema. But for advanced use cases you can enforce rules about what the content of a Slate document can contain.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -17,6 +15,7 @@ Every Slate editor has a "schema" associated with it, which contains information
|
||||
The top-level properties of a schema all give you a way to define validation "rules" that the schema enforces.
|
||||
|
||||
### `document`
|
||||
|
||||
`Object`
|
||||
|
||||
```js
|
||||
@ -30,6 +29,7 @@ The top-level properties of a schema all give you a way to define validation "ru
|
||||
A set of validation rules that apply to the top-level document.
|
||||
|
||||
### `blocks`
|
||||
|
||||
`Object`
|
||||
|
||||
```js
|
||||
@ -48,6 +48,7 @@ A set of validation rules that apply to the top-level document.
|
||||
A dictionary of blocks by type, each with its own set of validation rules.
|
||||
|
||||
### `inlines`
|
||||
|
||||
`Object`
|
||||
|
||||
```js
|
||||
@ -63,7 +64,6 @@ A dictionary of blocks by type, each with its own set of validation rules.
|
||||
|
||||
A dictionary of inlines by type, each with its own set of validation rules.
|
||||
|
||||
|
||||
## Rule Properties
|
||||
|
||||
```js
|
||||
@ -79,9 +79,10 @@ A dictionary of inlines by type, each with its own set of validation rules.
|
||||
}
|
||||
```
|
||||
|
||||
Slate schemas are built up of a set of validation rules. Each of the properties will validate certain pieces of the document based on the properties it defines.
|
||||
Slate schemas are built up of a set of validation rules. Each of the properties will validate certain pieces of the document based on the properties it defines.
|
||||
|
||||
### `data`
|
||||
|
||||
`Object`
|
||||
|
||||
```js
|
||||
@ -95,6 +96,7 @@ Slate schemas are built up of a set of validation rules. Each of the properties
|
||||
A dictionary of data attributes and their corresponding validation functions. The functions should return a boolean indicating whether the data value is valid or not.
|
||||
|
||||
### `first`
|
||||
|
||||
`Object`
|
||||
|
||||
```js
|
||||
@ -106,6 +108,7 @@ A dictionary of data attributes and their corresponding validation functions. Th
|
||||
Will validate the first child node. The `first` definition can declare `objects` and `types` properties.
|
||||
|
||||
### `isVoid`
|
||||
|
||||
`Boolean`
|
||||
|
||||
```js
|
||||
@ -117,6 +120,7 @@ Will validate the first child node. The `first` definition can declare `objects`
|
||||
Will validate a node's `isVoid` property.
|
||||
|
||||
### `last`
|
||||
|
||||
`Object`
|
||||
|
||||
```js
|
||||
@ -128,6 +132,7 @@ Will validate a node's `isVoid` property.
|
||||
Will validate the last child node. The `last` definition can declare `objects` and `types` properties.
|
||||
|
||||
### `nodes`
|
||||
|
||||
`Array`
|
||||
|
||||
```js
|
||||
@ -144,6 +149,7 @@ Will validate a node's children. The `nodes` definitions can declare the `object
|
||||
> 🤖 The `nodes` array is order-sensitive! The example above will require that the first node be either an `image` or `video`, and that it be followed by one or more `paragraph` nodes.
|
||||
|
||||
### `normalize`
|
||||
|
||||
`normalize(change: Change, violation: String, context: Object) => Void`
|
||||
|
||||
```js
|
||||
@ -164,17 +170,21 @@ A function that can be provided to override the default behavior in the case of
|
||||
For more information on the arguments passed to `normalize`, see the [Violations](#violations) reference.
|
||||
|
||||
### `parent`
|
||||
|
||||
`Array`
|
||||
|
||||
```js
|
||||
{
|
||||
parent: { types: ['list'] }
|
||||
parent: {
|
||||
types: ['list']
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Will validate a node's parent. The parent definition can declare the `objects` and/or `types` properties.
|
||||
|
||||
### `text`
|
||||
|
||||
`Array`
|
||||
|
||||
```js
|
||||
@ -185,36 +195,36 @@ Will validate a node's parent. The parent definition can declare the `objects` a
|
||||
|
||||
Will validate a node's text.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Schema.create`
|
||||
|
||||
`Schema.create(properties: Object) => Schema`
|
||||
|
||||
Create a new `Schema` instance with `properties`.
|
||||
|
||||
### `Schema.fromJSON`
|
||||
|
||||
`Schema.fromJSON(object: Object) => Schema`
|
||||
|
||||
Create a schema from a JSON `object`.
|
||||
|
||||
### `Schema.isSchema`
|
||||
|
||||
`Schema.isSchema(maybeSchema: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Schema`.
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the schema.
|
||||
|
||||
|
||||
## Violations
|
||||
|
||||
When supplying your own `normalize` property for a schema rule, it will be called with `(change, violation, context)`. The `violation` will be one of a set of potential violation strings, and `context` will vary depending on the violation.
|
||||
When supplying your own `normalize` property for a schema rule, it will be called with `(change, violation, context)`. The `violation` will be one of a set of potential violation strings, and `context` will vary depending on the violation.
|
||||
|
||||
A set of the invalid violation strings are available as constants via the [`slate-schema-violations`](../slate-schema-violations) package.
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Text`
|
||||
|
||||
```js
|
||||
@ -7,7 +6,6 @@ import { Text } from 'slate'
|
||||
|
||||
A text node in a Slate [`Document`](./document.md). Text nodes are always the bottom-most leaves in the document, just like in the DOM.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -22,45 +20,49 @@ Text({
|
||||
A list of [`Characters`](./character.md) with associated [`Marks`](./mark.md) that make up the text node's content.
|
||||
|
||||
### `key`
|
||||
|
||||
`String`
|
||||
|
||||
A unique identifier for the node.
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
An immutable string value of `'text'` for easily separating this node from [`Inline`](./inline.md) or [`Block`](./block.md) nodes.
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
### `text`
|
||||
|
||||
`String`
|
||||
|
||||
A concatenated string of all of the characters in the text node.
|
||||
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Text.create`
|
||||
|
||||
`Text.create(properties: Object) => Text`
|
||||
|
||||
Create a text from a plain Javascript object of `properties`.
|
||||
|
||||
### `Text.fromJSON`
|
||||
|
||||
`Text.fromJSON(object: Object) => Text`
|
||||
|
||||
Create a text from a JSON `object`.
|
||||
|
||||
### `Text.isText`
|
||||
|
||||
`Text.isText(maybeText: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Text`.
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the text.
|
||||
|
@ -1,24 +1,21 @@
|
||||
|
||||
# Utils
|
||||
|
||||
```js
|
||||
import {
|
||||
resetKeyGenerator,
|
||||
setKeyGenerator,
|
||||
} from 'slate'
|
||||
import { resetKeyGenerator, setKeyGenerator } from 'slate'
|
||||
```
|
||||
|
||||
Utility functions that ship with Slate that may be useful for certain use cases.
|
||||
|
||||
|
||||
## Functions
|
||||
|
||||
### `resetKeyGenerator`
|
||||
|
||||
`resetKeyGenerator() => Void`
|
||||
|
||||
Resets Slate's internal key generating function to its default state. This is useful for server-side rendering, or anywhere you want to ensure fresh, deterministic creation of keys.
|
||||
|
||||
### `setKeyGenerator`
|
||||
|
||||
`setKeyGenerator(generator: Function) => Void`
|
||||
|
||||
Allows you to specify your own key generating function, instead of using Slate's built-in default generator which simply uses auto-incrementing number strings. (eg. `'0'`, `'1'`, `'2'`, ...)
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# `Value`
|
||||
|
||||
```js
|
||||
@ -11,7 +10,6 @@ All changes to the document and selection are also performed through the value o
|
||||
|
||||
For convenience, in addition to changes, many of the selection and document properties are exposed as proxies on the `Value` object.
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
```js
|
||||
@ -26,97 +24,113 @@ Value({
|
||||
```
|
||||
|
||||
### `data`
|
||||
|
||||
`Data`
|
||||
|
||||
An object containing arbitrary data for the value.
|
||||
|
||||
### `decorations`
|
||||
|
||||
`List<Ranges>|Null`
|
||||
|
||||
A list of ranges in the document with marks that aren't part of the content itself—like matches for the current search string.
|
||||
|
||||
### `document`
|
||||
|
||||
`Document`
|
||||
|
||||
The current document of the value.
|
||||
|
||||
### `history`
|
||||
|
||||
`History`
|
||||
|
||||
An object that stores the history of changes.
|
||||
|
||||
### `object`
|
||||
|
||||
`String`
|
||||
|
||||
A string with a value of `'value'`.
|
||||
|
||||
### `schema`
|
||||
|
||||
`Schema`
|
||||
|
||||
An object representing the schema of the value's document.
|
||||
|
||||
### `selection`
|
||||
|
||||
`Range`
|
||||
|
||||
The current selection of the value.
|
||||
|
||||
|
||||
## Computed Properties
|
||||
|
||||
These properties aren't supplied when creating a `Value`, but are instead computed based on the current `document` and `selection`.
|
||||
|
||||
### `{edge}Text`
|
||||
|
||||
`Text`
|
||||
|
||||
Get the leaf [`Text`](./text.md) node at `{edge}`. Where `{edge}` is one of: `anchor`, `focus`, `start` or `end`.
|
||||
|
||||
|
||||
### `{edge}Block`
|
||||
|
||||
`Block`
|
||||
|
||||
Get the leaf [`Block`](./block.md) node at `{edge}`. Where `{edge}` is one of: `anchor`, `focus`, `start` or `end`.
|
||||
|
||||
### `marks`
|
||||
|
||||
`Set`
|
||||
|
||||
Get a set of the [`Marks`](./mark.md) in the current selection.
|
||||
|
||||
### `activeMarks`
|
||||
|
||||
`Set`
|
||||
|
||||
Get a subset of the [`Marks`](./mark.md) that are present in _all_ the characters in the current selection. It can be used to determine the active/inactive state of toolbar buttons corresponding to marks, based on the usual rich text editing conventions.
|
||||
|
||||
### `blocks`
|
||||
|
||||
`List`
|
||||
|
||||
Get a list of the lowest-depth [`Block`](./block.md) nodes in the current selection.
|
||||
|
||||
### `fragment`
|
||||
|
||||
`Document`
|
||||
|
||||
Get a [`Document`](./document.md) fragment of the current selection.
|
||||
|
||||
### `inlines`
|
||||
|
||||
`List`
|
||||
|
||||
Get a list of the lowest-depth [`Inline`](./inline.md) nodes in the current selection.
|
||||
|
||||
### `texts`
|
||||
|
||||
`List`
|
||||
|
||||
Get a list of the [`Text`](./text.md) nodes in the current selection.
|
||||
|
||||
### `characters`
|
||||
|
||||
`List`
|
||||
|
||||
Get a list of the [`Character`](./character.md) objects in the current selection.
|
||||
|
||||
### `hasUndos`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether there are undoable snapshots to revert to in the history.
|
||||
|
||||
### `hasRedos`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether there are redoable snapshots to revert to in the history.
|
||||
@ -126,46 +140,55 @@ Whether there are redoable snapshots to revert to in the history.
|
||||
These properties are exact proxies of the selection [`Range`](./range.md) equivalents.
|
||||
|
||||
### `{edge}Key`
|
||||
|
||||
`String`
|
||||
|
||||
Get the current key at an `{edge}`. Where `{edge}` is one of: `anchor`, `focus`, `start` or `end`.
|
||||
|
||||
### `{edge}Offset`
|
||||
|
||||
`Number`
|
||||
|
||||
Get the current offset at an `{edge}`. Where `{edge}` is one of: `anchor`, `focus`, `start` or `end`.
|
||||
|
||||
### `isBackward`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is backward.
|
||||
|
||||
### `isBlurred`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is blurred.
|
||||
|
||||
### `isCollapsed`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is collapsed.
|
||||
|
||||
### `isExpanded`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is expanded.
|
||||
|
||||
### `isFocused`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is focused.
|
||||
|
||||
### `isForward`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is forward.
|
||||
|
||||
### `isEmpty`
|
||||
|
||||
`Boolean`
|
||||
|
||||
Whether the current selection is empty.
|
||||
@ -173,29 +196,33 @@ Whether the current selection is empty.
|
||||
## Static Methods
|
||||
|
||||
### `Value.create`
|
||||
|
||||
`Value.create(properties: Object) => Value`
|
||||
|
||||
Create a new `Value` instance with `properties`.
|
||||
|
||||
### `Value.fromJSON`
|
||||
|
||||
`Value.fromJSON(object: Object) => Value`
|
||||
|
||||
Create a value from a JSON `object`.
|
||||
|
||||
### `Value.isValue`
|
||||
|
||||
`Value.isValue(any: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Value`.
|
||||
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `change`
|
||||
|
||||
`change() => Change`
|
||||
|
||||
Create a new [`Change`](./change.md) that acts on the current value.
|
||||
|
||||
### `toJSON`
|
||||
|
||||
`toJSON() => Object`
|
||||
|
||||
Returns a JSON representation of the value.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Previous:</strong><br/><a href="./installing-slate.md">Installing Slate</a></p>
|
||||
<br/>
|
||||
@ -15,9 +14,8 @@ So we start with our app from earlier:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -25,14 +23,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -40,9 +32,8 @@ And now we'll add an `onKeyDown` handler:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -63,7 +54,6 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -75,9 +65,8 @@ Our `onKeyDown` handler might look like this:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -105,7 +94,6 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Previous:</strong><br/><a href="./defining-custom-block-nodes.md">Defining Custom Block Nodes</a></p>
|
||||
<br/>
|
||||
@ -13,7 +12,6 @@ So we start with our app from earlier:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -41,13 +39,13 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = (props) => {
|
||||
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <CodeNode {...props} />
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -55,7 +53,6 @@ And now, we'll edit the `onKeyDown` handler to make it so that when you press `c
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -95,13 +92,13 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = (props) => {
|
||||
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <CodeNode {...props} />
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -126,7 +123,6 @@ function BoldMark(props) {
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -165,20 +161,21 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = (props) => {
|
||||
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <CodeNode {...props} />
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
// Add a `renderMark` method to render marks.
|
||||
renderMark = (props) => {
|
||||
renderMark = props => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold': return <BoldMark {...props} />
|
||||
case 'bold':
|
||||
return <BoldMark {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Previous:</strong><br/><a href="./adding-event-handlers.md">Adding Event Handlers</a></p>
|
||||
<br/>
|
||||
@ -13,9 +12,8 @@ We'll show you how. Let's start with our app from earlier:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -25,7 +23,7 @@ class App extends React.Component {
|
||||
onKeyDown = (event, change) => {
|
||||
if (event.key != '&') return
|
||||
event.preventDefault()
|
||||
change.insertText('and');
|
||||
change.insertText('and')
|
||||
return true
|
||||
}
|
||||
|
||||
@ -38,7 +36,6 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -51,7 +48,11 @@ Node renderers are just simple React components, like so:
|
||||
```js
|
||||
// Define a React component renderer for our code blocks.
|
||||
function CodeNode(props) {
|
||||
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||
return (
|
||||
<pre {...props.attributes}>
|
||||
<code>{props.children}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@ -65,11 +66,14 @@ Now, let's add that renderer to our `Editor`:
|
||||
|
||||
```js
|
||||
function CodeNode(props) {
|
||||
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||
return (
|
||||
<pre {...props.attributes}>
|
||||
<code>{props.children}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -98,12 +102,12 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
// Add a `renderNode` method to render a `CodeNode` for code blocks.
|
||||
renderNode = (props) => {
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <CodeNode {...props} />
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -111,11 +115,14 @@ Okay, but now we'll need a way for the user to actually turn a block into a code
|
||||
|
||||
```js
|
||||
function CodeNode(props) {
|
||||
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||
return (
|
||||
<pre {...props.attributes}>
|
||||
<code>{props.children}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -147,28 +154,31 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = (props) => {
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <CodeNode {...props} />
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Now, if you press `control-\`` the block your cursor is in should turn into a code block! Magic!
|
||||
Now, if you press `control-\`` the block your cursor is in should turn into a code block! Magic!
|
||||
|
||||
*Note: The Edge browser does not currently support `control-...` key events (see [issue](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/742263/)), so this example won't work on it.*
|
||||
_Note: The Edge browser does not currently support `control-...` key events (see [issue](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/742263/)), so this example won't work on it._
|
||||
|
||||
But we forgot one thing. When you hit `control-\`` 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
|
||||
function CodeNode(props) {
|
||||
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||
return (
|
||||
<pre {...props.attributes}>
|
||||
<code>{props.children}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -201,12 +211,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = (props) => {
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <CodeNode {...props} />
|
||||
case 'code':
|
||||
return <CodeNode {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
# Installing Slate
|
||||
|
||||
Slate is a monorepo divided up into multi npm packages, so to install it you do:
|
||||
@ -43,14 +42,14 @@ const initialValue = Value.fromJSON({
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
text: 'A line of text in a paragraph.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
@ -73,22 +72,21 @@ const initialValue = Value.fromJSON({
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
text: 'A line of text in a paragraph.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
// Define our app...
|
||||
class App extends React.Component {
|
||||
|
||||
// Set the initial value when the app is first constructed.
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
// On change, update the app's React state with the new editor value.
|
||||
@ -98,24 +96,17 @@ class App extends React.Component {
|
||||
|
||||
// Render the editor.
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
You'll notice that the `onChange` handler passed into the `Editor` component just updates the app's state with the newest changed value. That way, when it re-renders the editor, the new value is reflected with your changes.
|
||||
|
||||
And that's it!
|
||||
And that's it!
|
||||
|
||||
That's the most basic example of Slate. If you render that onto the page, you should see a paragraph with the text `A line of text in a paragraph.`. And when you type, you should see the text change!
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Next:</strong><br/><a href="./adding-event-handlers.md">Adding Event Handlers</a></p>
|
||||
<br/>
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Previous:</strong><br/><a href="./saving-to-a-database.md">Saving to a Database</a></p>
|
||||
<br/>
|
||||
@ -13,9 +12,8 @@ Let's start with a basic editor:
|
||||
import { Editor } from 'slate-react'
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: Plain.deserialize('')
|
||||
value: Plain.deserialize(''),
|
||||
}
|
||||
|
||||
onChange({ value }) {
|
||||
@ -23,14 +21,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -38,10 +30,10 @@ That will render a basic Slate editor on your page.
|
||||
|
||||
Now... we need to add the [`Html`](../reference/serializers/html.md) serializer. And to do that, we need to tell it a bit about the schema we plan on using. For this example, we'll work with a schema that has a few different parts:
|
||||
|
||||
- A `paragraph` block.
|
||||
- A `code` block for code samples.
|
||||
- A `quote` block for quotes...
|
||||
- And `bold`, `italic` and `underline` formatting.
|
||||
* A `paragraph` block.
|
||||
* A `code` block for code samples.
|
||||
* A `quote` block for quotes...
|
||||
* And `bold`, `italic` and `underline` formatting.
|
||||
|
||||
By default, the `Html` serializer, knows nothing about our schema just like Slate itself. To fix this, we need to pass it a set of `rules`. Each rule defines how to serialize and deserialize a Slate object.
|
||||
|
||||
@ -56,11 +48,11 @@ const rules = [
|
||||
return {
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
nodes: next(el.childNodes)
|
||||
nodes: next(el.childNodes),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
@ -76,7 +68,7 @@ const rules = [
|
||||
return {
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
nodes: next(el.childNodes)
|
||||
nodes: next(el.childNodes),
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -85,8 +77,8 @@ const rules = [
|
||||
if (obj.object == 'block' && obj.type == 'paragraph') {
|
||||
return <p>{children}</p>
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
@ -103,7 +95,7 @@ Let's add the other types of blocks we want:
|
||||
const BLOCK_TAGS = {
|
||||
p: 'paragraph',
|
||||
blockquote: 'quote',
|
||||
pre: 'code'
|
||||
pre: 'code',
|
||||
}
|
||||
|
||||
const rules = [
|
||||
@ -115,19 +107,26 @@ const rules = [
|
||||
return {
|
||||
object: 'block',
|
||||
type: type,
|
||||
nodes: next(el.childNodes)
|
||||
nodes: next(el.childNodes),
|
||||
}
|
||||
},
|
||||
// Switch serialize to handle more blocks...
|
||||
serialize(obj, children) {
|
||||
if (obj.object != 'block') return
|
||||
switch (obj.type) {
|
||||
case 'paragraph': return <p>{children}</p>
|
||||
case 'quote': return <blockquote>{children}</blockquote>
|
||||
case 'code': return <pre><code>{children}</code></pre>
|
||||
case 'paragraph':
|
||||
return <p>{children}</p>
|
||||
case 'quote':
|
||||
return <blockquote>{children}</blockquote>
|
||||
case 'code':
|
||||
return (
|
||||
<pre>
|
||||
<code>{children}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
@ -137,12 +136,11 @@ You'll notice that even though code blocks are nested in a `<pre>` and a `<code>
|
||||
|
||||
Okay. So now our serializer can handle blocks, but we need to add our marks to it as well. Let's do that with a new rule...
|
||||
|
||||
|
||||
```js
|
||||
const BLOCK_TAGS = {
|
||||
blockquote: 'quote',
|
||||
p: 'paragraph',
|
||||
pre: 'code'
|
||||
pre: 'code',
|
||||
}
|
||||
|
||||
// Add a dictionary of mark tags.
|
||||
@ -160,17 +158,24 @@ const rules = [
|
||||
return {
|
||||
object: 'block',
|
||||
type: type,
|
||||
nodes: next(el.childNodes)
|
||||
nodes: next(el.childNodes),
|
||||
}
|
||||
},
|
||||
serialize(obj, children) {
|
||||
if (obj.object != 'block') return
|
||||
switch (obj.type) {
|
||||
case 'code': return <pre><code>{children}</code></pre>
|
||||
case 'paragraph': return <p>{children}</p>
|
||||
case 'quote': return <blockquote>{children}</blockquote>
|
||||
case 'code':
|
||||
return (
|
||||
<pre>
|
||||
<code>{children}</code>
|
||||
</pre>
|
||||
)
|
||||
case 'paragraph':
|
||||
return <p>{children}</p>
|
||||
case 'quote':
|
||||
return <blockquote>{children}</blockquote>
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
// Add a new rule that handles marks...
|
||||
{
|
||||
@ -180,18 +185,21 @@ const rules = [
|
||||
return {
|
||||
object: 'mark',
|
||||
type: type,
|
||||
nodes: next(el.childNodes)
|
||||
nodes: next(el.childNodes),
|
||||
}
|
||||
},
|
||||
serialize(obj, children) {
|
||||
if (obj.object != 'mark') return
|
||||
switch (obj.type) {
|
||||
case 'bold': return <strong>{children}</strong>
|
||||
case 'italic': return <em>{children}</em>
|
||||
case 'underline': return <u>{children}</u>
|
||||
case 'bold':
|
||||
return <strong>{children}</strong>
|
||||
case 'italic':
|
||||
return <em>{children}</em>
|
||||
case 'underline':
|
||||
return <u>{children}</u>
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
@ -208,13 +216,9 @@ And finally, now that we have our serializer initialized, we can update our app
|
||||
|
||||
```js
|
||||
// Load the initial value from Local Storage or a default.
|
||||
const initialValue = (
|
||||
localStorage.getItem('content') ||
|
||||
'<p></p>'
|
||||
)
|
||||
const initialValue = localStorage.getItem('content') || '<p></p>'
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: html.deserialize(initialValue),
|
||||
}
|
||||
@ -240,24 +244,33 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderNode = (props) => {
|
||||
|
||||
renderNode = props => {
|
||||
switch (props.node.type) {
|
||||
case 'code': return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||
case 'paragraph': return <p {...props.attributes}>{props.children}</p>
|
||||
case 'quote': return <blockquote {...props.attributes}>{props.children}</blockquote>
|
||||
case 'code':
|
||||
return (
|
||||
<pre {...props.attributes}>
|
||||
<code>{props.children}</code>
|
||||
</pre>
|
||||
)
|
||||
case 'paragraph':
|
||||
return <p {...props.attributes}>{props.children}</p>
|
||||
case 'quote':
|
||||
return <blockquote {...props.attributes}>{props.children}</blockquote>
|
||||
}
|
||||
}
|
||||
|
||||
// Add a `renderMark` method to render marks.
|
||||
renderMark = (props) => {
|
||||
renderMark = props => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold': return <strong>{props.children}</strong>
|
||||
case 'italic': return <em>{props.children}</em>
|
||||
case 'underline': return <u>{props.children}</u>
|
||||
case 'bold':
|
||||
return <strong>{props.children}</strong>
|
||||
case 'italic':
|
||||
return <em>{props.children}</em>
|
||||
case 'underline':
|
||||
return <u>{props.children}</u>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Previous:</strong><br/><a href="./using-plugins.md">Using Plugins</a></p>
|
||||
<br/>
|
||||
@ -26,20 +25,19 @@ const initialValue = Value.fromJSON({
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
text: 'A line of text in a paragraph.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -47,14 +45,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -76,20 +68,19 @@ const initialValue = Value.fromJSON({
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
text: 'A line of text in a paragraph.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -101,14 +92,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -119,31 +104,32 @@ But... if you refresh the page, everything is still reset. That's because we nee
|
||||
```js
|
||||
// Update the initial content to be pulled from Local Storage if it exists.
|
||||
const existingValue = JSON.parse(localStorage.getItem('content'))
|
||||
const initialValue = Value.fromJSON(existingValue || {
|
||||
document: {
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
const initialValue = Value.fromJSON(
|
||||
existingValue || {
|
||||
document: {
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -154,14 +140,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -171,31 +151,32 @@ However, if you inspect the change handler, you'll notice that it's actually sav
|
||||
|
||||
```js
|
||||
const existingValue = JSON.parse(localStorage.getItem('content'))
|
||||
const initialValue = Value.fromJSON(existingValue || {
|
||||
document: {
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
const initialValue = Value.fromJSON(
|
||||
existingValue || {
|
||||
document: {
|
||||
nodes: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
nodes: [
|
||||
{
|
||||
object: 'text',
|
||||
leaves: [
|
||||
{
|
||||
text: 'A line of text in a paragraph.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -209,14 +190,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -232,12 +207,13 @@ import { Editor } from 'slate-react'
|
||||
import Plain from 'slate-plain-serializer'
|
||||
|
||||
const existingValue = localStorage.getItem('content')
|
||||
const initialValue = Plain.deserialize(existingValue || 'A string of plain text.')
|
||||
const initialValue = Plain.deserialize(
|
||||
existingValue || 'A string of plain text.'
|
||||
)
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue
|
||||
value: initialValue,
|
||||
}
|
||||
|
||||
onChange = ({ value }) => {
|
||||
@ -250,14 +226,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
return <Editor value={this.state.value} onChange={this.onChange} />
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -265,7 +235,6 @@ That works! Now you're working with plain text.
|
||||
|
||||
However, sometimes you may want something a bit more custom, and a bit more complex... good old fashioned HTML. In that case, check out the next guide...
|
||||
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Next:</strong><br/><a href="./saving-and-loading-html-content.md">Saving and Loading HTML Content</a></p>
|
||||
<br/>
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Previous:</strong><br/><a href="./applying-custom-formatting.md">Applying Custom Formatting</a></p>
|
||||
<br/>
|
||||
@ -15,7 +14,6 @@ Starting with our app from earlier:
|
||||
|
||||
```js
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -42,12 +40,12 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderMark = (props) => {
|
||||
renderMark = props => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold': return <strong>{props.children}</strong>
|
||||
case 'bold':
|
||||
return <strong>{props.children}</strong>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -82,7 +80,7 @@ function MarkHotkey(options) {
|
||||
// Toggle the mark `type`.
|
||||
change.toggleMark(type)
|
||||
return true
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -95,16 +93,13 @@ Now that we have our plugin, let's remove the hard-coded logic from our app, and
|
||||
// Initialize our bold-mark-adding plugin.
|
||||
const boldPlugin = MarkHotkey({
|
||||
type: 'bold',
|
||||
key: 'b'
|
||||
key: 'b',
|
||||
})
|
||||
|
||||
// Create an array of plugins.
|
||||
const plugins = [
|
||||
boldPlugin
|
||||
]
|
||||
const plugins = [boldPlugin]
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -124,13 +119,13 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderMark = (props) => {
|
||||
|
||||
renderMark = props => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold': return <strong>{props.children}</strong>
|
||||
case 'bold':
|
||||
return <strong>{props.children}</strong>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -145,11 +140,10 @@ const plugins = [
|
||||
MarkHotkey({ key: '`', type: 'code' }),
|
||||
MarkHotkey({ key: 'i', type: 'italic' }),
|
||||
MarkHotkey({ key: '~', type: 'strikethrough' }),
|
||||
MarkHotkey({ key: 'u', type: 'underline' })
|
||||
MarkHotkey({ key: 'u', type: 'underline' }),
|
||||
]
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
value: initialValue,
|
||||
}
|
||||
@ -168,18 +162,22 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderMark = (props) => {
|
||||
|
||||
renderMark = props => {
|
||||
switch (props.mark.type) {
|
||||
case 'bold': return <strong>{props.children}</strong>
|
||||
case 'bold':
|
||||
return <strong>{props.children}</strong>
|
||||
// Add our new mark renderers...
|
||||
case 'code': return <code>{props.children}</code>
|
||||
case 'italic': return <em>{props.children}</em>
|
||||
case 'strikethrough': return <del>{props.children}</del>
|
||||
case 'underline': return <u>{props.children}</u>
|
||||
case 'code':
|
||||
return <code>{props.children}</code>
|
||||
case 'italic':
|
||||
return <em>{props.children}</em>
|
||||
case 'strikethrough':
|
||||
return <del>{props.children}</del>
|
||||
case 'underline':
|
||||
return <u>{props.children}</u>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -187,7 +185,6 @@ And there you have it! We just added a ton of functionality to the editor with v
|
||||
|
||||
That's why plugins are awesome. They let you get really expressive while also making your codebase easier to manage. And since Slate is built with plugins as a primary consideration, using them is dead simple!
|
||||
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Next:</strong><br/><a href="./saving-to-a-database.md">Saving to a Database</a></p>
|
||||
<br/>
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
# Using the Bundled Source
|
||||
|
||||
For most folks, you'll want to install Slate via `npm`, in which case you can follow the regular [Installing Slate](./installing-slate.md) guide.
|
||||
For most folks, you'll want to install Slate via `npm`, in which case you can follow the regular [Installing Slate](./installing-slate.md) guide.
|
||||
|
||||
But, if you'd rather install Slate by simply adding a `<script>` tag to your application, this guide will help you. To make the "bundled" use case simpler, each version of Slate ships with a bundled source file called `slate.js`.
|
||||
|
||||
@ -55,4 +54,3 @@ That's it, you're ready to go!
|
||||
<br/>
|
||||
<p align="center"><strong>Next:</strong><br/><a href="./adding-event-handlers.md">Adding Event Handlers</a></p>
|
||||
<br/>
|
||||
|
||||
|
@ -1,25 +1,23 @@
|
||||
|
||||
# Examples
|
||||
|
||||
![](../docs/images/preview.png)
|
||||
|
||||
This directory contains a set of examples that give you an idea for how you might use Slate to implement your own editor. Take a look around!
|
||||
|
||||
- [**Plain text**](./plain-text) — showing the most basic case: a glorified `<textarea>`.
|
||||
- [**Rich text**](./rich-text) — showing the features you'd expect from a basic editor.
|
||||
- [**Forced Layout**](./forced-layout) - showing how to use schema rules to enforce document structure
|
||||
- [**Auto-markdown**](./auto-markdown) — showing how to add key handlers for Markdown-like shortcuts.
|
||||
- [**Links**](./links) — showing how wrap text in inline nodes with associated data.
|
||||
- [**Images**](./images) — showing how to use void (text-less) nodes to add images.
|
||||
- [**Hovering menu**](./hovering-menu) — showing how a contextual hovering menu can be implemented.
|
||||
- [**Tables**](./tables) — showing how to nest blocks to render more advanced components.
|
||||
- [**Paste HTML**](./paste-html) — showing how to use an HTML serializer to handle pasted HTML.
|
||||
- [**Code Highlighting**](./code-highlighting) — showing how to use decorators to dynamically mark text.
|
||||
- ...and more!
|
||||
* [**Plain text**](./plain-text) — showing the most basic case: a glorified `<textarea>`.
|
||||
* [**Rich text**](./rich-text) — showing the features you'd expect from a basic editor.
|
||||
* [**Forced Layout**](./forced-layout) - showing how to use schema rules to enforce document structure
|
||||
* [**Auto-markdown**](./auto-markdown) — showing how to add key handlers for Markdown-like shortcuts.
|
||||
* [**Links**](./links) — showing how wrap text in inline nodes with associated data.
|
||||
* [**Images**](./images) — showing how to use void (text-less) nodes to add images.
|
||||
* [**Hovering menu**](./hovering-menu) — showing how a contextual hovering menu can be implemented.
|
||||
* [**Tables**](./tables) — showing how to nest blocks to render more advanced components.
|
||||
* [**Paste HTML**](./paste-html) — showing how to use an HTML serializer to handle pasted HTML.
|
||||
* [**Code Highlighting**](./code-highlighting) — showing how to use decorators to dynamically mark text.
|
||||
* ...and more!
|
||||
|
||||
If you have an idea for an example that shows a common use case, pull request it!
|
||||
|
||||
|
||||
## Running the Examples
|
||||
|
||||
To get the examples running on your machine, you need to have the Slate repository cloned to your computer. After that, you need to `cd` into the directory where you cloned it, and install the dependencies with `yarn` and bootstrap the monorepo:
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "With Slate you can build complex block types that have their own embedded content and behaviors, like rendering checkboxes inside check list items!"
|
||||
"text":
|
||||
"With Slate you can build complex block types that have their own embedded content and behaviors, like rendering checkboxes inside check list items!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "There are certain behaviors that require rendering dynamic marks on string of text, like rendering code highlighting. For example:"
|
||||
"text":
|
||||
"There are certain behaviors that require rendering dynamic marks on string of text, like rendering code highlighting. For example:"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,9 +9,10 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "In addition to simple image nodes, you can actually create complex embedded nodes. For example, this one contains an input element that lets you change the video being rendered!"
|
||||
}
|
||||
]
|
||||
"text":
|
||||
"In addition to simple image nodes, you can actually create complex embedded nodes. For example, this one contains an input element that lets you change the video being rendered!"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -31,7 +32,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Try it out! If you want another good video URL to try, go with: https://www.youtube.com/embed/6Ejga4kJUts"
|
||||
"text":
|
||||
"Try it out! If you want another good video URL to try, go with: https://www.youtube.com/embed/6Ejga4kJUts"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"document": {
|
||||
"document": {
|
||||
"nodes": [
|
||||
{
|
||||
"object": "block",
|
||||
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "In addition to block nodes, you can create inline void nodes, like "
|
||||
"text":
|
||||
"In addition to block nodes, you can create inline void nodes, like "
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -23,7 +23,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "This example shows how to enforce your layout with schema-specific rules. This document will always have a title block at the top and at least one paragraph in the body. Try deleting them and see what happens!"
|
||||
"text":
|
||||
"This example shows how to enforce your layout with schema-specific rules. This document will always have a title block at the top and at least one paragraph in the body. Try deleting them and see what happens!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Slate editors save all changes to an internal \"history\" automatically, so you don't need to implement undo/redo yourself. And the editor automatically binds to the browser's default undo/redo keyboard shortcuts."
|
||||
"text":
|
||||
"Slate editors save all changes to an internal \"history\" automatically, so you don't need to implement undo/redo yourself. And the editor automatically binds to the browser's default undo/redo keyboard shortcuts."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -23,7 +24,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Try it out for yourself! Make any changes you'd like then press \"cmd+z\"."
|
||||
"text":
|
||||
"Try it out for yourself! Make any changes you'd like then press \"cmd+z\"."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "This example shows how you can make a hovering menu appear above your content, which you can use to make text "
|
||||
"text":
|
||||
"This example shows how you can make a hovering menu appear above your content, which you can use to make text "
|
||||
},
|
||||
{
|
||||
"text": "bold",
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "In addition to nodes that contain editable text, you can also create other types of nodes, like images or videos."
|
||||
"text":
|
||||
"In addition to nodes that contain editable text, you can also create other types of nodes, like images or videos."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -20,7 +21,8 @@
|
||||
"type": "image",
|
||||
"isVoid": true,
|
||||
"data": {
|
||||
"src": "https://img.washingtonpost.com/wp-apps/imrs.php?src=https://img.washingtonpost.com/news/speaking-of-science/wp-content/uploads/sites/36/2015/10/as12-49-7278-1024x1024.jpg&w=1484"
|
||||
"src":
|
||||
"https://img.washingtonpost.com/wp-apps/imrs.php?src=https://img.washingtonpost.com/news/speaking-of-science/wp-content/uploads/sites/36/2015/10/as12-49-7278-1024x1024.jpg&w=1484"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -31,7 +33,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "This example shows images in action. It features two ways to add images. You can either add an image via the toolbar icon above, or if you want in on a little secret, copy an image URL to your keyboard and paste it anywhere in the editor!"
|
||||
"text":
|
||||
"This example shows images in action. It features two ways to add images. You can either add an image via the toolbar icon above, or if you want in on a little secret, copy an image URL to your keyboard and paste it anywhere in the editor!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
html,
|
||||
input,
|
||||
textarea {
|
||||
@ -45,7 +44,7 @@ blockquote {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
blockquote[dir="rtl"] {
|
||||
blockquote[dir='rtl'] {
|
||||
border-left: none;
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
@ -63,9 +62,9 @@ td {
|
||||
|
||||
input {
|
||||
box-sizing: border-box;
|
||||
font-size: .85em;
|
||||
font-size: 0.85em;
|
||||
width: 100%;
|
||||
padding: .5em;
|
||||
padding: 0.5em;
|
||||
border: 2px solid #ddd;
|
||||
background: #fafafa;
|
||||
}
|
||||
@ -90,7 +89,7 @@ input:focus {
|
||||
|
||||
.nav {
|
||||
padding: 10px 15px;
|
||||
color: #AAA;
|
||||
color: #aaa;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
@ -104,12 +103,12 @@ input:focus {
|
||||
|
||||
.nav-link {
|
||||
margin-left: 1em;
|
||||
color: #AAA;
|
||||
color: #aaa;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
color: #FFF;
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@ -146,7 +145,8 @@ input:focus {
|
||||
* Example.
|
||||
*/
|
||||
|
||||
.example, .error {
|
||||
.example,
|
||||
.error {
|
||||
max-width: 42em;
|
||||
margin: 0 auto 20px;
|
||||
padding: 20px;
|
||||
@ -184,7 +184,7 @@ input:focus {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button[data-active="true"] {
|
||||
.button[data-active='true'] {
|
||||
color: black;
|
||||
}
|
||||
|
||||
@ -222,14 +222,14 @@ input:focus {
|
||||
opacity: 0;
|
||||
background-color: #222;
|
||||
border-radius: 4px;
|
||||
transition: opacity .75s;
|
||||
transition: opacity 0.75s;
|
||||
}
|
||||
|
||||
.hover-menu .button {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.hover-menu .button[data-active="true"] {
|
||||
.hover-menu .button[data-active='true'] {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@ -267,6 +267,6 @@ input:focus {
|
||||
.word-counter {
|
||||
margin-top: 10px;
|
||||
padding: 12px;
|
||||
background-color: #EBEBEB;
|
||||
background-color: #ebebeb;
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "In addition to block nodes, you can create inline nodes, like "
|
||||
"text":
|
||||
"In addition to block nodes, you can create inline nodes, like "
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -48,7 +49,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "This example shows hyperlinks in action. It features two ways to add links. You can either add a link via the toolbar icon above, or if you want in on a little secret, copy a URL to your keyboard and paste it while a range of text is selected."
|
||||
"text":
|
||||
"This example shows hyperlinks in action. It features two ways to add links. You can either add a link via the toolbar icon above, or if you want in on a little secret, copy a URL to your keyboard and paste it while a range of text is selected."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "The editor gives you full control over the logic you can add. For example, it's fairly common to want to add markdown-like shortcuts to editors. So that, when you start a line with \"> \" you get a blockquote that looks like this:"
|
||||
"text":
|
||||
"The editor gives you full control over the logic you can add. For example, it's fairly common to want to add markdown-like shortcuts to editors. So that, when you start a line with \"> \" you get a blockquote that looks like this:"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -37,7 +38,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Order when you start a line with \"## \" you get a level-two heading, like this:"
|
||||
"text":
|
||||
"Order when you start a line with \"## \" you get a level-two heading, like this:"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -65,7 +67,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Try it out for yourself! Try starting a new line with \">\", \"-\", or \"#\"s."
|
||||
"text":
|
||||
"Try it out for yourself! Try starting a new line with \">\", \"-\", or \"#\"s."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "By default, pasting content into a Slate editor will use the content's plain text representation. This is fine for some use cases, but sometimes you want to actually be able to paste in content and have it parsed into blocks and links and things. To do this, you need to add a parser that triggers on paste. This is an example of doing exactly that!"
|
||||
"text":
|
||||
"By default, pasting content into a Slate editor will use the content's plain text representation. This is fine for some use cases, but sometimes you want to actually be able to paste in content and have it parsed into blocks and links and things. To do this, you need to add a parser that triggers on paste. This is an example of doing exactly that!"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -23,7 +24,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Try it out for yourself! Copy and paste some HTML content from another site into this editor."
|
||||
"text":
|
||||
"Try it out for yourself! Copy and paste some HTML content from another site into this editor."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -56,7 +56,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Since it's rich text, you can do things like turn a selection of text "
|
||||
"text":
|
||||
"Since it's rich text, you can do things like turn a selection of text "
|
||||
},
|
||||
{
|
||||
"text": "bold",
|
||||
@ -65,8 +66,10 @@
|
||||
"type": "bold"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"text": ", or add a semantically rendered block quote in the middle of the page, like this:"
|
||||
},
|
||||
{
|
||||
"text":
|
||||
", or add a semantically rendered block quote in the middle of the page, like this:"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Slate supports both left-to-right text editing (English, French, etc.) and right-to-left text editing (Arabic, Hebrew, etc.) which it automatically detects. Here's an example featuring excerpts from Khalil Gibran:"
|
||||
"text":
|
||||
"Slate supports both left-to-right text editing (English, French, etc.) and right-to-left text editing (Arabic, Hebrew, etc.) which it automatically detects. Here's an example featuring excerpts from Khalil Gibran:"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -23,7 +24,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Et un jeune dit : parle-nous de l'amitié.\nEt il répondit, disant :\nVotre ami est votre besoin qui a trouvé une réponse.\nIl est le champ que vous semez avec amour et moissonnez avec reconnaissance.\nIl est votre table et votre foyer."
|
||||
"text":
|
||||
"Et un jeune dit : parle-nous de l'amitié.\nEt il répondit, disant :\nVotre ami est votre besoin qui a trouvé une réponse.\nIl est le champ que vous semez avec amour et moissonnez avec reconnaissance.\nIl est votre table et votre foyer."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -37,7 +39,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "ثم قال له شاب: هات حدثناعن الصداقة.\nفأجاب و قال:\nإن صديقك هو كفاية حاجاتك.\nهو حقك الذي تزرعه بالمحبة و تحصده بالشكر.\nهو مائدتك و موقدك."
|
||||
"text":
|
||||
"ثم قال له شاب: هات حدثناعن الصداقة.\nفأجاب و قال:\nإن صديقك هو كفاية حاجاتك.\nهو حقك الذي تزرعه بالمحبة و تحصده بالشكر.\nهو مائدتك و موقدك."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -51,7 +54,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "And a youth said, \"Speak to us of Friendship.\"\nYour friend is your needs answered.\nHe is your field which you sow with love and reap with thanksgiving.\nAnd he is your board and your fireside."
|
||||
"text":
|
||||
"And a youth said, \"Speak to us of Friendship.\"\nYour friend is your needs answered.\nHe is your field which you sow with love and reap with thanksgiving.\nAnd he is your board and your fireside."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "This is editable text that you can search. As you search, it looks for matching strings of text, and adds \"decoration\" marks to them in realtime."
|
||||
"text":
|
||||
"This is editable text that you can search. As you search, it looks for matching strings of text, and adds \"decoration\" marks to them in realtime."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -23,7 +24,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Try it out for yourself by typing in the search box above!"
|
||||
"text":
|
||||
"Try it out for yourself by typing in the search box above!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -34,7 +34,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "They achieve this by sending any document-altering operations to each other whenever a change occurs, and then applying them locally with "
|
||||
"text":
|
||||
"They achieve this by sending any document-altering operations to each other whenever a change occurs, and then applying them locally with "
|
||||
},
|
||||
{
|
||||
"text": "change.applyOperations()",
|
||||
@ -67,7 +68,8 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "this example doesn't showcase operational transforms or network communication, which are required for realtime editing with multiple people at once."
|
||||
"text":
|
||||
"this example doesn't showcase operational transforms or network communication, which are required for realtime editing with multiple people at once."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "Since the editor is based on a recursive tree model, similar to an HTML document, you can create complex nested structures, like tables:"
|
||||
"text":
|
||||
"Since the editor is based on a recursive tree model, similar to an HTML document, you can create complex nested structures, like tables:"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -240,7 +241,8 @@
|
||||
"object": "text",
|
||||
"leaves": [
|
||||
{
|
||||
"text": "This table is just a basic example of rendering a table, and it doesn't have fancy functionality. But you could augment it to add support for navigating with arrow keys, displaying table headers, adding column and rows, or even formulas if you wanted to get really crazy!"
|
||||
"text":
|
||||
"This table is just a basic example of rendering a table, and it doesn't have fancy functionality. But you could augment it to add support for navigating with arrow keys, displaying table headers, adding column and rows, or even formulas if you wanted to get really crazy!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -82,9 +82,9 @@
|
||||
"build": "rollup --config",
|
||||
"clean": "lerna run clean && rm -rf ./node_modules ./dist ./examples/build.*.js",
|
||||
"gh-pages": "cross-env NODE_ENV=production yarn build && gh-pages --dist ./examples",
|
||||
"lint": "eslint packages/*/src packages/*/test examples/*/*.js examples/dev/*/*.js && prettier --list-different '**/*.{js,jsx}'",
|
||||
"lint": "eslint packages/*/src packages/*/test examples/*/*.js examples/dev/*/*.js && prettier --list-different '**/*.{js,jsx,md,json,css}'",
|
||||
"open": "open http://localhost:8080/dev.html",
|
||||
"prettier": "prettier --write '**/*.{js,jsx}'",
|
||||
"prettier": "prettier --write '**/*.{js,jsx,md,json,css}'",
|
||||
"release": "yarn test && yarn lint && lerna publish && yarn gh-pages",
|
||||
"server": "http-server ./examples",
|
||||
"start": "npm-run-all --parallel --print-label watch server",
|
||||
|
@ -1,16 +1,15 @@
|
||||
|
||||
# Packages
|
||||
|
||||
Slate's codebase is monorepo managed with [Lerna](https://lernajs.io/). It consists of a handful of packages—although you won't always use all of them. They are:
|
||||
|
||||
|**Package**|**Version**|**Size**|**Description**|
|
||||
|---|---|---|---|
|
||||
|[`slate`](./slate)|[![](https://img.shields.io/npm/v/slate.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate/dist/slate.min.js?compression=gzip&label=size)](https://unpkg.com/slate/dist/slate.min.js)|Slate's core data model logic.|
|
||||
|[`slate-base64-serializer`](./slate-base64-serializer)|[![](https://img.shields.io/npm/v/slate-base64-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-base64-serializer/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-base64-serializer/dist/slate-base64-serializer.min.js?compression=gzip&label=size)](https://unpkg.com/slate-base64-serializer/dist/slate-base64-serializer.min.js)|A Base64 string serializer for Slate documents.|
|
||||
|[`slate-html-serializer`](./slate-html-serializer)|[![](https://img.shields.io/npm/v/slate-html-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-html-serializer/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-html-serializer/dist/slate-html-serializer.min.js?compression=gzip&label=size)](https://unpkg.com/slate-html-serializer/dist/slate-html-serializer.min.js)|An HTML serializer for Slate documents.|
|
||||
|[`slate-hyperscript`](./slate-hyperscript)|[![](https://img.shields.io/npm/v/slate-hyperscript.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-hyperscript/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-hyperscript/dist/slate-hyperscript.min.js?compression=gzip&label=size)](https://unpkg.com/slate-hyperscript/dist/slate-hyperscript.min.js)|A hyperscript tool to write JSX Slate documents!|
|
||||
|[`slate-plain-serializer`](./slate-plain-serializer)|[![](https://img.shields.io/npm/v/slate-plain-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-plain-serializer/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-plain-serializer/dist/slate-plain-serializer.min.js?compression=gzip&label=size)](https://unpkg.com/slate-plain-serializer/dist/slate-plain-serializer.min.js)|A plain text serializer for Slate documents.|
|
||||
|[`slate-prop-types`](./slate-prop-types)|[![](https://img.shields.io/npm/v/slate-prop-types.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-prop-types/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-prop-types/dist/slate-prop-types.min.js?compression=gzip&label=size)](https://unpkg.com/slate-prop-types/dist/slate-prop-types.min.js)|React prop types for checking Slate values.|
|
||||
|[`slate-react`](./slate-react)|[![](https://img.shields.io/npm/v/slate-react.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-react/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-react/dist/slate-react.min.js?compression=gzip&label=size)](https://unpkg.com/slate-react/dist/slate-react.min.js)|React components for rendering Slate editors.|
|
||||
|[`slate-schema-violations`](./slate-schema-violations)|[![](https://img.shields.io/npm/v/slate-schema-violations.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-schema-violations/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-schema-violations/dist/slate-schema-violations.min.js?compression=gzip&label=size)](https://unpkg.com/slate-schema-violations/dist/slate-schema-violations.min.js)|Constants for the built-in schema violations.|
|
||||
|[`slate-simulator`](./slate-simulator)|[![](https://img.shields.io/npm/v/slate-simulator.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-simulator/package.json)|[![](http://img.badgesize.io/https://unpkg.com/slate-simulator/dist/slate-simulator.min.js?compression=gzip&label=size)](https://unpkg.com/slate-simulator/dist/slate-simulator.min.js)|A simulator for testing Slate editors and plugins.|
|
||||
| **Package** | **Version** | **Size** | **Description** |
|
||||
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
|
||||
| [`slate`](./slate) | [![](https://img.shields.io/npm/v/slate.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate/dist/slate.min.js?compression=gzip&label=size)](https://unpkg.com/slate/dist/slate.min.js) | Slate's core data model logic. |
|
||||
| [`slate-base64-serializer`](./slate-base64-serializer) | [![](https://img.shields.io/npm/v/slate-base64-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-base64-serializer/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-base64-serializer/dist/slate-base64-serializer.min.js?compression=gzip&label=size)](https://unpkg.com/slate-base64-serializer/dist/slate-base64-serializer.min.js) | A Base64 string serializer for Slate documents. |
|
||||
| [`slate-html-serializer`](./slate-html-serializer) | [![](https://img.shields.io/npm/v/slate-html-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-html-serializer/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-html-serializer/dist/slate-html-serializer.min.js?compression=gzip&label=size)](https://unpkg.com/slate-html-serializer/dist/slate-html-serializer.min.js) | An HTML serializer for Slate documents. |
|
||||
| [`slate-hyperscript`](./slate-hyperscript) | [![](https://img.shields.io/npm/v/slate-hyperscript.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-hyperscript/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-hyperscript/dist/slate-hyperscript.min.js?compression=gzip&label=size)](https://unpkg.com/slate-hyperscript/dist/slate-hyperscript.min.js) | A hyperscript tool to write JSX Slate documents! |
|
||||
| [`slate-plain-serializer`](./slate-plain-serializer) | [![](https://img.shields.io/npm/v/slate-plain-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-plain-serializer/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-plain-serializer/dist/slate-plain-serializer.min.js?compression=gzip&label=size)](https://unpkg.com/slate-plain-serializer/dist/slate-plain-serializer.min.js) | A plain text serializer for Slate documents. |
|
||||
| [`slate-prop-types`](./slate-prop-types) | [![](https://img.shields.io/npm/v/slate-prop-types.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-prop-types/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-prop-types/dist/slate-prop-types.min.js?compression=gzip&label=size)](https://unpkg.com/slate-prop-types/dist/slate-prop-types.min.js) | React prop types for checking Slate values. |
|
||||
| [`slate-react`](./slate-react) | [![](https://img.shields.io/npm/v/slate-react.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-react/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-react/dist/slate-react.min.js?compression=gzip&label=size)](https://unpkg.com/slate-react/dist/slate-react.min.js) | React components for rendering Slate editors. |
|
||||
| [`slate-schema-violations`](./slate-schema-violations) | [![](https://img.shields.io/npm/v/slate-schema-violations.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-schema-violations/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-schema-violations/dist/slate-schema-violations.min.js?compression=gzip&label=size)](https://unpkg.com/slate-schema-violations/dist/slate-schema-violations.min.js) | Constants for the built-in schema violations. |
|
||||
| [`slate-simulator`](./slate-simulator) | [![](https://img.shields.io/npm/v/slate-simulator.svg?maxAge=2592000&label=version&colorB=007ec6)](./packages/slate-simulator/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-simulator/dist/slate-simulator.min.js?compression=gzip&label=size)](https://unpkg.com/slate-simulator/dist/slate-simulator.min.js) | A simulator for testing Slate editors and plugins. |
|
||||
|
@ -1,23 +1,17 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-base64-serializer` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to work with `slate@0.29.0`.** This is required because `slate-base64-serializer` needs access to the new `Value` model.
|
||||
|
||||
* **Updated to work with `slate@0.29.0`.** This is required because `slate-base64-serializer` needs access to the new `Value` model.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains a base 64 serializer for Slate documents.
|
||||
|
@ -1,13 +1,9 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-dev-logger` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains the logger that Slate uses to log warnings and deprecations only when in development environments.
|
||||
|
@ -1,55 +1,43 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-html-serializer` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.5.0` — January 4, 2018
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
- **Serializing with `parse5` is no longer possible.** The codebase previously made concessions to allow this, but it was never a good idea because `parse5` does not match the `DOMParser` behavior exactly. Instead, you should use `jsdom` to get a matching behavior, otherwise your serialization rules need to account for two slightly different syntax trees.
|
||||
* **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
* **Serializing with `parse5` is no longer possible.** The codebase previously made concessions to allow this, but it was never a good idea because `parse5` does not match the `DOMParser` behavior exactly. Instead, you should use `jsdom` to get a matching behavior, otherwise your serialization rules need to account for two slightly different syntax trees.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to work with `slate@0.29.0`.** This is required because `slate-html-serializer` needs access to the new `Value` model.
|
||||
|
||||
* **Updated to work with `slate@0.29.0`.** This is required because `slate-html-serializer` needs access to the new `Value` model.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — October 14, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
* **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains an HTML serializer for Slate documents, that you can configure depending on your custom schema.
|
||||
|
@ -1,57 +1,45 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-hyperscript` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.5.0` — January 4, 2018
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
* **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to work with `slate@0.29.0`.** This is required because `slate-hyperscript` needs access to the new `Value` model.
|
||||
* **Updated to work with `slate@0.29.0`.** This is required because `slate-hyperscript` needs access to the new `Value` model.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `<state>` tag has been renamed to `<value>`.** This is to stay in line with the newest version of Slate where the `State` object was renamed to `Value`.
|
||||
|
||||
* **The `<state>` tag has been renamed to `<value>`.** This is to stay in line with the newest version of Slate where the `State` object was renamed to `Value`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — October 14, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
* **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains a hyperscript helper for creating Slate documents with JSX!
|
||||
|
@ -1,53 +1,41 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-plain-serializer` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.5.0` — January 4, 2018
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
* **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to work with `slate@0.29.0`.** This is required because `slate-plain-serializer` needs access to the new `Value` model.
|
||||
|
||||
* **Updated to work with `slate@0.29.0`.** This is required because `slate-plain-serializer` needs access to the new `Value` model.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — October 14, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
* **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains a plain-text serializer for Slate documents.
|
||||
|
@ -1,47 +1,37 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-prop-types` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to work with `slate@0.29.0`.** This is required because `slate-prop-types` needs access to the new `Value` model.
|
||||
* **Updated to work with `slate@0.29.0`.** This is required because `slate-prop-types` needs access to the new `Value` model.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `state` prop type has been renamed to `value`.** This is to stay in line with `slate-react@0.29.0` where the `State` object was renamed.
|
||||
|
||||
* **The `state` prop type has been renamed to `value`.** This is to stay in line with `slate-react@0.29.0` where the `State` object was renamed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — October 14, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
* **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains a set of React prop types for Slate values that you can use in your own components and plugins.
|
||||
|
@ -1,165 +1,141 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-react` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.11.0` — January 4, 2018
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
* **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.10.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.9.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to use `slate@0.29.0`.** This is to gain access to the new `Value` model introduced in the newest version of Slate.
|
||||
* **Updated to use `slate@0.29.0`.** This is to gain access to the new `Value` model introduced in the newest version of Slate.
|
||||
|
||||
- **Custom components no longer receive `props.state` or `props.schema`.** These are now exposed directly on the `props.editor` instance itself as `editor.value` and `editor.schema`. This helps eliminate a common issue where because of `shouldComponentUpdate` returning `false`, the `props.state` value was actually outdated, and transforming from it would cause incorrect behaviors.
|
||||
* **Custom components no longer receive `props.state` or `props.schema`.** These are now exposed directly on the `props.editor` instance itself as `editor.value` and `editor.schema`. This helps eliminate a common issue where because of `shouldComponentUpdate` returning `false`, the `props.state` value was actually outdated, and transforming from it would cause incorrect behaviors.
|
||||
|
||||
- **The `plugin.renderEditor` function's signature has changed.** Previously it received `(props, state, editor)` but it now receives just `(props, editor)`. If you need access to the editor's current value, use the new `editor.value` property. This is simply to clean up the API, since the value is already accessible on `editor`.
|
||||
* **The `plugin.renderEditor` function's signature has changed.** Previously it received `(props, state, editor)` but it now receives just `(props, editor)`. If you need access to the editor's current value, use the new `editor.value` property. This is simply to clean up the API, since the value is already accessible on `editor`.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The "state" has been renamed to "value" everywhere.** All of the current references are maintained as deprecations, so you should be able to upgrade and see warnings logged instead of being greeted with a broken editor. This is to reduce the confusion between React's "state" and Slate's editor value, and in an effort to further mimic the native DOM APIs.
|
||||
* **The "state" has been renamed to "value" everywhere.** All of the current references are maintained as deprecations, so you should be able to upgrade and see warnings logged instead of being greeted with a broken editor. This is to reduce the confusion between React's "state" and Slate's editor value, and in an effort to further mimic the native DOM APIs.
|
||||
|
||||
- **The editor `getSchema()`, `getStack()` and `getState()` methods are deprecated.** These have been replaced by property getters on the editor instance itself—`editor.schema`, `editor.stack` and `editor.value`, respectively. This is to reduce confusion with React's own `setState`, and to make accessing these commonly used properties more convenient.
|
||||
* **The editor `getSchema()`, `getStack()` and `getState()` methods are deprecated.** These have been replaced by property getters on the editor instance itself—`editor.schema`, `editor.stack` and `editor.value`, respectively. This is to reduce confusion with React's own `setState`, and to make accessing these commonly used properties more convenient.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Added a new `editor.value` getter property.** This now mimics the DOM for things like `input.value` and `textarea.value`, and is the new way to access the editor's current value.
|
||||
|
||||
- **Added new `editor.schema` and `editor.stack` getters.** Similarly to the new `value` getter, these two new getters give you access to the editor's current schema and stack.
|
||||
* **Added a new `editor.value` getter property.** This now mimics the DOM for things like `input.value` and `textarea.value`, and is the new way to access the editor's current value.
|
||||
|
||||
* **Added new `editor.schema` and `editor.stack` getters.** Similarly to the new `value` getter, these two new getters give you access to the editor's current schema and stack.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.8.0` — October 25, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `Schema` objects in Slate have changed!** Previously, they used to be where you could define normalization rules, define rendering rules, and define decoration rules. This was overloaded, and made other improvements hard. Now, rendering and decorating is done via the newly added plugin functions (`renderNode`, `renderMark`, `decorateNode`). And validation is done either via the lower-level `validateNode` plugin function, or via the new `schema` objects.
|
||||
* **The `Schema` objects in Slate have changed!** Previously, they used to be where you could define normalization rules, define rendering rules, and define decoration rules. This was overloaded, and made other improvements hard. Now, rendering and decorating is done via the newly added plugin functions (`renderNode`, `renderMark`, `decorateNode`). And validation is done either via the lower-level `validateNode` plugin function, or via the new `schema` objects.
|
||||
|
||||
- **The `plugin.onBeforeChange` function was removed.** Previously there was both an `onBeforeChange` handler and an `onChange` handler. Now there is just an `onChange` handler, and the core plugin adds it's own logic before others.
|
||||
* **The `plugin.onBeforeChange` function was removed.** Previously there was both an `onBeforeChange` handler and an `onChange` handler. Now there is just an `onChange` handler, and the core plugin adds it's own logic before others.
|
||||
|
||||
- **The `plugin.render` function was renamed to `plugin.renderEditor`.** It performs the same function, but has been renamed to disambiguate between all of the other new rendering functions available to plugins.
|
||||
* **The `plugin.render` function was renamed to `plugin.renderEditor`.** It performs the same function, but has been renamed to disambiguate between all of the other new rendering functions available to plugins.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **`State` objects now have an embedded `state.schema` property.** This new schema property is used to automatically normalize the state as it changes, according to the editor's current schema. This makes normalization much easier.
|
||||
* **`State` objects now have an embedded `state.schema` property.** This new schema property is used to automatically normalize the state as it changes, according to the editor's current schema. This makes normalization much easier.
|
||||
|
||||
- **A new `renderNode` plugin function was added.** This is the new way to render nodes, instead of using the schema. Any plugin can define a `renderNode(props)` function which is passed the props to render the custom node component with. This is similar to `react-router`'s `render={...}` prop if you are familiar with that.
|
||||
* **A new `renderNode` plugin function was added.** This is the new way to render nodes, instead of using the schema. Any plugin can define a `renderNode(props)` function which is passed the props to render the custom node component with. This is similar to `react-router`'s `render={...}` prop if you are familiar with that.
|
||||
|
||||
- **A new `renderPlaceholder` plugin function was added.** This is similar to the `renderNode` helper, except for rendering placeholders.
|
||||
* **A new `renderPlaceholder` plugin function was added.** This is similar to the `renderNode` helper, except for rendering placeholders.
|
||||
|
||||
- **A new `decorateNode` plugin function was added.** This is similar to the old `rule.decorate` function from schemas. Any plugin can define a `decorateNode(node)` function and that can return extra decoration ranges of marks to apply to the document.
|
||||
|
||||
- **A new `validateNode` plugin function was added.** This is the new way to do specific, custom validations. (There's also the new schema, which is the easier way to do most common validations.) Any plugin can define a `validateNode(node)` function that will be called to ensure nodes are valid. If they are valid, the function should return nothing. Otherwise, it should return a change function that normalizes the node to make it valid again.
|
||||
* **A new `decorateNode` plugin function was added.** This is similar to the old `rule.decorate` function from schemas. Any plugin can define a `decorateNode(node)` function and that can return extra decoration ranges of marks to apply to the document.
|
||||
|
||||
* **A new `validateNode` plugin function was added.** This is the new way to do specific, custom validations. (There's also the new schema, which is the easier way to do most common validations.) Any plugin can define a `validateNode(node)` function that will be called to ensure nodes are valid. If they are valid, the function should return nothing. Otherwise, it should return a change function that normalizes the node to make it valid again.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.7.0` — October 18, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `<Placeholder>` component no longer exists!** Previously there was a `Placeholder` component exported from `slate-react`, but it had lots of problems and a confusing API. Instead, placeholder logic can now be defined via the `schema` by providing a `placeholder` component to render what a node is matched.
|
||||
|
||||
* **The `<Placeholder>` component no longer exists!** Previously there was a `Placeholder` component exported from `slate-react`, but it had lots of problems and a confusing API. Instead, placeholder logic can now be defined via the `schema` by providing a `placeholder` component to render what a node is matched.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.6.0` — October 16, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `data` argument to event handlers has been removed.** Previously event handlers had a signature of `(event, data, change, editor)`, but now they have a signature of just `(event, change, editor)`. This leads to simpler internal Slate logic, and less complex relationship dependencies between plugins. All of the information inside the old `data` argument can be accessed via the similar properties on the `event` argument, or via the `getEventRange`, `getEventTransfer` and `setEventTransfer` helpers.
|
||||
* **The `data` argument to event handlers has been removed.** Previously event handlers had a signature of `(event, data, change, editor)`, but now they have a signature of just `(event, change, editor)`. This leads to simpler internal Slate logic, and less complex relationship dependencies between plugins. All of the information inside the old `data` argument can be accessed via the similar properties on the `event` argument, or via the `getEventRange`, `getEventTransfer` and `setEventTransfer` helpers.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Added a new `setEventTransfer` helper.** This is useful if you're working with `onDrop` or `onPaste` event and you want to set custom data in the event, to retrieve later or for others to consume. It takes a data `type` and a `value` to set the type do.
|
||||
|
||||
- **Event handlers now have access to new events.** The `onClick`, `onCompositionEnd`, `onCompositionStart`, `onDragEnd`, `onDragEnter`, `onDragExit`, `onDragLeave`, `onDragOver`, `onDragStart`, and `onInput` events are all now newly exposed. Your plugin logic can use them to solve some more advanced use cases, and even override the internal Slate logic when necessary. 99% of use cases won't require them still, but they can be useful to have when needed.
|
||||
* **Added a new `setEventTransfer` helper.** This is useful if you're working with `onDrop` or `onPaste` event and you want to set custom data in the event, to retrieve later or for others to consume. It takes a data `type` and a `value` to set the type do.
|
||||
|
||||
* **Event handlers now have access to new events.** The `onClick`, `onCompositionEnd`, `onCompositionStart`, `onDragEnd`, `onDragEnter`, `onDragExit`, `onDragLeave`, `onDragOver`, `onDragStart`, and `onInput` events are all now newly exposed. Your plugin logic can use them to solve some more advanced use cases, and even override the internal Slate logic when necessary. 99% of use cases won't require them still, but they can be useful to have when needed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.5.0` — October 15, 2017
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `data` objects in event handlers have been deprecated.** There were a few different issues with these "helpers": `data.key` didn't account for international keyboards, many properties awkwardly duplicated information that was available on `event.*`, but not completely, and many properties were confusing as to when they applied. If you were using these, you'll now need to use the native `event.*` properties instead. There's also a helpful [`is-hotkey`](https://github.com/ianstormtaylor/is-hotkey) package for more complex hotkey matching.
|
||||
* **The `data` objects in event handlers have been deprecated.** There were a few different issues with these "helpers": `data.key` didn't account for international keyboards, many properties awkwardly duplicated information that was available on `event.*`, but not completely, and many properties were confusing as to when they applied. If you were using these, you'll now need to use the native `event.*` properties instead. There's also a helpful [`is-hotkey`](https://github.com/ianstormtaylor/is-hotkey) package for more complex hotkey matching.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Added a new `getEventRange` helper.** This gets the affected `Range` of Slate document given a DOM `event`. This is useful in the `onDrop` or `onPaste` handlers to retrieve the range in the document where the drop or paste will occur.
|
||||
|
||||
- **Added a new `getEventTransfer` helper.** This gets any Slate-related data from an `event`. It is modelled after the DOM's [`DataTransfer`](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) API, and is useful for retrieve the data being dropped or pasted in `onDrop` or `onPaste` events.
|
||||
* **Added a new `getEventRange` helper.** This gets the affected `Range` of Slate document given a DOM `event`. This is useful in the `onDrop` or `onPaste` handlers to retrieve the range in the document where the drop or paste will occur.
|
||||
|
||||
* **Added a new `getEventTransfer` helper.** This gets any Slate-related data from an `event`. It is modelled after the DOM's [`DataTransfer`](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) API, and is useful for retrieve the data being dropped or pasted in `onDrop` or `onPaste` events.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — October 14, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
* **Updated work with `slate@0.27.0`.** The new version of Slate renames the old `Range` model to `Leaf`, and the old `Selection` model to `Range`.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Added a new `findDOMRange` helper.** Give a Slate `Range` object, it will return a DOM `Range` object with the correct start and end points, making it easier to work with lower-level DOM selections.
|
||||
* **Added a new `findDOMRange` helper.** Give a Slate `Range` object, it will return a DOM `Range` object with the correct start and end points, making it easier to work with lower-level DOM selections.
|
||||
|
||||
- **Added a new `findRange` helper.** Given either a DOM `Selection` or DOM `Range` object and a Slate `State`, it will return a Slate `Range` representing the same part of the document, making it easier to work with DOM selection changes.
|
||||
|
||||
- **Added a new `findNode` helper.** Given a DOM `Element`, it will find the closest Slate `Node` that it represents, making
|
||||
* **Added a new `findRange` helper.** Given either a DOM `Selection` or DOM `Range` object and a Slate `State`, it will return a Slate `Range` representing the same part of the document, making it easier to work with DOM selection changes.
|
||||
|
||||
* **Added a new `findNode` helper.** Given a DOM `Element`, it will find the closest Slate `Node` that it represents, making
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — October 13, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The decoration logic has been updated to use `slate@0.26.0`.** This allows for more complex decoration logic, and even decorations based on external information.
|
||||
|
||||
* **The decoration logic has been updated to use `slate@0.26.0`.** This allows for more complex decoration logic, and even decorations based on external information.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — September 29, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **`onBeforeChange` is now called automatically again in `<Editor>`.** This was removed before, in attempt to decrease the "magic" that the editor was performing, since it normalizes when new props are passed to it, creating instant changes. But we discovered that it is actually necessary for now, so it has been added again.
|
||||
|
||||
* **`onBeforeChange` is now called automatically again in `<Editor>`.** This was removed before, in attempt to decrease the "magic" that the editor was performing, since it normalizes when new props are passed to it, creating instant changes. But we discovered that it is actually necessary for now, so it has been added again.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
|
||||
This package contains the React-specific logic for Slate. It's separated further into a series of directories:
|
||||
|
||||
- [**Components**](./src/components) — containing the React components for rendering Slate editors.
|
||||
- [**Constants**](./src/constants) — containing a few private constants modules.
|
||||
- [**Plugins**](./src/plugins) — containing the React-specific plugins for Slate editors.
|
||||
- [**Utils**](./src/utils) — containing a few private convenience modules.
|
||||
* [**Components**](./src/components) — containing the React components for rendering Slate editors.
|
||||
* [**Constants**](./src/constants) — containing a few private constants modules.
|
||||
* [**Plugins**](./src/plugins) — containing the React-specific plugins for Slate editors.
|
||||
* [**Utils**](./src/utils) — containing a few private convenience modules.
|
||||
|
||||
Feel free to poke around in each of them to learn more!
|
||||
|
@ -1,13 +1,9 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-schema-violations` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — January 26, 2018
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains a set of constants for the built-in violations in a Slate schema.
|
||||
|
@ -1,45 +1,35 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate-simulator` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — October 27, 2017
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `props.state` prop has been renamed to `props.value`.** This is to stay in line with `slate-react@0.9.0` where the same change was made to the `<Editor>`.
|
||||
|
||||
- **The `simulator.state` property is now `simulator.value`** This is to stay in line with `slate@0.29.0` where the same change as made to the `Change` objects.
|
||||
* **The `props.state` prop has been renamed to `props.value`.** This is to stay in line with `slate-react@0.9.0` where the same change was made to the `<Editor>`.
|
||||
|
||||
* **The `simulator.state` property is now `simulator.value`** This is to stay in line with `slate@0.29.0` where the same change as made to the `Change` objects.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — October 25, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Updated to work with `slate@0.28.0`.** Along with the new Schema, the `Stack` which is used internally by the simulator has changed slightly.
|
||||
|
||||
* **Updated to work with `slate@0.28.0`.** Along with the new Schema, the `Stack` which is used internally by the simulator has changed slightly.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — September 17, 2017
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
This package contains a simulator for testing Slate editors and plugins.
|
||||
|
@ -1,199 +1,176 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
This document maintains a list of changes to the `slate` package with each new version. Until `1.0.0` is released, breaking changes will be added as minor version bumps, and smaller changes won't be accounted for since the library is moving quickly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.32.0` — January 4, 2018
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
- **All normalization reasons containing `kind` have been renamed too.** Previously there were normalization reason strings like `child_kind_invalid`. These types of strings have been renamed to `child_object_invalid` to stay consistent.
|
||||
* **The `kind` property of Slate objects has been renamed to `object`.** This is to reduce the confusion over the difference between "kind" and "type" which are practically synonyms. The "object" name was chosen to match the Stripe API, since it seems like a sensible choice and reads much more nicely when looking through JSON.
|
||||
|
||||
* **All normalization reasons containing `kind` have been renamed too.** Previously there were normalization reason strings like `child_kind_invalid`. These types of strings have been renamed to `child_object_invalid` to stay consistent.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.31.0` — November 16, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Operation objects in Slate are now immutable records.** Previously they were native, mutable Javascript objects. Now, there's a new immutable `Operation` model in Slate, ensuring that all of the data inside `Value` objects are immutable. And it allows for easy serialization of operations using `operation.toJSON()` for when sending them between editors. This should not affect most users, unless you are relying on changing the values of the low-level Slate operations (simply reading them is fine).
|
||||
* **Operation objects in Slate are now immutable records.** Previously they were native, mutable Javascript objects. Now, there's a new immutable `Operation` model in Slate, ensuring that all of the data inside `Value` objects are immutable. And it allows for easy serialization of operations using `operation.toJSON()` for when sending them between editors. This should not affect most users, unless you are relying on changing the values of the low-level Slate operations (simply reading them is fine).
|
||||
|
||||
- **Operation lists in Slate are now immutable lists.** Previously they were native, mutable Javascript arrays. Now, to keep consistent with other immutable uses, they are immutable lists. This should not affect most users.
|
||||
* **Operation lists in Slate are now immutable lists.** Previously they were native, mutable Javascript arrays. Now, to keep consistent with other immutable uses, they are immutable lists. This should not affect most users.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Added a new `Operation` model.** This model is used to store operations for the history stack, and (de)serializes them in a consistent way for collaborative editing use cases.
|
||||
|
||||
* **Added a new `Operation` model.** This model is used to store operations for the history stack, and (de)serializes them in a consistent way for collaborative editing use cases.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.30.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
* **Remove all previously deprecated code paths.** This helps to reduce some of the complexity in Slate by not having to handle these code paths anymore. And it helps to reduce file size. When upgrading, it's _highly_ recommended that you upgrade to the previous version first and ensure there are no deprecation warnings being logged, then upgrade to this version.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.29.0` — October 27, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `set_state` operation has been renamed `set_value`**. This shouldn't affect almost anyone, but in the event that you were relying on the low-level operation types you'll need to update this.
|
||||
* **The `set_state` operation has been renamed `set_value`**. This shouldn't affect almost anyone, but in the event that you were relying on the low-level operation types you'll need to update this.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The "state" has been renamed to "value" everywhere.** All of the current references are maintained as deprecations, so you should be able to upgrade and see warnings logged instead of being greeted with a broken editor. This is to reduce the confusion between React's "state" and Slate's editor value, and in an effort to further mimic the native DOM APIs.
|
||||
* **The "state" has been renamed to "value" everywhere.** All of the current references are maintained as deprecations, so you should be able to upgrade and see warnings logged instead of being greeted with a broken editor. This is to reduce the confusion between React's "state" and Slate's editor value, and in an effort to further mimic the native DOM APIs.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Added the new `Value` model to replace `State`.** The new model is exactly the same, but with a new name. There is also a shimmed `State` model exported that warns when used, to ease migration.
|
||||
|
||||
* **Added the new `Value` model to replace `State`.** The new model is exactly the same, but with a new name. There is also a shimmed `State` model exported that warns when used, to ease migration.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.28.0` — October 25, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `Schema` objects in Slate have changed!** Previously, they used to be where you could define normalization rules, define rendering rules, and define decoration rules. This was overloaded, and made other improvements hard. Now, rendering and decorating is done via the newly added plugin functions (`renderNode`, `renderMark`, `decorateNode`). And validation is done either via the lower-level `validateNode` plugin function, or via the new `schema` objects.
|
||||
* **The `Schema` objects in Slate have changed!** Previously, they used to be where you could define normalization rules, define rendering rules, and define decoration rules. This was overloaded, and made other improvements hard. Now, rendering and decorating is done via the newly added plugin functions (`renderNode`, `renderMark`, `decorateNode`). And validation is done either via the lower-level `validateNode` plugin function, or via the new `schema` objects.
|
||||
|
||||
- **The `normalize*` change methods no longer take a `schema` argument.** Previously you had to maintain a reference to your schema, and pass it into the normalize methods when you called them. Since `State` objects now have an embedded `state.schema` property, this is no longer needed.
|
||||
* **The `normalize*` change methods no longer take a `schema` argument.** Previously you had to maintain a reference to your schema, and pass it into the normalize methods when you called them. Since `State` objects now have an embedded `state.schema` property, this is no longer needed.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **`State` objects now have an embedded `state.schema` property.** This new schema property is used to automatically normalize the state as it changes, according to the editor's current schema. This makes normalization much easier.
|
||||
|
||||
* **`State` objects now have an embedded `state.schema` property.** This new schema property is used to automatically normalize the state as it changes, according to the editor's current schema. This makes normalization much easier.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.27.0` — October 14, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `Range` model is now called `Leaf`.** This is to disambiguate with the concept of "ranges" that is used throughout the codebase to be synonymous to selections. For example in methods like `getBlocksAtRange(selection)`.
|
||||
* **The `Range` model is now called `Leaf`.** This is to disambiguate with the concept of "ranges" that is used throughout the codebase to be synonymous to selections. For example in methods like `getBlocksAtRange(selection)`.
|
||||
|
||||
- **The `text.ranges` property in the JSON representation is now `text.leaves`.** When passing in JSON with `text.ranges` you'll now receive a deprecation warning in the console in development.
|
||||
* **The `text.ranges` property in the JSON representation is now `text.leaves`.** When passing in JSON with `text.ranges` you'll now receive a deprecation warning in the console in development.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `Selection` model is now called `Range`.** This is to make it more clear what a "selection" really is, to make many of the other methods that act on "ranges" make sense, and to more closely parallel the native DOM API for selections and ranges. A mock `Selection` object is still exported with deprecated `static` methods, to make the transition to the new API easier.
|
||||
|
||||
- **The `Text.getRanges()` method is now `Text.getLeaves()`.** It will still work, and it will return a list of leaves, but you will see a deprecation warning in the console in development.
|
||||
* **The `Selection` model is now called `Range`.** This is to make it more clear what a "selection" really is, to make many of the other methods that act on "ranges" make sense, and to more closely parallel the native DOM API for selections and ranges. A mock `Selection` object is still exported with deprecated `static` methods, to make the transition to the new API easier.
|
||||
|
||||
* **The `Text.getRanges()` method is now `Text.getLeaves()`.** It will still work, and it will return a list of leaves, but you will see a deprecation warning in the console in development.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.26.0` — October 13, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `decorate` function of schema rules has changed.** Previously, in `decorate` you would receive a text node and the matched node, and you'd need to manually add any marks you wanted to the text node's characters. Now, "decorations" have changed to just be `Selection` objects with marks in the `selection.marks` property. Instead of applying the marks yourself, you simply return selection ranges with the marks to be applied, and Slate will apply them internally. This makes it possible to write much more complex decoration behaviors. Check out the revamped [`code-highlighting`](https://github.com/ianstormtaylor/slate/blob/master/examples/code-highlighting/index.js) example and the new [`search-highlighting`](https://github.com/ianstormtaylor/slate/blob/master/examples/search-highlighting/index.js) example to see this in action.
|
||||
* **The `decorate` function of schema rules has changed.** Previously, in `decorate` you would receive a text node and the matched node, and you'd need to manually add any marks you wanted to the text node's characters. Now, "decorations" have changed to just be `Selection` objects with marks in the `selection.marks` property. Instead of applying the marks yourself, you simply return selection ranges with the marks to be applied, and Slate will apply them internally. This makes it possible to write much more complex decoration behaviors. Check out the revamped [`code-highlighting`](https://github.com/ianstormtaylor/slate/blob/master/examples/code-highlighting/index.js) example and the new [`search-highlighting`](https://github.com/ianstormtaylor/slate/blob/master/examples/search-highlighting/index.js) example to see this in action.
|
||||
|
||||
- **The `set_data` operation type has been replaced by `set_state`.** With the new `state.decorations` property, it doesn't make sense to have a new operation type for every property of `State` objects. Instead, the new `set_state` operation more closely mimics the existing `set_mark` and `set_node` operations.
|
||||
* **The `set_data` operation type has been replaced by `set_state`.** With the new `state.decorations` property, it doesn't make sense to have a new operation type for every property of `State` objects. Instead, the new `set_state` operation more closely mimics the existing `set_mark` and `set_node` operations.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `setData` change method has been replaced by `setState`.** Previously you would call `change.setData(data)`. But as new `State` properties are introduced it doesn't make sense to need to add new change methods each time. Instead, the new `change.setState(properties)` more closesely mimics the existing `setMarkByKey` and `setNodeByKey`. To achieve the old behavior, you can do `change.setState({ data })`.
|
||||
* **The `setData` change method has been replaced by `setState`.** Previously you would call `change.setData(data)`. But as new `State` properties are introduced it doesn't make sense to need to add new change methods each time. Instead, the new `change.setState(properties)` more closesely mimics the existing `setMarkByKey` and `setNodeByKey`. To achieve the old behavior, you can do `change.setState({ data })`.
|
||||
|
||||
- **The `preserveStateData` option of `state.toJSON` has changed.** The same behavior is now called `preserveData` instead. This makes it consistent with all of the existing options, and the new `preserveDecorations` option as well.
|
||||
* **The `preserveStateData` option of `state.toJSON` has changed.** The same behavior is now called `preserveData` instead. This makes it consistent with all of the existing options, and the new `preserveDecorations` option as well.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **You can now set decorations based on external information.** Previously, the "decoration" logic in Slate was always based off of the text of a node, and would only re-render when that text changed. Now, there is a new `state.decorations` property that you can set via `change.setState({ decorations })`. You can use this to add presentation-only marks to arbitrary ranges of text in the document. Check out the new [`search-highlighting`](https://github.com/ianstormtaylor/slate/blob/master/examples/search-highlighting/index.js) example to see this in action.
|
||||
|
||||
* **You can now set decorations based on external information.** Previously, the "decoration" logic in Slate was always based off of the text of a node, and would only re-render when that text changed. Now, there is a new `state.decorations` property that you can set via `change.setState({ decorations })`. You can use this to add presentation-only marks to arbitrary ranges of text in the document. Check out the new [`search-highlighting`](https://github.com/ianstormtaylor/slate/blob/master/examples/search-highlighting/index.js) example to see this in action.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.25.0` — September 21, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `insertBlock` change method no longer replaces empty blocks.** Previously if you used `insertBlock` and the selection was in an empty block, it would replace it. Now you'll need to perform that check yourself and use the new `replaceNodeByKey` method instead.
|
||||
|
||||
- **The `Block.create` and `Inline.create` methods no longer normalize.** Previously if you used one of them to create a block or inline with zero nodes in it, they would automatically add a single empty text node as the only child. This was unexpected in certain situations, and if you were relying on this you'll need to handle it manually instead now.
|
||||
* **The `insertBlock` change method no longer replaces empty blocks.** Previously if you used `insertBlock` and the selection was in an empty block, it would replace it. Now you'll need to perform that check yourself and use the new `replaceNodeByKey` method instead.
|
||||
|
||||
* **The `Block.create` and `Inline.create` methods no longer normalize.** Previously if you used one of them to create a block or inline with zero nodes in it, they would automatically add a single empty text node as the only child. This was unexpected in certain situations, and if you were relying on this you'll need to handle it manually instead now.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.24.0` — September 11, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **`immutable` is now a _peer_ dependency of Slate.** Previously it was a regular dependency, but this prevented you from bringing your own version, or you'd have duplication. You'll need to ensure you install it!
|
||||
* **`immutable` is now a _peer_ dependency of Slate.** Previously it was a regular dependency, but this prevented you from bringing your own version, or you'd have duplication. You'll need to ensure you install it!
|
||||
|
||||
- **The `Html`, `Plain` and `Raw` serializers are broken into new packages.** Previously you'd import them from `slate`. But now you'll import them from `slate-html-serializer` and `slate-plain-serializer`. And the `Raw` serializer that was deprecated is now removed.
|
||||
* **The `Html`, `Plain` and `Raw` serializers are broken into new packages.** Previously you'd import them from `slate`. But now you'll import them from `slate-html-serializer` and `slate-plain-serializer`. And the `Raw` serializer that was deprecated is now removed.
|
||||
|
||||
- **The `Editor` and `Placeholder` components are broken into a new React-specific package.** Previously you'd import them from `slate`. But now you `import { Editor } from 'slate-react'` instead.
|
||||
* **The `Editor` and `Placeholder` components are broken into a new React-specific package.** Previously you'd import them from `slate`. But now you `import { Editor } from 'slate-react'` instead.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Slate is now a "monorepo".** Instead of a single package, Slate has been divided up into individual packages so that you can only require what you need, cutting down on file size. In the process, some helpful modules that used to be internal-only are now exposed.
|
||||
* **Slate is now a "monorepo".** Instead of a single package, Slate has been divided up into individual packages so that you can only require what you need, cutting down on file size. In the process, some helpful modules that used to be internal-only are now exposed.
|
||||
|
||||
- **There's a new `slate-hyperscript` helper.** This was possible thanks to the work on [`slate-sugar`](https://github.com/GitbookIO/slate-sugar), which paved the way.
|
||||
* **There's a new `slate-hyperscript` helper.** This was possible thanks to the work on [`slate-sugar`](https://github.com/GitbookIO/slate-sugar), which paved the way.
|
||||
|
||||
- **The `slate-prop-types` package is now exposed.** Previously this was an internal module, but now you can use it for adding prop types to any components or plugins you create.
|
||||
|
||||
- **The `slate-simulator` package is now exposed.** Previously this was an internal testing utility, but now you can use it in your own tests as well. It's currently pretty bare bones, but we can add to it over time.
|
||||
* **The `slate-prop-types` package is now exposed.** Previously this was an internal module, but now you can use it for adding prop types to any components or plugins you create.
|
||||
|
||||
* **The `slate-simulator` package is now exposed.** Previously this was an internal testing utility, but now you can use it in your own tests as well. It's currently pretty bare bones, but we can add to it over time.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.23.0` — September 10, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `isNative` property of `State` has been removed.** Previously this was used for performance reasons to avoid re-rendering, but it is no longer needed. This shouldn't really affect most people because it's rare that you'd be relying on this property to exist.
|
||||
* **The `isNative` property of `State` has been removed.** Previously this was used for performance reasons to avoid re-rendering, but it is no longer needed. This shouldn't really affect most people because it's rare that you'd be relying on this property to exist.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `Raw` serializer is now deprecated.** The entire "raw" concept is being removed, in favor of allowing all models to be able to serialize and deserialize to JSON themselves. Instead of using the `Raw` serializer, you can now use the `fromJSON` and `toJSON` on the models directly.
|
||||
* **The `Raw` serializer is now deprecated.** The entire "raw" concept is being removed, in favor of allowing all models to be able to serialize and deserialize to JSON themselves. Instead of using the `Raw` serializer, you can now use the `fromJSON` and `toJSON` on the models directly.
|
||||
|
||||
- **The `toRaw` options for the `Plain` and `Html` serializers are now called `toJSON`.** This is to stay symmetrical with the removal of the "raw" concept everywhere.
|
||||
* **The `toRaw` options for the `Plain` and `Html` serializers are now called `toJSON`.** This is to stay symmetrical with the removal of the "raw" concept everywhere.
|
||||
|
||||
- **The `terse` option for JSON serialization has been deprecated!** This option causes lots of abstraction leakiness because it means there is no one canonical JSON representation of objects. You had to work with either terse or not terse data.
|
||||
* **The `terse` option for JSON serialization has been deprecated!** This option causes lots of abstraction leakiness because it means there is no one canonical JSON representation of objects. You had to work with either terse or not terse data.
|
||||
|
||||
- **The `Html` serializer no longer uses the `terse` representation.** This shouldn't actually be an issue for anyone because the main manifestation of this has a deprecation notice with a patch in place for now.
|
||||
* **The `Html` serializer no longer uses the `terse` representation.** This shouldn't actually be an issue for anyone because the main manifestation of this has a deprecation notice with a patch in place for now.
|
||||
|
||||
- **The `defaultBlockType` of the `Html` serializer is now called `defaultBlock`.** This is just to make it more clear that it supports not only setting the default `type` but also `data` and `isVoid`.
|
||||
* **The `defaultBlockType` of the `Html` serializer is now called `defaultBlock`.** This is just to make it more clear that it supports not only setting the default `type` but also `data` and `isVoid`.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **Slate models now have `Model.fromJSON(object)` and `model.toJSON()` methods.** These methods operate with the canonical JSON form (which used to be called "raw"). This way you don't need to `import` a serializer to retrieve JSON, if you have the model you can serialize/deserialize.
|
||||
|
||||
- **Models also have `toJS` and `fromJS` aliases.** This is just to match Immutable.js objects, which have both methods. For Slate though, the methods are equivalent.
|
||||
* **Slate models now have `Model.fromJSON(object)` and `model.toJSON()` methods.** These methods operate with the canonical JSON form (which used to be called "raw"). This way you don't need to `import` a serializer to retrieve JSON, if you have the model you can serialize/deserialize.
|
||||
|
||||
* **Models also have `toJS` and `fromJS` aliases.** This is just to match Immutable.js objects, which have both methods. For Slate though, the methods are equivalent.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.22.0` — September 5, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `Plain` serializer now adds line breaks between blocks.** Previously between blocks the text would be joined without any space whatsoever, but this wasn't really that useful or what you'd expect.
|
||||
* **The `Plain` serializer now adds line breaks between blocks.** Previously between blocks the text would be joined without any space whatsoever, but this wasn't really that useful or what you'd expect.
|
||||
|
||||
- **The `toggleMark` transform now checks the intersection of marks.** Previously, toggling would remove the mark from the range if any of the characters in a range didn't have it. However, this wasn't what all other rich-text editors did, so the behavior has changed to mimic the standard behavior. Now, if any characters in the selection have the mark applied, it will first be added when toggling.
|
||||
* **The `toggleMark` transform now checks the intersection of marks.** Previously, toggling would remove the mark from the range if any of the characters in a range didn't have it. However, this wasn't what all other rich-text editors did, so the behavior has changed to mimic the standard behavior. Now, if any characters in the selection have the mark applied, it will first be added when toggling.
|
||||
|
||||
- **The `.length` property of nodes has been removed.** This property caused issues with code like in Lodash that checked for "array-likeness" by simply looking for a `.length` property that was a number.
|
||||
* **The `.length` property of nodes has been removed.** This property caused issues with code like in Lodash that checked for "array-likeness" by simply looking for a `.length` property that was a number.
|
||||
|
||||
- **`onChange` now receives a `Change` object (previously named `Transform`) instead of a `State`.** This is needed because it enforces that all changes are represented by a single set of operations. Otherwise right now it's possible to do things like `state.transform()....apply({ save: false }).transform()....apply()` and result in losing the operation information in the history. With OT, we need all transforms that may happen to be exposed and emitted by the editor. The new syntax looks like:
|
||||
* **`onChange` now receives a `Change` object (previously named `Transform`) instead of a `State`.** This is needed because it enforces that all changes are represented by a single set of operations. Otherwise right now it's possible to do things like `state.transform()....apply({ save: false }).transform()....apply()` and result in losing the operation information in the history. With OT, we need all transforms that may happen to be exposed and emitted by the editor. The new syntax looks like:
|
||||
|
||||
```js
|
||||
onChange(change) {
|
||||
@ -205,7 +182,7 @@ onChange({ state }) {
|
||||
}
|
||||
```
|
||||
|
||||
- **Similarly, handlers now receive `e, data, change` instead of `e, data, state`.** Instead of doing `return state.transform()....apply()` the plugins can now act on the change object directly. Plugins can still `return change...` if they want to break the stack from continuing on to other plugins. (Any `!= null` value will break out.) But they can also now not return anything, and the stack will apply their changes and continue onwards. This was previously impossible. The new syntax looks like:
|
||||
* **Similarly, handlers now receive `e, data, change` instead of `e, data, state`.** Instead of doing `return state.transform()....apply()` the plugins can now act on the change object directly. Plugins can still `return change...` if they want to break the stack from continuing on to other plugins. (Any `!= null` value will break out.) But they can also now not return anything, and the stack will apply their changes and continue onwards. This was previously impossible. The new syntax looks like:
|
||||
|
||||
```js
|
||||
function onKeyDown(e, data, change) {
|
||||
@ -215,298 +192,256 @@ function onKeyDown(e, data, change) {
|
||||
}
|
||||
```
|
||||
|
||||
- **The `onChange` and `on[Before]Change` handlers now receive `Change` objects.** Previously they would also receive a `state` object, but now they receive `change` objects like the rest of the plugin API.
|
||||
* **The `onChange` and `on[Before]Change` handlers now receive `Change` objects.** Previously they would also receive a `state` object, but now they receive `change` objects like the rest of the plugin API.
|
||||
|
||||
- **The `.apply({ save })` option is now `state.change({ save })` instead.** This is the easiest way to use it, but requires that you know whether to save or not up front. If you want to use it inline after already saving some changes, you can use the `change.setOperationFlag('save', true)` flag instead. This shouldn't be necessary for 99% of use cases though.
|
||||
* **The `.apply({ save })` option is now `state.change({ save })` instead.** This is the easiest way to use it, but requires that you know whether to save or not up front. If you want to use it inline after already saving some changes, you can use the `change.setOperationFlag('save', true)` flag instead. This shouldn't be necessary for 99% of use cases though.
|
||||
|
||||
- **The `.undo()` and `.redo()` transforms don't save by default.** Previously you had to specifically tell these transforms not to save into the history, which was awkward. Now they won't save the operations they're undoing/redoing by default.
|
||||
* **The `.undo()` and `.redo()` transforms don't save by default.** Previously you had to specifically tell these transforms not to save into the history, which was awkward. Now they won't save the operations they're undoing/redoing by default.
|
||||
|
||||
- **`onBeforeChange` is no longer called from `componentWillReceiveProps`,** when a new `state` is passed in as props to the `<Editor>` component. This caused lots of state-management issues and was weird in the first place because passing in props would result in changes firing. **It is now the parent component's responsibility to not pass in improperly formatted `State` objects**.
|
||||
* **`onBeforeChange` is no longer called from `componentWillReceiveProps`,** when a new `state` is passed in as props to the `<Editor>` component. This caused lots of state-management issues and was weird in the first place because passing in props would result in changes firing. **It is now the parent component's responsibility to not pass in improperly formatted `State` objects**.
|
||||
|
||||
- **The `splitNodeByKey` change method has changed to be shallow.** Previously, it would deeply split to an offset. But now it is shallow and another `splitDescendantsByKey` change method has been added (with a different signature) for the deep splitting behavior. This is needed because splitting and joining operations have been changed to all be shallow, which is required so that operational transforms can be written against them.
|
||||
* **The `splitNodeByKey` change method has changed to be shallow.** Previously, it would deeply split to an offset. But now it is shallow and another `splitDescendantsByKey` change method has been added (with a different signature) for the deep splitting behavior. This is needed because splitting and joining operations have been changed to all be shallow, which is required so that operational transforms can be written against them.
|
||||
|
||||
- **Blocks cannot have mixed "inline" and "block" children anymore.** Blocks were implicitly expected to either contain "text" and "inline" nodes only, or to contain "block" nodes only. Invalid case are now normalized by the core schema.
|
||||
* **Blocks cannot have mixed "inline" and "block" children anymore.** Blocks were implicitly expected to either contain "text" and "inline" nodes only, or to contain "block" nodes only. Invalid case are now normalized by the core schema.
|
||||
|
||||
- **The shape of many operations has changed.** This was needed to make operations completely invertible without any extra context. The operations were never really exposed in a consumable way, so I won't detail all of the changes here, but feel free to look at the source to see the details.
|
||||
* **The shape of many operations has changed.** This was needed to make operations completely invertible without any extra context. The operations were never really exposed in a consumable way, so I won't detail all of the changes here, but feel free to look at the source to see the details.
|
||||
|
||||
- **All references to "joining" nodes is now called "merging".** This is to be slightly clearer, since merging can only happen with adjacent nodes already, and to have a nicer parallel with "splitting", as in cells. The operation is now called `merge_node`, and the transforms are now `merge*`.
|
||||
* **All references to "joining" nodes is now called "merging".** This is to be slightly clearer, since merging can only happen with adjacent nodes already, and to have a nicer parallel with "splitting", as in cells. The operation is now called `merge_node`, and the transforms are now `merge*`.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **The `transform.apply()` method is deprecated.** Previously this is where the saving into the history would happen, but it created an awkward convention that wasn't necessary. Now operations are saved into the history as they are created with change methods, instead of waiting until the end. You can access the new `State` of a change at any time via `change.state`.
|
||||
* **The `transform.apply()` method is deprecated.** Previously this is where the saving into the history would happen, but it created an awkward convention that wasn't necessary. Now operations are saved into the history as they are created with change methods, instead of waiting until the end. You can access the new `State` of a change at any time via `change.state`.
|
||||
|
||||
###### NEW
|
||||
|
||||
- **The `state.activeMarks` returns the intersection of marks in the selection.** Previously there was only `state.marks` which returns marks that appeared on _any_ character in the selection. But `state.activeMarks` returns marks that appear on _every_ character in the selection, which is often more useful for implementing standard rich-text editor behaviors.
|
||||
|
||||
* **The `state.activeMarks` returns the intersection of marks in the selection.** Previously there was only `state.marks` which returns marks that appeared on _any_ character in the selection. But `state.activeMarks` returns marks that appear on _every_ character in the selection, which is often more useful for implementing standard rich-text editor behaviors.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.21.0` — July 20, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `Html` serializer now uses `DOMParser` instead of `cheerio`.** Previously, the `Html` serializer used the `cheerio` library for representing elements in the serialization rule logic, but cheerio was a very large dependency. It has been removed, and the native browser `DOMParser` is now used instead. All HTML serialization rules will need to be updated. If you are working with Slate on the server, you can now pass in a custom serializer to the `Html` constructor, using the `parse5` library.
|
||||
|
||||
* **The `Html` serializer now uses `DOMParser` instead of `cheerio`.** Previously, the `Html` serializer used the `cheerio` library for representing elements in the serialization rule logic, but cheerio was a very large dependency. It has been removed, and the native browser `DOMParser` is now used instead. All HTML serialization rules will need to be updated. If you are working with Slate on the server, you can now pass in a custom serializer to the `Html` constructor, using the `parse5` library.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.20.0` — May 17, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Returning `null` from the `Html` serializer skips the element.** Previously, `null` and `undefined` had the same behavior of skipping the rule and trying the rest of the rules. Now if you explicitly return `null` it will skip the element itself.
|
||||
|
||||
* **Returning `null` from the `Html` serializer skips the element.** Previously, `null` and `undefined` had the same behavior of skipping the rule and trying the rest of the rules. Now if you explicitly return `null` it will skip the element itself.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.19.0` — March 3, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `filterDescendants` and `findDescendants` methods are now depth-first.** This shouldn't affect almost anyone, since they are usually not the best things to be using for performance reasons. If you happen to have a very specific use case that needs breadth-first, (or even likely something better), you'll need to implement it yourself.
|
||||
* **The `filterDescendants` and `findDescendants` methods are now depth-first.** This shouldn't affect almost anyone, since they are usually not the best things to be using for performance reasons. If you happen to have a very specific use case that needs breadth-first, (or even likely something better), you'll need to implement it yourself.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **Some `Node` methods have been deprecated!** There were a few methods that had been added over time that were either poorly named that have been deprecated and renamed, and a handful of methods that are no longer useful for the core library that have been deprecated. Here's a full list:
|
||||
- `areDescendantSorted` -> `areDescendantsSorted`
|
||||
- `getHighestChild` -> `getFurthestAncestor`
|
||||
- `getHighestOnlyChildParent` -> `getFurthestOnlyChildAncestor`
|
||||
- `concatChildren`
|
||||
- `decorateTexts`
|
||||
- `filterDescendantsDeep`
|
||||
- `findDescendantDeep`
|
||||
- `getChildrenBetween`
|
||||
- `getChildrenBetweenIncluding`
|
||||
- `isInlineSplitAtRange`
|
||||
|
||||
* **Some `Node` methods have been deprecated!** There were a few methods that had been added over time that were either poorly named that have been deprecated and renamed, and a handful of methods that are no longer useful for the core library that have been deprecated. Here's a full list:
|
||||
* `areDescendantSorted` -> `areDescendantsSorted`
|
||||
* `getHighestChild` -> `getFurthestAncestor`
|
||||
* `getHighestOnlyChildParent` -> `getFurthestOnlyChildAncestor`
|
||||
* `concatChildren`
|
||||
* `decorateTexts`
|
||||
* `filterDescendantsDeep`
|
||||
* `findDescendantDeep`
|
||||
* `getChildrenBetween`
|
||||
* `getChildrenBetweenIncluding`
|
||||
* `isInlineSplitAtRange`
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.18.0` — March 2, 2017
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `plugin.render` property is now called `plugin.renderPortal`.** This is to make way for the new `plugin.render` property that offers HOC-like behavior, so that plugins can augment the editor however they choose.
|
||||
|
||||
* **The `plugin.render` property is now called `plugin.renderPortal`.** This is to make way for the new `plugin.render` property that offers HOC-like behavior, so that plugins can augment the editor however they choose.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.17.0` — February 27, 2017
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **Some `Selection` methods have been deprecated!** Previously there were many inconsistencies in the naming and handling of selection changes. This has all been cleaned up, but in the process some methods have been deprecated. Here is a full list of the deprecated methods and their new alternatives:
|
||||
- `moveToOffsets` -> `moveOffsetsTo`
|
||||
- `moveForward` -> `move`
|
||||
- `moveBackward` -> `move`
|
||||
- `moveAnchorOffset` -> `moveAnchor`
|
||||
- `moveFocusOffset` -> `moveFocus`
|
||||
- `moveStartOffset` -> `moveStart`
|
||||
- `moveEndOffset` -> `moveEnd`
|
||||
- `extendForward` -> `extend`
|
||||
- `extendBackward` -> `extend`
|
||||
- `unset` -> `deselect`
|
||||
* **Some `Selection` methods have been deprecated!** Previously there were many inconsistencies in the naming and handling of selection changes. This has all been cleaned up, but in the process some methods have been deprecated. Here is a full list of the deprecated methods and their new alternatives:
|
||||
|
||||
- **Some selection transforms have been deprecated!** Along with the methods, the selection-based transforms have also been refactored, resulting in deprecations. Here is a full list of the deprecated transforms and their new alternatives:
|
||||
- `moveTo` -> `select`
|
||||
- `moveToOffsets` -> `moveOffsetsTo`
|
||||
- `moveForward` -> `move`
|
||||
- `moveBackward` -> `move`
|
||||
- `moveStartOffset` -> `moveStart`
|
||||
- `moveEndOffset` -> `moveEnd`
|
||||
- `extendForward` -> `extend`
|
||||
- `extendBackward` -> `extend`
|
||||
- `flipSelection` -> `flip`
|
||||
- `unsetSelection` -> `deselect`
|
||||
- `unsetMarks`
|
||||
* `moveToOffsets` -> `moveOffsetsTo`
|
||||
* `moveForward` -> `move`
|
||||
* `moveBackward` -> `move`
|
||||
* `moveAnchorOffset` -> `moveAnchor`
|
||||
* `moveFocusOffset` -> `moveFocus`
|
||||
* `moveStartOffset` -> `moveStart`
|
||||
* `moveEndOffset` -> `moveEnd`
|
||||
* `extendForward` -> `extend`
|
||||
* `extendBackward` -> `extend`
|
||||
* `unset` -> `deselect`
|
||||
|
||||
* **Some selection transforms have been deprecated!** Along with the methods, the selection-based transforms have also been refactored, resulting in deprecations. Here is a full list of the deprecated transforms and their new alternatives:
|
||||
* `moveTo` -> `select`
|
||||
* `moveToOffsets` -> `moveOffsetsTo`
|
||||
* `moveForward` -> `move`
|
||||
* `moveBackward` -> `move`
|
||||
* `moveStartOffset` -> `moveStart`
|
||||
* `moveEndOffset` -> `moveEnd`
|
||||
* `extendForward` -> `extend`
|
||||
* `extendBackward` -> `extend`
|
||||
* `flipSelection` -> `flip`
|
||||
* `unsetSelection` -> `deselect`
|
||||
* `unsetMarks`
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.16.0` — December 2, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Inline nodes are now always surrounded by text nodes.** Previously this behavior only occured for inline nodes with `isVoid: true`. Now, all inline nodes will always be surrounded by text nodes. If text nodes don't exist, empty ones will be created. This allows for more consistent behavior across Slate, and parity with other editing experiences.
|
||||
|
||||
* **Inline nodes are now always surrounded by text nodes.** Previously this behavior only occured for inline nodes with `isVoid: true`. Now, all inline nodes will always be surrounded by text nodes. If text nodes don't exist, empty ones will be created. This allows for more consistent behavior across Slate, and parity with other editing experiences.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.15.0` - November 17, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The unique `key` generated values have changed.** Previously, Slate generated unique keys that looked like `'9dk3'`. But they were not very conflict-resistant. Now the keys are simple string of auto-incrementing numbers, like `'0'`, `'1'`, `'2'`. This makes more clear that keys are simply a convenient way to uniquely reference nodes in the **short-term** lifespan of a single in-memory instance of Slate. They are not designed to be used for long-term uniqueness. A new `setKeyGenerator` function has been exported that allows you to pass in your own key generating mechanism if you want to ensure uniqueness.
|
||||
* **The unique `key` generated values have changed.** Previously, Slate generated unique keys that looked like `'9dk3'`. But they were not very conflict-resistant. Now the keys are simple string of auto-incrementing numbers, like `'0'`, `'1'`, `'2'`. This makes more clear that keys are simply a convenient way to uniquely reference nodes in the **short-term** lifespan of a single in-memory instance of Slate. They are not designed to be used for long-term uniqueness. A new `setKeyGenerator` function has been exported that allows you to pass in your own key generating mechanism if you want to ensure uniqueness.
|
||||
|
||||
- **The `Raw` serializer doesn't preserve keys by default.** Previously, the `Raw` serializer would omit keys when passed the `terse: true` option, but preserve them without it. Now it will always omit keys, unless you pass the new `preserveKeys: true` option. This better reflects that keys are temporary, in-memory IDs.
|
||||
* **The `Raw` serializer doesn't preserve keys by default.** Previously, the `Raw` serializer would omit keys when passed the `terse: true` option, but preserve them without it. Now it will always omit keys, unless you pass the new `preserveKeys: true` option. This better reflects that keys are temporary, in-memory IDs.
|
||||
|
||||
- **Operations on the document now update the selection when needed.** This won't affect you unless you were doing some very specific things with transforms and updating selections. Overall, this makes it much easier to write transforms, since in most cases, the underlying operations will update the selection as you would expect without you doing anything.
|
||||
* **Operations on the document now update the selection when needed.** This won't affect you unless you were doing some very specific things with transforms and updating selections. Overall, this makes it much easier to write transforms, since in most cases, the underlying operations will update the selection as you would expect without you doing anything.
|
||||
|
||||
###### DEPRECATED
|
||||
|
||||
- **Node accessor methods no longer accept being passed another node!** Previously, node accessor methods like `node.getParent` could be passed either a `key` string or a `node` object. For performance reasons, passing in a `node` object is being deprecated. So if you have any calls that look like: `node.getParent(descendant)`, they will now need to be written as `node.getParent(descendant.key)`. They will throw a warning for now, and will throw an error in a later version of Slate.
|
||||
|
||||
* **Node accessor methods no longer accept being passed another node!** Previously, node accessor methods like `node.getParent` could be passed either a `key` string or a `node` object. For performance reasons, passing in a `node` object is being deprecated. So if you have any calls that look like: `node.getParent(descendant)`, they will now need to be written as `node.getParent(descendant.key)`. They will throw a warning for now, and will throw an error in a later version of Slate.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.14.0` — September 10, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `undo` and `redo` transforms need to be applied!** Previously, `undo` and `redo` were special cased such that they did not require an `.apply()` call, and instead would return a new `State` directly. Now this is no longer the case, and they are just like every other transform.
|
||||
* **The `undo` and `redo` transforms need to be applied!** Previously, `undo` and `redo` were special cased such that they did not require an `.apply()` call, and instead would return a new `State` directly. Now this is no longer the case, and they are just like every other transform.
|
||||
|
||||
- **Transforms are no longer exposed on `State` or `Node`.** The transforms API has been completely refactored to be built up of "operations" for collaborative editing support. As part of this refactor, the transforms are now only available via the `state.transform()` API, and aren't exposed on the `State` or `Node` objects as they were before.
|
||||
* **Transforms are no longer exposed on `State` or `Node`.** The transforms API has been completely refactored to be built up of "operations" for collaborative editing support. As part of this refactor, the transforms are now only available via the `state.transform()` API, and aren't exposed on the `State` or `Node` objects as they were before.
|
||||
|
||||
- **`Transform` objects are now mutable.** Previously `Transform` was an Immutable.js `Record`, but now it is a simple constructor. This is because transforms are inherently mutating their representation of a state, but this decision is [up for discussion](https://github.com/ianstormtaylor/slate/issues/328).
|
||||
|
||||
- **The selection can now be "unset".** Previously, a selection could never be in an "unset" state where the `anchorKey` or `focusKey` was null. This is no longer technically true, although this shouldn't really affect anyone in practice.
|
||||
* **`Transform` objects are now mutable.** Previously `Transform` was an Immutable.js `Record`, but now it is a simple constructor. This is because transforms are inherently mutating their representation of a state, but this decision is [up for discussion](https://github.com/ianstormtaylor/slate/issues/328).
|
||||
|
||||
* **The selection can now be "unset".** Previously, a selection could never be in an "unset" state where the `anchorKey` or `focusKey` was null. This is no longer technically true, although this shouldn't really affect anyone in practice.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.13.0` — August 15, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `renderNode` and `renderMark` properties are gone!** Previously, rendering nodes and marks happened via these two properties of the `<Editor>`, but this has been replaced by the new `schema` property. Check out the updated examples to see how to define a schema! There's a good chance this eliminates extra code for most use cases! :smile:
|
||||
|
||||
- **The `renderDecorations` property is gone!** Decoration rendering has also been replaced by the new `schema` property of the `<Editor>`.
|
||||
* **The `renderNode` and `renderMark` properties are gone!** Previously, rendering nodes and marks happened via these two properties of the `<Editor>`, but this has been replaced by the new `schema` property. Check out the updated examples to see how to define a schema! There's a good chance this eliminates extra code for most use cases! :smile:
|
||||
|
||||
* **The `renderDecorations` property is gone!** Decoration rendering has also been replaced by the new `schema` property of the `<Editor>`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.12.0` — August 9, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `data.files` property is now an `Array`.** Previously it was a native `FileList` object, but needed to be changed to add full support for pasting an dropping files in all browsers. This shouldn't affect you unless you were specifically depending on it being array-like instead of a true `Array`.
|
||||
|
||||
* **The `data.files` property is now an `Array`.** Previously it was a native `FileList` object, but needed to be changed to add full support for pasting an dropping files in all browsers. This shouldn't affect you unless you were specifically depending on it being array-like instead of a true `Array`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.11.0` — August 4, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Void nodes are renderered implicitly again!** Previously Slate had required that you wrap void node renderers yourself with the exposed `<Void>` wrapping component. This was to allow for selection styling, but a change was made to make selection styling able to handled in Javascript. Now the `<Void>` wrapper will be implicitly rendered by Slate, so you do not need to worry about it, and "voidness" only needs to toggled in one place, the `isVoid: true` property of a node.
|
||||
|
||||
* **Void nodes are renderered implicitly again!** Previously Slate had required that you wrap void node renderers yourself with the exposed `<Void>` wrapping component. This was to allow for selection styling, but a change was made to make selection styling able to handled in Javascript. Now the `<Void>` wrapper will be implicitly rendered by Slate, so you do not need to worry about it, and "voidness" only needs to toggled in one place, the `isVoid: true` property of a node.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.10.0` — July 29, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Marks are now renderable as components.** Previously the only supported way to render marks was by returning a `style` object. Now you can return a style object, a class name string, or a full React component. Because of this, the DOM will be renderered slightly differently than before, resulting in an extra `<span>` when rendering non-component marks. This won't affect you unless you were depending on the DOM output by Slate for some reason.
|
||||
|
||||
* **Marks are now renderable as components.** Previously the only supported way to render marks was by returning a `style` object. Now you can return a style object, a class name string, or a full React component. Because of this, the DOM will be renderered slightly differently than before, resulting in an extra `<span>` when rendering non-component marks. This won't affect you unless you were depending on the DOM output by Slate for some reason.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.9.0` — July 28, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `wrap` and `unwrap` method signatures have changed!** Previously, you would pass `type` and `data` as separate parameters, for example: `wrapBlock('code', { src: true })`. This was inconsistent with other transforms, and has been updated such that a single argument of `properties` is passed instead. So that example could now be: `wrapBlock({ type: 'code', { data: { src: true }})`. You can still pass a `type` string as shorthand, which will be the most frequent use case, for example: `wrapBlock('code')`.
|
||||
|
||||
* **The `wrap` and `unwrap` method signatures have changed!** Previously, you would pass `type` and `data` as separate parameters, for example: `wrapBlock('code', { src: true })`. This was inconsistent with other transforms, and has been updated such that a single argument of `properties` is passed instead. So that example could now be: `wrapBlock({ type: 'code', { data: { src: true }})`. You can still pass a `type` string as shorthand, which will be the most frequent use case, for example: `wrapBlock('code')`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.8.0` — July 27, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `onKeyDown` and `onBeforeInput` handlers signatures have changed!** Previously, some Slate handlers had a signature of `(e, state, editor)` and others had a signature of `(e, data, state, editor)`. Now all handlers will be passed a `data` object—which contains Slate-specific data related to the event—even if it is empty. This is helpful for future compatibility where we might need to add data to a handler that previously didn't have any, and is nicer for consistency. The `onKeyDown` handler's new `data` object contains the `key` name, `code` and a series of `is*` properties to make working with hotkeys easier. The `onBeforeInput` handler's new `data` object is empty.
|
||||
* **The `onKeyDown` and `onBeforeInput` handlers signatures have changed!** Previously, some Slate handlers had a signature of `(e, state, editor)` and others had a signature of `(e, data, state, editor)`. Now all handlers will be passed a `data` object—which contains Slate-specific data related to the event—even if it is empty. This is helpful for future compatibility where we might need to add data to a handler that previously didn't have any, and is nicer for consistency. The `onKeyDown` handler's new `data` object contains the `key` name, `code` and a series of `is*` properties to make working with hotkeys easier. The `onBeforeInput` handler's new `data` object is empty.
|
||||
|
||||
- **The `Utils` export has been removed.** Previously, a `Key` utility and the `findDOMNode` utility were exposed under the `Utils` object. The `Key` has been removed in favor of the `data` object passed to `onKeyDown`. And then `findDOMNode` utility has been upgraded to a top-level named export, so you'll now need to access it via `import { findDOMNode } from 'slate'`.
|
||||
* **The `Utils` export has been removed.** Previously, a `Key` utility and the `findDOMNode` utility were exposed under the `Utils` object. The `Key` has been removed in favor of the `data` object passed to `onKeyDown`. And then `findDOMNode` utility has been upgraded to a top-level named export, so you'll now need to access it via `import { findDOMNode } from 'slate'`.
|
||||
|
||||
- **Void nodes now permanently have `" "` as content.** Previously, they contained an empty string, but this isn't technically correct, since they have content and shouldn't be considered "empty". Now they will have a single space of content. This shouldn't really affect anyone, unless you happened to be accessing that string for serialization.
|
||||
|
||||
- **Empty inline nodes are now impossible.** This is to stay consistent with native `contenteditable` behavior, where although technically the elements can exist, they have odd behavior and can never be selected.
|
||||
* **Void nodes now permanently have `" "` as content.** Previously, they contained an empty string, but this isn't technically correct, since they have content and shouldn't be considered "empty". Now they will have a single space of content. This shouldn't really affect anyone, unless you happened to be accessing that string for serialization.
|
||||
|
||||
* **Empty inline nodes are now impossible.** This is to stay consistent with native `contenteditable` behavior, where although technically the elements can exist, they have odd behavior and can never be selected.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.7.0` — July 24, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **The `Raw` serializer is no longer terse by default!** Previously, the `Raw` serializer would return a "terse" representation of the document, omitting information that wasn't _strictly_ necessary to deserialize later, like the `key` of nodes. By default this no longer happens. You have to opt-in to the behavior by passing `{ terse: true }` as the second `options` argument of the `deserialize` and `serialize` methods.
|
||||
|
||||
* **The `Raw` serializer is no longer terse by default!** Previously, the `Raw` serializer would return a "terse" representation of the document, omitting information that wasn't _strictly_ necessary to deserialize later, like the `key` of nodes. By default this no longer happens. You have to opt-in to the behavior by passing `{ terse: true }` as the second `options` argument of the `deserialize` and `serialize` methods.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.6.0` — July 22, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **Void components are no longer rendered implicity!** Previously, Slate would automatically wrap any node with `isVoid: true` in a `<Void>` component. But doing this prevented you from customizing the wrapper, like adding a `className` or `style` property. So you **must now render the wrapper yourself**, and it has been exported as `Slate.Void`. This, combined with a small change to the `<Void>` component's structure allows the "selected" state of void nodes to be rendered purely with CSS based on the `:focus` property of a `<Void>` element, which previously [had to be handled in Javascript](https://github.com/ianstormtaylor/slate/commit/31782cb11a272466b6b9f1e4d6cc0c698504d97f). This allows us to streamline selection-handling logic, improving performance and reducing complexity.
|
||||
|
||||
- **`data-offset-key` is now `<key>-<index>` instead of `<key>:<start>-<end>`.** This shouldn't actually affect anyone, unless you were specifically relying on that attribute in the DOM. This change greatly reduces the number of re-renders needed, since previously any additional characters would cause a cascading change in the `<start>` and `<end>` offsets of latter text ranges.
|
||||
* **Void components are no longer rendered implicity!** Previously, Slate would automatically wrap any node with `isVoid: true` in a `<Void>` component. But doing this prevented you from customizing the wrapper, like adding a `className` or `style` property. So you **must now render the wrapper yourself**, and it has been exported as `Slate.Void`. This, combined with a small change to the `<Void>` component's structure allows the "selected" state of void nodes to be rendered purely with CSS based on the `:focus` property of a `<Void>` element, which previously [had to be handled in Javascript](https://github.com/ianstormtaylor/slate/commit/31782cb11a272466b6b9f1e4d6cc0c698504d97f). This allows us to streamline selection-handling logic, improving performance and reducing complexity.
|
||||
|
||||
* **`data-offset-key` is now `<key>-<index>` instead of `<key>:<start>-<end>`.** This shouldn't actually affect anyone, unless you were specifically relying on that attribute in the DOM. This change greatly reduces the number of re-renders needed, since previously any additional characters would cause a cascading change in the `<start>` and `<end>` offsets of latter text ranges.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.5.0` — July 20, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **`node.getTextNodes()` is now `node.getTexts()`.** This is just for consistency with the other existing `Node` methods like `getBlocks()`, `getInlines()`, etc. And it's nicely shorter. :wink:
|
||||
|
||||
- **`Node` methods now `throw` earlier during unexpected states.** This shouldn't break anything for most folks, unless a strange edge-case was going undetected previously.
|
||||
* **`node.getTextNodes()` is now `node.getTexts()`.** This is just for consistency with the other existing `Node` methods like `getBlocks()`, `getInlines()`, etc. And it's nicely shorter. :wink:
|
||||
|
||||
* **`Node` methods now `throw` earlier during unexpected states.** This shouldn't break anything for most folks, unless a strange edge-case was going undetected previously.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.4.0` — July 20, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **`renderMark(mark, state, editor)` is now `renderMark(mark, marks, state, editor)`.** This change allows you to render marks based on multiple `marks` presence at once on a given range of text, for example using a custom `BoldItalic.otf` font when text has both `bold` and `italic` marks.
|
||||
|
||||
* **`renderMark(mark, state, editor)` is now `renderMark(mark, marks, state, editor)`.** This change allows you to render marks based on multiple `marks` presence at once on a given range of text, for example using a custom `BoldItalic.otf` font when text has both `bold` and `italic` marks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.3.0` — July 20, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **`transform.unwrapBlock()` now unwraps selectively.** Previously, calling `unwrapBlock` with a range representing a middle sibling would unwrap _all_ of the siblings, removing the wrapping block entirely. Now, calling it with those same arguments will only move the middle sibling up a layer in the hierarchy, preserving the nesting on any of its siblings. This changes makes it much simpler to implement functionality like unwrapping a single list item, which previously would unwrap the entire list.
|
||||
|
||||
* **`transform.unwrapBlock()` now unwraps selectively.** Previously, calling `unwrapBlock` with a range representing a middle sibling would unwrap _all_ of the siblings, removing the wrapping block entirely. Now, calling it with those same arguments will only move the middle sibling up a layer in the hierarchy, preserving the nesting on any of its siblings. This changes makes it much simpler to implement functionality like unwrapping a single list item, which previously would unwrap the entire list.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.2.0` — July 18, 2016
|
||||
|
||||
###### BREAKING
|
||||
|
||||
- **`transform.mark()` is now `transform.addMark()` and `transform.unmark()` is now `transform.removeMark()`.** The new names make it clearer that the transforms are actions being performed, and it paves the way for adding a `toggleMark` convenience as well.
|
||||
|
||||
* **`transform.mark()` is now `transform.addMark()` and `transform.unmark()` is now `transform.removeMark()`.** The new names make it clearer that the transforms are actions being performed, and it paves the way for adding a `toggleMark` convenience as well.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.1.0` — July 13, 2016
|
||||
|
||||
:tada:
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
|
||||
This package contains the core logic of Slate. It's separated further into a series of directories:
|
||||
|
||||
- [**Changes**](./src/changes) — containing the changes that are used to alter a Slate document.
|
||||
- [**Constants**](./src/constants) — containing constants that are used in Slate's codebase.
|
||||
- [**Models**](./src/models) — containing the models that define Slate's data structure.
|
||||
- [**Operations**](./src/operations) — containing the low-level operations that create Slate changes.
|
||||
- [**Schemas**](./src/schemas) - containing the core schema that ships with Slate by default.
|
||||
- [**Utils**](./src/utils) — containing a few private convenience modules.
|
||||
* [**Changes**](./src/changes) — containing the changes that are used to alter a Slate document.
|
||||
* [**Constants**](./src/constants) — containing constants that are used in Slate's codebase.
|
||||
* [**Models**](./src/models) — containing the models that define Slate's data structure.
|
||||
* [**Operations**](./src/operations) — containing the low-level operations that create Slate changes.
|
||||
* [**Schemas**](./src/schemas) - containing the core schema that ships with Slate by default.
|
||||
* [**Utils**](./src/utils) — containing a few private convenience modules.
|
||||
|
||||
Feel free to poke around in each of them to learn more!
|
||||
|
Loading…
x
Reference in New Issue
Block a user