input coloring
This commit is contained in:
@@ -7,9 +7,22 @@ indirect enum MDInline: Sendable {
|
||||
case em([MDInline])
|
||||
case image(src: String, alt: String)
|
||||
case link(href: String, [MDInline])
|
||||
case mark(MDMark, [MDInline])
|
||||
case lineBreak
|
||||
}
|
||||
|
||||
enum MDMark: Sendable {
|
||||
case ok, warn, danger
|
||||
}
|
||||
|
||||
private let marks: [String: MDMark] = [
|
||||
"✓": .ok, "✔": .ok, "✔️": .ok, "✅": .ok, "☑": .ok, "☑️": .ok,
|
||||
"~": .warn, "≈": .warn, "〜": .warn, "⚠": .warn, "⚠️": .warn, "🟡": .warn,
|
||||
"x": .danger, "X": .danger, "×": .danger, "✗": .danger, "✘": .danger, "✕": .danger, "✖": .danger, "✖️": .danger, "❌": .danger,
|
||||
]
|
||||
|
||||
private let boldWrap = Re(#"^(\*\*|__)(.*)\1$"#)
|
||||
|
||||
struct MDItem: Sendable {
|
||||
var choice: String?
|
||||
var choiceIndex = 0
|
||||
@@ -301,6 +314,14 @@ private func cells(_ line: String) -> [String] {
|
||||
}
|
||||
|
||||
private func inline(_ src: String) -> [MDInline] {
|
||||
let t = trimmed(src)
|
||||
if let mark = marks[trimmed(boldWrap.exec(t)?[2] ?? t)] {
|
||||
return [.mark(mark, spans(src))]
|
||||
}
|
||||
return spans(src)
|
||||
}
|
||||
|
||||
private func spans(_ src: String) -> [MDInline] {
|
||||
var out: [MDInline] = []
|
||||
var rest = src
|
||||
while !rest.isEmpty {
|
||||
@@ -314,13 +335,13 @@ private func inline(_ src: String) -> [MDInline] {
|
||||
if let code = g[1] {
|
||||
out.append(.code(code))
|
||||
} else if let strong = g[2] ?? g[3] {
|
||||
out.append(.strong(inline(strong)))
|
||||
out.append(.strong(spans(strong)))
|
||||
} else if let em = g[4] ?? g[5] {
|
||||
out.append(.em(inline(em)))
|
||||
out.append(.em(spans(em)))
|
||||
} else if let alt = g[6] {
|
||||
out.append(.image(src: trimmed(g[7] ?? g[8]!), alt: alt))
|
||||
} else if let text = g[9] {
|
||||
out.append(.link(href: g[10]!, inline(text)))
|
||||
out.append(.link(href: g[10]!, spans(text)))
|
||||
} else if let bare = g[11] {
|
||||
out.append(.link(href: bare, [.text(bare)]))
|
||||
}
|
||||
|
||||
@@ -54,6 +54,24 @@ func openAppLink(_ url: URL, _ store: Store, _ overlays: Overlays) -> OpenURLAct
|
||||
return .handled
|
||||
}
|
||||
|
||||
extension MDMark {
|
||||
var color: Color {
|
||||
switch self {
|
||||
case .ok: Palette.ok
|
||||
case .warn: Palette.warn
|
||||
case .danger: Palette.danger
|
||||
}
|
||||
}
|
||||
|
||||
var tint: Color {
|
||||
switch self {
|
||||
case .ok: Palette.okTint
|
||||
case .warn: Palette.warnTint
|
||||
case .danger: Palette.dangerTint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let httpLink = Re(#"^https?://"#, caseless: true)
|
||||
private let taskHref = Re(#"^#/task/(\w+)(/\w+)?$"#)
|
||||
private let todoHref = Re(#"^#/todo/(\w+)/(.+)$"#)
|
||||
@@ -136,6 +154,10 @@ struct InlineRenderer {
|
||||
}
|
||||
case .link(let href, let inner):
|
||||
link(href, inner, style, &out)
|
||||
case .mark(let mark, let inner):
|
||||
var s = style
|
||||
s.color = mark.color
|
||||
render(inner, s, &out)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,13 +443,14 @@ private struct TableBlock: View {
|
||||
GridRow {
|
||||
ForEach(Array(head.enumerated()), id: \.offset) { _, cell in
|
||||
cellView([.strong(cell)])
|
||||
.background(Palette.surface)
|
||||
.background(tint(cell) ?? Palette.surface)
|
||||
}
|
||||
}
|
||||
ForEach(Array(rows.enumerated()), id: \.offset) { _, row in
|
||||
GridRow {
|
||||
ForEach(Array(row.enumerated()), id: \.offset) { _, cell in
|
||||
cellView(cell)
|
||||
.background(tint(cell) ?? .clear)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,6 +458,13 @@ private struct TableBlock: View {
|
||||
.overlay(Rectangle().stroke(Palette.border))
|
||||
}
|
||||
|
||||
private func tint(_ cell: [MDInline]) -> Color? {
|
||||
guard cell.count == 1, case .mark(let mark, _) = cell[0] else {
|
||||
return nil
|
||||
}
|
||||
return mark.tint
|
||||
}
|
||||
|
||||
private func cellView(_ cell: [MDInline]) -> some View {
|
||||
InlineView(inlines: cell, ctx: ctx)
|
||||
.padding(.horizontal, 8)
|
||||
|
||||
Reference in New Issue
Block a user