render markdown preview in the file browser

This commit is contained in:
Ian Gulliver
2026-10-18 11:48:53 -07:00
parent aac7cfe858
commit 4f9823129d
4 changed files with 37 additions and 8 deletions
+8 -6
View File
@@ -117,6 +117,7 @@ struct InlineRenderer {
let size: CGFloat
let taskId: String?
var weight: CGFloat = 400
var dir = ""
private struct Style {
var bold = false
@@ -189,7 +190,7 @@ struct InlineRenderer {
s.italic = true
render(inner, s, &out)
case .image(let src, let alt):
if let source = worktreeImageSource(src, taskId) {
if let source = worktreeImageSource(src, taskId, dir: dir) {
out.append(.image(source, src: src))
} else {
link(src, [.text(alt.isEmpty ? src : alt)], style, &out)
@@ -287,6 +288,7 @@ struct MDContext {
var choice: ((MDItem, Bool) -> AnyView)?
var gridColumns = 4
var weight: CGFloat = 400
var dir = ""
}
private enum MDRun {
@@ -418,7 +420,7 @@ private struct FlowBuilder {
}
private func inline(_ inlines: [MDInline], _ size: CGFloat) -> NSAttributedString {
let a = InlineRenderer(store: store, size: size, taskId: ctx.taskId, weight: ctx.weight).text(inlines)
let a = InlineRenderer(store: store, size: size, taskId: ctx.taskId, weight: ctx.weight, dir: ctx.dir).text(inlines)
return try! NSAttributedString(a, including: \.appKit)
}
@@ -585,7 +587,7 @@ struct InlineView: View {
@Environment(\.centerImages) private var centerImages
var body: some View {
let segs = InlineRenderer(store: store, size: ctx.size, taskId: ctx.taskId, weight: ctx.weight).segments(inlines)
let segs = InlineRenderer(store: store, size: ctx.size, taskId: ctx.taskId, weight: ctx.weight, dir: ctx.dir).segments(inlines)
VStack(alignment: .leading, spacing: 4) {
ForEach(Array(segs.enumerated()), id: \.offset) { _, seg in
switch seg {
@@ -631,7 +633,7 @@ private struct BlockView: View {
case .paragraph(let inlines):
InlineView(inlines: inlines, ctx: ctx)
case .heading(let level, let inlines):
InlineView(inlines: [.strong(inlines)], ctx: MDContext(size: level == 3 ? 14 : 13, color: ctx.color, taskId: ctx.taskId))
InlineView(inlines: [.strong(inlines)], ctx: MDContext(size: level == 3 ? 14 : 13, color: ctx.color, taskId: ctx.taskId, dir: ctx.dir))
.padding(.top, 4)
case .rule:
Rectangle()
@@ -639,7 +641,7 @@ private struct BlockView: View {
.frame(height: 1)
.padding(.vertical, 2)
case .quote(let blocks):
MarkdownView(blocks: blocks, ctx: MDContext(size: ctx.size, color: Palette.muted, taskId: ctx.taskId))
MarkdownView(blocks: blocks, ctx: MDContext(size: ctx.size, color: Palette.muted, taskId: ctx.taskId, dir: ctx.dir))
.padding(.leading, 13)
.overlay(alignment: .leading) {
Rectangle().fill(Palette.border).frame(width: 3)
@@ -786,7 +788,7 @@ private struct DetailsBlock: View {
HStack(alignment: .firstTextBaseline, spacing: 4) {
Text(open ? "▾" : "▸")
.foregroundStyle(Palette.accent)
InlineView(inlines: summary, ctx: MDContext(size: ctx.size, color: Palette.accent, taskId: ctx.taskId))
InlineView(inlines: summary, ctx: MDContext(size: ctx.size, color: Palette.accent, taskId: ctx.taskId, dir: ctx.dir))
}
.contentShape(Rectangle())
}