docs(ui): add live presentation verification
This commit is contained in:
parent
75da8d10e1
commit
78a44184f6
1 changed files with 95 additions and 0 deletions
|
|
@ -1277,6 +1277,101 @@ Remaining boundary:
|
||||||
|
|
||||||
Presentation determinism is now covered at the attributed-string and TextKit line-fragment level for fixed-width snapshots. It is not yet covered by end-to-end pixel screenshots of the live `NSTextView` inside a real window. The remaining possible nondeterminism is therefore platform drawing outside the attributed/layout model, such as AppKit control rasterization or OS-level antialiasing. That is a narrower visual QA problem, not a render or presentation state-model problem.
|
Presentation determinism is now covered at the attributed-string and TextKit line-fragment level for fixed-width snapshots. It is not yet covered by end-to-end pixel screenshots of the live `NSTextView` inside a real window. The remaining possible nondeterminism is therefore platform drawing outside the attributed/layout model, such as AppKit control rasterization or OS-level antialiasing. That is a narrower visual QA problem, not a render or presentation state-model problem.
|
||||||
|
|
||||||
|
## Finding #20 — Live Editor Presentation Reproduction
|
||||||
|
|
||||||
|
Milestone 3.5 invalidated the strongest claim from Milestone 3.4: synthetic presentation snapshots were not enough. They exercised `MarkdownTextStyler` and TextKit layout, but they did not reproduce the live SwiftUI/AppKit bridge lifecycle used by `HybridMarkdownEditor`.
|
||||||
|
|
||||||
|
Live path audited:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
Document["MarkdownDocument"] --> ViewModel["HybridMarkdownEditorViewModel"]
|
||||||
|
ViewModel --> SwiftUI["HybridMarkdownEditor body"]
|
||||||
|
SwiftUI --> Representable["NativeMarkdownTextView"]
|
||||||
|
Representable --> TextView["EditorTextView / NSTextView"]
|
||||||
|
TextView --> Coordinator["NativeMarkdownTextView.Coordinator"]
|
||||||
|
Coordinator --> Styler["MarkdownTextStyler.apply"]
|
||||||
|
Styler --> Storage["NSTextStorage"]
|
||||||
|
Storage --> TextKit["NSLayoutManager / NSTextContainer"]
|
||||||
|
Coordinator --> Widgets["ChecklistOverlayButton sync"]
|
||||||
|
TextKit --> Visible["Visible editor layout"]
|
||||||
|
Widgets --> Visible
|
||||||
|
```
|
||||||
|
|
||||||
|
The divergence was:
|
||||||
|
|
||||||
|
- Milestone 3.4 tests built attributed storage directly.
|
||||||
|
- The benchmark also calls the styler directly.
|
||||||
|
- The real app installs a native text view, delegate callbacks, first-responder state, selection state, overlay controls, and SwiftUI update cycles.
|
||||||
|
|
||||||
|
Reproduction harness:
|
||||||
|
|
||||||
|
`HybridMarkdownLiveEditorHarness` now instantiates the real macOS editor pieces in debug builds:
|
||||||
|
|
||||||
|
- `EditorTextView`
|
||||||
|
- `NativeMarkdownTextView.Coordinator`
|
||||||
|
- `ComfortableEditorScrollView`
|
||||||
|
- `NSWindow`
|
||||||
|
- real `NSTextStorage`
|
||||||
|
- real checklist overlay buttons
|
||||||
|
- real coordinator calls for focus, selection, styling, and checkbox toggles
|
||||||
|
|
||||||
|
The first live regression test reproduced the heading bug before the fix:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Live editor harness
|
||||||
|
-> assign document source
|
||||||
|
-> simulate app launch first responder
|
||||||
|
-> heading marker remained visible
|
||||||
|
```
|
||||||
|
|
||||||
|
Root cause:
|
||||||
|
|
||||||
|
The macOS live path installed the `NSTextView` delegate before assigning the initial document string. That allowed initial programmatic text loading to flow through live delegate behavior and mark the editor as if the user had activated editing. When the text view became first responder during launch, the default selection at offset 0 became an active source line, so the first heading appeared as raw Markdown.
|
||||||
|
|
||||||
|
Fix:
|
||||||
|
|
||||||
|
- Assign the initial string before installing the native text view delegate on macOS and iOS.
|
||||||
|
- Track user editing activation separately from first-responder state.
|
||||||
|
- First responder alone no longer creates an active source line.
|
||||||
|
- Mouse, keyboard, paste, and real text changes activate source presentation.
|
||||||
|
- Programmatic launch focus keeps all lines rendered.
|
||||||
|
|
||||||
|
Live regression tests:
|
||||||
|
|
||||||
|
- `testLiveInitialFirstResponderDoesNotShowHeadingSourceBeforeUserInteraction`
|
||||||
|
- `testLiveParagraphGeometryReturnsAfterClickAndFocusAway`
|
||||||
|
- `testLiveCheckboxClickPreservesSelectionActiveLineAndGeometry`
|
||||||
|
|
||||||
|
These tests use the live editor path, not the pure render model and not a standalone attributed-string snapshot.
|
||||||
|
|
||||||
|
Checkbox contract verified by the live harness:
|
||||||
|
|
||||||
|
- Clicking a rendered checkbox toggles Markdown source from `[ ]` to `[x]`.
|
||||||
|
- Selection remains unchanged.
|
||||||
|
- The active editing line remains unchanged.
|
||||||
|
- Checkbox label geometry remains unchanged.
|
||||||
|
- Checkbox overlay frame remains unchanged.
|
||||||
|
|
||||||
|
Manual verification checklist:
|
||||||
|
|
||||||
|
1. Launch Sapling.
|
||||||
|
2. Inspect the initially loaded Markdown document before clicking the editor.
|
||||||
|
3. Verify headings render visually and do not show leading `#` markers.
|
||||||
|
4. Click a paragraph containing bold, italic, inline code, and a link.
|
||||||
|
5. Move focus away from the paragraph.
|
||||||
|
6. Verify paragraph wrapping, spacing, and alignment return to the original rendered geometry.
|
||||||
|
7. Put the cursor on a different line from a task item.
|
||||||
|
8. Click a rendered task checkbox.
|
||||||
|
9. Verify only the checkbox state changes.
|
||||||
|
10. Verify checkbox-to-label spacing remains stable.
|
||||||
|
11. Verify the cursor remains on the original editing line.
|
||||||
|
12. Verify the task line does not become the active source line.
|
||||||
|
|
||||||
|
Current conclusion:
|
||||||
|
|
||||||
|
The live editor path now has regression coverage for the bugs that escaped Milestone 3.4. Future presentation claims should be based on live harness tests or manual app verification, not only semantic render snapshots or direct styler tests.
|
||||||
|
|
||||||
## AttributedString and NSAttributedString
|
## AttributedString and NSAttributedString
|
||||||
|
|
||||||
Swift `AttributedString` is useful for renderer-facing APIs and SwiftUI previews.
|
Swift `AttributedString` is useful for renderer-facing APIs and SwiftUI previews.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue