summaryrefslogtreecommitdiffhomepage
path: root/packages/web/src/components/share/content-markdown.tsx
diff options
context:
space:
mode:
authorDax <[email protected]>2025-07-07 15:53:43 -0400
committerGitHub <[email protected]>2025-07-07 15:53:43 -0400
commitf884766445bbf1fbce11f1db4bc6174e72d9baa5 (patch)
treee7d9e7b3d8efc8bed249f9d29e2d8fb838a275f2 /packages/web/src/components/share/content-markdown.tsx
parent76b2e4539cb97bae5812ed2d832ce49d02e70c64 (diff)
downloadopencode-f884766445bbf1fbce11f1db4bc6174e72d9baa5.tar.gz
opencode-f884766445bbf1fbce11f1db4bc6174e72d9baa5.zip
v2 message format and upgrade to ai sdk v5 (#743)
Co-authored-by: GitHub Action <[email protected]> Co-authored-by: Liang-Shih Lin <[email protected]> Co-authored-by: Dominik Engelhardt <[email protected]> Co-authored-by: Jay V <[email protected]> Co-authored-by: adamdottv <[email protected]>
Diffstat (limited to 'packages/web/src/components/share/content-markdown.tsx')
-rw-r--r--packages/web/src/components/share/content-markdown.tsx65
1 files changed, 65 insertions, 0 deletions
diff --git a/packages/web/src/components/share/content-markdown.tsx b/packages/web/src/components/share/content-markdown.tsx
new file mode 100644
index 000000000..f79271296
--- /dev/null
+++ b/packages/web/src/components/share/content-markdown.tsx
@@ -0,0 +1,65 @@
+import style from "./content-markdown.module.css"
+import { createResource, createSignal } from "solid-js"
+import { createOverflow } from "./common"
+import { transformerNotationDiff } from "@shikijs/transformers"
+import { marked } from "marked"
+import markedShiki from "marked-shiki"
+import { codeToHtml } from "shiki"
+
+const markedWithShiki = marked.use(
+ markedShiki({
+ highlight(code, lang) {
+ return codeToHtml(code, {
+ lang: lang || "text",
+ themes: {
+ light: "github-light",
+ dark: "github-dark",
+ },
+ transformers: [transformerNotationDiff()],
+ })
+ },
+ }),
+)
+
+interface Props {
+ text: string
+ expand?: boolean
+ highlight?: boolean
+}
+export function ContentMarkdown(props: Props) {
+ const [html] = createResource(
+ () => strip(props.text),
+ async (markdown) => {
+ return markedWithShiki.parse(markdown)
+ },
+ )
+ const [expanded, setExpanded] = createSignal(false)
+ const overflow = createOverflow()
+
+ return (
+ <div
+ class={style.root}
+ data-highlight={props.highlight === true ? true : undefined}
+ data-expanded={expanded() || props.expand === true ? true : undefined}
+ >
+ <div data-slot="markdown" ref={overflow.ref} innerHTML={html()} />
+
+ {!props.expand && overflow.status && (
+ <button
+ type="button"
+ data-component="text-button"
+ data-slot="expand-button"
+ onClick={() => setExpanded((e) => !e)}
+ >
+ {expanded() ? "Show less" : "Show more"}
+ </button>
+ )}
+ </div>
+ )
+}
+
+function strip(text: string): string {
+ const wrappedRe = /^\s*<([A-Za-z]\w*)>\s*([\s\S]*?)\s*<\/\1>\s*$/
+ const match = text.match(wrappedRe)
+ return match ? match[2] : text
+}