Build Preview mode rendering

The card body's resting state: swift-markdown (pinned 0.8.0, smart
typography off — Preview renders the bytes on disk) parsed into a pure
BodyMarkup model with UTF-8 source offsets, rendered on one hosted
TextKit 1 NSTextView — chosen because find-in-text is NSTextFinder,
checkbox clicks reuse AppKit character hit-testing, links are .link
attributes, and NSTextTable's automatic layout is exactly the
columns-sized-to-contents rule. The GFM subset renders per 05; HTML
stays verbatim code-styled text; relative images resolve against the
card folder while remote URLs are never fetched, drawing a quiet chip
instead. Task checkboxes are live: a click flips exactly one byte
through a fresh-read, refuse-uneditable, stamp, atomic-replace write —
the app's only offset-addressed write, so a moved target refuses as
staleTarget and what the user saw decides the direction, netting one
toggle on a double-click. Empty bodies open in Edit per CardBodyMode's
opening rule, applied once; the Edit surface itself stays an honest
read-only stub until its card. FindCommand prefers the card body's
find over board search when a card window is focused.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-28 09:59:18 -04:00
parent 7f1adf47c5
commit 6dc84176fb
15 changed files with 2608 additions and 18 deletions
+14 -2
View File
@@ -83,13 +83,25 @@ struct FindCommand: View {
@FocusedValue(\.boardStore) private var store
@FocusedValue(\.boardSearch) private var search
@FocusedValue(\.cardBody) private var cardBody
/// **The card window wins when it is the focused scene**, which is the whole of 11's split
/// ("Board window: board search; card window: find-in-text"): the two never both publish, so
/// this reads as a preference only because a scene value is `nil` in the scene that does not
/// have one. The card side is the standard find bar over its body surface
/// (`CardBodyPresentation.findInText`); the board side focuses the search field.
private var findInText: (() -> Void)? { cardBody?.findInText }
var body: some View {
Button("Find") {
search?.focusField?()
if let findInText {
findInText()
} else {
search?.focusField?()
}
}
.keyboardShortcut("f", modifiers: .command)
.disabled(store == nil || search?.focusField == nil)
.disabled(findInText == nil && (store == nil || search?.focusField == nil))
}
}