1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-09-01 03:11:44 +02:00

change from ordered map to list for nodes

This commit is contained in:
Ian Storm Taylor
2016-06-23 11:32:24 -07:00
parent a3c4c04193
commit d637d9e053
10 changed files with 83 additions and 129 deletions

View File

@@ -4,7 +4,7 @@ import Inline from './inline'
import Node from './node'
import Text from './text'
import uid from 'uid'
import Immutable, { Map, OrderedMap, Record } from 'immutable'
import Immutable, { Map, List, Record } from 'immutable'
/**
* Default properties.
@@ -13,7 +13,7 @@ import Immutable, { Map, OrderedMap, Record } from 'immutable'
const DEFAULTS = {
data: new Map(),
key: null,
nodes: new OrderedMap(),
nodes: new List(),
type: null
}
@@ -38,26 +38,21 @@ class Block extends Record(DEFAULTS) {
properties.key = uid(4)
properties.data = Data.create(properties.data)
properties.nodes = Block.createMap(properties.nodes)
properties.nodes = Block.createList(properties.nodes)
let block = new Block(properties)
return block.normalize()
return new Block(properties).normalize()
}
/**
* Create an ordered map of `Blocks` from an array of `Blocks`.
* Create a list of `Blocks` from an array.
*
* @param {Array} elements
* @return {OrderedMap} map
* @return {List} list
*/
static createMap(elements = []) {
if (OrderedMap.isOrderedMap(elements)) return elements
return elements
.map(Block.create)
.reduce((map, element) => {
return map.set(element.key, element)
}, new OrderedMap())
static createList(elements = []) {
if (List.isList(elements)) return elements
return new List(elements.map(Block.create))
}
/**

View File

@@ -26,11 +26,8 @@ class Document extends Record(DEFAULTS) {
static create(properties = {}) {
if (properties instanceof Document) return properties
properties.nodes = Block.createMap(properties.nodes)
let document = new Document(properties)
return document.normalize()
properties.nodes = Block.createList(properties.nodes)
return new Document(properties).normalize()
}
/**

View File

@@ -4,7 +4,7 @@ import Data from './data'
import Node from './node'
import Text from './text'
import uid from 'uid'
import Immutable, { Map, OrderedMap, Record } from 'immutable'
import { List, Map, Record } from 'immutable'
/**
* Record.
@@ -13,7 +13,7 @@ import Immutable, { Map, OrderedMap, Record } from 'immutable'
const DEFAULTS = {
data: new Map(),
key: null,
nodes: new OrderedMap(),
nodes: new List(),
type: null
}
@@ -38,26 +38,22 @@ class Inline extends Record(DEFAULTS) {
properties.key = uid(4)
properties.data = Data.create(properties.data)
properties.nodes = Inline.createMap(properties.nodes)
properties.nodes = Inline.createList(properties.nodes)
let inline = new Inline(properties)
return inline.normalize()
}
/**
* Create an ordered map of `Inlines` from an array of `Inlines`.
* Create a list of `Inlines` from an array.
*
* @param {Array} elements
* @return {OrderedMap} map
* @return {List} map
*/
static createMap(elements = []) {
if (OrderedMap.isOrderedMap(elements)) return elements
return elements
.map(Inline.create)
.reduce((map, element) => {
return map.set(element.key, element)
}, new OrderedMap())
static createList(elements = []) {
if (List.isList(elements)) return elements
return new List(elements.map(Inline.create))
}
/**

View File

@@ -27,9 +27,7 @@ class Mark extends Record(DEFAULTS) {
static create(properties = {}) {
if (properties instanceof Mark) 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)
}

View File

@@ -5,7 +5,7 @@ import Data from './data'
import Mark from './mark'
import Selection from './selection'
import Text from './text'
import { List, Map, OrderedMap, OrderedSet, Set } from 'immutable'
import { List, Map, Set } from 'immutable'
/**
* Node.
@@ -49,9 +49,7 @@ const Node = {
// If the start and end nodes are the same, remove the matching characters.
if (startKey == endKey) {
let { characters } = startNode
characters = characters.filterNot((char, i) => {
const characters = startNode.characters.filterNot((char, i) => {
return startOffset <= i && i < endOffset
})
@@ -92,7 +90,7 @@ const Node = {
const nodes = node.nodes
.takeUntil(child => child == startGrandestParent)
.set(startGrandestParent.key, startGrandestParent)
.push(startGrandestParent)
.concat(node.nodes.skipUntil(child => child == endGrandestParent))
node = node.merge({ nodes })
@@ -214,17 +212,11 @@ const Node = {
*/
filterDeep(iterator) {
return this.nodes.reduce((matches, child) => {
if (iterator(child, child.key, this.nodes)) {
matches = matches.set(child.key, child)
}
if (child.kind != 'text') {
matches = matches.concat(child.filterDeep(iterator))
}
return this.nodes.reduce((matches, child, i, nodes) => {
if (iterator(child, i, nodes)) matches = matches.push(child)
if (child.kind != 'text') matches = matches.concat(child.filterDeep(iterator))
return matches
}, new OrderedMap())
}, Block.createList())
},
/**
@@ -362,7 +354,8 @@ const Node = {
key = normalizeKey(key)
this.assertHasDeep(key)
if (this.nodes.has(key)) return startAt
const shallow = this.nodes.find(node => node.key == key)
if (shallow) return startAt
const child = this.nodes.find(node => {
return node.kind == 'text'
@@ -465,7 +458,8 @@ const Node = {
key = normalizeKey(key)
this.assertHasDeep(key)
if (this.nodes.has(key)) {
const shallow = this.nodes.find(node => node.key == key)
if (shallow) {
return this.nodes
.skipUntil(node => node.key == key)
.rest()
@@ -526,7 +520,7 @@ const Node = {
// If the child's parent is this node, return the offset of all of the nodes
// before it, otherwise recurse.
return this.nodes.has(match.key)
return this.nodes.find(node => node.key == match.key)
? offset
: offset + child.getOffset(key)
},
@@ -542,7 +536,8 @@ const Node = {
key = normalizeKey(key)
// this.assertHasDeep(key)
if (this.nodes.has(key)) return this
const shallow = this.nodes.find(node => node.key == key)
if (shallow) return this
let node = null
this.nodes.forEach((child) => {
@@ -565,7 +560,8 @@ const Node = {
key = normalizeKey(key)
this.assertHasDeep(key)
if (this.nodes.has(key)) {
const shallow = this.nodes.find(node => node.key == key)
if (shallow) {
return this.nodes
.takeUntil(node => node.key == key)
.last()
@@ -620,9 +616,9 @@ const Node = {
getTextNodes() {
return this.nodes.reduce((texts, node) => {
return node.kind == 'text'
? texts.set(node.key, node)
? texts.push(node)
: texts.concat(node.getTextNodes())
}, new OrderedMap())
}, Block.createList())
},
/**
@@ -648,7 +644,7 @@ const Node = {
const endNode = this.getDeep(endKey)
const afterStart = texts.skipUntil(node => node.key == startKey)
const upToEnd = afterStart.takeUntil(node => node.key == endKey)
const matches = upToEnd.set(endNode.key, endNode)
const matches = upToEnd.push(endNode)
return matches
},
@@ -802,18 +798,12 @@ const Node = {
/**
* Push a new `node` onto the map of nodes.
*
* @param {String or Node} key
* @param {Node} node (optional)
* @param {Node} node
* @return {Node} node
*/
pushNode(key, node) {
if (arguments.length == 1) {
node = key
key = normalizeKey(key)
}
let nodes = this.nodes.set(key, node)
pushNode(node) {
const nodes = this.nodes.push(node)
return this.merge({ nodes })
},
@@ -827,8 +817,7 @@ const Node = {
removeDeep(key) {
key = normalizeKey(key)
this.assertHasDeep(key)
let nodes = this.nodes.remove(key)
const nodes = this.nodes.filterNot(node => node.key == key)
return this.merge({ nodes })
},
@@ -943,8 +932,8 @@ const Node = {
// Replace the block in the parent with the two new blocks.
let parent = node.getParent(firstBlock)
const nodes = parent.nodes.takeUntil(n => n.key == firstBlock.key)
.set(firstBlock.key, firstBlock)
.set(secondBlock.key, secondBlock)
.push(firstBlock)
.push(secondBlock)
.concat(parent.nodes.skipUntil(n => n.key == firstBlock.key).rest())
// If the node is the parent, just merge, otherwise deep merge.
@@ -960,7 +949,6 @@ const Node = {
},
splitInlineAtRange(range) {
debugger
range = range.normalize(this)
const Inline = require('./inline').default
let node = this
@@ -979,7 +967,7 @@ const Node = {
// While the parent is an inline parent, split the inline nodes.
while (parent = node.getClosestInline(firstChild)) {
firstChild = parent.merge({ nodes: Inline.createMap([firstChild]) })
firstChild = parent.merge({ nodes: Inline.createList([firstChild]) })
secondChild = Inline.create({
nodes: [secondChild],
type: parent.type,
@@ -987,16 +975,15 @@ const Node = {
})
// Split the children.
const isGrandparent = node.nodes.has(parent.key)
const grandparent = isGrandparent ? node : node.getParent(parent)
const grandparent = node.getParent(parent)
const nodes = grandparent.nodes
.takeUntil(c => c.key == firstChild.key)
.set(firstChild.key, firstChild)
.set(secondChild.key, secondChild)
.push(firstChild)
.push(secondChild)
.concat(grandparent.nodes.skipUntil(n => n.key == firstChild.key).rest())
// Update the grandparent.
node = isGrandparent
node = grandparent == node
? node.merge({ nodes })
: node.updateDeep(grandparent.merge({ nodes }))
}
@@ -1034,8 +1021,8 @@ const Node = {
let parent = node.getParent(text)
const nodes = parent.nodes
.takeUntil(c => c.key == firstChild.key)
.set(firstChild.key, firstChild)
.set(secondChild.key, secondChild)
.push(firstChild)
.push(secondChild)
.concat(parent.nodes.skipUntil(n => n.key == firstChild.key).rest())
// Update the nodes.
@@ -1090,26 +1077,21 @@ const Node = {
/**
* Set a new value for a child node by `key`.
*
* @param {String or Node} key
* @param {Node} node (optional)
* @param {Node} node
* @return {Node} node
*/
updateDeep(key, node) {
if (arguments.length == 1) {
node = key
key = normalizeKey(key)
}
updateDeep(node) {
// this.assertHasDeep(key)
if (this.nodes.get(key)) {
const nodes = this.nodes.set(key, node)
return this.set('nodes', nodes)
const shallow = this.nodes.find(child => child.key == node.key)
if (shallow) {
const nodes = this.nodes.map(child => child.key == node.key ? node : child)
return this.merge({ nodes })
}
const nodes = this.nodes.map((child) => {
return child.kind == 'text' ? child : child.updateDeep(key, node)
return child.kind == 'text' ? child : child.updateDeep(node)
})
return this.merge({ nodes })
@@ -1146,9 +1128,9 @@ const Node = {
const sibling = node.getDepth(block) == depth
? block
: node.getClosest(block, (p) => node.getDepth(p) == depth)
siblings = siblings.set(sibling.key, sibling)
siblings = siblings.push(sibling)
return siblings
}, new OrderedMap())
}, Block.createList())
// Wrap the siblings in a new block.
const wrapper = Block.create({
@@ -1158,20 +1140,16 @@ const Node = {
})
// Replace the siblings with the wrapper.
const isDirectChild = node.nodes.has(highest.key)
let parent = isDirectChild ? node : node.getParent(highest)
const parent = node.getParent(highest)
const nodes = parent.nodes
.takeUntil(node => node == highest)
.set(wrapper.key, wrapper)
.push(wrapper)
.concat(parent.nodes.skipUntil(node => node == highest).rest())
// Update the parent.
if (isDirectChild) {
node = node.merge({ nodes })
} else {
parent = parent.merge({ nodes })
node = node.updateDeep(parent)
}
node = parent == node
? node.merge({ nodes })
: node.updateDeep(parent.merge({ nodes }))
return node
},
@@ -1208,14 +1186,13 @@ const Node = {
return true
})
if (match) wrappers = wrappers.set(match.key, match)
if (match) wrappers = wrappers.add(match)
return wrappers
}, new OrderedMap())
}, new Set())
// Replace each of the wrappers with their child nodes.
wrappers.forEach((wrapper) => {
const isDirectChild = node.nodes.has(wrapper.key)
let parent = isDirectChild ? node : node.getParent(wrapper)
const parent = node.getParent(wrapper)
// Replace the wrapper in the parent's nodes with the block.
const nodes = parent.nodes.takeUntil(n => n == wrapper)
@@ -1223,12 +1200,9 @@ const Node = {
.concat(parent.nodes.skipUntil(n => n == wrapper).rest())
// Update the parent.
if (isDirectChild) {
node = node.merge({ nodes })
} else {
parent = parent.merge({ nodes })
node = node.updateDeep(parent)
}
node = parent == node
? node.merge({ nodes })
: node.updateDeep(parent.merge({ nodes }))
})
return node.normalize()
@@ -1298,7 +1272,7 @@ const Node = {
// Replace the child in it's parent with the wrapper.
const parent = node.getParent(child)
const nodes = parent.nodes.takeUntil(n => n == child)
.set(wrapper.key, wrapper)
.push(wrapper)
.concat(parent.nodes.skipUntil(n => n == child).rest())
// Update the parent.
@@ -1343,14 +1317,13 @@ const Node = {
return true
})
if (match) wrappers = wrappers.set(match.key, match)
if (match) wrappers = wrappers.add(match)
return wrappers
}, new OrderedMap())
}, new Set())
// Replace each of the wrappers with their child nodes.
wrappers.forEach((wrapper) => {
const parent = node.getParent(wrapper)
const isDirectChild = parent == node
// Replace the wrapper in the parent's nodes with the block.
const nodes = parent.nodes.takeUntil(n => n == wrapper)
@@ -1358,7 +1331,7 @@ const Node = {
.concat(parent.nodes.skipUntil(n => n == wrapper).rest())
// Update the parent.
node = isDirectChild
node = parent == node
? node.merge({ nodes })
: node.updateDeep(parent.merge({ nodes }))
})

View File

@@ -60,10 +60,8 @@ class State extends Record(DEFAULTS) {
static create(properties = {}) {
if (properties instanceof State) return properties
properties.document = Document.create(properties.document)
properties.selection = Selection.create(properties.selection)
return new State(properties)
}

View File

@@ -27,10 +27,8 @@ class Text extends Record(DEFAULTS) {
static create(properties = {}) {
if (properties instanceof Text) return properties
properties.key = uid(4)
properties.characters = Character.createList(properties.characters)
return new Text(properties)
}

View File

@@ -94,7 +94,7 @@ function serializeMark(mark) {
function deserialize(object) {
return State.create({
document: Document.create({
nodes: Block.createMap(object.nodes.map(deserializeNode))
nodes: Block.createList(object.nodes.map(deserializeNode))
})
})
}
@@ -111,15 +111,15 @@ function deserializeNode(object) {
case 'block': {
return Block.create({
type: object.type,
data: new Map(object.data),
nodes: Block.createMap(object.nodes.map(deserializeNode))
data: object.data,
nodes: Block.createList(object.nodes.map(deserializeNode))
})
}
case 'inline': {
return Inline.create({
type: object.type,
data: new Map(object.data),
nodes: Inline.createMap(object.nodes.map(deserializeNode))
data: object.data,
nodes: Inline.createList(object.nodes.map(deserializeNode))
})
}
case 'text': {
@@ -161,10 +161,7 @@ function deserializeRanges(array) {
*/
function deserializeMark(object) {
return Mark.create({
type: object.type,
data: new Map(object.data)
})
return Mark.create(object)
}
/**

View File

@@ -25,6 +25,7 @@
"mocha-phantomjs": "^4.0.2",
"react-dom": "^15.1.0",
"read-metadata": "^1.0.0",
"source-map-support": "^0.4.0",
"standard": "^7.1.2",
"to-camel-case": "^1.0.0",
"watchify": "^3.7.0"

View File

@@ -1,2 +1,3 @@
import 'source-map-support/register'
import './transforms'