diff --git a/lib/serializers/html.js b/lib/serializers/html.js index 728e7b7e7..56980f528 100644 --- a/lib/serializers/html.js +++ b/lib/serializers/html.js @@ -9,6 +9,7 @@ import ReactDOMServer from 'react-dom/server' import State from '../models/state' import Text from '../models/text' import cheerio from 'cheerio' +import typeOf from 'type-of' import { Record } from 'immutable' /** @@ -133,11 +134,18 @@ class Html { elements.forEach((element) => { const node = this.deserializeElement(element) - if (!node) return - if (Array.isArray(node)) { - nodes = nodes.concat(node) - } else { - nodes.push(node) + switch (typeOf(node)) { + case 'array': + nodes = nodes.concat(node) + break + case 'object': + nodes.push(node) + break + case 'null': + case 'undefined': + return + default: + throw new Error(`A rule returned an invalid deserialized representation: "${node}".`) } }) @@ -155,9 +163,17 @@ class Html { let node const next = (elements) => { - return Array.isArray(elements) - ? this.deserializeElements(elements) - : this.deserializeElement(elements) + switch (typeOf(elements)) { + case 'array': + return this.deserializeElements(elements) + case 'object': + return this.deserializeElement(elements) + case 'null': + case 'undefined': + return + default: + throw new Error(`The \`next\` argument was called with invalid children: "${elements}".`) + } } for (const rule of this.rules) { @@ -246,6 +262,7 @@ class Html { const ret = rule.serialize(node, children) if (ret) return addKey(ret) } + throw new Error(`No serializer defined for node of type "${node.type}".`) } @@ -266,6 +283,7 @@ class Html { const ret = rule.serialize(mark, children) if (ret) return addKey(ret) } + throw new Error(`No serializer defined for mark of type "${mark.type}".`) }, text) } diff --git a/test/serializers/fixtures/html/deserialize/no-next/index.js b/test/serializers/fixtures/html/deserialize/no-next/index.js new file mode 100644 index 000000000..aa395c531 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/no-next/index.js @@ -0,0 +1,18 @@ + +export default { + rules: [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(undefined) + } + } + } + } + } + ] +} diff --git a/test/serializers/fixtures/html/deserialize/no-next/input.html b/test/serializers/fixtures/html/deserialize/no-next/input.html new file mode 100644 index 000000000..31ee88261 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/no-next/input.html @@ -0,0 +1 @@ +

diff --git a/test/serializers/fixtures/html/deserialize/no-next/output.yaml b/test/serializers/fixtures/html/deserialize/no-next/output.yaml new file mode 100644 index 000000000..337747150 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/no-next/output.yaml @@ -0,0 +1,7 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - characters: []