diff --git a/lib/models/block.js b/lib/models/block.js index 1db463e8e..be711f12e 100644 --- a/lib/models/block.js +++ b/lib/models/block.js @@ -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)) } /** diff --git a/lib/models/document.js b/lib/models/document.js index 427163dc8..47bc42653 100644 --- a/lib/models/document.js +++ b/lib/models/document.js @@ -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() } /** diff --git a/lib/models/inline.js b/lib/models/inline.js index 9c72639c8..60bdeb938 100644 --- a/lib/models/inline.js +++ b/lib/models/inline.js @@ -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)) } /** diff --git a/lib/models/mark.js b/lib/models/mark.js index 34b3f357a..3a39ad081 100644 --- a/lib/models/mark.js +++ b/lib/models/mark.js @@ -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) } diff --git a/lib/models/node.js b/lib/models/node.js index c558d069b..2ccc7c447 100644 --- a/lib/models/node.js +++ b/lib/models/node.js @@ -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 })) }) diff --git a/lib/models/state.js b/lib/models/state.js index 9ad5cd5f4..7cbbd9f29 100644 --- a/lib/models/state.js +++ b/lib/models/state.js @@ -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) } diff --git a/lib/models/text.js b/lib/models/text.js index 0ba88392d..a779467f3 100644 --- a/lib/models/text.js +++ b/lib/models/text.js @@ -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) } diff --git a/lib/serializers/raw.js b/lib/serializers/raw.js index 0508e698c..0f574f02c 100644 --- a/lib/serializers/raw.js +++ b/lib/serializers/raw.js @@ -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) } /** diff --git a/package.json b/package.json index 443b2aaed..40c3cc5ee 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/test/server/index.js b/test/server/index.js index f36494c7b..e7fb3a1bc 100644 --- a/test/server/index.js +++ b/test/server/index.js @@ -1,2 +1,3 @@ +import 'source-map-support/register' import './transforms'