UNPKG

marked-react

Version:
330 lines (323 loc) 10.2 kB
Object.defineProperty(exports, '__esModule', { value: true }); //#region rolldown:runtime var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion const react = __toESM(require("react")); const marked = __toESM(require("marked")); //#region src/helpers.ts const htmlUnescapes = { "&amp;": "&", "&lt;": "<", "&gt;": ">", "&quot;": "\"", "&#39;": "'" }; /** Used to match HTML entities and HTML characters. */ const reEscapedHtml = /&(?:amp|lt|gt|quot|#(?:0+)?39);/g; const reHasEscapedHtml = RegExp(reEscapedHtml.source); const unescape = (str = "") => { return reHasEscapedHtml.test(str) ? str.replace(reEscapedHtml, (entity) => htmlUnescapes[entity] || "'") : str; }; const joinBase = (path, base) => { if (!base) return path; try { return new URL(path, base).href; } catch { return path; } }; //#endregion //#region src/ReactParser.ts var ReactParser = class { renderer; constructor(options) { this.renderer = options.renderer; } parse(tokens) { this.renderer.elIdList.push(0); const result = tokens.map((token) => { switch (token.type) { case "space": return null; case "heading": { const level = token.depth; return this.renderer.heading(this.parseInline(token.tokens), level); } case "paragraph": return this.renderer.paragraph(this.parseInline(token.tokens)); case "text": { const textToken = token; return textToken.tokens ? this.parseInline(textToken.tokens) : token.text; } case "blockquote": { const blockquoteToken = token; const quote = this.parse(blockquoteToken.tokens); return this.renderer.blockquote(quote); } case "list": { const listToken = token; this.renderer.elIdList.push(0); const children = listToken.items.map((item) => { const listItemChildren = []; if (item.task) listItemChildren.push(this.renderer.checkbox(item.checked ?? false)); listItemChildren.push(this.parse(item.tokens)); return this.renderer.listItem(listItemChildren); }); this.renderer.elIdList.pop(); return this.renderer.list(children, token.ordered, token.ordered ? token.start : void 0); } case "code": return this.renderer.code(token.text, token.lang); case "html": return this.renderer.html(token.text); case "table": { const tableToken = token; this.renderer.elIdList.push(0); const headerCells = tableToken.header.map((cell, index) => { return this.renderer.tableCell(this.parseInline(cell.tokens), { header: true, align: token.align[index] }); }); this.renderer.elIdList.pop(); const headerRow = this.renderer.tableRow(headerCells); const header = this.renderer.tableHeader(headerRow); this.renderer.elIdList.push(0); const bodyChilren = tableToken.rows.map((row) => { this.renderer.elIdList.push(0); const rowChildren = row.map((cell, index) => { return this.renderer.tableCell(this.parseInline(cell.tokens), { header: false, align: token.align[index] }); }); this.renderer.elIdList.pop(); return this.renderer.tableRow(rowChildren); }); this.renderer.elIdList.pop(); const body = this.renderer.tableBody(bodyChilren); return this.renderer.table([header, body]); } case "hr": return this.renderer.hr(); default: { console.warn(`Token with "${token.type}" type was not found`); return null; } } }); this.renderer.elIdList.pop(); return result; } parseInline(tokens = []) { this.renderer.elIdList.push(0); const result = tokens.map((token) => { switch (token.type) { case "text": return this.renderer.text(unescape(token.text)); case "strong": return this.renderer.strong(this.parseInline(token.tokens)); case "em": return this.renderer.em(this.parseInline(token.tokens)); case "del": return this.renderer.del(this.parseInline(token.tokens)); case "codespan": return this.renderer.codespan(unescape(token.text)); case "link": return this.renderer.link(token.href, this.parseInline(token.tokens)); case "image": return this.renderer.image(token.href, token.text, token.title); case "html": return this.renderer.html(token.text); case "br": return this.renderer.br(); case "escape": return this.renderer.text(token.text); default: { console.warn(`Token with "${token.type}" type was not found`); return null; } } }); this.renderer.elIdList.pop(); return result; } }; var ReactParser_default = ReactParser; //#endregion //#region src/ReactRenderer.ts var ReactRenderer = class { elIdList = []; #options; constructor(options = {}) { const { renderer } = options; this.#options = options; if (renderer && typeof renderer === "object") Object.entries(renderer).forEach(([key, value]) => { const rendererName = key; const rendererFunction = value; if (!this[rendererName] || rendererName === "elementId" || rendererName === "elIdList" || typeof rendererFunction !== "function") return; Object.defineProperty(this, rendererName, { value(...args) { this.#incrementElId(); return rendererFunction.apply(this, args); }, writable: true, enumerable: true, configurable: true }); }); } #h(el, children = null, props = {}) { const elProps = { key: `marked-react-${this.elementId}`, suppressHydrationWarning: true }; this.#incrementElId(); return (0, react.createElement)(el, { ...props, ...elProps }, children); } #incrementElId() { this.elIdList[this.elIdList.length - 1] += 1; } get elementId() { return this.elIdList.join("-"); } heading(children, level) { return this.#h(`h${level}`, children); } paragraph(children) { return this.#h("p", children); } link(href, text) { const url = joinBase(href, this.#options.baseURL); const target = this.#options.openLinksInNewTab ? "_blank" : null; return this.#h("a", text, { href: url, target }); } image(src, alt, title = null) { const url = joinBase(src, this.#options.baseURL); return this.#h("img", null, { src: url, alt, title }); } codespan(code, lang = null) { const className = lang ? `${this.#options.langPrefix}${lang}` : null; return this.#h("code", code, { className }); } code(code, lang) { return this.#h("pre", this.codespan(code, lang)); } blockquote(children) { return this.#h("blockquote", children); } list(children, ordered, start) { return this.#h(ordered ? "ol" : "ul", children, ordered && start !== 1 ? { start } : {}); } listItem(children) { return this.#h("li", children); } checkbox(checked) { return this.#h("input", null, { type: "checkbox", disabled: true, checked }); } table(children) { return this.#h("table", children); } tableHeader(children) { return this.#h("thead", children); } tableBody(children) { return this.#h("tbody", children); } tableRow(children) { return this.#h("tr", children); } tableCell(children, flags) { const tag = flags.header ? "th" : "td"; return this.#h(tag, children, { align: flags.align }); } strong(children) { return this.#h("strong", children); } em(children) { return this.#h("em", children); } del(children) { return this.#h("del", children); } text(text) { return text; } html(html) { return html; } hr() { return this.#h("hr"); } br() { return this.#h("br"); } }; var ReactRenderer_default = ReactRenderer; //#endregion //#region src/Markdown.ts const validateComponentProps = (props) => { if (props.value && typeof props.value !== "string") throw new TypeError(`[marked-react]: Expected value to be of type string but got ${typeof props.value}`); if (props.children && typeof props.children !== "string") throw new TypeError(`[marked-react]: Expected children to be of type string but got ${typeof props.children}`); }; const defaultProps = { isInline: false, breaks: false, gfm: true, baseURL: void 0, openLinksInNewTab: true, langPrefix: "language-", renderer: void 0 }; const markedInstance = new marked.Marked(); const Markdown = (props) => { validateComponentProps(props); const options = { ...defaultProps, ...props }; const marked$1 = options.instance ?? markedInstance; const lexerOptions = { breaks: options.breaks, gfm: options.gfm, tokenizer: marked$1.defaults.tokenizer }; const markdownString = options.value ?? options.children ?? ""; const tokens = options.isInline ? marked$1.Lexer.lexInline(markdownString, lexerOptions) : marked$1.lexer(markdownString, lexerOptions); const parserOptions = { renderer: new ReactRenderer_default({ renderer: options.renderer, baseURL: options.baseURL, openLinksInNewTab: options.openLinksInNewTab, langPrefix: options.langPrefix }) }; const parser = new ReactParser_default(parserOptions); const children = options.isInline ? parser.parseInline(tokens) : parser.parse(tokens); return (0, react.createElement)(react.Fragment, null, children); }; var Markdown_default = Markdown; //#endregion //#region src/index.ts var src_default = Markdown_default; //#endregion exports.ReactParser = ReactParser_default; exports.ReactRenderer = ReactRenderer_default; exports.default = src_default; //# sourceMappingURL=index.cjs.map