UNPKG

ranui

Version:

A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.

302 lines (301 loc) 18 kB
import { T as x, _ as y, i as b } from "./factory-WDxu11V0.js"; import "./builder-EH76YCFS.js"; import { a as _, i as l, n, o as T, r as v, t as z } from "./utils-U-9uH7EX.js"; import { a as C, n as O } from "./ssr-BzykYefm.js"; import "./icon-DgLPjeVe.js"; var M = ':host{display:var(--ran-markdown-display, block);box-sizing:border-box;color:var(--ran-markdown-color, var(--ran-color-text, #171717));font-family:var(--ran-markdown-font-family, var(--ran-font-family, inherit));font-size:var(--ran-markdown-font-size, var(--ran-text-copy-1, 16px));line-height:var(--ran-markdown-line-height, 1.7);overflow-wrap:break-word;contain:inline-size;width:var(--ran-markdown-width, 100%);min-width:0;max-width:100%}:host([hidden]){display:none}.ran-markdown{position:relative}.ran-markdown-body{display:flex;flex-direction:column;gap:var(--ran-markdown-gap, var(--ran-space-4, 16px))}.ran-markdown-block{min-width:0;max-width:100%}.ran-markdown-block>:first-child{margin-top:0}.ran-markdown-block>:last-child{margin-bottom:0}:host([caret]) .ran-markdown-block:last-child:not([data-no-caret])>:last-child:after{content:var(--ran-markdown-caret, "▋");display:inline-block;margin-left:.15em;color:var(--ran-markdown-caret-color, var(--ran-color-text-secondary, #666));animation:ran-markdown-caret 1s steps(2,start) infinite}:host([caret="circle"]) .ran-markdown-block:last-child:not([data-no-caret])>:last-child:after{content:var(--ran-markdown-caret, "●");font-size:.6em;vertical-align:middle}@keyframes ran-markdown-caret{to{visibility:hidden}}h1,h2,h3,h4,h5,h6{margin:var(--ran-markdown-heading-margin, var(--ran-space-6, 32px) 0 var(--ran-space-3, 12px));color:var(--ran-markdown-heading-color, var(--ran-color-text, #171717));font-weight:var(--ran-markdown-heading-weight, var(--ran-text-heading-weight, 600));line-height:1.3;letter-spacing:-.01em}h1{font-size:var(--ran-markdown-h1-size, var(--ran-text-heading-1, 32px))}h2{font-size:var(--ran-markdown-h2-size, var(--ran-text-heading-2, 24px))}h3{font-size:var(--ran-markdown-h3-size, var(--ran-text-heading-3, 20px))}h4,h5,h6{font-size:var(--ran-markdown-h4-size, var(--ran-text-heading-4, 16px))}p{margin:0 0 var(--ran-markdown-paragraph-margin, var(--ran-space-3, 12px))}a{color:var(--ran-markdown-link-color, var(--ran-color-link, #0070f3));text-decoration:underline;text-underline-offset:.15em;text-decoration-color:var(--ran-markdown-link-underline, var(--ran-gray-alpha-500, currentColor))}a:hover{text-decoration-color:currentColor}a[data-incomplete]{color:inherit;text-decoration:none;cursor:text}strong{font-weight:var(--ran-markdown-strong-weight, 600)}del{color:var(--ran-color-text-secondary, #666)}hr{height:0;margin:var(--ran-space-6, 32px) 0;border:0;border-top:var(--ran-skin-border-width, 1px) var(--ran-skin-border-style, solid) var(--ran-markdown-hr-color, var(--ran-color-border, #eaeaea))}ul,ol{margin:0 0 var(--ran-markdown-paragraph-margin, var(--ran-space-3, 12px));padding-left:var(--ran-markdown-list-indent, var(--ran-space-6, 32px))}li{margin:var(--ran-markdown-list-item-margin, var(--ran-space-1, 4px)) 0}li>p{margin-bottom:var(--ran-space-2, 8px)}li>ul,li>ol{margin:var(--ran-space-1, 4px) 0 0}li:has(>input[type=checkbox]){list-style:none;margin-left:calc(-1 * var(--ran-space-5, 24px))}li>input[type=checkbox]{margin:0 var(--ran-space-2, 8px) 0 0;vertical-align:-.1em;accent-color:var(--ran-color-primary, #0070f3)}blockquote{margin:0 0 var(--ran-markdown-paragraph-margin, var(--ran-space-3, 12px));padding:var(--ran-space-1, 4px) 0 var(--ran-space-1, 4px) var(--ran-space-4, 16px);border-left:var(--ran-markdown-blockquote-border-width, 3px) solid var(--ran-markdown-blockquote-border, var(--ran-color-border-secondary, #d4d4d4));color:var(--ran-markdown-blockquote-color, var(--ran-color-text-secondary, #666))}blockquote>:last-child{margin-bottom:0}img{max-width:100%;height:auto;border-radius:var(--ran-markdown-image-radius, var(--ran-radius-sm, 6px))}:not(pre)>code{padding:.15em .4em;border-radius:var(--ran-radius-sm, 6px);background:var(--ran-markdown-inline-code-bg, var(--ran-gray-alpha-200, rgba(0, 0, 0, .06)));color:var(--ran-markdown-inline-code-color, inherit);font-family:var(--ran-markdown-mono-font, var(--ran-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace));font-size:.875em;overflow-wrap:anywhere}.ran-md-code{margin:0 0 var(--ran-markdown-paragraph-margin, var(--ran-space-3, 12px));border:var(--ran-skin-border-width, 1px) var(--ran-skin-border-style, solid) var(--ran-markdown-code-border, var(--ran-color-border, #eaeaea));border-radius:var(--ran-markdown-code-radius, var(--ran-radius-md, 12px));background:var(--ran-markdown-code-bg, var(--ran-color-bg-muted, #fafafa));overflow:hidden;content-visibility:auto;contain-intrinsic-size:auto 120px}.ran-md-code-header{display:flex;align-items:center;justify-content:space-between;gap:var(--ran-space-2, 8px);min-height:var(--ran-markdown-code-header-height, var(--ran-size-7, 32px));padding:0 var(--ran-space-2, 8px) 0 var(--ran-space-3, 12px);border-bottom:var(--ran-skin-border-width, 1px) var(--ran-skin-border-style, solid) var(--ran-markdown-code-border, var(--ran-color-border, #eaeaea));background:var(--ran-markdown-code-header-bg, transparent)}.ran-md-code-lang{color:var(--ran-markdown-code-lang-color, var(--ran-color-text-secondary, #666));font-family:var(--ran-markdown-mono-font, var(--ran-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace));font-size:var(--ran-text-label-3, 12px);line-height:1;text-transform:lowercase}.ran-md-code-actions{display:inline-flex;align-items:center;gap:var(--ran-space-1, 4px)}.ran-md-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--ran-markdown-button-size, var(--ran-size-4, 24px));height:var(--ran-markdown-button-size, var(--ran-size-4, 24px));padding:0;border:none;border-radius:var(--ran-radius-sm, 6px);background:transparent;color:var(--ran-markdown-button-color, var(--ran-color-text-secondary, #666));cursor:pointer}.ran-md-btn:hover{background:var(--ran-markdown-button-hover-background, var(--ran-gray-alpha-200, rgba(0, 0, 0, .06)));color:var(--ran-markdown-button-hover-color, var(--ran-color-text, #171717))}.ran-md-btn:focus-visible{outline:var(--ran-focus-ring, 2px solid var(--ran-color-primary, #0070f3));outline-offset:1px}.ran-md-pre{margin:0;padding:var(--ran-markdown-code-padding, var(--ran-space-3, 12px) var(--ran-space-4, 16px));overflow-x:auto;background:transparent!important;color:var(--ran-markdown-code-color, var(--ran-color-text, #171717));font-family:var(--ran-markdown-mono-font, var(--ran-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace));font-size:var(--ran-markdown-code-font-size, var(--ran-text-label-2, 13px));line-height:var(--ran-markdown-code-line-height, 1.6);tab-size:2}.ran-md-pre code{display:block;padding:0;background:transparent;font:inherit;white-space:pre}.ran-md-pre .line{display:inline}.ran-md-pre .line:empty:after{content:" "}.ran-md-code[data-line-numbers] .ran-md-pre code{counter-reset:line}.ran-md-code[data-line-numbers] .ran-md-pre .line:before{counter-increment:line;content:counter(line);display:inline-block;width:var(--ran-markdown-line-number-width, 2.5em);margin-right:var(--ran-space-3, 12px);color:var(--ran-markdown-line-number-color, var(--ran-color-text-disabled, #a3a3a3));text-align:right;-webkit-user-select:none;user-select:none}.ran-md-pre.shiki span{color:var(--shiki-light)}.is-dark .ran-md-pre.shiki span{color:var(--shiki-dark)}@media(prefers-color-scheme:dark){.is-system .ran-md-pre.shiki span{color:var(--shiki-dark)}}.ran-md-table-wrap{margin:0 0 var(--ran-markdown-paragraph-margin, var(--ran-space-3, 12px));border:var(--ran-skin-border-width, 1px) var(--ran-skin-border-style, solid) var(--ran-markdown-table-border, var(--ran-color-border, #eaeaea));border-radius:var(--ran-markdown-table-radius, var(--ran-radius-md, 12px));overflow-x:auto}table{width:100%;border-collapse:collapse;font-size:var(--ran-markdown-table-font-size, var(--ran-text-copy-2, 14px))}th,td{padding:var(--ran-markdown-table-cell-padding, var(--ran-space-2, 8px) var(--ran-space-3, 12px));border-bottom:var(--ran-skin-border-width, 1px) var(--ran-skin-border-style, solid) var(--ran-markdown-table-border, var(--ran-color-border, #eaeaea));text-align:left;vertical-align:top}th{background:var(--ran-markdown-table-header-bg, var(--ran-color-bg-muted, #fafafa));color:var(--ran-markdown-table-header-color, var(--ran-color-text-secondary, #666));font-weight:var(--ran-text-label-weight, 500);white-space:nowrap}tr:last-child td{border-bottom:0}.ran-md-mermaid,r-math[display=block]{display:block;max-width:100%;overflow-x:auto;margin:0 0 var(--ran-markdown-paragraph-margin, var(--ran-space-3, 12px))}.ran-md-math-block{overflow-x:auto}r-math[display=inline]{vertical-align:middle}.ran-markdown-error{margin:0;padding:var(--ran-markdown-error-padding, var(--ran-space-2, 8px) var(--ran-space-3, 12px));border-radius:var(--ran-radius-sm, 6px);background:var(--ran-markdown-error-background, var(--ran-red-100, #fff0f0));color:var(--ran-markdown-error-color, var(--ran-color-danger, #e5484d));font-family:var(--ran-font-mono, ui-monospace, monospace);font-size:var(--ran-text-label-2, 13px);white-space:pre-wrap}', E = { javascript: "js", js: "js", jsx: "jsx", typescript: "ts", ts: "ts", tsx: "tsx", python: "py", py: "py", rust: "rs", rs: "rs", go: "go", java: "java", kotlin: "kt", swift: "swift", c: "c", cpp: "cpp", "c++": "cpp", csharp: "cs", cs: "cs", "c#": "cs", php: "php", ruby: "rb", rb: "rb", bash: "sh", sh: "sh", shell: "sh", zsh: "sh", powershell: "ps1", sql: "sql", html: "html", css: "css", less: "less", scss: "scss", json: "json", yaml: "yaml", yml: "yml", toml: "toml", xml: "xml", markdown: "md", md: "md", dockerfile: "Dockerfile", vue: "vue", svelte: "svelte", dart: "dart", lua: "lua", r: "r", scala: "scala", haskell: "hs", elixir: "ex", graphql: "graphql", text: "txt" }, A = class extends O { _shadowDom; _wrap; _body; _blocks = []; _content = null; _pending = Promise.resolve(); _renderToken = 0; _renderModule = null; _themeObserver; _lightDomObserver; _copyResetTimer; _error; static get observedAttributes() { return [ "content", "mode", "theme", "caret", "copy", "download", "line-numbers", "highlight", "inline-math", "link-target", "sheet" ]; } constructor() { super(), this._shadowDom = z(this, M); const r = x(); this._wrap = b().class("ran-markdown").part("markdown").children(b().class("ran-markdown-body").part("body").ref(r)).build(), this._shadowDom.appendChild(this._wrap), this._body = _(r, "body"); } get content() { if (this._content !== null) return this._content; const r = n(this, "content"); return r || this.textContent || ""; } set content(r) { const e = r == null ? "" : String(r); this._content !== e && (this._content = e, this.render()); } get mode() { return n(this, "mode") || "streaming"; } set mode(r) { l(this, "mode", r); } get theme() { return n(this, "theme") || "auto"; } set theme(r) { l(this, "theme", r); } get caret() { return n(this, "caret"); } set caret(r) { l(this, "caret", r); } get copyable() { return this.hasAttribute("copy"); } set copyable(r) { v(this, "copy", r); } get downloadable() { return this.hasAttribute("download"); } set downloadable(r) { v(this, "download", r); } get lineNumbers() { return this.hasAttribute("line-numbers"); } set lineNumbers(r) { v(this, "line-numbers", r); } get highlight() { return this.hasAttribute("highlight") ? n(this, "highlight") : null; } set highlight(r) { l(this, "highlight", r); } get inlineMath() { return this.hasAttribute("inline-math"); } set inlineMath(r) { v(this, "inline-math", r); } get linkTarget() { return n(this, "link-target") || "_blank"; } set linkTarget(r) { l(this, "link-target", r); } get sheet() { return n(this, "sheet"); } set sheet(r) { l(this, "sheet", r); } label(r, e) { return n(this, `label-${r}`) || e; } emit(r, e) { this.dispatchEvent(new CustomEvent(r, { detail: e, bubbles: !0, composed: !0 })); } handlerExternalCss = () => { T(this, this._shadowDom, "sheet", null, this.sheet); }; resolveTheme() { const r = this.theme; if (r === "dark" || r === "light") return r; const e = document.documentElement, a = e.getAttribute("data-ran-theme") || e.getAttribute("theme"); return a === "dark" || e.classList.contains("dark") ? "dark" : a === "light" || e.classList.contains("light") ? "light" : "system"; } syncTheme() { const r = this.resolveTheme(); this._wrap.classList.toggle("is-dark", r === "dark"), this._wrap.classList.toggle("is-light", r === "light"), this._wrap.classList.toggle("is-system", r === "system"); for (const e of this._blocks) for (const a of e.themed) a.setAttribute("theme", this.theme); } observeTheme() { if (this.theme !== "auto") { this._themeObserver?.disconnect(), this._themeObserver = void 0; return; } this._themeObserver || typeof MutationObserver > "u" || (this._themeObserver = new MutationObserver(() => this.syncTheme()), this._themeObserver.observe(document.documentElement, { attributes: !0, attributeFilter: [ "class", "data-ran-theme", "theme" ] })); } render() { if (typeof document > "u") return; const r = ++this._renderToken, e = this.content; if (this._renderModule) { this.renderWith(this._renderModule, e, r); return; } this._pending = import("./render-CSi9KMUI.js").then((a) => { this._renderModule = a, r === this._renderToken && this.renderWith(a, e, r); }).catch((a) => this.showError(a?.message || String(a))); } renderWith(r, e, a) { if (a !== this._renderToken) return; const i = this.mode !== "static"; try { const o = i ? r.remend(e, { inlineKatex: this.inlineMath }) : e, s = r.parseDocument(o, { inlineMath: this.inlineMath, split: i }), m = s.blocks, w = m.length - 1, g = this.highlight, f = { copy: this.copyable, download: this.downloadable, lineNumbers: this.lineNumbers, highlight: g === null ? null : r.parseThemes(g), linkTarget: this.linkTarget, theme: this.theme, labels: { copy: this.label("copy", "Copy code"), download: this.label("download", "Download") }, onCopy: this.copyCode, onDownload: this.downloadCode }; let p = 0; for (m.forEach((d, k) => { const h = i && k === w && d.incompleteCode, t = this._blocks[k]; if (t && t.key === d.key && t.incomplete === h) return; const c = t ? t.el : this.createBlockElement(); c.replaceChildren(s.render(d)); const { themed: u } = r.enhance(c, { ...f, incomplete: h }); c.toggleAttribute("data-no-caret", h || d.hasTable), t ? (t.key = d.key, t.incomplete = h, t.themed = u) : (this._blocks.push({ key: d.key, incomplete: h, el: c, themed: u }), this._body.appendChild(c)), p += 1; }); this._blocks.length > m.length; ) this._blocks.pop()?.el.remove(), p += 1; this._wrap.classList.remove("has-error"), this._error?.remove(), this._error = void 0, this.syncTheme(), p > 0 && this.emit("render", { blocks: m.length, changed: p }); } catch (o) { this.showError(String(o?.message || o)); } } createBlockElement() { return b().class("ran-markdown-block").part("block").build(); } showError(r) { this._blocks.forEach((e) => e.el.remove()), this._blocks = [], this._error || (this._error = y("pre").class("ran-markdown-error").part("error").build(), this._wrap.appendChild(this._error)), this._error.textContent = r, this._wrap.classList.add("has-error"), this.emit("error", { message: r }); } rerender() { this._blocks.forEach((r) => r.el.remove()), this._blocks = [], this.render(); } copyCode = (r, e, a) => { navigator.clipboard && navigator.clipboard.writeText(e).then(() => { this.emit("copied", { kind: "code", language: a, code: e }), r && (r.setAttribute("name", "check"), window.clearTimeout(this._copyResetTimer), this._copyResetTimer = window.setTimeout(() => r.setAttribute("name", "copy"), 1200)); }); }; downloadCode = (r, e) => { const a = E[e] || e || "txt", i = a === "Dockerfile" ? "Dockerfile" : `code.${a}`, o = URL.createObjectURL(new Blob([r], { type: "text/plain;charset=utf-8" })), s = document.createElement("a"); s.href = o, s.download = i, s.click(), URL.revokeObjectURL(o), this.emit("download", { kind: "code", language: e, filename: i }); }; connectedCallback() { this.handlerExternalCss(), this.observeTheme(), typeof MutationObserver < "u" && !this._lightDomObserver && (this._lightDomObserver = new MutationObserver(() => { this._content === null && !this.hasAttribute("content") && this.render(); }), this._lightDomObserver.observe(this, { childList: !0, characterData: !0, subtree: !0 })), this.render(); } disconnectedCallback() { this._themeObserver?.disconnect(), this._themeObserver = void 0, this._lightDomObserver?.disconnect(), this._lightDomObserver = void 0, window.clearTimeout(this._copyResetTimer); } attributeChangedCallback(r, e, a) { e !== a && (r === "sheet" ? this.handlerExternalCss() : r === "content" ? this.render() : r === "theme" ? (this.observeTheme(), this.syncTheme()) : r === "caret" || this.isConnected && this.rerender()); } }; C("r-markdown", A); export { A as t };