Merge branch 'claude-markdown'
This commit is contained in:
commit
601170e2ab
|
|
@ -8,6 +8,9 @@
|
|||
"dependencies": {
|
||||
"commander": "^13.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test:markdown": "bun src/test-markdown.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.3.9"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import * as git from "./git.ts"
|
|||
import * as vm from "./vm.ts"
|
||||
import * as state from "./state.ts"
|
||||
import { spinner } from "./spinner.ts"
|
||||
import { renderMarkdown } from "./markdown.ts"
|
||||
|
||||
const pkg = await Bun.file(new URL("../package.json", import.meta.url)).json()
|
||||
|
||||
|
|
@ -179,7 +180,7 @@ program
|
|||
const output = await vm.claude(worktreeAbs, { prompt, print: opts.print })
|
||||
if (output) {
|
||||
spin.stop()
|
||||
process.stdout.write(output + "\n")
|
||||
process.stdout.write(renderMarkdown(output) + "\n")
|
||||
} else {
|
||||
spin.succeed("Done")
|
||||
}
|
||||
|
|
@ -311,7 +312,7 @@ program
|
|||
const output = await vm.claude(session.worktree, { prompt, print: opts.print })
|
||||
if (output) {
|
||||
spin.stop()
|
||||
process.stdout.write(output + "\n")
|
||||
process.stdout.write(renderMarkdown(output) + "\n")
|
||||
} else {
|
||||
spin.succeed("Done")
|
||||
}
|
||||
|
|
|
|||
30
src/markdown.ts
Normal file
30
src/markdown.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
export function renderMarkdown(text: string): string {
|
||||
// Extract code spans first so their contents aren't processed as bold/italic
|
||||
const codeSpans: string[] = []
|
||||
let result = text.replace(/`([^`]+)`/g, (_, code) => {
|
||||
codeSpans.push(code)
|
||||
return `\x00CODE${codeSpans.length - 1}\x00`
|
||||
})
|
||||
|
||||
// Bold: **text**
|
||||
result = result.replace(/\*\*(.+?)\*\*/g, "\x1b[1m$1\x1b[22m")
|
||||
|
||||
// Italic: *text*
|
||||
result = result.replace(/\*(.+?)\*/g, "\x1b[3m$1\x1b[23m")
|
||||
|
||||
// Restore code spans as light blue
|
||||
result = result.replace(/\x00CODE(\d+)\x00/g, (_, i) => {
|
||||
return `\x1b[38;5;147m${codeSpans[parseInt(i)]}\x1b[39m`
|
||||
})
|
||||
|
||||
// Breathe: add blank line before list starts when preceded by non-empty text
|
||||
const lines = result.split("\n")
|
||||
for (let i = lines.length - 1; i > 0; i--) {
|
||||
if (/^[\s]*[-*] /.test(lines[i]) && lines[i - 1].trim() !== "" && !/^[\s]*[-*] /.test(lines[i - 1])) {
|
||||
lines.splice(i, 0, "")
|
||||
}
|
||||
}
|
||||
result = lines.join("\n")
|
||||
|
||||
return result
|
||||
}
|
||||
18
src/test-markdown.ts
Normal file
18
src/test-markdown.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { renderMarkdown } from "./markdown"
|
||||
|
||||
const lines = [
|
||||
"This is **bold** text",
|
||||
"This is *italic* text",
|
||||
"This is `inline code` text",
|
||||
"Mix of **bold**, *italic*, and `code` in one line",
|
||||
"**bold with `code` inside** bold",
|
||||
"No markdown here",
|
||||
"Multiple **bold one** and **bold two**",
|
||||
"Nested-ish: **bold and *italic* together**",
|
||||
]
|
||||
|
||||
for (const line of lines) {
|
||||
console.log(` ${line}`)
|
||||
console.log(` ${renderMarkdown(line)}`)
|
||||
console.log()
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user