UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

137 lines 3.67 kB
import _pushInstanceProperty from "core-js-pure/stable/instance/push.js"; import React, { Fragment } from 'react'; import InlineLink from "./internal/InlineLink.js"; import CodeEl from "../elements/Code.js"; const Strong = c => React.createElement("strong", null, c); const Em = c => React.createElement("em", null, c); const Code = c => React.createElement(CodeEl, null, c); const Link = (c, href) => React.createElement(InlineLink, { href: href, rel: "noopener noreferrer" }, c); export default function renderWithFormatting(text, { br = '{br}', strong = Strong, em = Em, link = Link, code = Code } = {}) { if (typeof text === 'string') { const HAS_MARKERS_RE = /(`[^`]+`|\[[^\]]+\]\([^)\s]+\)|\bhttps?:\/\/[^\s<>()]+|\*\*[^*]+\*\*|_[^_]+_)/; const hasFormatting = br && text.includes(br) || HAS_MARKERS_RE.test(text); if (!hasFormatting) { return text; } } return withFormatting(text, { strong, em, br, link, code }); } function withFormatting(text, { br, strong, em, link, code }) { let nodes = Array.isArray(text) ? text : [text]; nodes = splitToken(nodes, br, ({ k }) => React.createElement("br", { key: k() })); const codeRe = /(`[^`]+`)/g; nodes = replaceInStrings(nodes, codeRe, (m, { k }) => [React.createElement(Fragment, { key: `c-${k()}` }, code(m[0].slice(1, -1)))]); const linkRe = /\[([^\]]+)\]\(([^)\s]+)\)/g; nodes = replaceInStrings(nodes, linkRe, (m, { k }) => { const [, label, href] = m; const children = withFormatting(label, { br, strong, em, link, code }); return [React.createElement(Fragment, { key: `a-${k()}` }, link(children, href))]; }); const bareUrlRe = /\b((?:https?:\/\/)[^\s<>()]+)\b/g; nodes = replaceInStrings(nodes, bareUrlRe, (m, { k }) => { const href = m[1]; return [React.createElement(Fragment, { key: `l-${k()}` }, link(href, href))]; }); const boldRe = /\*\*([^*]+)\*\*/g; nodes = replaceInStrings(nodes, boldRe, (m, { k }) => [React.createElement(Fragment, { key: `b-${k()}` }, strong(m[1]))]); const italicRe = /_([^_]+)_/g; nodes = replaceInStrings(nodes, italicRe, (m, { k }) => [React.createElement(Fragment, { key: `i-${k()}` }, em(m[1]))]); return React.createElement(Fragment, { key: "renderWithFormatting" }, nodes); } function replaceInStrings(nodes, re, replacer) { let key = 0; const k = () => String(key++); return nodes.flatMap((n, i) => { if (typeof n !== 'string') return [n]; const out = []; let last = 0; let m; while ((m = re.exec(n)) !== null) { const before = n.slice(last, m.index); if (before) _pushInstanceProperty(out).call(out, before); _pushInstanceProperty(out).call(out, ...replacer(m, { i, k })); last = m.index + m[0].length; if (re.lastIndex === m.index) re.lastIndex++; } const tail = n.slice(last); if (tail) _pushInstanceProperty(out).call(out, tail); return out; }); } function splitToken(nodes, token, make) { let key = 0; const k = () => String(key++); return nodes.flatMap((n, i) => { if (typeof n !== 'string') return [n]; const parts = n.split(token); const out = []; parts.forEach((chunk, idx) => { if (chunk) _pushInstanceProperty(out).call(out, chunk); if (idx < parts.length - 1) _pushInstanceProperty(out).call(out, React.createElement(Fragment, { key: k() }, make({ i, idx, k }))); }); return out; }); } //# sourceMappingURL=renderWithFormatting.js.map