diff --git a/lib/serializers/raw.js b/lib/serializers/raw.js index 4e4bd822f..0c5e2ca3d 100644 --- a/lib/serializers/raw.js +++ b/lib/serializers/raw.js @@ -116,7 +116,7 @@ function deserializeNode(object) { type: object.type, data: object.data, isVoid: object.isVoid, - nodes: Block.createList(object.nodes.map(deserializeNode)) + nodes: Block.createList((object.nodes || []).map(deserializeNode)) }) } case 'inline': { @@ -124,12 +124,12 @@ function deserializeNode(object) { type: object.type, data: object.data, isVoid: object.isVoid, - nodes: Inline.createList(object.nodes.map(deserializeNode)) + nodes: Inline.createList((object.nodes || []).map(deserializeNode)) }) } case 'text': { return Text.create({ - characters: deserializeRanges(object.ranges) + characters: object.ranges ? deserializeRanges(object.ranges) : '' }) } default: { diff --git a/test/serializers/fixtures/html/deserialize/block-nested/index.js b/test/serializers/fixtures/html/deserialize/block-nested/index.js new file mode 100644 index 000000000..40ee3b4ec --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-nested/index.js @@ -0,0 +1,23 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'blockquote': { + return { + kind: 'block', + type: 'quote', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/block-nested/input.html b/test/serializers/fixtures/html/deserialize/block-nested/input.html new file mode 100644 index 000000000..6db5cf1b7 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-nested/input.html @@ -0,0 +1 @@ +
diff --git a/test/serializers/fixtures/html/deserialize/block-nested/output.yaml b/test/serializers/fixtures/html/deserialize/block-nested/output.yaml new file mode 100644 index 000000000..f46e65acb --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-nested/output.yaml @@ -0,0 +1,17 @@ + +nodes: + - type: quote + isVoid: false + data: {} + nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: [] + - text: n + marks: [] + - text: e + marks: [] diff --git a/test/serializers/fixtures/html/deserialize/block-with-data/index.js b/test/serializers/fixtures/html/deserialize/block-with-data/index.js new file mode 100644 index 000000000..fb09dd585 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-with-data/index.js @@ -0,0 +1,17 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + data: { key: 'value' }, + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/block-with-data/input.html b/test/serializers/fixtures/html/deserialize/block-with-data/input.html new file mode 100644 index 000000000..84a25b07c --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-with-data/input.html @@ -0,0 +1 @@ +one
one
diff --git a/test/serializers/fixtures/html/deserialize/block-with-data/output.yaml b/test/serializers/fixtures/html/deserialize/block-with-data/output.yaml new file mode 100644 index 000000000..183a31ee8 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-with-data/output.yaml @@ -0,0 +1,14 @@ + +nodes: + - type: paragraph + isVoid: false + data: + key: value + nodes: + - characters: + - text: o + marks: [] + - text: n + marks: [] + - text: e + marks: [] diff --git a/test/serializers/fixtures/html/deserialize/block-with-is-void/index.js b/test/serializers/fixtures/html/deserialize/block-with-is-void/index.js new file mode 100644 index 000000000..96483e174 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-with-is-void/index.js @@ -0,0 +1,16 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + isVoid: true + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/block-with-is-void/input.html b/test/serializers/fixtures/html/deserialize/block-with-is-void/input.html new file mode 100644 index 000000000..84a25b07c --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-with-is-void/input.html @@ -0,0 +1 @@ +one
diff --git a/test/serializers/fixtures/html/deserialize/block-with-is-void/output.yaml b/test/serializers/fixtures/html/deserialize/block-with-is-void/output.yaml new file mode 100644 index 000000000..c18f3f47e --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block-with-is-void/output.yaml @@ -0,0 +1,7 @@ + +nodes: + - type: paragraph + isVoid: true + data: {} + nodes: + - characters: [] diff --git a/test/serializers/fixtures/html/deserialize/block/index.js b/test/serializers/fixtures/html/deserialize/block/index.js new file mode 100644 index 000000000..5b7c1e619 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block/index.js @@ -0,0 +1,16 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/block/input.html b/test/serializers/fixtures/html/deserialize/block/input.html new file mode 100644 index 000000000..84a25b07c --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block/input.html @@ -0,0 +1 @@ +one
diff --git a/test/serializers/fixtures/html/deserialize/block/output.yaml b/test/serializers/fixtures/html/deserialize/block/output.yaml new file mode 100644 index 000000000..4c208207b --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/block/output.yaml @@ -0,0 +1,13 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: [] + - text: n + marks: [] + - text: e + marks: [] diff --git a/test/serializers/fixtures/html/deserialize/inline-nested/index.js b/test/serializers/fixtures/html/deserialize/inline-nested/index.js new file mode 100644 index 000000000..709586a9f --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-nested/index.js @@ -0,0 +1,30 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'a': { + return { + kind: 'inline', + type: 'link', + nodes: next(el.children) + } + } + case 'b': { + return { + kind: 'inline', + type: 'hashtag', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/inline-nested/input.html b/test/serializers/fixtures/html/deserialize/inline-nested/input.html new file mode 100644 index 000000000..aa14ba2a1 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-nested/input.html @@ -0,0 +1 @@ + diff --git a/test/serializers/fixtures/html/deserialize/inline-nested/output.yaml b/test/serializers/fixtures/html/deserialize/inline-nested/output.yaml new file mode 100644 index 000000000..6cc09ef75 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-nested/output.yaml @@ -0,0 +1,21 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - type: link + isVoid: false + data: {} + nodes: + - type: hashtag + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: [] + - text: n + marks: [] + - text: e + marks: [] diff --git a/test/serializers/fixtures/html/deserialize/inline-with-data/index.js b/test/serializers/fixtures/html/deserialize/inline-with-data/index.js new file mode 100644 index 000000000..17d656636 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-with-data/index.js @@ -0,0 +1,26 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'a': { + return { + kind: 'inline', + type: 'link', + nodes: next(el.children), + data: { + href: el.attribs.href + } + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/inline-with-data/input.html b/test/serializers/fixtures/html/deserialize/inline-with-data/input.html new file mode 100644 index 000000000..54b075fe5 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-with-data/input.html @@ -0,0 +1 @@ + diff --git a/test/serializers/fixtures/html/deserialize/inline-with-data/output.yaml b/test/serializers/fixtures/html/deserialize/inline-with-data/output.yaml new file mode 100644 index 000000000..126ef10f5 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-with-data/output.yaml @@ -0,0 +1,18 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - type: link + isVoid: false + data: + href: https://google.com + nodes: + - characters: + - text: o + marks: [] + - text: n + marks: [] + - text: e + marks: [] diff --git a/test/serializers/fixtures/html/deserialize/inline-with-is-void/index.js b/test/serializers/fixtures/html/deserialize/inline-with-is-void/index.js new file mode 100644 index 000000000..e4d708733 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-with-is-void/index.js @@ -0,0 +1,23 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'a': { + return { + kind: 'inline', + type: 'link', + isVoid: true + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/inline-with-is-void/input.html b/test/serializers/fixtures/html/deserialize/inline-with-is-void/input.html new file mode 100644 index 000000000..20c6fcd32 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-with-is-void/input.html @@ -0,0 +1 @@ + diff --git a/test/serializers/fixtures/html/deserialize/inline-with-is-void/output.yaml b/test/serializers/fixtures/html/deserialize/inline-with-is-void/output.yaml new file mode 100644 index 000000000..d43f53514 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline-with-is-void/output.yaml @@ -0,0 +1,11 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - type: link + isVoid: true + data: {} + nodes: + - characters: [] diff --git a/test/serializers/fixtures/html/deserialize/inline/index.js b/test/serializers/fixtures/html/deserialize/inline/index.js new file mode 100644 index 000000000..776ac0183 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline/index.js @@ -0,0 +1,23 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'a': { + return { + kind: 'inline', + type: 'link', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/inline/input.html b/test/serializers/fixtures/html/deserialize/inline/input.html new file mode 100644 index 000000000..20c6fcd32 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline/input.html @@ -0,0 +1 @@ + diff --git a/test/serializers/fixtures/html/deserialize/inline/output.yaml b/test/serializers/fixtures/html/deserialize/inline/output.yaml new file mode 100644 index 000000000..963558dc1 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/inline/output.yaml @@ -0,0 +1,17 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - type: link + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: [] + - text: n + marks: [] + - text: e + marks: [] diff --git a/test/serializers/fixtures/html/deserialize/mark-interleaved/index.js b/test/serializers/fixtures/html/deserialize/mark-interleaved/index.js new file mode 100644 index 000000000..b3f711620 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark-interleaved/index.js @@ -0,0 +1,30 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'em': { + return { + kind: 'mark', + type: 'italic', + nodes: next(el.children) + } + } + case 'strong': { + return { + kind: 'mark', + type: 'bold', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/mark-interleaved/input.html b/test/serializers/fixtures/html/deserialize/mark-interleaved/input.html new file mode 100644 index 000000000..ef7e16c4d --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark-interleaved/input.html @@ -0,0 +1 @@ +one
diff --git a/test/serializers/fixtures/html/deserialize/mark-interleaved/output.yaml b/test/serializers/fixtures/html/deserialize/mark-interleaved/output.yaml new file mode 100644 index 000000000..301ed48a8 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark-interleaved/output.yaml @@ -0,0 +1,25 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: + - type: bold + data: {} + - type: italic + data: {} + - text: n + marks: + - type: bold + data: {} + - type: italic + data: {} + - text: e + marks: + - type: bold + data: {} + - type: italic + data: {} diff --git a/test/serializers/fixtures/html/deserialize/mark-nested/index.js b/test/serializers/fixtures/html/deserialize/mark-nested/index.js new file mode 100644 index 000000000..b3f711620 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark-nested/index.js @@ -0,0 +1,30 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'em': { + return { + kind: 'mark', + type: 'italic', + nodes: next(el.children) + } + } + case 'strong': { + return { + kind: 'mark', + type: 'bold', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/mark-nested/input.html b/test/serializers/fixtures/html/deserialize/mark-nested/input.html new file mode 100644 index 000000000..b1024beed --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark-nested/input.html @@ -0,0 +1 @@ +one
diff --git a/test/serializers/fixtures/html/deserialize/mark-nested/output.yaml b/test/serializers/fixtures/html/deserialize/mark-nested/output.yaml new file mode 100644 index 000000000..301ed48a8 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark-nested/output.yaml @@ -0,0 +1,25 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: + - type: bold + data: {} + - type: italic + data: {} + - text: n + marks: + - type: bold + data: {} + - type: italic + data: {} + - text: e + marks: + - type: bold + data: {} + - type: italic + data: {} diff --git a/test/serializers/fixtures/html/deserialize/mark/index.js b/test/serializers/fixtures/html/deserialize/mark/index.js new file mode 100644 index 000000000..e5f82aff6 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark/index.js @@ -0,0 +1,23 @@ + +export default [ + { + deserialize(el, next) { + switch (el.tagName) { + case 'p': { + return { + kind: 'block', + type: 'paragraph', + nodes: next(el.children) + } + } + case 'em': { + return { + kind: 'mark', + type: 'italic', + nodes: next(el.children) + } + } + } + } + } +] diff --git a/test/serializers/fixtures/html/deserialize/mark/input.html b/test/serializers/fixtures/html/deserialize/mark/input.html new file mode 100644 index 000000000..0ef34951a --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark/input.html @@ -0,0 +1 @@ +one
diff --git a/test/serializers/fixtures/html/deserialize/mark/output.yaml b/test/serializers/fixtures/html/deserialize/mark/output.yaml new file mode 100644 index 000000000..7465a65d4 --- /dev/null +++ b/test/serializers/fixtures/html/deserialize/mark/output.yaml @@ -0,0 +1,19 @@ + +nodes: + - type: paragraph + isVoid: false + data: {} + nodes: + - characters: + - text: o + marks: + - type: italic + data: {} + - text: n + marks: + - type: italic + data: {} + - text: e + marks: + - type: italic + data: {} diff --git a/test/serializers/index.js b/test/serializers/index.js index 574f0b616..689a91a89 100644 --- a/test/serializers/index.js +++ b/test/serializers/index.js @@ -6,85 +6,111 @@ import { Html, Plain, Raw } from '../..' import { equal, strictEqual } from '../helpers/assert-json' import { resolve } from 'path' -/** - * Serializers. - */ - -const SERIALIZERS = { - - html: (dir) => { - const module = require(dir) - const html = new Html(module) - return { - extension: 'html', - deserialize: html.deserialize, - serialize: html.serialize, - read: file => fs.readFileSync(file, 'utf8').trim() - } - }, - - plain: (dir) => ({ - extension: 'txt', - deserialize: Plain.deserialize, - serialize: Plain.serialize, - read: file => fs.readFileSync(file, 'utf8').trim() - }), - - raw: (dir) => ({ - extension: 'yaml', - deserialize: Raw.deserialize, - serialize: Raw.serialize, - read: file => readMetadata.sync(file) - }) - -} - /** * Tests. */ describe('serializers', () => { - const serializers = fs.readdirSync(resolve(__dirname, './fixtures')) + describe('html', () => { + describe('deserialize()', () => { + const dir = resolve(__dirname, './fixtures/html/deserialize') + const tests = fs.readdirSync(dir) - for (const serializer of serializers) { - describe(serializer, () => { - describe('deserialize()', () => { - const dir = resolve(__dirname, './fixtures', serializer, 'deserialize') - const tests = fs.readdirSync(dir) - - for (const test of tests) { - it(test, () => { - const innerDir = resolve(dir, test) - const Serializer = SERIALIZERS[serializer](innerDir) - - const expected = readMetadata.sync(resolve(innerDir, 'output.yaml')) - const input = Serializer.read(resolve(innerDir, `input.${Serializer.extension}`)) - const state = Serializer.deserialize(input) - const json = state.document.toJS() - strictEqual(clean(json), expected) - }) - } - }) - - describe('serialize()', () => { - const dir = resolve(__dirname, './fixtures', serializer, 'serialize') - const tests = fs.readdirSync(dir) - - for (const test of tests) { - it(test, () => { - const innerDir = resolve(dir, test) - const Serializer = SERIALIZERS[serializer](innerDir) - - const input = require(resolve(innerDir, 'input.js')).default - const expected = Serializer.read(resolve(innerDir, `output.${Serializer.extension}`)) - const serialized = Serializer.serialize(input) - debugger - strictEqual(serialized, expected) - }) - } - }) + for (const test of tests) { + it(test, () => { + const innerDir = resolve(dir, test) + const html = new Html(require(innerDir).default) + const expected = readMetadata.sync(resolve(innerDir, 'output.yaml')) + const input = fs.readFileSync(resolve(innerDir, 'input.html'), 'utf8') + const state = html.deserialize(input) + const json = state.document.toJS() + strictEqual(clean(json), expected) + }) + } }) - } + + describe('serialize()', () => { + const dir = resolve(__dirname, './fixtures/html/serialize') + const tests = fs.readdirSync(dir) + + for (const test of tests) { + it(test, () => { + const innerDir = resolve(dir, test) + const html = new Html(require(innerDir).default) + const input = require(resolve(innerDir, 'input.js')).default + const expected = fs.readFileSync(resolve(innerDir, 'output.html'), 'utf8') + const serialized = html.serialize(input) + strictEqual(serialized, expected.trim()) + }) + } + }) + }) + + describe('plain', () => { + describe('deserialize()', () => { + const dir = resolve(__dirname, './fixtures/plain/deserialize') + const tests = fs.readdirSync(dir) + + for (const test of tests) { + it(test, () => { + const innerDir = resolve(dir, test) + const expected = readMetadata.sync(resolve(innerDir, 'output.yaml')) + const input = fs.readFileSync(resolve(innerDir, 'input.txt'), 'utf8') + const state = Plain.deserialize(input.trim()) + const json = state.document.toJS() + strictEqual(clean(json), expected) + }) + } + }) + + describe('serialize()', () => { + const dir = resolve(__dirname, './fixtures/plain/serialize') + const tests = fs.readdirSync(dir) + + for (const test of tests) { + it(test, () => { + const innerDir = resolve(dir, test) + const input = require(resolve(innerDir, 'input.js')).default + const expected = fs.readFileSync(resolve(innerDir, 'output.txt'), 'utf8') + const serialized = Plain.serialize(input) + strictEqual(serialized, expected.trim()) + }) + } + }) + }) + + describe('raw', () => { + describe('deserialize()', () => { + const dir = resolve(__dirname, './fixtures/raw/deserialize') + const tests = fs.readdirSync(dir) + + for (const test of tests) { + it(test, () => { + const innerDir = resolve(dir, test) + const expected = readMetadata.sync(resolve(innerDir, 'output.yaml')) + const input = readMetadata.sync(resolve(innerDir, 'input.yaml')) + const state = Raw.deserialize(input) + const json = state.document.toJS() + strictEqual(clean(json), expected) + }) + } + }) + + describe('serialize()', () => { + const dir = resolve(__dirname, './fixtures/raw/serialize') + const tests = fs.readdirSync(dir) + + for (const test of tests) { + it(test, () => { + const innerDir = resolve(dir, test) + const input = require(resolve(innerDir, 'input.js')).default + const expected = readMetadata.sync(resolve(innerDir, 'output.yaml')) + const serialized = Raw.serialize(input) + strictEqual(serialized, expected) + }) + } + }) + }) }) /**