"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.markdownFactory = exports.default = exports.Markdown = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _classnames = _interopRequireDefault(require("classnames")); var _react = _interopRequireWildcard(require("react")); var _markdownIt = _interopRequireDefault(require("markdown-it")); var _lodash = require("lodash"); var _eui = require("@elastic/eui"); require("./index.scss"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ /** * Return a memoized markdown rendering function that use the specified * whiteListedRules and openLinksInNewTab configurations. * @param {Array of Strings} whiteListedRules - white list of markdown rules * list of rules can be found at https://github.com/markdown-it/markdown-it/issues/361 * @param {Boolean} openLinksInNewTab * @return {Function} Returns an Object to use with dangerouslySetInnerHTML * with the rendered markdown HTML */ const markdownFactory = (0, _lodash.memoize)((whiteListedRules = [], openLinksInNewTab = false) => { let markdownIt; // It is imperative that the html config property be set to false, to mitigate XSS: the output of markdown-it is // fed directly to the DOM via React's dangerouslySetInnerHTML below. if (whiteListedRules && whiteListedRules.length > 0) { markdownIt = new _markdownIt.default('zero', { html: false, linkify: true }); markdownIt.enable(whiteListedRules); } else { markdownIt = new _markdownIt.default({ html: false, linkify: true }); } if (openLinksInNewTab) { // All links should open in new browser tab. // Define custom renderer to add 'target' attribute // https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer const originalLinkRender = markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) { return self.renderToken(tokens, idx, options); }; markdownIt.renderer.rules.link_open = function (tokens, idx, options, env, self) { const href = tokens[idx].attrGet('href'); const target = '_blank'; const rel = (0, _eui.getSecureRelForTarget)({ href: href === null ? undefined : href, target }); // https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/ tokens[idx].attrPush(['target', target]); if (rel) { tokens[idx].attrPush(['rel', rel]); } return originalLinkRender(tokens, idx, options, env, self); }; } /** * This method is used to render markdown from the passed parameter * into HTML. It will just return an empty string when the markdown is empty. * @param {String} markdown - The markdown String * @return {String} - Returns the rendered HTML as string. */ return markdown => { return markdown ? markdownIt.render(markdown) : ''; }; }, (whiteListedRules = [], openLinksInNewTab = false) => { return `${whiteListedRules.join('_')}${openLinksInNewTab}`; }); exports.markdownFactory = markdownFactory; const Markdown = props => { (0, _react.useEffect)(() => { var _props$onRender; (_props$onRender = props.onRender) === null || _props$onRender === void 0 ? void 0 : _props$onRender.call(props); }, [props]); const { className, markdown = '', openLinksInNewTab, whiteListedRules, ...rest } = props; const classes = (0, _classnames.default)('kbnMarkdown__body', className); const markdownRenderer = markdownFactory(whiteListedRules, openLinksInNewTab); const renderedMarkdown = markdownRenderer(markdown); return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, rest, { className: classes /* * Justification for dangerouslySetInnerHTML: * The Markdown Visualization is, believe it or not, responsible for rendering Markdown. * This relies on `markdown-it` to produce safe and correct HTML. */, dangerouslySetInnerHTML: { __html: renderedMarkdown } // eslint-disable-line react/no-danger })); }; // Needed for React.lazy // eslint-disable-next-line import/no-default-export exports.Markdown = Markdown; var _default = Markdown; exports.default = _default;