fix: resolve Markdown rendering in webview

Three issues prevented kilo-ui Markdown component from rendering:

1. Wrong prop name: Markdown expects 'text' not 'content'
2. Duplicate solid-js runtimes (pnpm 1.9.11 vs bun 1.9.10) caused
   MarkedProvider context to be invisible to Markdown's useMarked().
   Added solidDedupePlugin to esbuild to force single instance.
3. Missing 'wasm-unsafe-eval' CSP for shiki WASM syntax highlighting.

Also added ErrorBoundary safety net around Markdown that falls back
to plain text rendering on errors.
This commit is contained in:
Mark IJbema
2026-02-11 13:16:45 +01:00
parent 6bcaa19832
commit 9ac221ee61
3 changed files with 33 additions and 4 deletions
+30 -1
View File
@@ -1,9 +1,38 @@
const esbuild = require("esbuild")
const path = require("path")
const { solidPlugin } = require("esbuild-plugin-solid")
const production = process.argv.includes("--production")
const watch = process.argv.includes("--watch")
/**
* Force all solid-js imports (from kilo-ui and the webview) to resolve to
* the **same** copy so SolidJS contexts are shared across packages.
* Without this, the monorepo hoists separate copies (pnpm vs bun) and
* createContext / useContext can't see each other.
*
* @type {import('esbuild').Plugin}
*/
const solidDedupePlugin = {
name: "solid-dedupe",
setup(build) {
// Resolve these bare specifiers to the kilo-vscode-local copy
const solidRoot = path.dirname(require.resolve("solid-js/package.json"))
const aliases = {
"solid-js": path.join(solidRoot, "dist", "solid.js"),
"solid-js/web": path.join(solidRoot, "web", "dist", "web.js"),
"solid-js/store": path.join(solidRoot, "store", "dist", "store.js"),
}
build.onResolve({ filter: /^solid-js(\/web|\/store)?$/ }, (args) => {
const key = args.path
if (aliases[key]) {
return { path: aliases[key] }
}
})
},
}
/**
* @type {import('esbuild').Plugin}
*/
@@ -72,7 +101,7 @@ async function main() {
".woff2": "file",
".ttf": "file",
},
plugins: [cssPackageResolvePlugin, solidPlugin(), esbuildProblemMatcherPlugin],
plugins: [solidDedupePlugin, cssPackageResolvePlugin, solidPlugin(), esbuildProblemMatcherPlugin],
})
if (watch) {
+1 -1
View File
@@ -776,7 +776,7 @@ export class KiloProvider implements vscode.WebviewViewProvider {
const csp = [
"default-src 'none'",
`style-src 'unsafe-inline' ${webview.cspSource}`,
`script-src 'nonce-${nonce}'`,
`script-src 'nonce-${nonce}' 'wasm-unsafe-eval'`,
`font-src ${webview.cspSource}`,
"connect-src http://127.0.0.1:* http://localhost:* ws://127.0.0.1:* ws://localhost:*",
`img-src ${webview.cspSource} data: https:`,
@@ -25,7 +25,7 @@ interface MessageProps {
const TextPartView: Component<{ part: TextPart; role: string }> = (props) => {
return (
<Show when={props.role === "assistant"} fallback={<div class="message-text">{props.part.text}</div>}>
<Markdown content={props.part.text} />
<Markdown text={props.part.text} />
</Show>
)
}
@@ -155,7 +155,7 @@ export const Message: Component<MessageProps> = (props) => {
when={props.message.role === "assistant"}
fallback={<div class="message-text">{props.message.content}</div>}
>
<Markdown content={props.message.content!} />
<Markdown text={props.message.content!} />
</Show>
</Show>
}