1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-02-01 05:16:10 +01:00

cleanup object type checking and interface

This commit is contained in:
Ian Storm Taylor 2018-09-27 16:36:37 -07:00
parent aba8f19d0e
commit e7ab7f8279
23 changed files with 163 additions and 512 deletions

View File

@ -1,44 +0,0 @@
/**
* Slate-specific model types.
*
* @type {Object}
*/
const MODEL_TYPES = {
BLOCK: '@@__SLATE_BLOCK__@@',
CHANGE: '@@__SLATE_CHANGE__@@',
DECORATION: '@@__SLATE_DECORATION__@@',
DOCUMENT: '@@__SLATE_DOCUMENT__@@',
HISTORY: '@@__SLATE_HISTORY__@@',
INLINE: '@@__SLATE_INLINE__@@',
LEAF: '@@__SLATE_LEAF__@@',
MARK: '@@__SLATE_MARK__@@',
OPERATION: '@@__SLATE_OPERATION__@@',
POINT: '@@__SLATE_POINT__@@',
RANGE: '@@__SLATE_RANGE__@@',
SCHEMA: '@@__SLATE_SCHEMA__@@',
SELECTION: '@@__SLATE_SELECTION__@@',
STACK: '@@__SLATE_STACK__@@',
TEXT: '@@__SLATE_TEXT__@@',
VALUE: '@@__SLATE_VALUE__@@',
}
/**
* Export type identification function
*
* @param {string} type
* @param {any} any
* @return {boolean}
*/
export function isType(type, any) {
return !!(any && any[MODEL_TYPES[type]])
}
/**
* Export.
*
* @type {Object}
*/
export default MODEL_TYPES

View File

@ -1,6 +1,7 @@
import './interfaces/common'
import './interfaces/element'
import './interfaces/object'
import './interfaces/model'
import './interfaces/node'
import './interfaces/element'
import './interfaces/range'
import Block from './models/block'

View File

@ -23,7 +23,7 @@ import Value from '../models/value'
* @type {Class}
*/
class CommonInterface {
class ModelInterface {
/**
* Alias `fromJS`.
*/
@ -47,7 +47,7 @@ class CommonInterface {
* @param {Record}
*/
mixin(CommonInterface, [
mixin(ModelInterface, [
Block,
Change,
Decoration,

View File

@ -0,0 +1,71 @@
import Block from '../models/block'
import Change from '../models/change'
import Decoration from '../models/decoration'
import Document from '../models/document'
import History from '../models/history'
import Inline from '../models/inline'
import Leaf from '../models/leaf'
import Mark from '../models/mark'
import Node from '../models/node'
import Operation from '../models/operation'
import Point from '../models/point'
import Range from '../models/range'
import Schema from '../models/schema'
import Selection from '../models/selection'
import Stack from '../models/stack'
import Text from '../models/text'
import Value from '../models/value'
import isObject, { TYPES } from '../utils/is-object'
import mixin from '../utils/mixin'
/**
* A factory for the interface that all Slate objects implement.
*
* @type {Function}
*/
function create(type) {
const TYPE = TYPES[type]
const camel = `${type.charAt(0).toUpperCase()}${type.slice(1)}`
const is = `is${camel}`
class ObjectInterface {
/**
* Return the type of the object.
*
* @return {String}
*/
get object() {
return type
}
}
ObjectInterface[is] = isObject.bind(null, type)
ObjectInterface.prototype[TYPE] = true
return ObjectInterface
}
/**
* Mix in the object interfaces.
*/
debugger
mixin(create('block'), [Block])
mixin(create('change'), [Change])
mixin(create('decoration'), [Decoration])
mixin(create('document'), [Document])
mixin(create('history'), [History])
mixin(create('inline'), [Inline])
mixin(create('leaf'), [Leaf])
mixin(create('mark'), [Mark])
mixin(create('node'), [Node])
mixin(create('operation'), [Operation])
mixin(create('point'), [Point])
mixin(create('range'), [Range])
mixin(create('schema'), [Schema])
mixin(create('selection'), [Selection])
mixin(create('stack'), [Stack])
mixin(create('text'), [Text])
mixin(create('value'), [Value])

View File

@ -2,7 +2,6 @@ import isPlainObject from 'is-plain-object'
import { List, Map, Record } from 'immutable'
import KeyUtils from '../utils/key-utils'
import MODEL_TYPES, { isType } from '../constants/model-types'
import Node from './node'
/**
@ -12,9 +11,9 @@ import Node from './node'
*/
const DEFAULTS = {
data: new Map(),
data: undefined,
key: undefined,
nodes: new List(),
nodes: undefined,
type: undefined,
}
@ -96,15 +95,6 @@ class Block extends Record(DEFAULTS) {
return block
}
/**
* Check if `any` is a `Block`.
*
* @param {Any} any
* @return {Boolean}
*/
static isBlock = isType.bind(null, 'BLOCK')
/**
* Check if `any` is a block list.
*
@ -116,16 +106,6 @@ class Block extends Record(DEFAULTS) {
return List.isList(any) && any.every(item => Block.isBlock(item))
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'block'
}
/**
* Return a JSON representation of the block.
*
@ -149,12 +129,6 @@ class Block extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Block.prototype[MODEL_TYPES.BLOCK] = true
/**
* Export.
*

View File

@ -3,7 +3,6 @@ import isPlainObject from 'is-plain-object'
import warning from 'slate-dev-warning'
import { List, Map } from 'immutable'
import MODEL_TYPES, { isType } from '../constants/model-types'
import Changes from '../changes'
import Operation from './operation'
import PathUtils from '../utils/path-utils'
@ -23,15 +22,6 @@ const debug = Debug('slate:change')
*/
class Change {
/**
* Check if `any` is a `Change`.
*
* @param {Any} any
* @return {Boolean}
*/
static isChange = isType.bind(null, 'CHANGE')
/**
* Create a new `Change` with `attrs`.
*
@ -52,16 +42,6 @@ class Change {
}
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'change'
}
/**
* Apply an `operation` to the current value, saving the operation to the
* history if needed.
@ -461,12 +441,6 @@ function getDirtyKeys(operation, newValue, oldValue) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Change.prototype[MODEL_TYPES.CHANGE] = true
/**
* Add a change method for each of the changes.
*/

View File

@ -2,7 +2,6 @@ import isPlainObject from 'is-plain-object'
import { List, Record } from 'immutable'
import Mark from './mark'
import MODEL_TYPES from '../constants/model-types'
import Point from './point'
import Range from './range'
@ -13,8 +12,8 @@ import Range from './range'
*/
const DEFAULTS = {
anchor: Point.create(),
focus: Point.create(),
anchor: undefined,
focus: undefined,
mark: undefined,
}
@ -124,27 +123,6 @@ class Decoration extends Record(DEFAULTS) {
return decoration
}
/**
* Check if an `obj` is a `Decoration`.
*
* @param {Any} obj
* @return {Boolean}
*/
static isDecoration(obj) {
return !!(obj && obj[MODEL_TYPES.DECORATION])
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'decoration'
}
/**
* Set new `properties` on the decoration.
*
@ -192,12 +170,6 @@ class Decoration extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Decoration.prototype[MODEL_TYPES.DECORATION] = true
/**
* Export.
*

View File

@ -2,7 +2,6 @@ import isPlainObject from 'is-plain-object'
import { List, Map, Record } from 'immutable'
import KeyUtils from '../utils/key-utils'
import MODEL_TYPES, { isType } from '../constants/model-types'
import Node from './node'
/**
@ -12,9 +11,9 @@ import Node from './node'
*/
const DEFAULTS = {
data: new Map(),
data: undefined,
key: undefined,
nodes: new List(),
nodes: undefined,
}
/**
@ -72,25 +71,6 @@ class Document extends Record(DEFAULTS) {
return document
}
/**
* Check if `any` is a `Document`.
*
* @param {Any} any
* @return {Boolean}
*/
static isDocument = isType.bind(null, 'DOCUMENT')
/**
* Object.
*
* @return {String}
*/
get object() {
return 'document'
}
/**
* Return a JSON representation of the document.
*
@ -113,12 +93,6 @@ class Document extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Document.prototype[MODEL_TYPES.DOCUMENT] = true
/**
* Export.
*

View File

@ -2,8 +2,6 @@ import Debug from 'debug'
import isPlainObject from 'is-plain-object'
import { List, Record, Stack } from 'immutable'
import MODEL_TYPES, { isType } from '../constants/model-types'
/**
* Debug.
*
@ -19,8 +17,8 @@ const debug = Debug('slate:history')
*/
const DEFAULTS = {
redos: new Stack(),
undos: new Stack(),
redos: undefined,
undos: undefined,
}
/**
@ -90,25 +88,6 @@ class History extends Record(DEFAULTS) {
return history
}
/**
* Check if `any` is a `History`.
*
* @param {Any} any
* @return {Boolean}
*/
static isHistory = isType.bind(null, 'HISTORY')
/**
* Object.
*
* @return {String}
*/
get object() {
return 'history'
}
/**
* Save an `operation` into the history.
*
@ -174,12 +153,6 @@ class History extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
History.prototype[MODEL_TYPES.HISTORY] = true
/**
* Check whether to merge a new operation `o` into the previous operation `p`.
*

View File

@ -2,7 +2,6 @@ import isPlainObject from 'is-plain-object'
import { List, Map, Record } from 'immutable'
import KeyUtils from '../utils/key-utils'
import MODEL_TYPES, { isType } from '../constants/model-types'
import Node from './node'
/**
@ -12,9 +11,9 @@ import Node from './node'
*/
const DEFAULTS = {
data: new Map(),
data: undefined,
key: undefined,
nodes: new List(),
nodes: undefined,
type: undefined,
}
@ -96,15 +95,6 @@ class Inline extends Record(DEFAULTS) {
return inline
}
/**
* Check if `any` is a `Inline`.
*
* @param {Any} any
* @return {Boolean}
*/
static isInline = isType.bind(null, 'INLINE')
/**
* Check if `any` is a list of inlines.
*
@ -116,16 +106,6 @@ class Inline extends Record(DEFAULTS) {
return List.isList(any) && any.every(item => Inline.isInline(item))
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'inline'
}
/**
* Return a JSON representation of the inline.
*
@ -149,12 +129,6 @@ class Inline extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Inline.prototype[MODEL_TYPES.INLINE] = true
/**
* Export.
*

View File

@ -1,7 +1,6 @@
import isPlainObject from 'is-plain-object'
import { List, Record, Set } from 'immutable'
import MODEL_TYPES, { isType } from '../constants/model-types'
import Mark from './mark'
/**
@ -11,8 +10,8 @@ import Mark from './mark'
*/
const DEFAULTS = {
marks: Set(),
text: '',
marks: undefined,
text: undefined,
}
/**
@ -192,15 +191,6 @@ class Leaf extends Record(DEFAULTS) {
return leaf
}
/**
* Check if `any` is a `Leaf`.
*
* @param {Any} any
* @return {Boolean}
*/
static isLeaf = isType.bind(null, 'LEAF')
/**
* Check if `any` is a list of leaves.
*
@ -212,16 +202,6 @@ class Leaf extends Record(DEFAULTS) {
return List.isList(any) && any.every(item => Leaf.isLeaf(item))
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'leaf'
}
/**
* Update a `mark` at leaf, replace with newMark
*
@ -293,12 +273,6 @@ class Leaf extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Leaf.prototype[MODEL_TYPES.LEAF] = true
/**
* Export.
*

View File

@ -1,7 +1,6 @@
import isPlainObject from 'is-plain-object'
import { Map, Record, Set } from 'immutable'
import MODEL_TYPES, { isType } from '../constants/model-types'
import Data from './data'
/**
@ -11,7 +10,7 @@ import Data from './data'
*/
const DEFAULTS = {
data: new Map(),
data: undefined,
type: undefined,
}
@ -122,15 +121,6 @@ class Mark extends Record(DEFAULTS) {
return mark
}
/**
* Check if `any` is a `Mark`.
*
* @param {Any} any
* @return {Boolean}
*/
static isMark = isType.bind(null, 'MARK')
/**
* Check if `any` is a set of marks.
*
@ -142,14 +132,6 @@ class Mark extends Record(DEFAULTS) {
return Set.isSet(any) && any.every(item => Mark.isMark(item))
}
/**
* Object.
*/
get object() {
return 'mark'
}
/**
* Return a JSON representation of the mark.
*
@ -167,12 +149,6 @@ class Mark extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Mark.prototype[MODEL_TYPES.MARK] = true
/**
* Export.
*

View File

@ -7,7 +7,6 @@ import Data from './data'
import Document from './document'
import Inline from './inline'
import Text from './text'
import { isType } from '../constants/model-types'
/**
* A pseudo-model that is used for its static methods only.
@ -155,8 +154,11 @@ class Node {
*/
static isNode(any) {
return !!['BLOCK', 'DOCUMENT', 'INLINE', 'TEXT'].find(type =>
isType(type, any)
return (
Block.isBlock(any) ||
Document.isDocument(any) ||
Inline.isInline(any) ||
Text.isText(any)
)
}

View File

@ -1,7 +1,6 @@
import isPlainObject from 'is-plain-object'
import { List, Record } from 'immutable'
import MODEL_TYPES from '../constants/model-types'
import Mark from './mark'
import Node from './node'
import PathUtils from '../utils/path-utils'
@ -194,17 +193,6 @@ class Operation extends Record(DEFAULTS) {
return node
}
/**
* Check if `any` is a `Operation`.
*
* @param {Any} any
* @return {Boolean}
*/
static isOperation(any) {
return !!(any && any[MODEL_TYPES.OPERATION])
}
/**
* Check if `any` is a list of operations.
*
@ -216,16 +204,6 @@ class Operation extends Record(DEFAULTS) {
return List.isList(any) && any.every(item => Operation.isOperation(item))
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'operation'
}
/**
* Apply the operation to a `value`.
*
@ -327,12 +305,6 @@ class Operation extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Operation.prototype[MODEL_TYPES.OPERATION] = true
/**
* Export.
*

View File

@ -4,7 +4,6 @@ import { Record } from 'immutable'
import KeyUtils from '../utils/key-utils'
import PathUtils from '../utils/path-utils'
import MODEL_TYPES from '../constants/model-types'
/**
* Default properties.
@ -13,9 +12,9 @@ import MODEL_TYPES from '../constants/model-types'
*/
const DEFAULTS = {
key: null,
offset: null,
path: null,
key: undefined,
offset: undefined,
path: undefined,
}
/**
@ -101,27 +100,6 @@ class Point extends Record(DEFAULTS) {
return point
}
/**
* Check if an `obj` is a `Point`.
*
* @param {Any} obj
* @return {Boolean}
*/
static isPoint(obj) {
return !!(obj && obj[MODEL_TYPES.POINT])
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'point'
}
/**
* Check whether all properties of the point are set.
*
@ -411,12 +389,6 @@ class Point extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Point.prototype[MODEL_TYPES.POINT] = true
/**
* Export.
*

View File

@ -2,9 +2,9 @@ import isPlainObject from 'is-plain-object'
import { List, Record } from 'immutable'
import Decoration from './decoration'
import MODEL_TYPES from '../constants/model-types'
import Point from './point'
import Selection from './selection'
import isObject from '../utils/is-object'
/**
* Default properties.
@ -13,8 +13,8 @@ import Selection from './selection'
*/
const DEFAULTS = {
anchor: Point.create(),
focus: Point.create(),
anchor: undefined,
focus: undefined,
}
/**
@ -112,30 +112,20 @@ class Range extends Record(DEFAULTS) {
}
/**
* Check if an `obj` is a `Range`, or is range-like.
* Check if a `value` is a `Range`, or is range-like.
*
* @param {Any} obj
* @param {Any} value
* @return {Boolean}
*/
static isRange(obj) {
static isRange(value) {
return (
!!(obj && obj[MODEL_TYPES.RANGE]) ||
Decoration.isDecoration(obj) ||
Selection.isSelection(obj)
isObject('range', value) ||
Decoration.isDecoration(value) ||
Selection.isSelection(value)
)
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'range'
}
/**
* Return a JSON representation of the range.
*
@ -154,12 +144,6 @@ class Range extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Range.prototype[MODEL_TYPES.RANGE] = true
/**
* Export.
*

View File

@ -2,7 +2,6 @@ import Debug from 'debug'
import isPlainObject from 'is-plain-object'
import { Record } from 'immutable'
import MODEL_TYPES from '../constants/model-types'
import Stack from './stack'
import Text from './text'
import SlateError from '../utils/slate-error'
@ -140,8 +139,8 @@ const CORE_RULES = [
*/
const DEFAULTS = {
stack: Stack.create(),
rules: [],
stack: undefined,
rules: undefined,
}
/**
@ -229,27 +228,6 @@ class Schema extends Record(DEFAULTS) {
return ret
}
/**
* Check if `any` is a `Schema`.
*
* @param {Any} any
* @return {Boolean}
*/
static isSchema(any) {
return !!(any && any[MODEL_TYPES.SCHEMA])
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'schema'
}
/**
* Get the schema rules for a `node`.
*
@ -744,12 +722,6 @@ function fail(code, attrs) {
return { code, ...attrs }
}
/**
* Attach a pseudo-symbol for type checking.
*/
Schema.prototype[MODEL_TYPES.SCHEMA] = true
/**
* Export.
*

View File

@ -1,7 +1,6 @@
import isPlainObject from 'is-plain-object'
import { Record, Set } from 'immutable'
import MODEL_TYPES from '../constants/model-types'
import Mark from './mark'
import Point from './point'
import Range from './range'
@ -13,10 +12,10 @@ import Range from './range'
*/
const DEFAULTS = {
anchor: Point.create(),
focus: Point.create(),
isFocused: false,
marks: null,
anchor: undefined,
focus: undefined,
isFocused: undefined,
marks: undefined,
}
/**
@ -109,27 +108,6 @@ class Selection extends Record(DEFAULTS) {
return selection
}
/**
* Check if an `obj` is a `Selection`.
*
* @param {Any} obj
* @return {Boolean}
*/
static isSelection(obj) {
return !!(obj && obj[MODEL_TYPES.SELECTION])
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'selection'
}
/**
* Check whether the selection is blurred.
*
@ -208,12 +186,6 @@ class Selection extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Selection.prototype[MODEL_TYPES.SELECTION] = true
/**
* Export.
*

View File

@ -1,6 +1,5 @@
import { Record } from 'immutable'
import MODEL_TYPES from '../constants/model-types'
import memoize from '../utils/memoize'
/**
@ -10,7 +9,7 @@ import memoize from '../utils/memoize'
*/
const DEFAULTS = {
plugins: [],
plugins: undefined,
}
/**
@ -32,27 +31,6 @@ class Stack extends Record(DEFAULTS) {
return stack
}
/**
* Check if `any` is a `Stack`.
*
* @param {Any} any
* @return {Boolean}
*/
static isStack(any) {
return !!(any && any[MODEL_TYPES.STACK])
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'stack'
}
/**
* Get all plugins with `property`.
*
@ -136,12 +114,6 @@ class Stack extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Stack.prototype[MODEL_TYPES.STACK] = true
/**
* Memoize read methods.
*/

View File

@ -3,7 +3,6 @@ import warning from 'slate-dev-warning'
import { List, OrderedSet, Record, Set } from 'immutable'
import Leaf from './leaf'
import MODEL_TYPES, { isType } from '../constants/model-types'
import KeyUtils from '../utils/key-utils'
import memoize from '../utils/memoize'
@ -14,7 +13,7 @@ import memoize from '../utils/memoize'
*/
const DEFAULTS = {
leaves: List(),
leaves: undefined,
key: undefined,
}
@ -117,15 +116,6 @@ class Text extends Record(DEFAULTS) {
return node
}
/**
* Check if `any` is a `Text`.
*
* @param {Any} any
* @return {Boolean}
*/
static isText = isType.bind(null, 'TEXT')
/**
* Check if `any` is a list of texts.
*
@ -137,16 +127,6 @@ class Text extends Record(DEFAULTS) {
return List.isList(any) && any.every(item => Text.isText(item))
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'text'
}
/**
* Find the 'first' leaf at offset; By 'first' the alorighthm prefers `endOffset === offset` than `startOffset === offset`
* Corner Cases:
@ -650,12 +630,6 @@ class Text extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Text.prototype[MODEL_TYPES.TEXT] = true
/**
* Memoize read methods.
*/

View File

@ -1,14 +1,12 @@
import isPlainObject from 'is-plain-object'
import { Record, Set, List, Map } from 'immutable'
import { Record, Set, List } from 'immutable'
import MODEL_TYPES from '../constants/model-types'
import PathUtils from '../utils/path-utils'
import Change from './change'
import Data from './data'
import Decoration from './decoration'
import Document from './document'
import History from './history'
import Selection from './selection'
import Schema from './schema'
/**
@ -18,12 +16,12 @@ import Schema from './schema'
*/
const DEFAULTS = {
data: Map(),
decorations: List(),
document: Document.create(),
history: History.create(),
schema: Schema.create(),
selection: Selection.create(),
data: undefined,
decorations: undefined,
document: undefined,
history: undefined,
schema: undefined,
selection: undefined,
}
/**
@ -98,6 +96,7 @@ class Value extends Record(DEFAULTS) {
static fromJSON(object, options = {}) {
let {
data = {},
decorations = [],
document = {},
selection = {},
schema = {},
@ -109,6 +108,7 @@ class Value extends Record(DEFAULTS) {
history = History.fromJSON(history)
document = Document.fromJSON(document)
selection = document.createSelection(selection)
decorations = List(decorations.map(d => Decoration.fromJSON(d)))
if (selection.isUnset) {
const text = document.getFirstText()
@ -118,6 +118,7 @@ class Value extends Record(DEFAULTS) {
let value = new Value({
data,
decorations,
document,
selection,
schema,
@ -133,27 +134,6 @@ class Value extends Record(DEFAULTS) {
return value
}
/**
* Check if a `value` is a `Value`.
*
* @param {Any} value
* @return {Boolean}
*/
static isValue(value) {
return !!(value && value[MODEL_TYPES.VALUE])
}
/**
* Object.
*
* @return {String}
*/
get object() {
return 'value'
}
/**
* Get the current start text node's closest block parent.
*
@ -959,12 +939,6 @@ class Value extends Record(DEFAULTS) {
}
}
/**
* Attach a pseudo-symbol for type checking.
*/
Value.prototype[MODEL_TYPES.VALUE] = true
/**
* Export.
*/

View File

@ -0,0 +1,36 @@
/**
* Slate-specific object types.
*
* @type {Object}
*/
export const TYPES = {
block: '@@__SLATE_BLOCK__@@',
change: '@@__SLATE_CHANGE__@@',
decoration: '@@__SLATE_DECORATION__@@',
document: '@@__SLATE_DOCUMENT__@@',
history: '@@__SLATE_HISTORY__@@',
inline: '@@__SLATE_INLINE__@@',
leaf: '@@__SLATE_LEAF__@@',
mark: '@@__SLATE_MARK__@@',
operation: '@@__SLATE_OPERATION__@@',
point: '@@__SLATE_POINT__@@',
range: '@@__SLATE_RANGE__@@',
schema: '@@__SLATE_SCHEMA__@@',
selection: '@@__SLATE_SELECTION__@@',
stack: '@@__SLATE_STACK__@@',
text: '@@__SLATE_TEXT__@@',
value: '@@__SLATE_VALUE__@@',
}
/**
* Determine whether a `value` is of `type`.
*
* @param {string} type
* @param {any} value
* @return {boolean}
*/
export default function isObject(type, value) {
return !!(value && value[TYPES[type]])
}

View File

@ -1,18 +1,20 @@
/**
* Mix in an `Interface` to a `Class`.
*
* @param {Class} Class
* @param {Class} Interface
* @param {Class} Class
*/
export default function mixin(Interface, Classes) {
for (const Class of Classes) {
// Copy static properties from the interface.
for (const name of Object.getOwnPropertyNames(Interface)) {
if (Class.hasOwnProperty(name)) continue
const desc = Object.getOwnPropertyDescriptor(Interface, name)
Object.defineProperty(Class, name, desc)
}
// Copy instance properties from the interface.
for (const name of Object.getOwnPropertyNames(Interface.prototype)) {
if (Class.prototype.hasOwnProperty(name)) continue
const desc = Object.getOwnPropertyDescriptor(Interface.prototype, name)