feat(draw): d2 diagram template — compile d2 source to SVG (T-494)

The d2 drawing template compiles a diagram's source to SVG through the d2
binary (resolved via the D-104 path layer), then paints it with the same
renderer the svg card uses. `clide draw --file x.d2` infers the type from
the extension; `.svg` files render directly. Template handlers now return
a DrawResult so a compile failure or an unresolved d2 surface as an honest
userError with an install hint, not a generic "no SVG". Real d2 0.7.1
verified end to end.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 11:19:48 +02:00
co-authored by Claude Opus 4.8
parent 67edf732f1
commit 64d77ec5dc
10 changed files with 234 additions and 19 deletions
+4 -4
View File
@@ -37,15 +37,15 @@ void main() {
});
test('template: a registered handler lowers the doc to SVG', () async {
final reg = DrawingRegistry()..register('d2', (doc) async => '<svg data-src="${doc.fields['source']}"/>');
final reg = DrawingRegistry()..register('d2', (doc) async => DrawOk('<svg data-src="${doc.fields['source']}"/>'));
final r = await resolve(parseDrawingCardDoc({'template': 'd2', 'source': 'a -> b'})!, reg);
expect((r as DrawOk).svg, '<svg data-src="a -> b"/>');
});
test('template: a handler that returns null is an error', () async {
final reg = DrawingRegistry()..register('d2', (_) async => null);
test('template: a handler error propagates with its message', () async {
final reg = DrawingRegistry()..register('d2', (_) async => const DrawErr('d2 not found'));
final r = await resolve(parseDrawingCardDoc({'template': 'd2'})!, reg);
expect(r, isA<DrawErr>());
expect((r as DrawErr).message, contains('d2 not found'));
});
});
}