UNPKG

react-showdown

Version:

Render React components within markdown and markdown as React components!

243 lines (199 loc) 7.71 kB
import { Converter, setFlavor, getFlavor, setOption, getOption, getOptions, resetOptions, getAllExtensions, removeExtension, resetExtensions, extension } from 'showdown'; import React, { useMemo, createElement } from 'react'; import { parseDOM } from 'htmlparser2'; import { Element, DataNode } from 'domhandler'; function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } function MarkdownView(props) { var dangerouslySetInnerHTML = props.dangerouslySetInnerHTML, flavor = props.flavor, markdown = props.markdown, markup = props.markup, options = props.options, extensions = props.extensions, components = props.components, sanitizeHtml = props.sanitizeHtml, otherProps = _objectWithoutPropertiesLoose(props, ["dangerouslySetInnerHTML", "flavor", "markdown", "markup", "options", "extensions", "components", "sanitizeHtml"]); var mapElement = useMemo(function () { return function mapElement(node, index) { if (node.type === 'tag' && node instanceof Element) { var elementType = (components === null || components === void 0 ? void 0 : components[node.name]) || node.name; var _props = _extends({ key: index }, node.attribs); // Rename class to className to hide react warning if (_props["class"] && !_props.className) { _props.className = _props["class"]; delete _props["class"]; } // Map style strings to style objects if (typeof _props.style === 'string') { var styles = {}; _props.style.split(';').forEach(function (style) { if (style.indexOf(':') !== -1) { var _style$split = style.split(':'), key = _style$split[0], value = _style$split[1]; key = key.trim().replace(/-([a-z])/g, function (match) { return match[1].toUpperCase(); }); value = value.trim(); styles[key] = value; } }); _props.style = styles; } var children = skipAnyChildrenFor.includes(node.name) ? null : skipWhitespaceElementsFor.includes(node.name) ? node.children.filter(filterWhitespaceElements).map(mapElement) : node.children.map(mapElement); return createElement(elementType, _props, children); } else if (node.type === 'text' && node instanceof DataNode) { return node.data; } else if (node.type === 'comment') { return null; // noop } else if (node.type === 'style' && node instanceof Element) { var _props2 = _extends({ key: index }, node.attribs); var _children = node.children.map(mapElement); return createElement('style', _props2, _children); } else { console.warn("Warning: Could not map element with type \"" + node.type + "\".", node); return null; } }; }, [components]); if (dangerouslySetInnerHTML && components) { console.warn('MarkdownView could not render custom components when dangerouslySetInnerHTML is enabled.'); } var converter = new Converter(); if (flavor) { converter.setFlavor(flavor); } if (options) { for (var key in options) { if (key === 'extensions' && options.extensions) { for (var _iterator = _createForOfIteratorHelperLoose(options.extensions), _step; !(_step = _iterator()).done;) { var extension = _step.value; if (typeof extension === 'string') { converter.useExtension(extension); } else { converter.addExtension(extension); } } } converter.setOption(key, options[key]); } } if (extensions) { converter.addExtension(extensions); } var html = converter.makeHtml(markdown !== null && markdown !== void 0 ? markdown : markup); if (sanitizeHtml) { html = sanitizeHtml(html); } if (dangerouslySetInnerHTML) { return React.createElement("div", { dangerouslySetInnerHTML: { __html: html } }); } var root = parseDOM(html, { // Don't change the case of parsed html tags to match inline components. lowerCaseTags: false, // Don't change the attribute names so that stuff like `className` works correctly. lowerCaseAttributeNames: false, // Encode entities automatically, so that &copy; and &uuml; works correctly. decodeEntities: true, // Fix issue with content after a self closing tag. recognizeSelfClosing: true }); return createElement('div', otherProps, root.map(mapElement)); } // Match react-dom omittedCloseTags. See also: // https://github.com/facebook/react/blob/master/packages/react-dom/src/shared/omittedCloseTags.js var skipAnyChildrenFor = ['area', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'param', 'source', 'track', 'wbr']; var skipWhitespaceElementsFor = ['table', 'thead', 'tbody', 'tr']; function filterWhitespaceElements(node) { if (node.type === 'text' && node instanceof DataNode) { return node.data.trim().length > 0; } else { return true; } } var Markdown = MarkdownView; var setExtension = extension; var getExtension = extension; var GlobalConfiguration = { // Flavors, setFlavor: setFlavor, getFlavor: getFlavor, // Options setOption: setOption, getOption: getOption, getOptions: getOptions, resetOptions: resetOptions, // Extensions setExtension: setExtension, getExtension: getExtension, getAllExtensions: getAllExtensions, removeExtension: removeExtension, resetExtensions: resetExtensions }; export default MarkdownView; export { GlobalConfiguration, Markdown }; //# sourceMappingURL=react-showdown.esm.js.map