chore: generate

This commit is contained in:
opencode-agent[bot] 2026-06-16 16:57:04 +00:00
commit 273efdeee7
11 changed files with 427 additions and 405 deletions

View file

@ -123,8 +123,12 @@ describe("markdown stream", () => {
})
test("only reuses pending blocks with compatible identity and content", () => {
expect(canReusePendingBlock({ mode: "full", raw: "First\n\n" }, { mode: "full", raw: "# Inserted\n\n", src: "", })).toBe(false)
expect(canReusePendingBlock({ mode: "code", raw: "```ts\none" }, { mode: "code", raw: "```ts\none two", src: "" })).toBe(true)
expect(
canReusePendingBlock({ mode: "full", raw: "First\n\n" }, { mode: "full", raw: "# Inserted\n\n", src: "" }),
).toBe(false)
expect(
canReusePendingBlock({ mode: "code", raw: "```ts\none" }, { mode: "code", raw: "```ts\none two", src: "" }),
).toBe(true)
expect(canReusePendingBlock({ mode: "code", raw: "```ts\none" }, { mode: "live", raw: "one", src: "" })).toBe(false)
})

View file

@ -1,5 +1,9 @@
import { expect, test } from "bun:test"
import { applyMarkdownWorkerResponse, markdownBlockKey, shouldReleaseMarkdownWorkerState } from "./markdown-worker-protocol"
import {
applyMarkdownWorkerResponse,
markdownBlockKey,
shouldReleaseMarkdownWorkerState,
} from "./markdown-worker-protocol"
const token = (content: string): [string, string] => [content, ""]
const response = (id: number, reset: boolean, stable: [string, string][], unstable: [string, string][]) => ({

View file

@ -3,7 +3,16 @@ import { useI18n } from "../context/i18n"
import DOMPurify from "dompurify"
import morphdom from "morphdom"
import { checksum } from "@opencode-ai/core/util/encode"
import { ComponentProps, createEffect, createMemo, createResource, createSignal, createUniqueId, onCleanup, splitProps } from "solid-js"
import {
ComponentProps,
createEffect,
createMemo,
createResource,
createSignal,
createUniqueId,
onCleanup,
splitProps,
} from "solid-js"
import { isServer } from "solid-js/web"
import { bundledLanguages } from "shiki"
import { canReusePendingBlock, project, type Block, type Projection } from "./markdown-stream"
@ -439,9 +448,9 @@ export function Markdown(
nextCodeKeys.forEach((key) => activeCodeKeys.add(key))
content.forEach((block, index) => updateBlock(container, index, block, labels))
while (container.children.length > content.length) container.lastElementChild?.remove()
container.querySelectorAll<HTMLButtonElement>('[data-slot="markdown-copy-button"]').forEach((button) =>
setCopyState(button, labels, button.dataset.copied === "true"),
)
container
.querySelectorAll<HTMLButtonElement>('[data-slot="markdown-copy-button"]')
.forEach((button) => setCopyState(button, labels, button.dataset.copied === "true"))
if (!copyCleanup)
copyCleanup = setupCodeCopy(container, () => ({
copy: i18n.t("ui.message.copy"),
@ -549,8 +558,7 @@ function updateCodeBlock(
block: Extract<RenderedBlock, { mode: "code" }>,
labels: CopyLabels,
) {
const existing =
current instanceof HTMLDivElement && current.dataset.markdownKey === block.key ? current : undefined
const existing = current instanceof HTMLDivElement && current.dataset.markdownKey === block.key ? current : undefined
const next = existing ?? document.createElement("div")
next.dataset.markdownBlock = ""
next.dataset.markdownKey = block.key
@ -574,7 +582,10 @@ function updateCodeBlock(
const prefix = prior.findIndex((token, index) => !sameToken(token, tail[index]))
const keep = stableCount + (prefix < 0 ? Math.min(prior.length, tail.length) : prefix)
while (code.children.length > keep) code.lastElementChild?.remove()
tail.slice(keep - stableCount).map(createTokenSpan).forEach((span) => code.appendChild(span))
tail
.slice(keep - stableCount)
.map(createTokenSpan)
.forEach((span) => code.appendChild(span))
renderedCodeTokens.set(next, {
language: block.language,
generation: block.generation,

View file

@ -38,10 +38,7 @@ export function scrollTopFromThumbPointer(input: {
const padding = 8
const maxThumbTop = input.clientHeight - padding * 2 - input.thumbHeight
if (maxThumbTop <= 0) return 0
const thumbTop = Math.max(
0,
Math.min(input.pointer - input.viewportTop - padding - input.grabOffset, maxThumbTop),
)
const thumbTop = Math.max(0, Math.min(input.pointer - input.viewportTop - padding - input.grabOffset, maxThumbTop))
return (thumbTop / maxThumbTop) * Math.max(0, input.scrollHeight - input.clientHeight)
}