termcast 1.3.36 → 1.3.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +12 -2
- package/dist/components/detail.js.map +1 -1
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +11 -2
- package/dist/components/list.js.map +1 -1
- package/dist/diagram-parser.d.ts +34 -0
- package/dist/diagram-parser.d.ts.map +1 -0
- package/dist/diagram-parser.js +114 -0
- package/dist/diagram-parser.js.map +1 -0
- package/dist/examples/simple-detail-markdown.d.ts +2 -0
- package/dist/examples/simple-detail-markdown.d.ts.map +1 -0
- package/dist/examples/simple-detail-markdown.js +94 -0
- package/dist/examples/simple-detail-markdown.js.map +1 -0
- package/dist/internal/scrollbox.d.ts.map +1 -1
- package/dist/internal/scrollbox.js +1 -2
- package/dist/internal/scrollbox.js.map +1 -1
- package/dist/markdown-utils.d.ts +14 -0
- package/dist/markdown-utils.d.ts.map +1 -0
- package/dist/markdown-utils.js +138 -0
- package/dist/markdown-utils.js.map +1 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +5 -24
- package/dist/theme.js.map +1 -1
- package/dist/themes/termcast.json +4 -4
- package/dist/themes.d.ts +12 -0
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +79 -0
- package/dist/themes.js.map +1 -1
- package/package.json +3 -3
- package/src/components/detail.tsx +16 -2
- package/src/components/list.tsx +15 -2
- package/src/diagram-parser.tsx +141 -0
- package/src/examples/list-with-detail.vitest.tsx +34 -34
- package/src/examples/list-with-sections.vitest.tsx +1 -1
- package/src/examples/simple-detail-markdown.tsx +96 -0
- package/src/examples/simple-detail-markdown.vitest.tsx +156 -0
- package/src/examples/simple-grid.vitest.tsx +2 -2
- package/src/examples/swift-extension.vitest.tsx +1 -1
- package/src/internal/scrollbox.tsx +1 -3
- package/src/markdown-utils.tsx +182 -0
- package/src/theme.tsx +5 -24
- package/src/themes/termcast.json +4 -4
- package/src/themes.ts +98 -0
package/src/components/list.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
TextAttributes,
|
|
5
5
|
TextareaRenderable,
|
|
6
6
|
} from '@opentui/core'
|
|
7
|
-
import { useKeyboard, flushSync } from '@opentui/react'
|
|
7
|
+
import { useKeyboard, flushSync, useRenderer } from '@opentui/react'
|
|
8
8
|
import React, {
|
|
9
9
|
ReactElement,
|
|
10
10
|
ReactNode,
|
|
@@ -32,6 +32,7 @@ import { Color, resolveColor } from 'termcast/src/colors'
|
|
|
32
32
|
import { getIconEmoji, getIconValue } from 'termcast/src/components/icon'
|
|
33
33
|
import { ActionPanel } from 'termcast/src/components/actions'
|
|
34
34
|
import { useTheme, markdownSyntaxStyle } from 'termcast/src/theme'
|
|
35
|
+
import { createMarkdownRenderNode } from 'termcast/src/markdown-utils'
|
|
35
36
|
import { CommonProps } from 'termcast/src/utils'
|
|
36
37
|
|
|
37
38
|
export { Color }
|
|
@@ -1412,6 +1413,18 @@ const ListItem: ListItemType = (props) => {
|
|
|
1412
1413
|
)
|
|
1413
1414
|
}
|
|
1414
1415
|
|
|
1416
|
+
// Renders markdown with link URL stripping via renderNode for list detail panel.
|
|
1417
|
+
function ListMarkdownContent({ markdown }: { markdown: string }): any {
|
|
1418
|
+
const renderer = useRenderer()
|
|
1419
|
+
const renderNode = React.useMemo(() => {
|
|
1420
|
+
return createMarkdownRenderNode(renderer)
|
|
1421
|
+
}, [renderer])
|
|
1422
|
+
|
|
1423
|
+
return (
|
|
1424
|
+
<markdown content={markdown} syntaxStyle={markdownSyntaxStyle} conceal renderNode={renderNode} />
|
|
1425
|
+
)
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1415
1428
|
const ListItemDetail: ListItemDetailType = (props) => {
|
|
1416
1429
|
const theme = useTheme()
|
|
1417
1430
|
const { isLoading, markdown, metadata } = props
|
|
@@ -1441,7 +1454,7 @@ const ListItemDetail: ListItemDetailType = (props) => {
|
|
|
1441
1454
|
>
|
|
1442
1455
|
<box gap={1} style={{ flexDirection: 'column' }}>
|
|
1443
1456
|
{markdown && (
|
|
1444
|
-
<
|
|
1457
|
+
<ListMarkdownContent markdown={markdown} />
|
|
1445
1458
|
)}
|
|
1446
1459
|
{metadata && (
|
|
1447
1460
|
<box
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// ASCII/Unicode diagram parser for syntax highlighting in markdown code blocks.
|
|
2
|
+
// Separates structural characters (box-drawing, arrows) from text content
|
|
3
|
+
// to render diagrams with muted structural elements and highlighted labels.
|
|
4
|
+
// Ported from critique (https://github.com/remorses/critique)
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A segment of text with a specific color type
|
|
8
|
+
*/
|
|
9
|
+
export interface DiagramSegment {
|
|
10
|
+
text: string
|
|
11
|
+
type: 'text' | 'muted'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A parsed line of diagram content
|
|
16
|
+
*/
|
|
17
|
+
export interface ParsedDiagramLine {
|
|
18
|
+
segments: DiagramSegment[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Box drawing characters (Unicode)
|
|
22
|
+
const BOX_DRAWING_CHARS = new Set([
|
|
23
|
+
// Light box drawing
|
|
24
|
+
'┌', '┐', '└', '┘', '─', '│', '├', '┤', '┬', '┴', '┼',
|
|
25
|
+
// Double box drawing
|
|
26
|
+
'╔', '╗', '╚', '╝', '═', '║', '╠', '╣', '╦', '╩', '╬',
|
|
27
|
+
// Heavy box drawing
|
|
28
|
+
'┏', '┓', '┗', '┛', '━', '┃', '┣', '┫', '┳', '┻', '╋',
|
|
29
|
+
// Mixed light/heavy
|
|
30
|
+
'┍', '┎', '┑', '┒', '┕', '┖', '┙', '┚',
|
|
31
|
+
'┝', '┞', '┟', '┠', '┡', '┢', '┥', '┦', '┧', '┨', '┩', '┪',
|
|
32
|
+
'┭', '┮', '┯', '┰', '┱', '┲', '┵', '┶', '┷', '┸', '┹', '┺',
|
|
33
|
+
'┽', '┾', '┿', '╀', '╁', '╂', '╃', '╄', '╅', '╆', '╇', '╈', '╉', '╊',
|
|
34
|
+
// Rounded corners
|
|
35
|
+
'╭', '╮', '╯', '╰',
|
|
36
|
+
])
|
|
37
|
+
|
|
38
|
+
// Arrow characters
|
|
39
|
+
const ARROW_CHARS = new Set([
|
|
40
|
+
// Unicode arrows
|
|
41
|
+
'▶', '◀', '▼', '▲', '►', '◄', '▾', '▴',
|
|
42
|
+
'→', '←', '↓', '↑', '↔', '↕', '↖', '↗', '↘', '↙',
|
|
43
|
+
'⇒', '⇐', '⇓', '⇑', '⇔', '⇕',
|
|
44
|
+
// Triangle arrows
|
|
45
|
+
'△', '▽', '◁', '▷', '⊳', '⊲', '⊴', '⊵',
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
// ASCII diagram characters (structural, not text)
|
|
49
|
+
// Note: "v" and "V" are NOT included because they appear in regular text
|
|
50
|
+
// like "Server", "Validate", etc.
|
|
51
|
+
const ASCII_STRUCTURAL_CHARS = new Set(['-', '|', '+', '/', '\\', '<', '>', '^'])
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if a character is a diagram structural character (should be muted)
|
|
55
|
+
*/
|
|
56
|
+
function isDiagramChar(char: string): boolean {
|
|
57
|
+
return (
|
|
58
|
+
BOX_DRAWING_CHARS.has(char) ||
|
|
59
|
+
ARROW_CHARS.has(char) ||
|
|
60
|
+
ASCII_STRUCTURAL_CHARS.has(char)
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Parse a single line of diagram content into segments
|
|
66
|
+
*/
|
|
67
|
+
export function parseDiagramLine(line: string): ParsedDiagramLine {
|
|
68
|
+
if (!line) {
|
|
69
|
+
return { segments: [] }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const segments: DiagramSegment[] = []
|
|
73
|
+
let currentText = ''
|
|
74
|
+
let currentType: 'text' | 'muted' | null = null
|
|
75
|
+
|
|
76
|
+
// Iterate through each character (handling Unicode properly)
|
|
77
|
+
for (const char of line) {
|
|
78
|
+
const isMuted = isDiagramChar(char) || char === ' '
|
|
79
|
+
const type = isMuted ? 'muted' : 'text'
|
|
80
|
+
|
|
81
|
+
if (currentType === null) {
|
|
82
|
+
currentType = type
|
|
83
|
+
currentText = char
|
|
84
|
+
} else if (type === currentType) {
|
|
85
|
+
currentText += char
|
|
86
|
+
} else {
|
|
87
|
+
// Type changed, push current segment and start new one
|
|
88
|
+
segments.push({ text: currentText, type: currentType })
|
|
89
|
+
currentText = char
|
|
90
|
+
currentType = type
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Push final segment
|
|
95
|
+
if (currentText && currentType !== null) {
|
|
96
|
+
segments.push({ text: currentText, type: currentType })
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return { segments }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Parse entire diagram content into lines of segments
|
|
104
|
+
*/
|
|
105
|
+
export function parseDiagram(content: string): ParsedDiagramLine[] {
|
|
106
|
+
const lines = content.split('\n')
|
|
107
|
+
return lines.map(parseDiagramLine)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Convert parsed diagram to a debug string for testing
|
|
112
|
+
* Muted segments are replaced with '*' characters
|
|
113
|
+
*/
|
|
114
|
+
export function diagramToDebugString(parsed: ParsedDiagramLine[]): string {
|
|
115
|
+
return parsed
|
|
116
|
+
.map((line) => {
|
|
117
|
+
return line.segments
|
|
118
|
+
.map((segment) => {
|
|
119
|
+
if (segment.type === 'muted') {
|
|
120
|
+
return '*'.repeat([...segment.text].length)
|
|
121
|
+
}
|
|
122
|
+
return segment.text
|
|
123
|
+
})
|
|
124
|
+
.join('')
|
|
125
|
+
})
|
|
126
|
+
.join('\n')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Convert ASCII diagram characters to Unicode box-drawing equivalents.
|
|
131
|
+
* Eliminates visual gaps between lines.
|
|
132
|
+
* - `|` -> `│` (vertical lines)
|
|
133
|
+
* - `--` or more -> `──` (horizontal lines, but not single hyphens in text)
|
|
134
|
+
*/
|
|
135
|
+
export function convertAsciiToUnicode(content: string): string {
|
|
136
|
+
return content
|
|
137
|
+
.replace(/\|/g, '│')
|
|
138
|
+
.replace(/-{2,}/g, (match) => {
|
|
139
|
+
return '─'.repeat(match.length)
|
|
140
|
+
})
|
|
141
|
+
}
|
|
@@ -39,25 +39,25 @@ test('list with detail view display and navigation', async () => {
|
|
|
39
39
|
|
|
40
40
|
›bulbasaur #001
|
|
41
41
|
ivysaur #002 │ bulbasaur ▲
|
|
42
|
-
charmander #004 │
|
|
42
|
+
charmander #004 │ ▀
|
|
43
43
|
charmeleon #005 │ Illustration
|
|
44
44
|
squirtle #007 │
|
|
45
45
|
wartortle #008 │ Types
|
|
46
|
+
│
|
|
46
47
|
│ Grass / Poison
|
|
47
48
|
│
|
|
48
49
|
│ Characteristics
|
|
50
|
+
│
|
|
49
51
|
│ - Height: 0.7m
|
|
50
52
|
│ - Weight: 6.9kg
|
|
51
53
|
│
|
|
52
54
|
│ Abilities
|
|
55
|
+
│
|
|
53
56
|
│ - Chlorophyll
|
|
54
57
|
│ - Overgrow
|
|
55
58
|
│
|
|
56
59
|
│
|
|
57
60
|
│ Types
|
|
58
|
-
│
|
|
59
|
-
│ Grass
|
|
60
|
-
│ ─────────────────
|
|
61
61
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
62
62
|
|
|
63
63
|
"
|
|
@@ -78,25 +78,25 @@ test('list with detail view display and navigation', async () => {
|
|
|
78
78
|
|
|
79
79
|
bulbasaur #001
|
|
80
80
|
›ivysaur #002 │ ivysaur ▲
|
|
81
|
-
charmander #004 │
|
|
81
|
+
charmander #004 │ ▀
|
|
82
82
|
charmeleon #005 │ Illustration
|
|
83
83
|
squirtle #007 │
|
|
84
84
|
wartortle #008 │ Types
|
|
85
|
+
│
|
|
85
86
|
│ Grass / Poison
|
|
86
87
|
│
|
|
87
88
|
│ Characteristics
|
|
89
|
+
│
|
|
88
90
|
│ - Height: 1m
|
|
89
91
|
│ - Weight: 13kg
|
|
90
92
|
│
|
|
91
93
|
│ Abilities
|
|
94
|
+
│
|
|
92
95
|
│ - Chlorophyll
|
|
93
96
|
│ - Overgrow
|
|
94
97
|
│
|
|
95
98
|
│
|
|
96
99
|
│ Types
|
|
97
|
-
│
|
|
98
|
-
│ Grass
|
|
99
|
-
│ ─────────────────
|
|
100
100
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
101
101
|
|
|
102
102
|
"
|
|
@@ -119,21 +119,21 @@ test('list with detail view display and navigation', async () => {
|
|
|
119
119
|
charmeleon #005 │ Illustration
|
|
120
120
|
squirtle #007 │
|
|
121
121
|
wartortle #008 │ Types
|
|
122
|
+
│
|
|
122
123
|
│ Fire
|
|
123
124
|
│
|
|
124
125
|
│ Characteristics
|
|
126
|
+
│
|
|
125
127
|
│ - Height: 0.6m
|
|
126
128
|
│ - Weight: 8.5kg
|
|
127
129
|
│
|
|
128
130
|
│ Abilities
|
|
131
|
+
│
|
|
129
132
|
│ - Blaze
|
|
130
133
|
│ - Solar Power
|
|
131
134
|
│
|
|
132
135
|
│
|
|
133
136
|
│ Types
|
|
134
|
-
│
|
|
135
|
-
│ Fire
|
|
136
|
-
│ ─────────────────
|
|
137
137
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
138
138
|
|
|
139
139
|
"
|
|
@@ -173,7 +173,7 @@ test('list with detail view display and navigation', async () => {
|
|
|
173
173
|
│ ↵ select ↑↓ navigate │
|
|
174
174
|
│ │
|
|
175
175
|
╰──────────────────────────────────────────────────────────────────────────╯
|
|
176
|
-
│
|
|
176
|
+
│ Types
|
|
177
177
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
178
178
|
|
|
179
179
|
"
|
|
@@ -242,21 +242,21 @@ test('list with detail view display and navigation', async () => {
|
|
|
242
242
|
charmeleon #005 │ Illustration
|
|
243
243
|
squirtle #007 │
|
|
244
244
|
wartortle #008 │ Types
|
|
245
|
+
│
|
|
245
246
|
│ Fire
|
|
246
247
|
│
|
|
247
248
|
│ Characteristics
|
|
249
|
+
│
|
|
248
250
|
│ - Height: 0.6m
|
|
249
251
|
│ - Weight: 8.5kg
|
|
250
252
|
│
|
|
251
253
|
│ Abilities
|
|
254
|
+
│
|
|
252
255
|
│ - Blaze
|
|
253
256
|
│ - Solar Power
|
|
254
257
|
│
|
|
255
258
|
│
|
|
256
259
|
│ Types
|
|
257
|
-
│
|
|
258
|
-
│ Fire
|
|
259
|
-
│ ─────────────────
|
|
260
260
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
261
261
|
|
|
262
262
|
"
|
|
@@ -291,21 +291,21 @@ test('list detail view search functionality', async () => {
|
|
|
291
291
|
│ Illustration
|
|
292
292
|
│
|
|
293
293
|
│ Types
|
|
294
|
+
│
|
|
294
295
|
│ Fire
|
|
295
296
|
│
|
|
296
297
|
│ Characteristics
|
|
298
|
+
│
|
|
297
299
|
│ - Height: 0.6m
|
|
298
300
|
│ - Weight: 8.5kg
|
|
299
301
|
│
|
|
300
302
|
│ Abilities
|
|
303
|
+
│
|
|
301
304
|
│ - Blaze
|
|
302
305
|
│ - Solar Power
|
|
303
306
|
│
|
|
304
307
|
│
|
|
305
308
|
│ Types
|
|
306
|
-
│
|
|
307
|
-
│ Fire
|
|
308
|
-
│ ─────────────────
|
|
309
309
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
310
310
|
|
|
311
311
|
"
|
|
@@ -337,21 +337,21 @@ test('list detail view search functionality', async () => {
|
|
|
337
337
|
│ Illustration
|
|
338
338
|
│
|
|
339
339
|
│ Types
|
|
340
|
+
│
|
|
340
341
|
│ Water
|
|
341
342
|
│
|
|
342
343
|
│ Characteristics
|
|
344
|
+
│
|
|
343
345
|
│ - Height: 1m
|
|
344
346
|
│ - Weight: 22.5kg
|
|
345
347
|
│
|
|
346
348
|
│ Abilities
|
|
349
|
+
│
|
|
347
350
|
│ - Torrent
|
|
348
351
|
│ - Rain Dish
|
|
349
352
|
│
|
|
350
353
|
│
|
|
351
354
|
│ Types
|
|
352
|
-
│
|
|
353
|
-
│ Water
|
|
354
|
-
│ ─────────────────
|
|
355
355
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
356
356
|
|
|
357
357
|
"
|
|
@@ -374,21 +374,21 @@ test('list detail view search functionality', async () => {
|
|
|
374
374
|
│ Illustration
|
|
375
375
|
│
|
|
376
376
|
│ Types
|
|
377
|
+
│
|
|
377
378
|
│ Water
|
|
378
379
|
│
|
|
379
380
|
│ Characteristics
|
|
381
|
+
│
|
|
380
382
|
│ - Height: 1m
|
|
381
383
|
│ - Weight: 22.5kg
|
|
382
384
|
│
|
|
383
385
|
│ Abilities
|
|
386
|
+
│
|
|
384
387
|
│ - Torrent
|
|
385
388
|
│ - Rain Dish
|
|
386
389
|
│
|
|
387
390
|
│
|
|
388
391
|
│ Types
|
|
389
|
-
│
|
|
390
|
-
│ Water
|
|
391
|
-
│ ─────────────────
|
|
392
392
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
393
393
|
|
|
394
394
|
"
|
|
@@ -419,25 +419,25 @@ test('list detail metadata rendering', async () => {
|
|
|
419
419
|
|
|
420
420
|
›bulbasaur #001
|
|
421
421
|
ivysaur #002 │ bulbasaur ▲
|
|
422
|
-
charmander #004 │
|
|
422
|
+
charmander #004 │ ▀
|
|
423
423
|
charmeleon #005 │ Illustration
|
|
424
424
|
squirtle #007 │
|
|
425
425
|
wartortle #008 │ Types
|
|
426
|
+
│
|
|
426
427
|
│ Grass / Poison
|
|
427
428
|
│
|
|
428
429
|
│ Characteristics
|
|
430
|
+
│
|
|
429
431
|
│ - Height: 0.7m
|
|
430
432
|
│ - Weight: 6.9kg
|
|
431
433
|
│
|
|
432
434
|
│ Abilities
|
|
435
|
+
│
|
|
433
436
|
│ - Chlorophyll
|
|
434
437
|
│ - Overgrow
|
|
435
438
|
│
|
|
436
439
|
│
|
|
437
440
|
│ Types
|
|
438
|
-
│
|
|
439
|
-
│ Grass
|
|
440
|
-
│ ─────────────────
|
|
441
441
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
442
442
|
|
|
443
443
|
"
|
|
@@ -467,21 +467,21 @@ test('list detail metadata rendering', async () => {
|
|
|
467
467
|
charmeleon #005 │ Illustration
|
|
468
468
|
›squirtle #007 │
|
|
469
469
|
wartortle #008 │ Types
|
|
470
|
+
│
|
|
470
471
|
│ Water
|
|
471
472
|
│
|
|
472
473
|
│ Characteristics
|
|
474
|
+
│
|
|
473
475
|
│ - Height: 0.5m
|
|
474
476
|
│ - Weight: 9kg
|
|
475
477
|
│
|
|
476
478
|
│ Abilities
|
|
479
|
+
│
|
|
477
480
|
│ - Torrent
|
|
478
481
|
│ - Rain Dish
|
|
479
482
|
│
|
|
480
483
|
│
|
|
481
484
|
│ Types
|
|
482
|
-
│
|
|
483
|
-
│ Water
|
|
484
|
-
│ ─────────────────
|
|
485
485
|
↵ toggle detail ↑↓ navigate ^k a │ ▼
|
|
486
486
|
|
|
487
487
|
"
|
|
@@ -563,6 +563,7 @@ test('list with detail layout consistency - short vs long detail content', async
|
|
|
563
563
|
Another Item │ content ▀
|
|
564
564
|
│
|
|
565
565
|
│ Section 1
|
|
566
|
+
│
|
|
566
567
|
│ This is a very long description
|
|
567
568
|
│ that contains multiple paragraphs
|
|
568
569
|
│ and sections to test how the
|
|
@@ -570,11 +571,10 @@ test('list with detail layout consistency - short vs long detail content', async
|
|
|
570
571
|
│ panel content overflows.
|
|
571
572
|
│
|
|
572
573
|
│ Section 2
|
|
574
|
+
│
|
|
573
575
|
│ More content here to ensure we
|
|
574
576
|
│ have enough text to cause
|
|
575
|
-
|
|
576
|
-
│ panel scrollbox.
|
|
577
|
-
↑↓ navigate ^k actions │ ▼
|
|
577
|
+
↑↓ navigate ^k actions │ vertical overflow in the detail ▼
|
|
578
578
|
|
|
579
579
|
"
|
|
580
580
|
`)
|
|
@@ -313,6 +313,7 @@ test('list with sections search functionality', async () => {
|
|
|
313
313
|
Freshly baked bread from our bakery.
|
|
314
314
|
|
|
315
315
|
Product Details
|
|
316
|
+
|
|
316
317
|
- Baked fresh daily
|
|
317
318
|
- Made with organic flour
|
|
318
319
|
- No preservatives
|
|
@@ -322,7 +323,6 @@ test('list with sections search functionality', async () => {
|
|
|
322
323
|
esc go back
|
|
323
324
|
|
|
324
325
|
|
|
325
|
-
|
|
326
326
|
"
|
|
327
327
|
`)
|
|
328
328
|
}, 10000)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Example: Detail view with markdown content including a diagram code block.
|
|
2
|
+
// Tests that the <markdown> element properly renders headings, prose,
|
|
3
|
+
// code blocks, and diagram content.
|
|
4
|
+
|
|
5
|
+
import { Detail } from 'termcast'
|
|
6
|
+
import { renderWithProviders } from '../utils'
|
|
7
|
+
|
|
8
|
+
const markdown = `# Architecture Overview
|
|
9
|
+
|
|
10
|
+
This document describes the system architecture.
|
|
11
|
+
|
|
12
|
+
## Components
|
|
13
|
+
|
|
14
|
+
The system has three main components:
|
|
15
|
+
|
|
16
|
+
- **Client** - handles user interaction
|
|
17
|
+
- **Server** - processes requests
|
|
18
|
+
- **Database** - stores data
|
|
19
|
+
|
|
20
|
+
## Links
|
|
21
|
+
|
|
22
|
+
Check out the [GitHub repository](https://github.com/remorses/termcast) for the source code.
|
|
23
|
+
|
|
24
|
+
See the [API documentation](https://developers.raycast.com/api-reference) for more details.
|
|
25
|
+
|
|
26
|
+
A paragraph with [multiple](https://example.com/one) links [inline](https://example.com/two) here.
|
|
27
|
+
|
|
28
|
+
Nested formatting: **bold with [link inside](https://example.com/bold)** and *italic with [link](https://example.com/italic)*.
|
|
29
|
+
|
|
30
|
+
## Configuration Table
|
|
31
|
+
|
|
32
|
+
| Setting | Default | Description |
|
|
33
|
+
|---------|---------|-------------|
|
|
34
|
+
| Host | localhost | Database host address |
|
|
35
|
+
| Port | 5432 | Database port number |
|
|
36
|
+
| SSL | false | Enable TLS encryption |
|
|
37
|
+
| Pool Size | 10 | Max connections |
|
|
38
|
+
|
|
39
|
+
## Flow Diagram
|
|
40
|
+
|
|
41
|
+
\`\`\`diagram
|
|
42
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
43
|
+
│ Client │────▶│ Server │────▶│ Database │
|
|
44
|
+
└─────────────┘ └─────────────┘ └─────────────┘
|
|
45
|
+
\`\`\`
|
|
46
|
+
|
|
47
|
+
## Vertical Flow
|
|
48
|
+
|
|
49
|
+
\`\`\`diagram
|
|
50
|
+
┌─────────┐
|
|
51
|
+
│ Start │
|
|
52
|
+
└────┬────┘
|
|
53
|
+
│
|
|
54
|
+
▼
|
|
55
|
+
┌─────────┐
|
|
56
|
+
│ Process │
|
|
57
|
+
└────┬────┘
|
|
58
|
+
│
|
|
59
|
+
▼
|
|
60
|
+
┌─────────┐
|
|
61
|
+
│ End │
|
|
62
|
+
└─────────┘
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
## Code Example
|
|
66
|
+
|
|
67
|
+
\`\`\`typescript
|
|
68
|
+
interface Config {
|
|
69
|
+
host: string
|
|
70
|
+
port: number
|
|
71
|
+
ssl: boolean
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function connect(config: Config): Promise<Connection> {
|
|
75
|
+
const validated = validate(config)
|
|
76
|
+
return db.connect(validated)
|
|
77
|
+
}
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
## Task List
|
|
81
|
+
|
|
82
|
+
- [x] Design system architecture
|
|
83
|
+
- [x] Implement core components
|
|
84
|
+
- [ ] Add monitoring
|
|
85
|
+
- [ ] Deploy to production
|
|
86
|
+
|
|
87
|
+
> **Note:** All connections use TLS encryption in production.
|
|
88
|
+
|
|
89
|
+
The system handles ~10k requests/second. For more info visit [the docs](https://termcast.app).
|
|
90
|
+
`
|
|
91
|
+
|
|
92
|
+
function SimpleDetailMarkdown() {
|
|
93
|
+
return <Detail markdown={markdown} />
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
renderWithProviders(<SimpleDetailMarkdown />)
|