Skip to content

Instantly share code, notes, and snippets.

@ababol
Last active January 29, 2019 17:29
Show Gist options
  • Save ababol/f1243d2b250ed20ccc9814f502a9a63b to your computer and use it in GitHub Desktop.
Save ababol/f1243d2b250ed20ccc9814f502a9a63b to your computer and use it in GitHub Desktop.
import React from 'react';
import { BLOCKS } from '@contentful/rich-text-types';
import { documentToHtmlString } from './lib';
import BlogPostBlockquoteEmoji, {
contentfulId as BLOCKQUOTE_EMOJI,
} from '../BlogPostBlockquoteEmoji';
import BlogPostCaption, { contentfulId as CAPTION } from '../BlogPostCaption';
import BlogPostColumns, { contentfulId as COLUMNS } from '../BlogPostColumns';
import BlogPostImage from '../BlogPostImage';
const renderComponent = node => {
const {
data: {
target: {
fields,
sys: {
contentType: {
sys: { id },
},
},
},
},
} = node;
switch (id) {
case BLOCKQUOTE_EMOJI:
return <BlogPostBlockquoteEmoji {...fields} />;
case CAPTION:
return <BlogPostCaption {...fields} />;
case COLUMNS:
return <BlogPostColumns {...fields} />;
default:
return <span />;
}
};
const renderingOptions = {
renderNode: {
[BLOCKS.EMBEDDED_ASSET]: node => {
const {
data: {
target: {
fields: {
file: { url },
title,
},
},
},
} = node;
return <BlogPostImage title={title} url={url} />;
},
[BLOCKS.EMBEDDED_ENTRY]: node => renderComponent(node),
},
};
export default richText => documentToHtmlString(richText, renderingOptions);
import React from 'react';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
let NODE_KEY_I = 0;
var __assign = function() {
__assign =
Object.assign ||
function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function unwrapExports(x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default')
? x.default
: x;
}
function createCommonjsModule(fn, module) {
return (module = { exports: {} }), fn(module, module.exports), module.exports;
}
var richTextTypes_es5 = createCommonjsModule(function(module, exports) {
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Map of all Contentful block types. Blocks contain inline or block nodes.
*/
var BLOCKS = {
DOCUMENT: 'document',
PARAGRAPH: 'paragraph',
HEADING_1: 'heading-1',
HEADING_2: 'heading-2',
HEADING_3: 'heading-3',
HEADING_4: 'heading-4',
HEADING_5: 'heading-5',
HEADING_6: 'heading-6',
OL_LIST: 'ordered-list',
UL_LIST: 'unordered-list',
LIST_ITEM: 'list-item',
HR: 'hr',
QUOTE: 'blockquote',
EMBEDDED_ENTRY: 'embedded-entry-block',
EMBEDDED_ASSET: 'embedded-asset-block',
};
/**
* Map of all Contentful inline types. Inline contain inline or text nodes.
*/
var INLINES = {
HYPERLINK: 'hyperlink',
ENTRY_HYPERLINK: 'entry-hyperlink',
ASSET_HYPERLINK: 'asset-hyperlink',
EMBEDDED_ENTRY: 'embedded-entry-inline',
};
/**
* Map of all Contentful marks.
*/
var marks = {
BOLD: 'bold',
ITALIC: 'italic',
UNDERLINE: 'underline',
CODE: 'code',
};
var _a;
/**
* Array of all top level block types.
* Only these block types can be the direct children of the document.
*/
var TOP_LEVEL_BLOCKS = [
BLOCKS.PARAGRAPH,
BLOCKS.HEADING_1,
BLOCKS.HEADING_2,
BLOCKS.HEADING_3,
BLOCKS.HEADING_4,
BLOCKS.HEADING_5,
BLOCKS.HEADING_6,
BLOCKS.OL_LIST,
BLOCKS.UL_LIST,
BLOCKS.HR,
BLOCKS.QUOTE,
BLOCKS.EMBEDDED_ENTRY,
BLOCKS.EMBEDDED_ASSET,
];
/**
* Array of all void block types
*/
var VOID_BLOCKS = [BLOCKS.HR, BLOCKS.EMBEDDED_ENTRY, BLOCKS.EMBEDDED_ASSET];
/**
* Dictionary of all container block types, and the set block types they accept as children.
*/
var CONTAINERS = ((_a = {}),
(_a[BLOCKS.OL_LIST] = [BLOCKS.LIST_ITEM]),
(_a[BLOCKS.UL_LIST] = [BLOCKS.LIST_ITEM]),
(_a[BLOCKS.LIST_ITEM] = TOP_LEVEL_BLOCKS.slice()),
(_a[BLOCKS.QUOTE] = [BLOCKS.PARAGRAPH]),
_a);
/**
* Checks if the node is an instance of Inline.
*/
function isInline(node) {
return Object.values(INLINES).includes(node.nodeType);
}
/**
* Checks if the node is an instance of Block.
*/
function isBlock(node) {
return Object.values(BLOCKS).includes(node.nodeType);
}
/**
* Checks if the node is an instance of Text.
*/
function isText(node) {
return node.nodeType === 'text';
}
var helpers = /*#__PURE__*/ Object.freeze({
isInline: isInline,
isBlock: isBlock,
isText: isText,
});
exports.helpers = helpers;
exports.BLOCKS = BLOCKS;
exports.INLINES = INLINES;
exports.MARKS = marks;
exports.TOP_LEVEL_BLOCKS = TOP_LEVEL_BLOCKS;
exports.VOID_BLOCKS = VOID_BLOCKS;
exports.CONTAINERS = CONTAINERS;
});
unwrapExports(richTextTypes_es5);
var richTextTypes_es5_1 = richTextTypes_es5.helpers;
var richTextTypes_es5_2 = richTextTypes_es5.BLOCKS;
var richTextTypes_es5_3 = richTextTypes_es5.INLINES;
var richTextTypes_es5_4 = richTextTypes_es5.MARKS;
var richTextTypes_es5_5 = richTextTypes_es5.TOP_LEVEL_BLOCKS;
var richTextTypes_es5_6 = richTextTypes_es5.VOID_BLOCKS;
var richTextTypes_es5_7 = richTextTypes_es5.CONTAINERS;
var _a, _b;
var defaultNodeRenderers = ((_a = {}),
(_a[richTextTypes_es5_2.PARAGRAPH] = function(node, next) {
return <p>{next(node.content)}</p>;
}),
(_a[richTextTypes_es5_2.HEADING_1] = function(node, next) {
return <h1>{next(node.content)}</h1>;
}),
(_a[richTextTypes_es5_2.HEADING_2] = function(node, next) {
return <h2>{next(node.content)}</h2>;
}),
(_a[richTextTypes_es5_2.HEADING_3] = function(node, next) {
return <h3>{next(node.content)}</h3>;
}),
(_a[richTextTypes_es5_2.HEADING_4] = function(node, next) {
return <h4>{next(node.content)}</h4>;
}),
(_a[richTextTypes_es5_2.HEADING_5] = function(node, next) {
return <h5>{next(node.content)}</h5>;
}),
(_a[richTextTypes_es5_2.HEADING_6] = function(node, next) {
return <h6>{next(node.content)}</h6>;
}),
(_a[richTextTypes_es5_2.EMBEDDED_ENTRY] = function(node, next) {
return <div>{next(node.content)}</div>;
}),
(_a[richTextTypes_es5_2.UL_LIST] = function(node, next) {
return <ul>{next(node.content)}</ul>;
}),
(_a[richTextTypes_es5_2.OL_LIST] = function(node, next) {
return <ol>{next(node.content)}</ol>;
}),
(_a[richTextTypes_es5_2.LIST_ITEM] = function(node, next) {
return <li>{next(node.content)}</li>;
}),
(_a[richTextTypes_es5_2.QUOTE] = function(node, next) {
return <blockquote>{next(node.content)}</blockquote>;
}),
(_a[richTextTypes_es5_2.HR] = function() {
return <hr />;
}),
(_a[richTextTypes_es5_3.ASSET_HYPERLINK] = function(node) {
return defaultInline(richTextTypes_es5_3.ASSET_HYPERLINK, node);
}),
(_a[richTextTypes_es5_3.ENTRY_HYPERLINK] = function(node) {
return defaultInline(richTextTypes_es5_3.ENTRY_HYPERLINK, node);
}),
(_a[richTextTypes_es5_3.EMBEDDED_ENTRY] = function(node) {
return defaultInline(richTextTypes_es5_3.EMBEDDED_ENTRY, node);
}),
(_a[richTextTypes_es5_3.HYPERLINK] = function(node, next) {
return <a href={node.data.uri}>{next(node.content)}</a>;
}),
_a);
var defaultMarkRenderers = ((_b = {}),
(_b[richTextTypes_es5_4.BOLD] = function(text) {
return <strong>{text}</strong>;
}),
(_b[richTextTypes_es5_4.ITALIC] = function(text) {
return <i>{text}</i>;
}),
(_b[richTextTypes_es5_4.UNDERLINE] = function(text) {
return <u>{text}</u>;
}),
(_b[richTextTypes_es5_4.CODE] = function(text) {
return <code>{text}</code>;
}),
_b);
var defaultInline = function(type, node) {
return '<span>type: ' + type + ' id: ' + node.data.target.sys.id + '</span>';
};
function nodeListToHtmlString(nodes, _a) {
var renderNode = _a.renderNode,
renderMark = _a.renderMark;
return nodes.map(function(node) {
return nodeToHtmlString(node, {
renderNode: renderNode,
renderMark: renderMark,
});
});
}
function nodeToHtmlString(node, _a) {
var renderNode = _a.renderNode,
renderMark = _a.renderMark;
if (richTextTypes_es5_1.isText(node)) {
if (node.marks.length > 0) {
return node.marks.reduce(function(value, mark) {
if (!renderMark[mark.type]) {
return value;
}
return {
...renderMark[mark.type](value),
key: NODE_KEY_I++,
};
}, node.value);
}
return node.value;
} else {
var nextNode = function(nodes) {
return nodeListToHtmlString(nodes, {
renderMark: renderMark,
renderNode: renderNode,
});
};
if (!node.nodeType || !renderNode[node.nodeType]) {
// TODO: Figure what to return when passed an unrecognized node.
return null;
}
return {
...renderNode[node.nodeType](node, nextNode),
key: NODE_KEY_I++,
};
}
}
/**
* Serialize a Contentful Rich Text `document` to an html string.
*/
export const documentToHtmlString = (richTextDocument, options) => {
NODE_KEY_I = 0;
if (options === void 0) {
options = {};
}
return nodeListToHtmlString(richTextDocument.content, {
renderNode: __assign({}, defaultNodeRenderers, options.renderNode),
renderMark: __assign({}, defaultMarkRenderers, options.renderMark),
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment