render markdown hard breaks and image placeholders (T-379)

Both node types fell through the inline-span switch to an empty
textContent span: words on either side of a hard break glued
together, and images vanished with no trace. A br now emits a
newline; an img renders a muted italic "[image: alt]" placeholder
(falling back to the src) — no inline network loading in the owned
renderer; live-pane images keep going through clide image show.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 01:18:41 +02:00
co-authored by Claude Fable 5
parent e413380ea9
commit 01c3de37e1
5 changed files with 55 additions and 0 deletions
+22
View File
@@ -49,4 +49,26 @@ void main() {
expect(find.textContaining('https://example.com'), findsOneWidget);
expect(tester.takeException(), isNull);
});
// T-379: hard breaks and images fell through to empty text spans —
// words glued together, images vanished without a trace.
testWidgets('a hard line break splits the line instead of gluing words', (tester) async {
// Two trailing spaces = a markdown hard break.
await tester.pumpWidget(harness(f, const ClideMarkdown('alpha \nbeta')));
await tester.pump();
expect(find.textContaining('alpha\nbeta'), findsOneWidget);
expect(find.textContaining('alphabeta'), findsNothing);
});
testWidgets('an image renders its alt text as a visible placeholder', (tester) async {
await tester.pumpWidget(harness(f, const ClideMarkdown('before ![a diagram](http://x/y.png) after')));
await tester.pump();
expect(find.textContaining('[image: a diagram]'), findsOneWidget);
});
testWidgets('an image with no alt text falls back to its source', (tester) async {
await tester.pumpWidget(harness(f, const ClideMarkdown('![](http://x/y.png)')));
await tester.pump();
expect(find.textContaining('[image: http://x/y.png]'), findsOneWidget);
});
}