Last active
January 29, 2019 17:29
-
-
Save ababol/f1243d2b250ed20ccc9814f502a9a63b to your computer and use it in GitHub Desktop.
Uggly Contentful fork of HTML renderer to support React Component - see https://github.com/shinetools/rich-text/tree/feat-add-rich-text-react-renderer/packages/rich-text-react-renderer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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