From a7f65841796e65b30d2d16dbbcbeabee36125512 Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Mon, 6 Feb 2017 17:28:46 -0800 Subject: [PATCH] added `toRaw` option to Html and Plain serializers, fixes #583 #584 --- docs/reference/serializers/html.md | 8 +++- docs/reference/serializers/plain.md | 4 +- src/serializers/html.js | 18 +++++++- src/serializers/plain.js | 66 ++++++++++++----------------- src/serializers/raw.js | 2 +- test/serializers/index.js | 52 +++++++++++++++++++++++ 6 files changed, 106 insertions(+), 44 deletions(-) diff --git a/docs/reference/serializers/html.md b/docs/reference/serializers/html.md index 62f77167d..75bdf0748 100644 --- a/docs/reference/serializers/html.md +++ b/docs/reference/serializers/html.md @@ -46,14 +46,18 @@ An array of rules to initialize the `Html` serializer with, defining your schema ## Methods ### `Html.deserialize` -`Html.deserialize(html: String) => State` +`Html.deserialize(html: String, [options: Object]) => State` Deserialize an HTML `string` into a [`State`](../models/state.md). How the string is deserialized will be determined by the rules that the `Html` serializer was constructed with. +If you pass `toRaw: true` as an option, the return value will be a [`Raw`](./raw.md) JSON object instead of a [`State`](../models/state.md) object. + ### `Html.serialize` `Html.serialize(state: State, [options: Object]) => String || Array` -Serialize a `state` into an HTML string. How the string is serialized will be determined by the rules that the `Html` serializer was constructed with. If you pass `render: false` as an option, the return value will instead be an iterable list of the top-level React elements, to be rendered as children in your own React component. +Serialize a `state` into an HTML string. How the string is serialized will be determined by the rules that the `Html` serializer was constructed with. + +If you pass `render: false` as an option, the return value will instead be an iterable list of the top-level React elements, to be rendered as children in your own React component. ## Rules diff --git a/docs/reference/serializers/plain.md b/docs/reference/serializers/plain.md index 9cdbb6b33..409a4b250 100644 --- a/docs/reference/serializers/plain.md +++ b/docs/reference/serializers/plain.md @@ -25,10 +25,12 @@ Check out http://slatejs.org for examples! ## Methods ### `Plain.deserialize` -`Plain.deserialize(string: String) => State` +`Plain.deserialize(string: String, [options: Object]) => State` Deserialize a plain text `string` into a [`State`](../models/state.md). A series of blocks will be created by splitting the input string on `\n` characters. Each block is given a type of `'line'`. +If you pass `toRaw: true` as an option, the return value will be a [`Raw`](./raw.md) JSON object instead of a [`State`](../models/state.md) object. + ### `Plain.serialize` `Plain.serialize(state: State) => String` diff --git a/src/serializers/html.js b/src/serializers/html.js index 3e8c1405d..8ecd648b3 100644 --- a/src/serializers/html.js +++ b/src/serializers/html.js @@ -85,10 +85,12 @@ class Html { * Deserialize pasted HTML. * * @param {String} html + * @param {Object} options + * @property {Boolean} toRaw * @return {State} */ - deserialize = (html) => { + deserialize = (html, options = {}) => { const $ = cheerio.load(html).root() const children = $.children().toArray() let nodes = this.deserializeElements(children) @@ -116,7 +118,19 @@ class Html { return memo }, []) - const state = Raw.deserialize({ nodes }, { terse: true }) + const raw = { + kind: 'state', + document: { + kind: 'document', + nodes, + } + } + + if (options.toRaw) { + return raw + } + + const state = Raw.deserialize(raw, { terse: true }) return state } diff --git a/src/serializers/plain.js b/src/serializers/plain.js index 93020f2b0..81491b63a 100644 --- a/src/serializers/plain.js +++ b/src/serializers/plain.js @@ -1,51 +1,41 @@ -import Block from '../models/block' -import Document from '../models/document' -import State from '../models/state' -import Text from '../models/text' +import Raw from '../serializers/raw' /** * Deserialize a plain text `string` to a state. * * @param {String} string + * @param {Object} options + * @property {Boolean} toRaw * @return {State} */ -function deserialize(string) { - return State.create({ - document: Document.create({ - nodes: string.split('\n').map(deserializeLine) - }) - }) -} +function deserialize(string, options = {}) { + const raw = { + kind: 'state', + document: { + kind: 'document', + nodes: string.split('\n').map((line) => { + return { + kind: 'block', + type: 'line', + nodes: [ + { + kind: 'text', + ranges: [ + { + text: line, + marks: [], + } + ] + } + ] + } + }), + } + } -/** - * Deserialize a `line` of text. - * - * @param {String} line - * @return {Block} - */ - -function deserializeLine(line) { - return Block.create({ - type: 'line', - nodes: [ - Text.create({ - characters: line.split('').map(deserializeCharacter) - }) - ] - }) -} - -/** - * Deserialize a `character`. - * - * @param {String} char - * @return {Character} - */ - -function deserializeCharacter(char) { - return { text: char } + return options.toRaw ? raw : Raw.deserialize(raw) } /** diff --git a/src/serializers/raw.js b/src/serializers/raw.js index dc000c361..b4327e32b 100644 --- a/src/serializers/raw.js +++ b/src/serializers/raw.js @@ -671,7 +671,7 @@ const Raw = { */ untersifyState(object) { - if (object.selection != null) { + if (object.selection || object.document) { return { kind: 'state', document: object.document, diff --git a/test/serializers/index.js b/test/serializers/index.js index 8a71af4e5..bc9e59599 100644 --- a/test/serializers/index.js +++ b/test/serializers/index.js @@ -30,6 +30,30 @@ describe('serializers', () => { assert.deepEqual(strip(json), expected) }) } + + it('optionally returns a raw representation', () => { + const html = new Html(require('./fixtures/html/deserialize/block').default) + const input = fs.readFileSync(resolve(__dirname, './fixtures/html/deserialize/block/input.html'), 'utf8') + const serialized = html.deserialize(input, { toRaw: true }) + assert.deepEqual(serialized, { + kind: 'state', + document: { + kind: 'document', + nodes: [ + { + kind: 'block', + type: 'paragraph', + nodes: [ + { + kind: 'text', + text: 'one' + } + ] + } + ] + } + }) + }) }) describe('serialize()', () => { @@ -74,6 +98,34 @@ describe('serializers', () => { assert.deepEqual(strip(json), expected) }) } + + it('optionally returns a raw representation', () => { + const input = fs.readFileSync(resolve(__dirname, './fixtures/plain/deserialize/line/input.txt'), 'utf8') + const serialized = Plain.deserialize(input.replace(/\n$/m, ''), { toRaw: true }) + assert.deepEqual(serialized, { + kind: 'state', + document: { + kind: 'document', + nodes: [ + { + kind: 'block', + type: 'line', + nodes: [ + { + kind: 'text', + ranges: [ + { + marks: [], + text: 'one', + } + ] + } + ] + } + ] + } + }) + }) }) describe('serialize()', () => {