mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-29 18:09:49 +02:00
Remove instanceOf checks to allow Slate objects to be identifiable across module instances (#930)
* putting in the correct type pseudo-symbols * getting the pseudo symbols everywhere that the instance of's are * Making Ian's suggestions on checking types with static methods * cleaning up leftover hard checks * adding in slate proptypes, cleaning up unneeded whitespace * updating documentation, moving keys to prototypes finally, al tests passing * organizing types, prop-types, more succint type names * eslint fix * fixing model-types bug, changing proptype names
This commit is contained in:
committed by
Ian Storm Taylor
parent
469d8b394c
commit
3eb72a8642
@@ -22,6 +22,7 @@ Block nodes may contain nested block nodes, inline nodes, and text nodes—just
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Block.create`](#blockcreate)
|
||||
- [`Block.createList`](#blockcreatelist)
|
||||
- [`Block.isBlock`](#blockisblock)
|
||||
- [Node Methods](#node-methods)
|
||||
|
||||
|
||||
@@ -95,6 +96,10 @@ Create a block from a plain Javascript object of `properties`.
|
||||
|
||||
Create a list of block nodes from a plain Javascript `array`.
|
||||
|
||||
### `Block.isBlock`
|
||||
`Block.isBlock(maybeBlock: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Block`.
|
||||
|
||||
## Node Methods
|
||||
|
||||
|
@@ -15,6 +15,7 @@ Characters are how Slate associates [`Marks`](./mark.md) with a range of text, f
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Character.create`](#charactercreate)
|
||||
- [`Character.createList`](#charactercreatelist)
|
||||
- [`Character.isCharacter`](#characterischaracter)
|
||||
|
||||
|
||||
## Properties
|
||||
@@ -48,3 +49,8 @@ Create a character from a plain Javascript object of `properties`.
|
||||
`Character.createList(array: Array) => List`
|
||||
|
||||
Create a list of characters from a plain Javascript `array`.
|
||||
|
||||
### `Character.isCharacter`
|
||||
`Character.isCharacter(maybeCharacter: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Character`.
|
||||
|
@@ -20,6 +20,7 @@ In some places, you'll see mention of "fragments", which are also `Document` obj
|
||||
- [`text`](#text)
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Document.create`](#documentcreate)
|
||||
- [`Document.isDocument`](#documentisdocument)
|
||||
- [Node Methods](#node-methods)
|
||||
|
||||
|
||||
@@ -67,6 +68,11 @@ A concatenated string of all of the descendant [`Text`](./text.md) nodes of this
|
||||
|
||||
Create a block from a plain Javascript object of `properties`.
|
||||
|
||||
### `Document.isDocument`
|
||||
`Document.isDocument(maybeDocument: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Document`.
|
||||
|
||||
|
||||
## Node Methods
|
||||
|
||||
|
@@ -22,6 +22,7 @@ Inline nodes may contain nested inline nodes and text nodes—just like in the D
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Inline.create`](#inlinecreate)
|
||||
- [`Inline.createList`](#inlinecreatelist)
|
||||
- [`Inline.isInline`](#inlineisinline)
|
||||
- [Node Methods](#node-methods)
|
||||
|
||||
|
||||
@@ -95,6 +96,11 @@ Create a block from a plain Javascript object of `properties`.
|
||||
|
||||
Create a list of inline nodes from a plain Javascript `array`.
|
||||
|
||||
### `Inline.isInline`
|
||||
`Inline.isInline(maybeInline: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Inline`.
|
||||
|
||||
|
||||
## Node Methods
|
||||
|
||||
|
@@ -13,6 +13,7 @@ A formatting mark that can be associated with [`Characters`](./character.md). Ma
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Mark.create`](#markcreate)
|
||||
- [`Mark.createSet`](#markcreateset)
|
||||
- [`Mark.isMark`](#markismark)
|
||||
|
||||
|
||||
## Properties
|
||||
@@ -46,3 +47,8 @@ Create a mark from a plain Javascript object of `properties`.
|
||||
`Mark.createSet(array: Array) => Set`
|
||||
|
||||
Create a set of marks from a plain Javascript `array`.
|
||||
|
||||
### `Mark.isMark`
|
||||
`Mark.isMark(maybeMark: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Mark`.
|
||||
|
@@ -13,6 +13,8 @@ Every Slate editor has a "schema" associated with it, which contains information
|
||||
- [`normalize`](#normalize)
|
||||
- [`render`](#render)
|
||||
- [`validate`](#validate)
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Schema.isSchema`](#schemaisschema)
|
||||
|
||||
|
||||
## Properties
|
||||
@@ -177,3 +179,10 @@ The `render` property determines which React component Slate will use to render
|
||||
```
|
||||
|
||||
The `validate` property allows you to define a constraint that the matching object must abide by. It should return either `Void` if the object is valid, or any non-void value if it is invalid. This makes it easy to return the exact reason that the object is invalid, which makes it simple to recover from the invalid state with the `normalize` property.
|
||||
|
||||
## Static Methods
|
||||
|
||||
### `Schema.isSchema`
|
||||
`Schema.isSchema(maybeSchema: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Schema`.
|
||||
|
@@ -20,7 +20,7 @@ Often times, you don't need to specifically know which point is the "anchor" and
|
||||
- [`isFocused`](#isfocused)
|
||||
- [Computed Properties](#computed-properties)
|
||||
- [`endKey`](#endkey)
|
||||
- [`endOffset`](#endoffset)
|
||||
- [`endOffset`](#endoffset)
|
||||
- [`isBlurred`](#isblurred)
|
||||
- [`isCollapsed`](#iscollapsed)
|
||||
- [`isExpanded`](#isExpanded)
|
||||
@@ -28,7 +28,8 @@ Often times, you don't need to specifically know which point is the "anchor" and
|
||||
- [`startKey`](#startkey)
|
||||
- [`startOffset`](#startoffset)
|
||||
- [Static Methods](#static-methods)
|
||||
- [`Selection.create`](#selectioncreate)
|
||||
- [`Selection.create`](#selectioncreate)
|
||||
- [`Selection.isSelection`](#selectionisselection)
|
||||
- [Checking Methods](#checking-methods)
|
||||
- [`has{Edge}AtEndOf`](#hasedgeatendof)
|
||||
- [`has{Edge}AtStartOf`](#hasedgeatstartof)
|
||||
@@ -121,6 +122,11 @@ A few convenience properties for accessing the first and last point of the selec
|
||||
|
||||
Create a new `Selection` instance with `properties`.
|
||||
|
||||
### `Selection.isSelection`
|
||||
`Selection.isSelection(maybeSelection: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Selection`.
|
||||
|
||||
|
||||
## Checking Methods
|
||||
|
||||
@@ -129,27 +135,27 @@ Create a new `Selection` instance with `properties`.
|
||||
|
||||
Determine whether a selection 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`
|
||||
`has{Edge}AtEndOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether a selection 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`
|
||||
`has{Edge}Between(node: Node, start: Number, end: Number) => Boolean`
|
||||
|
||||
Determine whether a selection 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`
|
||||
`has{Edge}In(node: Node) => Boolean`
|
||||
|
||||
Determine whether a selection has an edge inside a `node`. Where `{Edge}` can be one of: `Anchor`, `Focus`, `Start`, `End` or `Edge` (referring to either point).
|
||||
|
||||
### `isAtStartOf`
|
||||
### `isAtStartOf`
|
||||
`isAtStartOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether the selection is at the start of a `node`.
|
||||
|
||||
### `isAtEndOf`
|
||||
### `isAtEndOf`
|
||||
`isAtEndOf(node: Node) => Boolean`
|
||||
|
||||
Determine whether the selection is at the end of a `node`.
|
||||
|
@@ -36,6 +36,7 @@ For convenience, in addition to transforms, many of the [`Selection`](./selectio
|
||||
- [`isEmpty`](#isEmpty)
|
||||
- [Static Methods](#static-methods)
|
||||
- [`State.create`](#statecreate)
|
||||
- [`State.isState`](#stateisstate)
|
||||
- [Methods](#methods)
|
||||
- [`transform`](#transform)
|
||||
|
||||
@@ -166,6 +167,11 @@ Whether the current selection is empty.
|
||||
|
||||
Create a new `State` instance with `properties`.
|
||||
|
||||
### `State.isState`
|
||||
`State.isState(maybeState: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `State`.
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
|
@@ -18,6 +18,7 @@ A text node in a Slate [`Document`](./document.md). Text nodes are always the bo
|
||||
- [`Text.create`](#textcreate)
|
||||
- [`Text.createFromString`](#textcreatefromstring)
|
||||
- [`Text.createFromRanges`](#textcreatefromranges)
|
||||
- [`Text.isText`](#textistext)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -72,3 +73,8 @@ Create a text from a list of text ranges.
|
||||
`Text.createFromString(text: String, marks: Set) => Text`
|
||||
|
||||
Create a text from a plain `String` and a set of marks.
|
||||
|
||||
### `Text.isText`
|
||||
`Text.isText(maybeText: Any) => Boolean`
|
||||
|
||||
Returns a boolean if the passed in argument is a `Text`.
|
||||
|
@@ -5,7 +5,7 @@ import Types from 'prop-types'
|
||||
import getWindow from 'get-window'
|
||||
import keycode from 'keycode'
|
||||
|
||||
import TYPES from '../constants/types'
|
||||
import TRANSFER_TYPES from '../constants/transfer-types'
|
||||
import Base64 from '../serializers/base-64'
|
||||
import Node from './node'
|
||||
import Selection from '../models/selection'
|
||||
@@ -476,7 +476,7 @@ class Content extends React.Component {
|
||||
const { fragment } = state
|
||||
const encoded = Base64.serializeNode(fragment)
|
||||
|
||||
setTransferData(dataTransfer, TYPES.FRAGMENT, encoded)
|
||||
setTransferData(dataTransfer, TRANSFER_TYPES.FRAGMENT, encoded)
|
||||
|
||||
debug('onDragStart', { event })
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import React from 'react'
|
||||
import Types from 'prop-types'
|
||||
|
||||
import Stack from '../models/stack'
|
||||
import State from '../models/state'
|
||||
import SlatePropTypes from '../utils/prop-types'
|
||||
import noop from '../utils/noop'
|
||||
|
||||
/**
|
||||
@@ -79,7 +79,7 @@ class Editor extends React.Component {
|
||||
role: Types.string,
|
||||
schema: Types.object,
|
||||
spellCheck: Types.bool,
|
||||
state: Types.instanceOf(State).isRequired,
|
||||
state: SlatePropTypes.state.isRequired,
|
||||
style: Types.object,
|
||||
tabIndex: Types.number,
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import Types from 'prop-types'
|
||||
|
||||
import TYPES from '../constants/types'
|
||||
import TRANSFER_TYPES from '../constants/transfer-types'
|
||||
import Base64 from '../serializers/base-64'
|
||||
import Leaf from './leaf'
|
||||
import Void from './void'
|
||||
@@ -221,7 +221,7 @@ class Node extends React.Component {
|
||||
const encoded = Base64.serializeNode(node, { preserveKeys: true })
|
||||
const { dataTransfer } = e.nativeEvent
|
||||
|
||||
setTransferData(dataTransfer, TYPES.NODE, encoded)
|
||||
setTransferData(dataTransfer, TRANSFER_TYPES.NODE, encoded)
|
||||
|
||||
this.debug('onDragStart', e)
|
||||
}
|
||||
|
26
src/constants/model-types.js
Normal file
26
src/constants/model-types.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Slate-specific item types.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
const MODEL_TYPES = {
|
||||
STATE: '@@__SLATE_STATE__@@',
|
||||
DOCUMENT: '@@__SLATE_DOCUMENT__@@',
|
||||
BLOCK: '@@__SLATE_BLOCK__@@',
|
||||
INLINE: '@@__SLATE_INLINE__@@',
|
||||
TEXT: '@@__SLATE_TEXT__@@',
|
||||
CHARACTER: '@@__SLATE_CHARACTER__@@',
|
||||
MARK: '@@__SLATE_MARK__@@',
|
||||
RANGE: '@@__SLATE_RANGE__@@',
|
||||
SELECTION: '@@__SLATE_SELECTION__@@',
|
||||
SCHEMA: '@@__SLATE_SCHEMA__@@',
|
||||
}
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
export default MODEL_TYPES
|
@@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Slate-specific data transfer types.
|
||||
*
|
@@ -4,16 +4,16 @@
|
||||
*/
|
||||
|
||||
import './document'
|
||||
import './inline'
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
*/
|
||||
|
||||
import Data from './data'
|
||||
import Inline from './inline'
|
||||
import Node from './node'
|
||||
import Inline from './inline'
|
||||
import Text from './text'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import generateKey from '../utils/generate-key'
|
||||
import { Map, List, Record } from 'immutable'
|
||||
|
||||
@@ -47,9 +47,9 @@ class Block extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Block) return properties
|
||||
if (properties instanceof Inline) return properties
|
||||
if (properties instanceof Text) return properties
|
||||
if (Block.isBlock(properties)) return properties
|
||||
if (Inline.isInline(properties)) return properties
|
||||
if (Text.isText(properties)) return properties
|
||||
if (!properties.type) throw new Error('You must pass a block `type`.')
|
||||
|
||||
properties.key = properties.key || generateKey()
|
||||
@@ -76,6 +76,17 @@ class Block extends new Record(DEFAULTS) {
|
||||
return new List(elements.map(Block.create))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Block or not
|
||||
*
|
||||
* @param {*} maybeBlock
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isBlock(maybeBlock) {
|
||||
return !!(maybeBlock && maybeBlock[MODEL_TYPES.BLOCK])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the node's kind.
|
||||
*
|
||||
@@ -118,6 +129,12 @@ class Block extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Block
|
||||
*/
|
||||
|
||||
Block.prototype[MODEL_TYPES.BLOCK] = true
|
||||
|
||||
/**
|
||||
* Mix in `Node` methods.
|
||||
*/
|
||||
@@ -126,7 +143,6 @@ for (const method in Node) {
|
||||
Block.prototype[method] = Node[method]
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
|
@@ -1,5 +1,6 @@
|
||||
|
||||
import Mark from './mark'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import { List, Record, Set } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -29,7 +30,7 @@ class Character extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Character) return properties
|
||||
if (Character.isCharacter(properties)) return properties
|
||||
properties.marks = Mark.createSet(properties.marks)
|
||||
return new Character(properties)
|
||||
}
|
||||
@@ -60,6 +61,17 @@ class Character extends new Record(DEFAULTS) {
|
||||
return list
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Character or not
|
||||
*
|
||||
* @param {*} maybeCharacter
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isCharacter(maybeCharacter) {
|
||||
return !!(maybeCharacter && maybeCharacter[MODEL_TYPES.CHARACTER])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind.
|
||||
*
|
||||
@@ -72,6 +84,12 @@ class Character extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Character
|
||||
*/
|
||||
|
||||
Character.prototype[MODEL_TYPES.CHARACTER] = true
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
|
@@ -13,6 +13,7 @@ import './inline'
|
||||
import Data from './data'
|
||||
import Block from './block'
|
||||
import Node from './node'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import generateKey from '../utils/generate-key'
|
||||
import { List, Map, Record } from 'immutable'
|
||||
|
||||
@@ -44,7 +45,7 @@ class Document extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Document) return properties
|
||||
if (Document.isDocument(properties)) return properties
|
||||
|
||||
properties.key = properties.key || generateKey()
|
||||
properties.data = Data.create(properties.data)
|
||||
@@ -53,6 +54,17 @@ class Document extends new Record(DEFAULTS) {
|
||||
return new Document(properties)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Document or not
|
||||
*
|
||||
* @param {*} maybeDocument
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isDocument(maybeDocument) {
|
||||
return !!(maybeDocument && maybeDocument[MODEL_TYPES.DOCUMENT])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the node's kind.
|
||||
*
|
||||
@@ -95,6 +107,12 @@ class Document extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Document
|
||||
*/
|
||||
|
||||
Document.prototype[MODEL_TYPES.DOCUMENT] = true
|
||||
|
||||
/**
|
||||
* Mix in `Node` methods.
|
||||
*/
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Prevent circular dependencies.
|
||||
*/
|
||||
|
||||
import './block'
|
||||
import './document'
|
||||
|
||||
/**
|
||||
@@ -14,6 +13,7 @@ import Block from './block'
|
||||
import Data from './data'
|
||||
import Node from './node'
|
||||
import Text from './text'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import generateKey from '../utils/generate-key'
|
||||
import { List, Map, Record } from 'immutable'
|
||||
|
||||
@@ -47,9 +47,9 @@ class Inline extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Block) return properties
|
||||
if (properties instanceof Inline) return properties
|
||||
if (properties instanceof Text) return properties
|
||||
if (Block.isBlock(properties)) return properties
|
||||
if (Inline.isInline(properties)) return properties
|
||||
if (Text.isText(properties)) return properties
|
||||
if (!properties.type) throw new Error('You must pass an inline `type`.')
|
||||
|
||||
properties.key = properties.key || generateKey()
|
||||
@@ -76,6 +76,17 @@ class Inline extends new Record(DEFAULTS) {
|
||||
return new List(elements.map(Inline.create))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Inline or not
|
||||
*
|
||||
* @param {*} maybeInline
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isInline(maybeInline) {
|
||||
return !!(maybeInline && maybeInline[MODEL_TYPES.INLINE])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the node's kind.
|
||||
*
|
||||
@@ -118,6 +129,12 @@ class Inline extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Inline
|
||||
*/
|
||||
|
||||
Inline.prototype[MODEL_TYPES.INLINE] = true
|
||||
|
||||
/**
|
||||
* Mix in `Node` methods.
|
||||
*/
|
||||
|
@@ -1,6 +1,7 @@
|
||||
|
||||
import Data from './data'
|
||||
import memoize from '../utils/memoize'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import { Map, Record, Set } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ class Mark extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Mark) return properties
|
||||
if (Mark.isMark(properties)) return properties
|
||||
if (!properties.type) throw new Error('You must provide a `type` for the mark.')
|
||||
properties.data = Data.create(properties.data)
|
||||
return new Mark(properties)
|
||||
@@ -49,9 +50,18 @@ class Mark extends new Record(DEFAULTS) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind.
|
||||
* Determines if the passed in paramter is a Slate Mark or not
|
||||
*
|
||||
* @return {String}
|
||||
* @param {*} maybeMark
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isMark(maybeMark) {
|
||||
return !!(maybeMark && maybeMark[MODEL_TYPES.MARK])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind.
|
||||
*/
|
||||
|
||||
get kind() {
|
||||
@@ -71,6 +81,12 @@ class Mark extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Mark
|
||||
*/
|
||||
|
||||
Mark.prototype[MODEL_TYPES.MARK] = true
|
||||
|
||||
/**
|
||||
* Memoize read methods.
|
||||
*/
|
||||
|
@@ -1,6 +1,7 @@
|
||||
|
||||
import Character from './character'
|
||||
import Mark from './mark'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import { Record, Set } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -30,12 +31,23 @@ class Range extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Range) return properties
|
||||
if (Range.isRange(properties)) return properties
|
||||
properties.text = properties.text
|
||||
properties.marks = Mark.createSet(properties.marks)
|
||||
return new Range(properties)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Range or not
|
||||
*
|
||||
* @param {*} maybeRange
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isRange(maybeRange) {
|
||||
return !!(maybeRange && maybeRange[MODEL_TYPES.RANGE])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the node's kind.
|
||||
*
|
||||
@@ -67,6 +79,12 @@ class Range extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Range
|
||||
*/
|
||||
|
||||
Range.prototype[MODEL_TYPES.RANGE] = true
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import React from 'react'
|
||||
import isReactComponent from '../utils/is-react-component'
|
||||
import typeOf from 'type-of'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import { Record } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -30,10 +31,21 @@ class Schema extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Schema) return properties
|
||||
if (Schema.isSchema(properties)) return properties
|
||||
return new Schema(normalizeProperties(properties))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Schema or not
|
||||
*
|
||||
* @param {*} maybeSchema
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isSchema(maybeSchema) {
|
||||
return !!(maybeSchema && maybeSchema[MODEL_TYPES.SCHEMA])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind.
|
||||
*
|
||||
@@ -235,6 +247,12 @@ function normalizeMarkComponent(render) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Schema
|
||||
*/
|
||||
|
||||
Schema.prototype[MODEL_TYPES.SCHEMA] = true
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
|
@@ -1,5 +1,6 @@
|
||||
|
||||
import warn from '../utils/warn'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import { Record } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -34,10 +35,21 @@ class Selection extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Selection) return properties
|
||||
if (Selection.isSelection(properties)) return properties
|
||||
return new Selection(properties)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Selection or not
|
||||
*
|
||||
* @param {*} maybeSelection
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isSelection(maybeSelection) {
|
||||
return !!(maybeSelection && maybeSelection[MODEL_TYPES.SELECTION])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind.
|
||||
*
|
||||
@@ -737,6 +749,12 @@ class Selection extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate Selection
|
||||
*/
|
||||
|
||||
Selection.prototype[MODEL_TYPES.SELECTION] = true
|
||||
|
||||
/**
|
||||
* Mix in some "move" convenience methods.
|
||||
*/
|
||||
|
@@ -196,7 +196,7 @@ for (const method of STATE_ACCUMULATOR_METHODS) {
|
||||
*/
|
||||
|
||||
function assertState(value) {
|
||||
if (value instanceof State) return
|
||||
if (State.isState(value)) return
|
||||
throw new Error(`A plugin returned an unexpected state value: ${value}`)
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ import Document from './document'
|
||||
import SCHEMA from '../schemas/core'
|
||||
import Selection from './selection'
|
||||
import Transform from './transform'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import { Record, Set, Stack, List, Map } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -49,7 +50,7 @@ class State extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}, options = {}) {
|
||||
if (properties instanceof State) return properties
|
||||
if (State.isState(properties)) return properties
|
||||
|
||||
const document = Document.create(properties.document)
|
||||
let selection = Selection.create(properties.selection)
|
||||
@@ -77,6 +78,17 @@ class State extends new Record(DEFAULTS) {
|
||||
: state.transform().normalize(SCHEMA).apply({ save: false })
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate State or not
|
||||
*
|
||||
* @param {*} maybeState
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isState(maybeState) {
|
||||
return !!(maybeState && maybeState[MODEL_TYPES.STATE])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind.
|
||||
*
|
||||
@@ -474,6 +486,12 @@ class State extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseduo-symbol that shows this is a Slate State
|
||||
*/
|
||||
|
||||
State.prototype[MODEL_TYPES.STATE] = true
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*/
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import Character from './character'
|
||||
import Mark from './mark'
|
||||
import Range from './range'
|
||||
import MODEL_TYPES from '../constants/model-types'
|
||||
import memoize from '../utils/memoize'
|
||||
import generateKey from '../utils/generate-key'
|
||||
import { List, Record, OrderedSet, Set, is } from 'immutable'
|
||||
@@ -33,7 +34,7 @@ class Text extends new Record(DEFAULTS) {
|
||||
*/
|
||||
|
||||
static create(properties = {}) {
|
||||
if (properties instanceof Text) return properties
|
||||
if (Text.isText(properties)) return properties
|
||||
properties.key = properties.key || generateKey()
|
||||
properties.characters = Character.createList(properties.characters)
|
||||
return new Text(properties)
|
||||
@@ -81,6 +82,17 @@ class Text extends new Record(DEFAULTS) {
|
||||
return new List(elements.map(Text.create))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in paramter is a Slate Text or not
|
||||
*
|
||||
* @param {*} maybeText
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
static isText(maybeText) {
|
||||
return !!(maybeText && maybeText[MODEL_TYPES.TEXT])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the node's kind.
|
||||
*
|
||||
@@ -402,6 +414,12 @@ class Text extends new Record(DEFAULTS) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseudo-symbol that shows this is a Slate Text
|
||||
*/
|
||||
|
||||
Text.prototype[MODEL_TYPES.TEXT] = true
|
||||
|
||||
/**
|
||||
* Memoize read methods.
|
||||
*/
|
||||
|
@@ -225,7 +225,7 @@ function normalizeNode(transform, node, schema) {
|
||||
*/
|
||||
|
||||
function assertSchema(schema) {
|
||||
if (schema instanceof Schema) {
|
||||
if (Schema.isSchema(schema)) {
|
||||
return
|
||||
} else if (schema == null) {
|
||||
throw new Error('You must pass a `schema` object.')
|
||||
|
@@ -1,6 +1,6 @@
|
||||
|
||||
import Base64 from '../serializers/base-64'
|
||||
import TYPES from '../constants/types'
|
||||
import TRANSFER_TYPES from '../constants/transfer-types'
|
||||
|
||||
/**
|
||||
* Fragment matching regexp for HTML nodes.
|
||||
@@ -18,8 +18,8 @@ const FRAGMENT_MATCHER = / data-slate-fragment="([^\s]+)"/
|
||||
*/
|
||||
|
||||
function getTransferData(transfer) {
|
||||
let fragment = getType(transfer, TYPES.FRAGMENT)
|
||||
let node = getType(transfer, TYPES.NODE)
|
||||
let fragment = getType(transfer, TRANSFER_TYPES.FRAGMENT)
|
||||
let node = getType(transfer, TRANSFER_TYPES.NODE)
|
||||
const html = getType(transfer, 'text/html')
|
||||
const rich = getType(transfer, 'text/rtf')
|
||||
let text = getType(transfer, 'text/plain')
|
||||
@@ -42,8 +42,8 @@ function getTransferData(transfer) {
|
||||
if (text) {
|
||||
const embeddedTypes = getEmbeddedTypes(text)
|
||||
|
||||
if (embeddedTypes[TYPES.FRAGMENT]) fragment = embeddedTypes[TYPES.FRAGMENT]
|
||||
if (embeddedTypes[TYPES.NODE]) node = embeddedTypes[TYPES.NODE]
|
||||
if (embeddedTypes[TRANSFER_TYPES.FRAGMENT]) fragment = embeddedTypes[TRANSFER_TYPES.FRAGMENT]
|
||||
if (embeddedTypes[TRANSFER_TYPES.NODE]) node = embeddedTypes[TRANSFER_TYPES.NODE]
|
||||
if (embeddedTypes['text/plain']) text = embeddedTypes['text/plain']
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,7 @@ import typeOf from 'type-of'
|
||||
*/
|
||||
|
||||
function block(value) {
|
||||
if (value instanceof Block) return value
|
||||
if (Block.isBlock(value)) return value
|
||||
|
||||
switch (typeOf(value)) {
|
||||
case 'string':
|
||||
@@ -37,7 +37,7 @@ function block(value) {
|
||||
*/
|
||||
|
||||
function inline(value) {
|
||||
if (value instanceof Inline) return value
|
||||
if (Inline.isInline(value)) return value
|
||||
|
||||
switch (typeOf(value)) {
|
||||
case 'string':
|
||||
@@ -60,10 +60,10 @@ function key(value) {
|
||||
if (typeOf(value) == 'string') return value
|
||||
|
||||
warn('An object was passed to a Node method instead of a `key` string. This was previously supported, but is being deprecated because it can have a negative impact on performance. The object in question was:', value)
|
||||
if (value instanceof Block) return value.key
|
||||
if (value instanceof Document) return value.key
|
||||
if (value instanceof Inline) return value.key
|
||||
if (value instanceof Text) return value.key
|
||||
if (Block.isBlock(value)) return value.key
|
||||
if (Document.isDocument(value)) return value.key
|
||||
if (Inline.isInline(value)) return value.key
|
||||
if (Text.isText(value)) return value.key
|
||||
|
||||
throw new Error(`Invalid \`key\` argument! It must be either a block, an inline, a text, or a string. You passed: "${value}".`)
|
||||
}
|
||||
@@ -76,7 +76,7 @@ function key(value) {
|
||||
*/
|
||||
|
||||
function mark(value) {
|
||||
if (value instanceof Mark) return value
|
||||
if (Mark.isMark(value)) return value
|
||||
|
||||
switch (typeOf(value)) {
|
||||
case 'string':
|
||||
@@ -161,7 +161,7 @@ function nodeProperties(value = {}) {
|
||||
*/
|
||||
|
||||
function selection(value) {
|
||||
if (value instanceof Selection) return value
|
||||
if (Selection.isSelection(value)) return value
|
||||
|
||||
switch (typeOf(value)) {
|
||||
case 'object':
|
||||
|
172
src/utils/prop-types.js
Normal file
172
src/utils/prop-types.js
Normal file
@@ -0,0 +1,172 @@
|
||||
import Block from '../models/block'
|
||||
import Character from '../models/character'
|
||||
import Document from '../models/document'
|
||||
import Inline from '../models/inline'
|
||||
import Mark from '../models/mark'
|
||||
import Range from '../models/range'
|
||||
import Schema from '../models/schema'
|
||||
import Selection from '../models/selection'
|
||||
import State from '../models/state'
|
||||
import Text from '../models/text'
|
||||
|
||||
/**
|
||||
* HOC Function that takes in a predicate prop type function, and allows an isRequired chain
|
||||
*
|
||||
* @param {Function} predicate
|
||||
* @return {Function}
|
||||
*/
|
||||
|
||||
function createChainablePropType(predicate) {
|
||||
function propType(props, propName, componentName) {
|
||||
if (props[propName] == null) return
|
||||
|
||||
return predicate(props, propName, componentName)
|
||||
}
|
||||
|
||||
propType.isRequired = (props, propName, componentName) => {
|
||||
if (props[propName] == null) return new Error(`Required prop \`${propName}\` was not specified in \`${componentName}\`.`)
|
||||
|
||||
return predicate(props, propName, componentName)
|
||||
}
|
||||
|
||||
return propType
|
||||
}
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Block
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const block = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Block.isBlock(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Block`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Character
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const character = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Character.isCharacter(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Character`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Document
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const document = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Document.isDocument(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Document`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Inline
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const inline = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Inline.isInline(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Inline`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Mark
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const mark = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Mark.isMark(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Mark`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Range
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const range = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Range.isRange(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Range`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Schema
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const schema = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Schema.isSchema(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Schema`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Selection
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const selection = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Selection.isSelection(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Selection`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate State
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const state = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !State.isState(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate State ${props[propName]}`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptype that checks if a prop is a Slate Text
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
const text = createChainablePropType(
|
||||
(props, propName, componentName) => {
|
||||
return !Text.isText(props[propName]) ? new Error(`${propName} in ${componentName} is not a Slate Text`) : null
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Exported Slate proptypes
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
export default {
|
||||
block,
|
||||
character,
|
||||
document,
|
||||
inline,
|
||||
mark,
|
||||
range,
|
||||
schema,
|
||||
selection,
|
||||
state,
|
||||
text,
|
||||
}
|
Reference in New Issue
Block a user