diff --git a/docs/reference/serializers/html.md b/docs/reference/serializers/html.md index 6c73070a9..62f77167d 100644 --- a/docs/reference/serializers/html.md +++ b/docs/reference/serializers/html.md @@ -51,9 +51,9 @@ An array of rules to initialize the `Html` serializer with, defining your schema 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. ### `Html.serialize` -`Html.serialize(state: State) => String` +`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. +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 @@ -73,7 +73,7 @@ Each rule must define two properties: #### `rule.deserialize` `rule.deserialize(el: CheerioElement, next: Function) => Object || Void` -The `deserialize` function should return a plain Javascript object representing the deserialized state, or nothing if the rule in question doesn't know how to deserialize the object, in which case the next rule in the stack will be attempted. +The `deserialize` function should return a plain Javascript object representing the deserialized state, or nothing if the rule in question doesn't know how to deserialize the object, in which case the next rule in the stack will be attempted. The returned object is almost exactly equivalent to the objects returned by the [`Raw`](./raw.md) serializer, except an extra `kind: 'mark'` is added to account for the ability to nest marks. diff --git a/src/serializers/Readme.md b/src/serializers/Readme.md index 7130a0ed9..2ade83fac 100644 --- a/src/serializers/Readme.md +++ b/src/serializers/Readme.md @@ -8,10 +8,12 @@ This directory contains the serializers that ship by default with Slate. They ar The `Html` serializer offers a simple way to serialize and deserialize an HTML schema of your choosing. -It doesn't hardcode any information about the schema itself (like which tag means "bold"), but allows you to build up a simple HTML serializer for your own use case. +It doesn't hardcode any information about the schema itself (like which tag means "bold"), but allows you to build up a simple HTML serializer for your own use case. It handles all of the heavy lifting of actually parsing the HTML, and iterating over the elements, and all you have to supply it is a `serialize()` and `deserialize()` function for each type of [`Node`](../models#node) or [`Mark`](../models/#mark) you want it to handle. +If called with `{render: false}` as the optional second argument, the serializer will return an iterable list of the top-level React elements generated, instead of automatically rendering these to a markup string. + #### Raw @@ -20,4 +22,3 @@ The `Raw` serializer is the simplest serializer, which translates a [`State`](.. It doesn't just use Immutable.js's [`.toJSON()`](https://facebook.github.io/immutable-js/docs/#/List/toJS) method. Instead, it performs a little bit of "minifying" logic to reduce unnecessary information from being in the raw output. It also transforms [`Text`](../models#text) nodes's content from being organized by [`Characters`](../models#character) into the concept of "ranges", which have a unique set of [`Marks`](../models#mark). - diff --git a/src/serializers/html.js b/src/serializers/html.js index 56980f528..6ddc946fd 100644 --- a/src/serializers/html.js +++ b/src/serializers/html.js @@ -231,12 +231,16 @@ class Html { * Serialize a `state` object into an HTML string. * * @param {State} state - * @return {String} html + * @param {Object} options + * @property {Boolean} render + * @return {String|Array} html */ - serialize = (state) => { + serialize = (state, options = {}) => { const { document } = state const elements = document.nodes.map(this.serializeNode) + if (options.render === false) return elements + const html = ReactDOMServer.renderToStaticMarkup({elements}) const inner = html.slice(6, -7) return inner diff --git a/test/serializers/index.js b/test/serializers/index.js index 95e08aafe..79a372611 100644 --- a/test/serializers/index.js +++ b/test/serializers/index.js @@ -1,11 +1,14 @@ import assert from 'assert' +import type from 'type-of' import fs from 'fs' import readMetadata from 'read-metadata' import strip from '../helpers/strip-dynamic' import { Html, Json, Plain, Raw } from '../..' import { equal, strictEqual } from '../helpers/assert-json' import { resolve } from 'path' +import React from 'react' +import { Iterable } from 'immutable' /** * Tests. @@ -46,6 +49,14 @@ describe('serializers', () => { strictEqual(serialized, expected.trim()) }) } + + it('optionally returns an iterable list of React elements', () => { + const html = new Html(require('./fixtures/html/serialize/block-nested').default) + const input = require('./fixtures/html/serialize/block-nested/input.js').default + const serialized = html.serialize(input, { render: false }) + assert(Iterable.isIterable(serialized), 'did not return an interable list') + assert(React.isValidElement(serialized.first()), 'did not return valid React elements') + }) }) })