1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-19 05:31:56 +02:00

Remove deprecations (#2113)

#### Is this adding or improving a _feature_ or fixing a _bug_?

Debt.

#### What's the new behavior?

This removes almost all existing deprecations from previous API changes, to save on filesize and reduce complexity in the codebase going forward.

It also changes from using the `slate-dev-logger` to using the Facebook-inspired `slate-dev-warning` which can be compiled out of production builds with [`babel-plugin-dev-expression`](https://github.com/4Catalyzer/babel-plugin-dev-expression) to save even further on file size.

The only deprecations it keeps are in the `fromJSON` methods for data model changes like `.kind` and `.leaves` which may still may not have been migrated in databases, since this is a bigger pain point.

#### Have you checked that...?

* [x] The new code matches the existing patterns and styles.
* [x] The tests pass with `yarn test`.
* [x] The linter passes with `yarn lint`. (Fix errors with `yarn prettier`.)
* [x] The relevant examples still work. (Run examples with `yarn watch`.)

#### Does this fix any issues or need any specific reviewers?

Fixes: #1922 
Fixes: #2105
Fixes: #646 
Fixes: #2109
Fixes: #2107 
Fixes: #2018
This commit is contained in:
Ian Storm Taylor
2018-08-22 18:22:40 -07:00
committed by GitHub
parent 3d48f7a3e0
commit 36ed4397d8
223 changed files with 2767 additions and 4575 deletions

View File

@@ -4,11 +4,10 @@ Since Slate is a monorepo with many packages that are versioned separately, we m
* [`slate`](./packages/slate/Changelog.md)
* [`slate-base64-serializer`](./packages/slate-base64-serializer/Changelog.md)
* [`slate-dev-logger`](./packages/slate-dev-logger/Changelog.md)
* [`slate-dev-warning`](./packages/slate-dev-warning/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)

View File

@@ -15,19 +15,13 @@ const h = createHyperscript({
code: 'code',
list: 'list',
item: 'item',
image: {
type: 'image',
isVoid: true,
},
image: 'image',
},
inlines: {
link: 'link',
hashtag: 'hashtag',
comment: 'comment',
emoji: {
type: 'emoji',
isVoid: true,
},
emoji: 'emoji',
},
marks: {
b: 'bold',

View File

@@ -11,12 +11,10 @@ const input = {
nodes: Array.from(Array(100)).map(() => ({
type: 'list',
object: 'block',
isVoid: false,
data: {},
nodes: Array.from(Array(10)).map(() => ({
type: 'list-item',
object: 'block',
isVoid: false,
data: {},
nodes: [
{
@@ -32,7 +30,6 @@ const input = {
{
type: 'link',
object: 'inline',
isVoid: false,
data: {
id: 1,
},

View File

@@ -32,6 +32,7 @@
* [Block](./reference/slate/block.md)
* [Change](./reference/slate/change.md)
* [Data](./reference/slate/data.md)
* [Decoration](./reference/slate/decoration.md)
* [Document](./reference/slate/document.md)
* [Inline](./reference/slate/inline.md)
* [Mark](./reference//slate/mark.md)
@@ -40,6 +41,7 @@
* [Point](./reference/slate/point.md)
* [Range](./reference/slate/range.md)
* [Schema](./reference/slate/schema.md)
* [Selection](./reference/slate/selection.md)
* [Text](./reference/slate/text.md)
* [Value](./reference/slate/value.md)
* [setKeyGenerator](./reference/slate/utils.md)
@@ -66,5 +68,4 @@
* [`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)

View File

@@ -4,11 +4,9 @@ Since Slate is a monorepo with many packages that are versioned separately, we m
* [`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)

View File

@@ -9,7 +9,7 @@ These libraries are helpful when developing with Slate:
* [`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
## Tools
These tools are helpful when developing with Slate:

View File

@@ -28,7 +28,6 @@ change
.moveToEndOfBlock()
.insertBlock({
type: 'image',
isVoid: true,
data: {
src: 'http://placekitten.com/200/300',
alt: 'Kittens',
@@ -145,7 +144,7 @@ When a rule's validation fails, Slate passes a [`Change`](../reference/slate/cha
### 4. From Outside Slate
This is the fourth place you might want to make changes, and also the most dangerous. You should know that any changes you make outside of the Slate editor might not be seen by your plugins, might interact with the history in weird ways, and may not work with collaborative editing implements.
This is the fourth place you might want to make changes, and also the most dangerous. You should know that any changes you make outside of the Slate editor might not be seen by your plugins (eg. if they register an `onChange` handler) and may not work with collaborative editing implements.
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:
@@ -176,7 +175,6 @@ function insertParagraph(change) {
function insertImage(change, src) {
change.insertBlock({
type: 'image',
isVoid: true,
data: { src },
})
}

View File

@@ -8,7 +8,7 @@ One of the main principles of Slate is that it tries to mirror the native DOM AP
If you think about it, this makes sense. Slate is kind of like a nicer implementation of `contenteditable`, which itself is built with the DOM. And people use the DOM to represent documents with rich-text-like structures all the time. Mirroring the DOM helps make the library familiar for new users, and it lets us reuse battle-tested patterns without having to reinvent them ourselves.
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.
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-like object called a [`Selection`](../reference/slate/selection.md) that represents the user's current cursor selection.
## Immutable Objects
@@ -39,7 +39,7 @@ It is made up of a document filled with content, and a selection representing th
## 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 and figures with captions.
Slate documents are nested and recursive. This means that a document has block nodes, and those block nodes can have child nodes—all the way down. This lets you model more complex nested behaviors like tables and figures with captions.
Unlike the DOM though, Slate enforces a few more restrictions on its documents. This reduces the complexity involved in manipulating them and prevents "impossible" situations from arising. These restrictions are:
@@ -49,15 +49,13 @@ Unlike the DOM though, Slate enforces a few more restrictions on its documents.
* **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.
* **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.
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)!
> 🙃 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).
@@ -92,7 +90,7 @@ That all sounds pretty complex, but you don't have to think about it much, as lo
## Ranges, Points and "The Selection"
Just like in the DOM, you can reference a part of the document using a `Range`. And there's one special range that Slate keeps track of that refers to the user's current cursor selection, called the "selection".
Just like in the DOM, you can reference a part of the document using a `Range`. And there's one special range that Slate keeps track of that refers to the user's current cursor selection, called the `Selection`.
Ranges are defined by two `Point`s, an "anchor" point and a "focus" point. The anchor is where the range starts, and the focus is where it ends. And each point is a combination of a "path" or "key" referencing a specific node, and an "offset". This ends up looking like this:
@@ -100,20 +98,11 @@ Ranges are defined by two `Point`s, an "anchor" point and a "focus" point. The a
const range = Range.create({
anchor: {
key: 'node-a',
offset: 0,
},
focus: {
key: 'node-b',
offset: 4,
},
})
const range = Range.create({
anchor: {
path: [0, 2, 1],
offset: 0,
},
focus: {
key: 'node-b',
path: [0, 3, 2],
offset: 4,
},
@@ -136,3 +125,41 @@ These `start` and `end` points are what most of your logic will be based on, sin
One important thing to note is that the anchor and focus points of ranges **always reference the "leaf-most" text nodes** in a document. They never reference blocks or inlines, always their child text nodes. This is different than in the DOM API, but it makes dealing with ranges a _lot_ easier because there are less edge cases to handle.
> 📋 For more info, check out the [`Range` reference](../reference/slate/range.md).
The `Selection` model contains slightly more information than the simple `Range` model, because it needs to keep track of "focus" and "marks" for the user. For example:
```js
const selection = Selection.create({
anchor: {
key: 'node-a',
path: [0, 2, 1],
offset: 0,
},
focus: {
key: 'node-b',
path: [0, 3, 2],
offset: 4,
},
isFocused: true,
marks: [{ type: 'bold' }],
})
```
However, keeping the `key` and `path` of ranges or selections in sync yourself is tedious. Instead, you can create selections using either and have the other automatically be inferred by the document. To do that, you use the `createRange` and `createSelection` methods:
```js
const selection = document.createSelection({
anchor: {
key: 'node-a',
offset: 0,
},
focus: {
key: 'node-b',
offset: 4,
},
isFocused: true,
marks: [{ type: 'bold' }],
})
```
The resulting `selection` will have a both the `key` and `path` set for its points, with the `key` being used to look up the `path` in the document.

View File

@@ -24,7 +24,7 @@ const value = (
</inline>{' '}
editor!
</block>
<block type="image" data={{ src: 'https://...' }} isVoid />
<block type="image" data={{ src: 'https://...' }} />
</document>
</value>
)
@@ -38,10 +38,7 @@ import { createHyperscript } from 'slate-hyperscript'
const h = createHyperscript({
blocks: {
paragraph: 'paragraph',
image: {
type: 'image',
isVoid: true,
},
image: 'image',
},
inlines: {
link: 'link',
@@ -83,6 +80,8 @@ The other export is a `createHyperscript` helper that you can use to create your
blocks: Object,
inlines: Object,
marks: Object,
decorations: Object,
schema: Object,
creators: Object,
}
```

View File

@@ -42,7 +42,7 @@ When the user pastes content into the editor, the core plugin handles all pastes
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`
### `renderEditor`
Renders all of the default contents of the editor!

View File

@@ -136,7 +136,6 @@ If this function returns `true`, it can force updating the editor where otherwis
renderMark: Function,
renderNode: Function,
renderPlaceholder: Function,
renderPortal: Function,
}
```
@@ -168,12 +167,6 @@ Render the placeholder that is shown when the editor has no `value`.
The `placeholder` prop that was passed to the editor can be found at `editor.props.placeholder`.
### `renderPortal`
`Function renderPortal(value: Value, editor: Editor) => ReactNode || Void`
Unlike the other renderProps, this one is mapped, so each plugin that returns something gets its own Portal. The return value is given as `children` to a `react-portal` `<Portal/>`.
## Other Properties
```js

View File

@@ -1,214 +0,0 @@
# `slate-schema-violations`
```js
import {
CHILD_OBJECT_INVALID,
CHILD_REQUIRED,
CHILD_TYPE_INVALID,
CHILD_UNKNOWN,
FIRST_CHILD_OBJECT_INVALID,
FIRST_CHILD_TYPE_INVALID,
LAST_CHILD_OBJECT_INVALID,
LAST_CHILD_TYPE_INVALID,
NODE_DATA_INVALID,
NODE_IS_VOID_INVALID,
NODE_MARK_INVALID,
NODE_TEXT_INVALID,
PARENT_OBJECT_INVALID,
PARENT_TYPE_INVALID,
} from 'slate-schema-violations'
```
A set of constants for the built-in violations in a Slate schema.
## Example
```js
import React from 'react'
import Types from 'slate-prop-types'
class Toolbar extends React.Component {
propTypes = {
block: Types.block,
schema: Types.schema.isRequired,
value: Types.value.isRequired,
}
...
}
```
## Exports
### `CHILD_OBJECT_INVALID`
```js
{
child: Node,
index: Number,
node: Node,
rule: Object,
}
```
Raised when the `object` property of a child node is invalid.
### `CHILD_REQUIRED`
```js
{
index: Number,
node: Node,
rule: Object,
}
```
Raised when a child node was required but none was found.
### `CHILD_TYPE_INVALID`
```js
{
child: Node,
index: Number,
node: Node,
rule: Object,
}
```
Raised when the `type` property of a child node is invalid.
### `CHILD_UNKNOWN`
```js
{
child: Node,
index: Number,
node: Node,
rule: Object,
}
```
Raised when a child was not expected but one was found.
### `FIRST_CHILD_OBJECT_INVALID`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `object` property of the first child node is invalid, when a specific `first` rule was defined in a schema.
### `FIRST_CHILD_TYPE_INVALID`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `type` property of the first child node is invalid, when a specific `first` rule was defined in a schema.
### `LAST_CHILD_OBJECT_INVALID`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `object` property of the last child node is invalid, when a specific `last` rule was defined in a schema.
### `LAST_CHILD_TYPE_INVALID`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `type` property of the last child node is invalid, when a specific `last` rule was defined in a schema.
### `NODE_DATA_INVALID`
```js
{
key: String,
node: Node,
rule: Object,
value: Mixed,
}
```
Raised when the `data` property of a node contains an invalid entry.
### `NODE_IS_VOID_INVALID`
```js
{
node: Node,
rule: Object,
}
```
Raised when the `isVoid` property of a node is invalid.
### `NODE_MARK_INVALID`
```js
{
mark: Mark,
node: Node,
rule: Object,
}
```
Raised when one of the marks in a node is invalid.
### `NODE_TEXT_INVALID`
```js
{
text: String,
node: Node,
rule: Object,
}
```
Raised when the text content of a node is invalid.
### `PARENT_OBJECT_INVALID`
```js
{
node: Node,
parent: Node,
rule: Object,
}
```
Raised when the `object` property of the parent of a node is invalid, when a specific `parent` rule was defined in a schema.
### `PARENT_TYPE_INVALID`
```js
{
node: Node,
parent: Node,
rule: Object,
}
```
Raised when the `type` property of the parent of a node is invalid, when a specific `parent` rule was defined in a schema.

View File

@@ -13,7 +13,6 @@ Block nodes may contain nested block nodes, inline nodes, and text nodes—just
```js
Block({
data: Data,
isVoid: Boolean,
key: String,
nodes: Immutable.List<Node>,
type: String
@@ -26,14 +25,6 @@ Block({
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`.
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`

View File

@@ -0,0 +1,73 @@
# `Decoration`
```js
import { Decoration } from 'slate'
```
A decoration is a range of the document that has a specific [`Mark`](./mark.md) dynamically applied to it based on its content or some other external state. It is not actually reflected in the document's structure itself. This can be useful for cases like syntax highlighting, or search result highlighting.
Decorations implement the [`Range`](./range.md) interface, but also contain a `mark`.
## Properties
```js
Decoration({
anchor: Point,
focus: Point,
mark: Mark,
})
```
### `mark`
`Mark`
The mark associated with the decoration.
### `object`
`String`
A string with a value of `'decoration'`.
## Static Methods
### `Decoration.create`
`Decoration.create(properties: Object) => Decoration`
Create a new `Decoration` instance with `properties`.
### `Decoration.createProperties`
`Decoration.createProperties(object: Object|Decoration) => Object`
Create a new dictionary of range properties from an `object`.
### `Decoration.fromJSON`
`Decoration.fromJSON(object: Object) => Decoration`
Create a range from a JSON `object`.
### `Decoration.isDecoration`
`Decoration.isDecoration(value: Any) => Boolean`
Check whether a `value` is a `Decoration`.
## Instance Methods
### `toJSON`
`toJSON() => Object`
Return a JSON representation of the range.
## Mutating Methods
### `setMark`
`setMark(mark: Mark) => Decoration`
Return a new decoration with a new `mark`.

View File

@@ -13,7 +13,6 @@ Inline nodes may contain nested inline nodes and text nodes—just like in the D
```js
Inline({
data: Data,
isVoid: Boolean,
key: String,
nodes: Immutable.List<Node>,
type: String
@@ -26,14 +25,6 @@ Inline({
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`.
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`

View File

@@ -13,10 +13,10 @@ There are a handful of Slate operation types. The goal is to have the fewest pos
```js
{
type: 'insert_text',
path: Array,
path: List,
offset: Number,
text: String,
marks: Array,
marks: List,
}
```
@@ -27,7 +27,7 @@ Inserts a `text` string at `offset` into a text node at `path`, with optional `m
```js
{
type: 'remove_text',
path: Array,
path: List,
offset: Number,
text: String,
}
@@ -42,10 +42,10 @@ Removes a string of `text` at `offset` into a text node at `path`.
```js
{
type: 'add_mark',
path: Array,
path: List,
offset: Number,
length: Number,
mark: Object,
mark: Mark,
}
```
@@ -56,10 +56,10 @@ Adds a `mark` to the text node at `path` starting at an `offset` and spanning `l
```js
{
type: 'remove_mark',
path: Array,
path: List,
offset: Number,
length: Number,
mark: Object,
mark: Mark,
}
```
@@ -70,10 +70,10 @@ Removes a `mark` from a text node at `path` starting at an `offset` and spanning
```js
{
type: 'set_mark',
path: Array,
path: List,
offset: Number,
length: Number,
mark: Object,
mark: Mark,
properties: Object,
}
```
@@ -87,8 +87,8 @@ Set new `properties` on any marks that match an existing `mark` in a text node a
```js
{
type: 'insert_node',
path: Array,
node: Object,
path: List,
node: Node,
}
```
@@ -99,7 +99,7 @@ Insert a new `node` at `path`.
```js
{
type: 'merge_node',
path: Array,
path: List,
position: Number,
properties: Object,
}
@@ -112,7 +112,7 @@ Merge the node at `path` with its previous sibling. The `position` refers to eit
```js
{
type: 'move_node',
path: Array,
path: List,
newPath: Array,
}
```
@@ -124,8 +124,8 @@ Move the node at `path` to a `newPath`.
```js
{
type: 'remove_node',
path: Array,
node: Object,
path: List,
node: Node,
}
```
@@ -136,9 +136,9 @@ Remove the node at `path`.
```js
{
type: 'set_node',
path: Array,
path: List,
properties: Object,
node: Object,
node: Node,
}
```
@@ -149,7 +149,7 @@ Set new `properties` on the node at `path`.
```js
{
type: 'split_node',
path: Array,
path: List,
position: Number,
target: Number,
properties: Object,
@@ -166,7 +166,7 @@ Split the node at `path` at `position`. The `position` refers to either the inde
{
type: 'set_selection',
properties: Object,
selection: Object,
selection: Selection,
}
```
@@ -178,7 +178,7 @@ Set new `properties` on the selection.
{
type: 'set_value',
properties: Object,
value: Object,
value: Value,
}
```

View File

@@ -171,3 +171,9 @@ Return a new point with a new `offset`.
`setPath(path: List|Array|Null) => Point`
Return a new point with a new `path`.
### `unset`
`unset() => Point`
Return a new point with the key, path, and offset all set to `null`.

View File

@@ -10,15 +10,14 @@ 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.
The `Range` model is also used as an interface and implemented by the [`Decoration`](./decoration.md) and [`Selection`](./selection.md) models.
## Properties
```js
Range({
anchor: Point,
focus: Point,
isAtomic: Boolean,
isFocused: Boolean,
marks: Set,
})
```
@@ -34,24 +33,6 @@ The range's anchor point.
The range's focus point.
### `isAtomic`
`Boolean`
Whether the range is atomic (for decorations only).
### `isFocused`
`Boolean`
Whether the range currently has focus.
### `marks`
`Set`
A set of marks associated with the range.
### `object`
`String`
@@ -72,12 +53,6 @@ Either the `anchor` or the `focus` point, depending on which comes last in the d
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.
### `isBlurred`
`Boolean`
The opposite of `isFocused`, for convenience.
### `isCollapsed`
`Boolean`
@@ -224,24 +199,6 @@ Return a new range with a new `end` point.
Return a new range with a new `focus` point.
### `setIsAtomic`
`setIsAtomic(isAtomic: Boolean) => Range`
Return a new range with a new `isAtomic` value.
### `setIsFocused`
`setIsFocused(isFocused: Boolean) => Range`
Return a new range with a new `isFocused` value.
### `setMarks`
`setMarks(marks: Set|Null) => Range`
Return a new range with a new set of `marks`.
### `setProperties`
`setProperties(properties: Object|Range) => Range`
@@ -253,3 +210,9 @@ Return a new range with new `properties` set.
`setStart(start: Point) => Range`
Return a new range with a new `start` point.
### `unset`
`unset() => Range`
Return a new range with both of its point unset.

View File

@@ -134,7 +134,7 @@ Will validate the first child node against a [`match`](#match).
}
```
Will validate a node's `isVoid` property.
Will determine whether the node is treated as a "void" node or not, making its content a black box that Slate doesn't control editing for.
### `last`
@@ -277,8 +277,177 @@ Returns a boolean if the passed in argument is a `Schema`.
Returns a JSON representation of the schema.
## Normalizing
## Errors
When supplying your own `normalize` property for a schema rule, it will be called with `(change, error)`. The error `code` will be one of a set of potential code strings, and it will contain additional helpful properties depending on the type of error.
A set of the invalid violation strings are available as constants via the [`slate-schema-violations`](../slate-schema-violations/index.md) package.
### `'child_object_invalid'`
```js
{
child: Node,
index: Number,
node: Node,
rule: Object,
}
```
Raised when the `object` property of a child node is invalid.
### `'child_required'`
```js
{
index: Number,
node: Node,
rule: Object,
}
```
Raised when a child node was required but none was found.
### `'child_type_invalid'`
```js
{
child: Node,
index: Number,
node: Node,
rule: Object,
}
```
Raised when the `type` property of a child node is invalid.
### `'child_unknown'`
```js
{
child: Node,
index: Number,
node: Node,
rule: Object,
}
```
Raised when a child was not expected but one was found.
### `'first_child_object_invalid'`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `object` property of the first child node is invalid, when a specific `first` rule was defined in a schema.
### `'first_child_type_invalid'`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `type` property of the first child node is invalid, when a specific `first` rule was defined in a schema.
### `'last_child_object_invalid'`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `object` property of the last child node is invalid, when a specific `last` rule was defined in a schema.
### `'last_child_type_invalid'`
```js
{
child: Node,
node: Node,
rule: Object,
}
```
Raised when the `type` property of the last child node is invalid, when a specific `last` rule was defined in a schema.
### `'node_data_invalid'`
```js
{
key: String,
node: Node,
rule: Object,
value: Mixed,
}
```
Raised when the `data` property of a node contains an invalid entry.
### `'node_is_void_invalid'`
```js
{
node: Node,
rule: Object,
}
```
Raised when the `isVoid` property of a node is invalid.
### `'node_mark_invalid'`
```js
{
mark: Mark,
node: Node,
rule: Object,
}
```
Raised when one of the marks in a node is invalid.
### `'node_text_invalid'`
```js
{
text: String,
node: Node,
rule: Object,
}
```
Raised when the text content of a node is invalid.
### `'parent_object_invalid'`
```js
{
node: Node,
parent: Node,
rule: Object,
}
```
Raised when the `object` property of the parent of a node is invalid, when a specific `parent` rule was defined in a schema.
### `'parent_type_invalid'`
```js
{
node: Node,
parent: Node,
rule: Object,
}
```
Raised when the `type` property of the parent of a node is invalid, when a specific `parent` rule was defined in a schema.

View File

@@ -0,0 +1,92 @@
# `Selection`
```js
import { Selection } from 'slate'
```
The user's current selection in a Slate [`Document`](./document.md). Selections implement the [`Range`](./range.md) interface, but also expose data about the current "focus" and the cursor current marks.
## Properties
```js
Selection({
anchor: Point,
focus: Point,
isFocused: Boolean,
marks: Set,
})
```
### `isFocused`
`Boolean`
Whether the range currently has focus.
### `marks`
`Set`
A set of marks associated with the range.
### `object`
`String`
A string with a value of `'selection'`.
## Computed Properties
### `isBlurred`
`Boolean`
The opposite of `isFocused`, for convenience.
## Static Methods
### `Selection.create`
`Selection.create(properties: Object) => Selection`
Create a new `Selection` instance with `properties`.
### `Selection.createProperties`
`Selection.createProperties(object: Object|Selection) => Object`
Create a new dictionary of range properties from an `object`.
### `Selection.fromJSON`
`Selection.fromJSON(object: Object) => Selection`
Create a range from a JSON `object`.
### `Selection.isSelection`
`Selection.isSelection(value: Any) => Boolean`
Check whether a `value` is a `Selection`.
## Instance Methods
### `toJSON`
`toJSON() => Object`
Return a JSON representation of the range.
## Mutating Methods
### `setIsFocused`
`setIsFocused(isFocused: Boolean) => Selection`
Return a new range with a new `isFocused` value.
### `setMarks`
`setMarks(marks: Set|Null) => Selection`
Return a new range with a new set of `marks`.

View File

@@ -1,22 +1,28 @@
# Utils
```js
import { resetKeyGenerator, setKeyGenerator } from 'slate'
import { KeyUtils } from 'slate'
```
Utility functions that ship with Slate that may be useful for certain use cases.
## Functions
## Key Utils
### `resetKeyGenerator`
### `KeyUtils.create`
`resetKeyGenerator() => Void`
`create() => String`
Create a new key using the current key generator.
### `KeyUtils.resetGenerator`
`resetGenerator() => 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`
### `KeyUtils.setGenerator`
`setKeyGenerator(generator: Function) => Void`
`setGenerator(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'`, ...)

View File

@@ -4,7 +4,7 @@
import { Value } from 'slate'
```
A `Value` is the top-level representation of data in Slate, containing both a [`Document`](./document.md) and a selection [`Range`](./range.md). It's what you need to pass into the Slate [`<Editor>`](../slate-react/editor.md) to render something onto the page.
A `Value` is the top-level representation of data in Slate, containing both a [`Document`](./document.md) and a [`Selection`](./selection.md). It's what you need to pass into the Slate [`<Editor>`](../slate-react/editor.md) to render something onto the page.
All changes to the document and selection are also performed through the value object, so that they can stay in sync, and be propagated to its internal history of undo/redo value.
@@ -15,11 +15,11 @@ For convenience, in addition to changes, many of the selection and document prop
```js
Value({
document: Document,
selection: Range,
selection: Selection,
history: History,
schema: Schema,
data: Data,
decorations: List<Ranges>|Null,
decorations: List<Decoration>,
})
```
@@ -31,7 +31,7 @@ An object containing arbitrary data for the value.
### `decorations`
`List<Ranges>|Null`
`List<Decoration>`
A list of ranges in the document with marks that aren't part of the content itself—like matches for the current search string.
@@ -61,7 +61,7 @@ An object representing the schema of the value's document.
### `selection`
`Range`
`Selection`
The current selection of the value.

View File

@@ -22,6 +22,20 @@ class Embeds extends React.Component {
value: Value.fromJSON(initialValue),
}
/**
* The editor's schema.
*
* @type {Object}
*/
schema = {
blocks: {
video: {
isVoid: true,
},
},
}
/**
* Render the app.
*
@@ -33,6 +47,7 @@ class Embeds extends React.Component {
<Editor
placeholder="Enter some text..."
value={this.state.value}
schema={this.schema}
onChange={this.onChange}
renderNode={this.renderNode}
/>

View File

@@ -19,7 +19,6 @@
{
"object": "block",
"type": "video",
"isVoid": true,
"data": {
"video": "https://www.youtube.com/embed/FaHEusBG20c"
}

View File

@@ -67,6 +67,20 @@ class Emojis extends React.Component {
value: Value.fromJSON(initialValue),
}
/**
* The editor's schema.
*
* @type {Object}
*/
schema = {
inlines: {
emoji: {
isVoid: true,
},
},
}
/**
* Render the app.
*
@@ -86,6 +100,7 @@ class Emojis extends React.Component {
<Editor
placeholder="Write some 😍👋🎉..."
value={this.state.value}
schema={this.schema}
onChange={this.onChange}
renderNode={this.renderNode}
/>
@@ -147,7 +162,6 @@ class Emojis extends React.Component {
change
.insertInline({
type: 'emoji',
isVoid: true,
data: { code },
})
.moveToStartOfNextText()

View File

@@ -17,7 +17,6 @@
{
"object": "inline",
"type": "emoji",
"isVoid": true,
"data": {
"code": "😃"
}
@@ -39,7 +38,6 @@
{
"object": "inline",
"type": "emoji",
"isVoid": true,
"data": {
"code": "🍔"
}

View File

@@ -1,6 +1,5 @@
import { Editor } from 'slate-react'
import { Block, Value } from 'slate'
import { CHILD_REQUIRED, CHILD_TYPE_INVALID } from 'slate-schema-violations'
import React from 'react'
import initialValue from './value.json'
@@ -19,11 +18,11 @@ const schema = {
],
normalize: (change, { code, node, child, index }) => {
switch (code) {
case CHILD_TYPE_INVALID: {
case 'child_type_invalid': {
const type = index === 0 ? 'title' : 'paragraph'
return change.setNodeByKey(child.key, type)
}
case CHILD_REQUIRED: {
case 'child_required': {
const block = Block.create(index === 0 ? 'title' : 'paragraph')
return change.insertNodeByKey(node.key, index, block)
}

View File

@@ -1,6 +1,5 @@
import { Editor, getEventRange, getEventTransfer } from 'slate-react'
import { Block, Value } from 'slate'
import { LAST_CHILD_TYPE_INVALID } from 'slate-schema-violations'
import React from 'react'
import initialValue from './value.json'
@@ -48,13 +47,12 @@ function insertImage(change, src, target) {
change.insertBlock({
type: 'image',
isVoid: true,
data: { src },
})
}
/**
* A schema to enforce that there's always a paragraph as the last block.
* The editor's schema.
*
* @type {Object}
*/
@@ -64,13 +62,18 @@ const schema = {
last: { type: 'paragraph' },
normalize: (change, { code, node, child }) => {
switch (code) {
case LAST_CHILD_TYPE_INVALID: {
case 'last_child_type_invalid': {
const paragraph = Block.create('paragraph')
return change.insertNodeByKey(node.key, node.nodes.size, paragraph)
}
}
},
},
blocks: {
image: {
isVoid: true,
},
},
}
/**

View File

@@ -19,7 +19,6 @@
{
"object": "block",
"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"

View File

@@ -112,7 +112,6 @@ const RULES = [
return {
object: 'block',
type: 'image',
isVoid: true,
nodes: next(el.childNodes),
data: {
src: el.getAttribute('src'),
@@ -163,6 +162,20 @@ class PasteHtml extends React.Component {
value: Value.fromJSON(initialValue),
}
/**
* The editor's schema.
*
* @type {Object}
*/
schema = {
blocks: {
image: {
isVoid: true,
},
},
}
/**
* Render.
*
@@ -174,6 +187,7 @@ class PasteHtml extends React.Component {
<Editor
placeholder="Paste in some HTML..."
value={this.state.value}
schema={this.schema}
onPaste={this.onPaste}
onChange={this.onChange}
renderNode={this.renderNode}

View File

@@ -89,8 +89,7 @@
"slate": "*",
"slate-html-serializer": "*",
"slate-plain-serializer": "*",
"slate-react": "*",
"slate-schema-violations": "*"
"slate-react": "*"
},
"scripts": {
"benchmark": "cross-env COMPARE=compare node --expose-gc ./tmp/benchmark/index.js",

View File

@@ -11,6 +11,5 @@ Slate's codebase is monorepo managed with [Lerna](https://lernajs.io/). It consi
| [`slate-plain-serializer`](./slate-plain-serializer) | [![](https://img.shields.io/npm/v/slate-plain-serializer.svg?maxAge=2592000&label=version&colorB=007ec6)](./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)](./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)](./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)](./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)](./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. |
| [`slate-hotkeys`](./slate-hotkeys) | [![](https://img.shields.io/npm/v/slate-hotkeys.svg?maxAge=2592000&label=version&colorB=007ec6)](./slate-hotkeys/package.json) | [![](http://img.badgesize.io/https://unpkg.com/slate-hotkeys/dist/slate-hotkeys.min.js?compression=gzip&label=size)](https://unpkg.com/slate-hotkeys/dist/slate-hotkeys.min.js) | Detect common keypresses in a platform-agnostic way |

View File

@@ -1 +0,0 @@
This package contains the logger that Slate uses to log warnings and deprecations only when in development environments.

View File

@@ -1,21 +0,0 @@
{
"name": "slate-dev-logger",
"description": "INTERNAL: A simple, development-only logger for Slate.",
"version": "0.1.43",
"license": "MIT",
"repository": "git://github.com/ianstormtaylor/slate.git",
"main": "lib/slate-dev-logger.js",
"module": "lib/slate-dev-logger.es.js",
"umd": "dist/slate-dev-logger.js",
"umdMin": "dist/slate-dev-logger.min.js",
"files": [
"dist/",
"lib/"
],
"devDependencies": {
"mocha": "^2.5.3"
},
"scripts": {
"clean": "rm -rf ./dist ./lib ./node_modules"
}
}

View File

@@ -1,110 +0,0 @@
/* eslint-disable no-console */
/**
* Is deprecate interface forbidden?
*/
const FORBID_DEPRECATE =
process && process.env && process.env.FORBID_DEPRECATIONS
/**
* Is warning scenarios forbidden?
*/
const FORBID_WARNING = process && process.env && process.env.FORBID_WARNINGS
/**
* Is in development?
*
* @type {Boolean}
*/
const IS_DEV =
typeof process !== 'undefined' &&
process.env &&
process.env.NODE_ENV !== 'production'
/**
* Has console?
*
* @type {Boolean}
*/
const HAS_CONSOLE =
typeof console != 'undefined' &&
typeof console.log == 'function' &&
typeof console.warn == 'function' &&
typeof console.error == 'function'
/**
* Log a `message` at `level`.
*
* @param {String} level
* @param {String} message
* @param {Any} ...args
*/
function log(level, message, ...args) {
if (!IS_DEV) {
return
}
if (HAS_CONSOLE) {
console[level](message, ...args)
}
}
/**
* Log an error `message`.
*
* @param {String} message
* @param {Any} ...args
*/
function error(message, ...args) {
if (HAS_CONSOLE) {
console.error(message, ...args)
}
}
/**
* Log a warning `message` in development only.
*
* @param {String} message
* @param {Any} ...args
*/
function warn(message, ...args) {
const logger = FORBID_WARNING ? forbidden : log
logger('warn', `Warning: ${message}`, ...args)
}
/**
* Log a deprecation warning `message`, with helpful `version` number in
* development only.
*
* @param {String} version
* @param {String} message
* @param {Any} ...args
*/
function deprecate(version, message, ...args) {
const logger = FORBID_DEPRECATE ? forbidden : log
logger('warn', `Deprecation (${version}): ${message}`, ...args)
}
function forbidden(level, message) {
throw new Error(message)
}
/**
* Export.
*
* @type {Function}
*/
export default {
deprecate,
error,
warn,
}

View File

@@ -0,0 +1 @@
This package contains the warning logger that Slate uses to log warnings and deprecations only when in development environments.

View File

@@ -0,0 +1,21 @@
{
"name": "slate-dev-warning",
"description": "INTERNAL: A simple, development-only warning helper for Slate.",
"version": "0.0.0",
"license": "MIT",
"repository": "git://github.com/ianstormtaylor/slate.git",
"main": "lib/slate-dev-warning.js",
"module": "lib/slate-dev-warning.es.js",
"umd": "dist/slate-dev-warning.js",
"umdMin": "dist/slate-dev-warning.min.js",
"files": [
"dist/",
"lib/"
],
"devDependencies": {
"mocha": "^2.5.3"
},
"scripts": {
"clean": "rm -rf ./dist ./lib ./node_modules"
}
}

View File

@@ -0,0 +1,19 @@
/**
* A `warning` helper, modeled after Facebook's and the `tiny-invariant` library.
*
* @param {Mixed} condition
* @param {String} message
*/
export default function warning(condition, message = '') {
if (condition) return
const isProduction = process.env.NODE_ENV === 'production'
const log = console.warn || console.log // eslint-disable-line no-console
if (isProduction) {
log('Warning')
} else {
log(`Warning: ${message}`)
}
}

View File

@@ -4,6 +4,14 @@ This document maintains a list of changes to the `slate-html-serializer` package
---
### `0.7.0` — August 22, 2018
###### 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.
---
### `0.6.0` — March 22, 2018
###### BREAKING

View File

@@ -13,7 +13,6 @@
"lib/"
],
"dependencies": {
"slate-dev-logger": "^0.1.43",
"type-of": "^2.0.1"
},
"peerDependencies": {

View File

@@ -144,7 +144,6 @@ class Html {
const block = {
object: 'block',
data: {},
isVoid: false,
...defaultBlock,
nodes: [node],
}
@@ -159,7 +158,6 @@ class Html {
{
object: 'block',
data: {},
isVoid: false,
...defaultBlock,
nodes: [
{

View File

@@ -11,7 +11,6 @@ export const config = {
return {
object: 'block',
type: 'image',
isVoid: true,
}
}
}

View File

@@ -18,7 +18,6 @@ export const config = {
return {
object: 'inline',
type: 'emoji',
isVoid: true,
nodes: next(el.childNodes),
}
}

View File

@@ -25,7 +25,6 @@ export const config = {
return {
object: 'inline',
type: 'linebreak',
isVoid: true,
}
}
}

View File

@@ -21,7 +21,6 @@ export const config = {
return {
object: 'block',
type: 'image',
isVoid: true,
}
}
}

View File

@@ -12,23 +12,14 @@ const h = createHyperscript({
paragraph: 'paragraph',
quote: 'quote',
code: 'code',
image: {
type: 'image',
isVoid: true,
},
image: 'image',
},
inlines: {
link: 'link',
hashtag: 'hashtag',
comment: 'comment',
emoji: {
type: 'emoji',
isVoid: true,
},
linebreak: {
type: 'linebreak',
isVoid: true,
},
emoji: 'emoji',
linebreak: 'linebreak',
},
marks: {
b: 'bold',

View File

@@ -4,6 +4,14 @@ This document maintains a list of changes to the `slate-hyperscript` package wit
---
### `0.10.0` — August 22, 2018
###### 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.
---
### `0.9.0` — August 22, 2018
###### NEW

View File

@@ -13,9 +13,7 @@
"lib/"
],
"dependencies": {
"is-empty": "^1.0.0",
"is-plain-object": "^2.0.4",
"slate-dev-logger": "^0.1.43"
"is-plain-object": "^2.0.4"
},
"peerDependencies": {
"slate": ">=0.37.0"

View File

@@ -7,7 +7,6 @@ import {
Mark,
Node,
Point,
Schema,
Selection,
Text,
Value,
@@ -173,7 +172,6 @@ const CREATORS = {
value(tagName, attributes, children) {
const { data, normalize = true } = attributes
const schema = Schema.create(attributes.schema || {})
const document = children.find(Document.isDocument)
let selection = children.find(Selection.isSelection) || Selection.create()
let anchor
@@ -263,7 +261,7 @@ const CREATORS = {
}
let value = Value.fromJSON(
{ data, document, selection, schema },
{ data, document, selection, ...attributes },
{ normalize }
)
@@ -471,19 +469,19 @@ function resolveCreators(options) {
}
Object.keys(blocks).map(key => {
creators[key] = normalizeNode(key, blocks[key], 'block')
creators[key] = normalizeNode(blocks[key], 'block')
})
Object.keys(inlines).map(key => {
creators[key] = normalizeNode(key, inlines[key], 'inline')
creators[key] = normalizeNode(inlines[key], 'inline')
})
Object.keys(marks).map(key => {
creators[key] = normalizeMark(key, marks[key])
creators[key] = normalizeMark(marks[key])
})
Object.keys(decorations).map(key => {
creators[key] = normalizeNode(key, decorations[key], 'decoration')
creators[key] = normalizeNode(decorations[key], 'decoration')
})
creators.value = (tagName, attributes = {}, children) => {
@@ -495,15 +493,14 @@ function resolveCreators(options) {
}
/**
* Normalize a node creator with `key` and `value`, of `object`.
* Normalize a node creator of `value` and `object`.
*
* @param {String} key
* @param {Function|Object|String} value
* @param {String} object
* @return {Function}
*/
function normalizeNode(key, value, object) {
function normalizeNode(value, object) {
if (typeof value == 'function') {
return value
}
@@ -514,11 +511,11 @@ function normalizeNode(key, value, object) {
if (isPlainObject(value)) {
return (tagName, attributes, children) => {
const { key: attrKey, ...rest } = attributes
const { key, ...rest } = attributes
const attrs = {
...value,
object,
key: attrKey,
key,
data: {
...(value.data || {}),
...rest,
@@ -535,14 +532,13 @@ function normalizeNode(key, value, object) {
}
/**
* Normalize a mark creator with `key` and `value`.
* Normalize a mark creator of `value`.
*
* @param {String} key
* @param {Function|Object|String} value
* @return {Function}
*/
function normalizeMark(key, value) {
function normalizeMark(value) {
if (typeof value == 'function') {
return value
}

View File

@@ -33,7 +33,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -51,7 +50,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -37,7 +37,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -36,13 +36,11 @@ export const output = {
{
object: 'block',
type: 'ul',
isVoid: false,
data: {},
nodes: [
{
object: 'block',
type: 'li',
isVoid: false,
data: {},
nodes: [
{
@@ -60,7 +58,6 @@ export const output = {
{
object: 'block',
type: 'li',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -37,7 +37,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -33,7 +33,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -51,7 +50,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -33,7 +33,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -51,7 +50,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -15,7 +15,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -28,7 +28,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -35,7 +35,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -53,7 +52,6 @@ export const output = {
object: 'inline',
key: '1',
type: 'link',
isVoid: false,
data: {},
nodes: [
{
@@ -86,7 +84,6 @@ export const output = {
object: 'block',
key: '7',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -104,7 +101,6 @@ export const output = {
object: 'inline',
key: '5',
type: 'link',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -31,7 +31,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -51,7 +50,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -31,7 +31,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -51,7 +50,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -31,7 +31,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -51,7 +50,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -52,7 +51,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -72,7 +70,6 @@ export const output = {
object: 'block',
key: '5',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -52,7 +51,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -72,7 +70,6 @@ export const output = {
object: 'block',
key: '5',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -52,7 +51,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -72,7 +70,6 @@ export const output = {
object: 'block',
key: '5',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -28,7 +28,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -28,7 +28,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -28,7 +28,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -34,7 +34,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '4',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -50,7 +49,6 @@ export const output = {
object: 'inline',
key: '1',
type: 'link',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '4',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -50,7 +49,6 @@ export const output = {
object: 'inline',
key: '1',
type: 'link',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '4',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -50,7 +49,6 @@ export const output = {
object: 'inline',
key: '1',
type: 'link',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -5,10 +5,7 @@ import { createHyperscript } from 'slate-hyperscript'
const h = createHyperscript({
blocks: {
paragraph: 'paragraph',
image: {
type: 'image',
isVoid: true,
},
image: 'image',
},
inlines: {
link: 'link',
@@ -39,7 +36,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -71,7 +67,6 @@ export const output = {
{
object: 'inline',
type: 'link',
isVoid: false,
data: {
src: 'http://slatejs.org',
},
@@ -103,7 +98,6 @@ export const output = {
{
object: 'block',
type: 'image',
isVoid: true,
data: {
src: 'https://...',
},

View File

@@ -40,7 +40,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -60,7 +59,6 @@ export const output = {
object: 'block',
key: '3',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -37,7 +37,6 @@ export const output = {
object: 'block',
key: '1',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -17,7 +17,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -20,7 +20,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -20,7 +20,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -32,7 +32,6 @@ export const output = {
object: 'block',
key: '0',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -24,7 +24,6 @@ export const output = {
object: 'block',
key: '4',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -43,7 +42,6 @@ export const output = {
key: '1',
type: 'link',
data: {},
isVoid: false,
nodes: [
{
object: 'text',

View File

@@ -12,7 +12,7 @@ export const input = (
</inline>{' '}
editor!
</block>
<block type="image" data={{ src: 'https://...' }} isVoid />
<block type="image" data={{ src: 'https://...' }} />
</document>
</value>
)
@@ -26,7 +26,6 @@ export const output = {
{
object: 'block',
type: 'paragraph',
isVoid: false,
data: {},
nodes: [
{
@@ -58,7 +57,6 @@ export const output = {
{
object: 'inline',
type: 'link',
isVoid: false,
data: {
src: 'http://slatejs.org',
},
@@ -90,7 +88,6 @@ export const output = {
{
object: 'block',
type: 'image',
isVoid: true,
data: {
src: 'https://...',
},

View File

@@ -4,6 +4,14 @@ This document maintains a list of changes to the `slate-plain-serializer` packag
---
### `0.6.0` — August 22, 2018
###### 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.
---
### `0.5.0` — January 4, 2018
###### BREAKING

View File

@@ -12,9 +12,6 @@
"dist/",
"lib/"
],
"dependencies": {
"slate-dev-logger": "^0.1.43"
},
"peerDependencies": {
"immutable": ">=3.8.1",
"slate": ">=0.32.0"

View File

@@ -31,7 +31,6 @@ function deserialize(string, options = {}) {
return {
...defaultBlock,
object: 'block',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -11,7 +11,6 @@ export const output = {
{
object: 'block',
type: 'line',
isVoid: false,
data: {},
nodes: [
{

View File

@@ -12,19 +12,13 @@ const h = createHyperscript({
paragraph: 'paragraph',
quote: 'quote',
code: 'code',
image: {
type: 'image',
isVoid: true,
},
image: 'image',
},
inlines: {
link: 'link',
hashtag: 'hashtag',
comment: 'comment',
emoji: {
type: 'emoji',
isVoid: true,
},
emoji: 'emoji',
},
marks: {
b: 'bold',

View File

@@ -12,9 +12,6 @@
"dist/",
"lib/"
],
"dependencies": {
"slate-dev-logger": "^0.1.43"
},
"peerDependencies": {
"immutable": ">=3.8.1",
"slate": ">=0.32.0"

View File

@@ -4,6 +4,14 @@ This document maintains a list of changes to the `slate-react` package with each
---
### `0.18.0` — August 22, 2018
###### 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.
---
### `0.17.0` — August 22, 2018
###### NEW

View File

@@ -16,16 +16,14 @@
"debug": "^3.1.0",
"get-window": "^1.1.1",
"is-window": "^1.0.2",
"keycode": "^2.1.2",
"lodash": "^4.1.1",
"memoize-one": "^4.0.0",
"prop-types": "^15.5.8",
"react-immutable-proptypes": "^2.1.0",
"react-portal": "^3.1.0",
"selection-is-backward": "^1.0.0",
"slate-base64-serializer": "^0.2.60",
"slate-dev-environment": "^0.2.0",
"slate-dev-logger": "^0.1.43",
"slate-dev-warning": "^0.0.0",
"slate-hotkeys": "^0.2.3",
"slate-plain-serializer": "^0.5.41",
"slate-prop-types": "^0.4.58"

View File

@@ -2,9 +2,9 @@ import Debug from 'debug'
import React from 'react'
import Types from 'prop-types'
import getWindow from 'get-window'
import { IS_FIREFOX, HAS_INPUT_EVENTS_LEVEL_2 } from 'slate-dev-environment'
import logger from 'slate-dev-logger'
import warning from 'slate-dev-warning'
import throttle from 'lodash/throttle'
import { IS_FIREFOX, HAS_INPUT_EVENTS_LEVEL_2 } from 'slate-dev-environment'
import EVENT_HANDLERS from '../constants/event-handlers'
import Node from './node'
@@ -37,7 +37,6 @@ class Content extends React.Component {
static propTypes = {
autoCorrect: Types.bool.isRequired,
children: Types.any.isRequired,
className: Types.string,
editor: Types.object.isRequired,
readOnly: Types.bool.isRequired,
@@ -165,10 +164,11 @@ class Content extends React.Component {
const range = findDOMRange(selection, window)
if (!range) {
logger.error(
'Unable to find a native DOM range from the current selection.',
{ selection }
warning(
false,
'Unable to find a native DOM range from the current selection.'
)
return
}
@@ -426,7 +426,6 @@ class Content extends React.Component {
data-gramm={false}
>
{children}
{this.props.children}
</Container>
)
}

View File

@@ -1,9 +1,8 @@
import Debug from 'debug'
import Portal from 'react-portal'
import React from 'react'
import SlateTypes from 'slate-prop-types'
import Types from 'prop-types'
import logger from 'slate-dev-logger'
import warning from 'slate-dev-warning'
import { Schema, Stack } from 'slate'
import memoizeOne from 'memoize-one'
@@ -136,11 +135,10 @@ class Editor extends React.Component {
// If we've resolved a few times already, and it's exactly in line with
// the updates, then warn the user that they may be doing something wrong.
if (resolves > 5 && resolves === updates) {
logger.warn(
warning(
resolves < 5 || resolves !== updates,
'A Slate <Editor> component is re-resolving `props.plugins` or `props.schema` on each update, which leads to poor performance. This is often due to passing in a new `schema` or `plugins` prop with each render by declaring them inline in your render function. Do not do this!'
)
}
if (change) {
this.onChange(change)
@@ -155,16 +153,7 @@ class Editor extends React.Component {
render() {
debug('render', this)
const children = this.stack
.map('renderPortal', this.value, this)
.map((child, i) => (
<Portal key={i} isOpened>
{child}
</Portal>
))
const props = { ...this.props, children }
const props = { ...this.props }
const tree = this.stack.render('renderEditor', props, this)
return tree
}
@@ -231,7 +220,8 @@ class Editor extends React.Component {
change = (...args) => {
if (this.tmp.isChanging) {
logger.warn(
warning(
false,
"The `editor.change` method was called from within an existing `editor.change` callback. This is not allowed, and often due to calling `editor.change` directly from a plugin's event handler which is unnecessary."
)

View File

@@ -143,13 +143,13 @@ class Leaf extends React.Component {
text === '' &&
parent.object === 'block' &&
parent.text === '' &&
parent.nodes.size === 1
parent.nodes.last() === node
) {
return <span data-slate-zero-width="n">{'\u200B'}</span>
}
// COMPAT: If the text is empty, it's because it's on the edge of an inline
// void node, so we render a zero-width space so that the selection can be
// node, so we render a zero-width space so that the selection can be
// inserted next to it still.
if (text === '') {
return <span data-slate-zero-width="z">{'\u200B'}</span>

View File

@@ -2,7 +2,7 @@ import Debug from 'debug'
import ImmutableTypes from 'react-immutable-proptypes'
import React from 'react'
import SlateTypes from 'slate-prop-types'
import logger from 'slate-dev-logger'
import warning from 'slate-dev-warning'
import Types from 'prop-types'
import Void from './void'
@@ -81,12 +81,11 @@ class Node extends React.Component {
return true
}
if (shouldUpdate === false) {
logger.warn(
warning(
shouldUpdate !== false,
"Returning false in `shouldNodeComponentUpdate` does not disable Slate's internal `shouldComponentUpdate` logic. If you want to prevent updates, use React's `shouldComponentUpdate` instead."
)
}
}
// If the `readOnly` status has changed, re-render in case there is any
// user-land logic that depends on it, like nested editable contents.

View File

@@ -64,7 +64,7 @@ function AfterPlugin() {
event.preventDefault()
const { value } = change
const { selection } = value
const { document, selection, schema } = value
const range = findRange(targetRange, value)
switch (event.inputType) {
@@ -101,7 +101,12 @@ function AfterPlugin() {
case 'insertLineBreak':
case 'insertParagraph': {
if (change.value.isInVoid) {
const hasVoidParent = document.hasVoidParent(
selection.start.path,
schema
)
if (hasVoidParent) {
change.moveToStartOfNextText()
} else {
change.splitBlockAtRange(range)
@@ -450,13 +455,14 @@ function AfterPlugin() {
debug('onKeyDown', { event })
const { value } = change
const { schema } = value
const { document, selection, schema } = value
const hasVoidParent = document.hasVoidParent(selection.start.path, schema)
// COMPAT: In iOS, some of these hotkeys are handled in the
// `onNativeBeforeInput` handler of the `<Content>` component in order to
// preserve native autocorrect behavior, so they shouldn't be handled here.
if (Hotkeys.isSplitBlock(event) && !IS_IOS) {
return value.isInVoid
return hasVoidParent
? change.moveToStartOfNextText()
: change.splitBlock()
}
@@ -520,44 +526,44 @@ function AfterPlugin() {
// an inline is selected, we need to handle these hotkeys manually because
// browsers won't know what to do.
if (Hotkeys.isMoveBackward(event)) {
const { document, isInVoid, previousText, startText } = value
const { previousText, startText } = value
const isPreviousInVoid =
previousText && document.hasVoidParent(previousText.key, schema)
if (isInVoid || isPreviousInVoid || startText.text == '') {
if (hasVoidParent || isPreviousInVoid || startText.text == '') {
event.preventDefault()
return change.moveBackward()
}
}
if (Hotkeys.isMoveForward(event)) {
const { document, isInVoid, nextText, startText } = value
const { nextText, startText } = value
const isNextInVoid =
nextText && document.hasVoidParent(nextText.key, schema)
if (isInVoid || isNextInVoid || startText.text == '') {
if (hasVoidParent || isNextInVoid || startText.text == '') {
event.preventDefault()
return change.moveForward()
}
}
if (Hotkeys.isExtendBackward(event)) {
const { document, isInVoid, previousText, startText } = value
const { previousText, startText } = value
const isPreviousInVoid =
previousText && document.hasVoidParent(previousText.key, schema)
if (isInVoid || isPreviousInVoid || startText.text == '') {
if (hasVoidParent || isPreviousInVoid || startText.text == '') {
event.preventDefault()
return change.moveFocusBackward()
}
}
if (Hotkeys.isExtendForward(event)) {
const { document, isInVoid, nextText, startText } = value
const { nextText, startText } = value
const isNextInVoid =
nextText && document.hasVoidParent(nextText.key, schema)
if (isInVoid || isNextInVoid || startText.text == '') {
if (hasVoidParent || isNextInVoid || startText.text == '') {
event.preventDefault()
return change.moveFocusForward()
}
@@ -686,13 +692,11 @@ function AfterPlugin() {
function renderEditor(props, editor) {
const { handlers } = editor
return (
<Content
{...handlers}
autoCorrect={props.autoCorrect}
className={props.className}
children={props.children}
editor={editor}
readOnly={props.readOnly}
role={props.role}

View File

@@ -12,19 +12,13 @@ const h = createHyperscript({
paragraph: 'paragraph',
quote: 'quote',
code: 'code',
image: {
type: 'image',
isVoid: true,
},
image: 'image',
},
inlines: {
link: 'link',
hashtag: 'hashtag',
comment: 'comment',
emoji: {
type: 'emoji',
isVoid: true,
},
emoji: 'emoji',
},
marks: {
b: 'bold',

View File

@@ -0,0 +1,16 @@
import { Schema } from 'slate'
const schema = Schema.create({
blocks: {
image: {
isVoid: true,
},
},
inlines: {
emoji: {
isVoid: true,
},
},
})
export default schema

Some files were not shown because too many files have changed in this diff Show More