From ff1f25585e99ceca72603d75988db79c27f7bdf9 Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Tue, 16 Aug 2016 12:50:35 -0700 Subject: [PATCH] refactor normalizing function --- lib/models/node.js | 27 +-- lib/transforms/at-current-range.js | 9 +- lib/transforms/at-range.js | 27 ++- lib/transforms/by-key.js | 4 +- lib/utils/normalize-block.js | 35 ---- lib/utils/normalize-inline.js | 35 ---- lib/utils/normalize-mark.js | 35 ---- .../normalize-node-or-mark-properties.js | 47 ----- lib/utils/normalize.js | 180 ++++++++++++++++++ 9 files changed, 207 insertions(+), 192 deletions(-) delete mode 100644 lib/utils/normalize-block.js delete mode 100644 lib/utils/normalize-inline.js delete mode 100644 lib/utils/normalize-mark.js delete mode 100644 lib/utils/normalize-node-or-mark-properties.js create mode 100644 lib/utils/normalize.js diff --git a/lib/models/node.js b/lib/models/node.js index 418371b26..147d616f7 100644 --- a/lib/models/node.js +++ b/lib/models/node.js @@ -5,6 +5,7 @@ import Data from './data' import Document from './document' import Inline from './inline' import Mark from './mark' +import Normalize from '../utils/normalize' import Selection from './selection' import Text from './text' import direction from 'direction' @@ -34,7 +35,7 @@ const Node = { const child = this.getChild(key) if (!child) { - key = normalizeKey(key) + key = Normalize.key(key) throw new Error(`Could not find a child node with key "${key}".`) } @@ -52,7 +53,7 @@ const Node = { const descendant = this.getDescendant(key) if (!descendant) { - key = normalizeKey(key) + key = Normalize.key(key) throw new Error(`Could not find a descendant node with key "${key}".`) } @@ -308,7 +309,7 @@ const Node = { */ getChild(key) { - key = normalizeKey(key) + key = Normalize.key(key) return this.nodes.find(node => node.key == key) }, @@ -390,7 +391,7 @@ const Node = { */ getDescendant(key) { - key = normalizeKey(key) + key = Normalize.key(key) let child = this.getChild(key) if (child) return child @@ -511,7 +512,7 @@ const Node = { */ getHighestChild(key) { - key = normalizeKey(key) + key = Normalize.key(key) return this.nodes.find(node => { if (node.key == key) return true if (node.kind == 'text') return false @@ -653,7 +654,7 @@ const Node = { */ getNextText(key) { - key = normalizeKey(key) + key = Normalize.key(key) return this.getTexts() .skipUntil(text => text.key == key) .get(1) @@ -744,7 +745,7 @@ const Node = { */ getPreviousText(key) { - key = normalizeKey(key) + key = Normalize.key(key) return this.getTexts() .takeUntil(text => text.key == key) .last() @@ -1186,18 +1187,6 @@ memoize(Node, [ 'validate' ]) -/** - * Normalize a `key`, from a key string or a node. - * - * @param {String or Node} key - * @return {String} key - */ - -function normalizeKey(key) { - if (typeof key == 'string') return key - return key.key -} - /** * Export. */ diff --git a/lib/transforms/at-current-range.js b/lib/transforms/at-current-range.js index 9492bdbd4..778ec88cd 100644 --- a/lib/transforms/at-current-range.js +++ b/lib/transforms/at-current-range.js @@ -1,5 +1,6 @@ -import normalizeMark from '../utils/normalize-mark' +import Normalize from '../utils/normalize' + import { addMarkAtRange, deleteAtRange, @@ -32,7 +33,7 @@ import { */ export function addMark(state, mark) { - mark = normalizeMark(mark) + mark = Normalize.mark(mark) let { cursorMarks, document, selection } = state // If the selection is collapsed, add the mark to the cursor instead. @@ -463,7 +464,7 @@ export function splitInline(state, depth = Infinity) { */ export function removeMark(state, mark) { - mark = normalizeMark(mark) + mark = Normalize.mark(mark) let { cursorMarks, document, selection } = state // If the selection is collapsed, remove the mark from the cursor instead. @@ -486,7 +487,7 @@ export function removeMark(state, mark) { */ export function toggleMark(state, mark) { - mark = normalizeMark(mark) + mark = Normalize.mark(mark) const exists = state.marks.some(m => m.equals(mark)) return exists ? removeMark(state, mark) diff --git a/lib/transforms/at-range.js b/lib/transforms/at-range.js index ffa8104a8..5492b4427 100644 --- a/lib/transforms/at-range.js +++ b/lib/transforms/at-range.js @@ -1,13 +1,10 @@ import Block from '../models/block' import Inline from '../models/inline' +import Normalize from '../utils/normalize' import Selection from '../models/selection' import Text from '../models/text' import isInRange from '../utils/is-in-range' -import normalizeBlock from '../utils/normalize-block' -import normalizeInline from '../utils/normalize-inline' -import normalizeMark from '../utils/normalize-mark' -import normalizeProperties from '../utils/normalize-node-or-mark-properties' import uid from '../utils/uid' import { Set } from 'immutable' @@ -24,7 +21,7 @@ export function addMarkAtRange(state, range, mark) { let { document } = state // Normalize the mark. - mark = normalizeMark(mark) + mark = Normalize.mark(mark) // When the range is collapsed, do nothing. if (range.isCollapsed) return state @@ -276,7 +273,7 @@ export function insertBlockAtRange(state, range, block) { let { document } = state // Normalize the block argument. - block = normalizeBlock(block) + block = Normalize.block(block) // If expanded, delete the range first. if (range.isExpanded) { @@ -460,7 +457,7 @@ export function insertInlineAtRange(state, range, inline) { let { document } = state // Normalize the inline argument. - inline = normalizeInline(inline) + inline = Normalize.inline(inline) // If expanded, delete the range first. if (range.isExpanded) { @@ -542,7 +539,7 @@ export function insertTextAtRange(state, range, string, marks) { */ export function removeMarkAtRange(state, range, mark) { - mark = normalizeMark(mark) + mark = Normalize.mark(mark) let { document } = state // When the range is collapsed, do nothing. @@ -584,7 +581,7 @@ export function removeMarkAtRange(state, range, mark) { */ export function setBlockAtRange(state, range, properties = {}) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state const blocks = document.getBlocksAtRange(range) @@ -608,7 +605,7 @@ export function setBlockAtRange(state, range, properties = {}) { */ export function setInlineAtRange(state, range, properties = {}) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state const inlines = document.getInlinesAtRange(range) @@ -801,7 +798,7 @@ export function splitTextAtRange(state, range) { */ export function toggleMarkAtRange(state, range, mark) { - mark = normalizeMark(mark) + mark = Normalize.mark(mark) let { document } = state // When the range is collapsed, do nothing. @@ -826,7 +823,7 @@ export function toggleMarkAtRange(state, range, mark) { */ export function unwrapBlockAtRange(state, range, properties) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state // Get the deepest blocks in the range. @@ -921,7 +918,7 @@ export function unwrapBlockAtRange(state, range, properties) { */ export function unwrapInlineAtRange(state, range, properties) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state let blocks = document.getInlinesAtRange(range) @@ -969,7 +966,7 @@ export function unwrapInlineAtRange(state, range, properties) { */ export function wrapBlockAtRange(state, range, properties) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state // Get the block nodes, sorted by depth. @@ -1028,7 +1025,7 @@ export function wrapBlockAtRange(state, range, properties) { */ export function wrapInlineAtRange(state, range, properties) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state // If collapsed, there's nothing to wrap. diff --git a/lib/transforms/by-key.js b/lib/transforms/by-key.js index 92f93154a..c593a7a52 100644 --- a/lib/transforms/by-key.js +++ b/lib/transforms/by-key.js @@ -1,5 +1,5 @@ -import normalizeProperties from '../utils/normalize-node-or-mark-properties' +import Normalize from '../utils/normalize' /** * Remove a node by `key`. @@ -27,7 +27,7 @@ export function removeNodeByKey(state, key) { */ export function setNodeByKey(state, key, properties) { - properties = normalizeProperties(properties) + properties = Normalize.nodeProperties(properties) let { document } = state let descendant = document.assertDescendant(key) descendant = descendant.merge(properties) diff --git a/lib/utils/normalize-block.js b/lib/utils/normalize-block.js deleted file mode 100644 index 28a6ed820..000000000 --- a/lib/utils/normalize-block.js +++ /dev/null @@ -1,35 +0,0 @@ - -import Block from '../models/block' -import normalizeProperties from './normalize-node-or-mark-properties' -import typeOf from 'type-of' - -/** - * Normalize a `block` argument, which can be a string or plain object too. - * - * @param {Block or String or Object} block - * @return {Block} - */ - -function normalizeBlock(block) { - if (block instanceof Block) return block - - const type = typeOf(block) - - switch (type) { - case 'string': - case 'object': { - return Block.create(normalizeProperties(block)) - } - default: { - throw new Error(`A \`block\` argument must be a block, an object or a string, but you passed: "${type}".`) - } - } -} - -/** - * Export. - * - * @type {Function} - */ - -export default normalizeBlock diff --git a/lib/utils/normalize-inline.js b/lib/utils/normalize-inline.js deleted file mode 100644 index 2ab963790..000000000 --- a/lib/utils/normalize-inline.js +++ /dev/null @@ -1,35 +0,0 @@ - -import Inline from '../models/inline' -import normalizeProperties from './normalize-node-or-mark-properties' -import typeOf from 'type-of' - -/** - * Normalize an `inline` argument, which can be a string or plain object too. - * - * @param {Inline or String or Object} inline - * @return {Inline} - */ - -function normalizeInline(inline) { - if (inline instanceof Inline) return inline - - const type = typeOf(inline) - - switch (type) { - case 'string': - case 'object': { - return Inline.create(normalizeProperties(inline)) - } - default: { - throw new Error(`An \`inline\` argument must be an inline, an object or a string, but you passed: "${type}".`) - } - } -} - -/** - * Export. - * - * @type {Function} - */ - -export default normalizeInline diff --git a/lib/utils/normalize-mark.js b/lib/utils/normalize-mark.js deleted file mode 100644 index 292204585..000000000 --- a/lib/utils/normalize-mark.js +++ /dev/null @@ -1,35 +0,0 @@ - -import Mark from '../models/mark' -import typeOf from 'type-of' -import normalizeProperties from './normalize-node-or-mark-properties' - -/** - * Normalize a `mark` argument, which can be a string or plain object too. - * - * @param {Mark or String or Object} mark - * @return {Mark} - */ - -function normalizeMark(mark) { - if (mark instanceof Mark) return mark - - const type = typeOf(mark) - - switch (type) { - case 'string': - case 'object': { - return Mark.create(normalizeProperties(mark)) - } - default: { - throw new Error(`A \`mark\` argument must be a mark, an object or a string, but you passed: "${type}".`) - } - } -} - -/** - * Export. - * - * @type {Function} - */ - -export default normalizeMark diff --git a/lib/utils/normalize-node-or-mark-properties.js b/lib/utils/normalize-node-or-mark-properties.js deleted file mode 100644 index e0d618e0c..000000000 --- a/lib/utils/normalize-node-or-mark-properties.js +++ /dev/null @@ -1,47 +0,0 @@ - -import Data from '../models/data' -import typeOf from 'type-of' - -/** - * Normalize the `properties` of a node or mark, which can be either a type - * string or a dictionary of properties. If it's a dictionary, `data` is - * optional and shouldn't be set if null or undefined. - * - * @param {String or Object} properties - * @return {Object} - */ - -function normalizeNodeOrMarkProperties(properties = {}) { - const ret = {} - const type = typeOf(properties) - - switch (type) { - case 'string': { - ret.type = properties - break - } - case 'object': { - for (const key in properties) { - if (key == 'data') { - if (properties[key] != null) ret[key] = Data.create(properties[key]) - } else { - ret[key] = properties[key] - } - } - break - } - default: { - throw new Error(`A \`properties\` argument must be an object or a string, but you passed: "${type}".`) - } - } - - return ret -} - -/** - * Export. - * - * @type {Function} - */ - -export default normalizeNodeOrMarkProperties diff --git a/lib/utils/normalize.js b/lib/utils/normalize.js new file mode 100644 index 000000000..63b010be0 --- /dev/null +++ b/lib/utils/normalize.js @@ -0,0 +1,180 @@ + +import Block from '../models/block' +import Document from '../models/document' +import Inline from '../models/inline' +import Data from '../models/data' +import Mark from '../models/mark' +import Text from '../models/text' +import typeOf from 'type-of' + +/** + * Normalize a block argument `value`. + * + * @param {Block || String || Object} value + * @return {Block} + */ + +function block(value) { + if (value instanceof Block) return value + const type = typeOf(value) + + switch (type) { + case 'string': + case 'object': { + return Block.create(nodeProperties(value)) + } + default: { + throw new Error(`Invalid \`block\` argument! It must be a block, an object, or a string. You passed: "${value}".`) + } + } +} + +/** + * Normalize an inline argument `value`. + * + * @param {Inline || String || Object} value + * @return {Inline} + */ + +function inline(value) { + if (value instanceof Inline) return value + const type = typeOf(value) + + switch (type) { + case 'string': + case 'object': { + return Inline.create(nodeProperties(value)) + } + default: { + throw new Error(`Invalid \`inline\` argument! It must be an inline, an object, or a string. You passed: "${value}".`) + } + } +} + +/** + * Normalize a key argument `value`. + * + * @param {String || Node} value + * @return {String} + */ + +function key(value) { + if (value instanceof Block) return value.key + if (value instanceof Inline) return value.key + if (value instanceof Text) return value.key + + // Special-case document for now. + if (value instanceof Document) return + + const type = typeOf(value) + if (type == 'string') return value + + throw new Error(`Invalid \`key\` argument! It must be either a block, an inline, a text, or a string. You passed: "${value}".`) +} + +/** + * Normalize a mark argument `value`. + * + * @param {Mark || String || Object} mark + * @return {Mark} + */ + +function mark(value) { + if (value instanceof Mark) return value + const type = typeOf(value) + + switch (type) { + case 'string': + case 'object': { + return Mark.create(markProperties(value)) + } + default: { + throw new Error(`Invalid \`mark\` argument! It must be a mark, an object, or a string. You passed: "${value}".`) + } + } +} + +/** + * Normalize a mark properties argument `value`. + * + * @param {String || Object} value + * @return {Object} + */ + +function markProperties(value = {}) { + const ret = {} + const type = typeOf(value) + + switch (type) { + case 'string': { + ret.type = value + break + } + case 'object': { + for (const k in value) { + if (k == 'data') { + if (value[k] != null) ret[k] = Data.create(value[k]) + } else { + ret[k] = value[k] + } + } + break + } + default: { + throw new Error(`Invalid mark \`properties\` argument! It must be an object or a string. You passed: "${value}".`) + } + } + + return ret +} + +/** + * Normalize a node properties argument `value`. + * + * @param {String || Object} value + * @return {Object} + */ + +function nodeProperties(value = {}) { + const ret = {} + const type = typeOf(value) + + switch (type) { + case 'string': { + ret.type = value + break + } + case 'object': { + if (value.isVoid != null) ret.isVoid = !!value.isVoid + for (const k in value) { + if (k == 'data') { + if (value[k] != null) ret[k] = Data.create(value[k]) + } else { + ret[k] = value[k] + } + } + break + } + default: { + throw new Error(`Invalid node \`properties\` argument! It must be an object or a string. You passed: "${value}".`) + } + } + + return ret +} + +/** + * Export. + * + * @type {Object} + */ + +export default { + block, + inline, + key, + mark, + markProperties, + nodeProperties, +} +