terminfo.dev 0.7.0 → 1.0.0
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/package.json +4 -1
- package/src/index.ts +17 -39
- package/src/report.tsx +113 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminfo.dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Test your terminal's feature support and contribute to terminfo.dev",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"silvery": "^0.4.3"
|
|
37
|
+
},
|
|
35
38
|
"engines": {
|
|
36
39
|
"node": ">=23.6.0"
|
|
37
40
|
}
|
package/src/index.ts
CHANGED
|
@@ -44,11 +44,6 @@ function loadFeatureSlugs(): Record<string, string> {
|
|
|
44
44
|
return {} // fallback: featureSlug() will use id.replaceAll(".", "-")
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/** OSC 8 hyperlink — clickable link in supporting terminals */
|
|
48
|
-
function link(url: string, text: string): string {
|
|
49
|
-
return `\x1b]8;;${url}\x07${text}\x1b]8;;\x07`
|
|
50
|
-
}
|
|
51
|
-
|
|
52
47
|
interface ResultEntry {
|
|
53
48
|
terminal: string
|
|
54
49
|
terminalVersion: string
|
|
@@ -69,19 +64,6 @@ async function main() {
|
|
|
69
64
|
// Detect terminal
|
|
70
65
|
const terminal = detectTerminal()
|
|
71
66
|
|
|
72
|
-
if (!jsonMode) {
|
|
73
|
-
console.log(`\x1b[1mterminfo.dev\x1b[0m — can your terminal do that?\n`)
|
|
74
|
-
console.log(` Terminal: \x1b[1m${terminal.name}\x1b[0m${terminal.version ? ` ${terminal.version}` : ""}`)
|
|
75
|
-
console.log(` Platform: ${terminal.os}${terminal.osVersion ? ` ${terminal.osVersion}` : ""}`)
|
|
76
|
-
console.log(` Probes: ${ALL_PROBES.length} features across ${new Set(ALL_PROBES.map(p => p.id.split(".")[0])).size} categories`)
|
|
77
|
-
console.log(` Website: https://terminfo.dev`)
|
|
78
|
-
console.log(``)
|
|
79
|
-
console.log(`\x1b[2mResults are compared against ${ALL_PROBES.length} terminal features from the`)
|
|
80
|
-
console.log(`ECMA-48, VT100/VT510, xterm, and Kitty specifications.`)
|
|
81
|
-
console.log(`Run with --submit to contribute your results to the database.\x1b[0m\n`)
|
|
82
|
-
console.log(`Running probes...`)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
67
|
const results: Record<string, boolean> = {}
|
|
86
68
|
const notes: Record<string, string> = {}
|
|
87
69
|
const responses: Record<string, string> = {}
|
|
@@ -134,10 +116,7 @@ async function main() {
|
|
|
134
116
|
return
|
|
135
117
|
}
|
|
136
118
|
|
|
137
|
-
//
|
|
138
|
-
console.log(`\n\x1b[1mResults: ${passed}/${total} (${pct}%)\x1b[0m\n`)
|
|
139
|
-
|
|
140
|
-
// Show categories with OSC 8 hyperlinks
|
|
119
|
+
// Build category data for report
|
|
141
120
|
const slugs = loadFeatureSlugs()
|
|
142
121
|
const categories = new Map<string, Array<{ id: string; name: string; pass: boolean; note?: string }>>()
|
|
143
122
|
for (const probe of ALL_PROBES) {
|
|
@@ -151,20 +130,22 @@ async function main() {
|
|
|
151
130
|
})
|
|
152
131
|
}
|
|
153
132
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
133
|
+
// Render with silvery
|
|
134
|
+
const { renderReport } = await import("./report.tsx")
|
|
135
|
+
const output = await renderReport({
|
|
136
|
+
terminal: terminal.name,
|
|
137
|
+
terminalVersion: terminal.version,
|
|
138
|
+
os: terminal.os,
|
|
139
|
+
osVersion: terminal.osVersion,
|
|
140
|
+
probeCount: total,
|
|
141
|
+
categoryCount: new Set(ALL_PROBES.map(p => p.id.split(".")[0])).size,
|
|
142
|
+
passed,
|
|
143
|
+
total,
|
|
144
|
+
categories,
|
|
145
|
+
slugs,
|
|
146
|
+
submitMode,
|
|
147
|
+
})
|
|
148
|
+
console.log(output)
|
|
168
149
|
|
|
169
150
|
if (submitMode) {
|
|
170
151
|
console.log(`\nSubmitting results to terminfo.dev...`)
|
|
@@ -172,9 +153,6 @@ async function main() {
|
|
|
172
153
|
if (url) {
|
|
173
154
|
console.log(`\x1b[32m✓ Issue created:\x1b[0m ${url}`)
|
|
174
155
|
}
|
|
175
|
-
} else {
|
|
176
|
-
console.log(`\n\x1b[2mSubmit results to terminfo.dev: npx terminfo --submit\x1b[0m`)
|
|
177
|
-
console.log(`\x1b[2mJSON output: npx terminfo --json\x1b[0m`)
|
|
178
156
|
}
|
|
179
157
|
}
|
|
180
158
|
|
package/src/report.tsx
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Silvery-rendered CLI report for terminfo probe results.
|
|
3
|
+
*/
|
|
4
|
+
import React from "react"
|
|
5
|
+
import { Box, Text } from "silvery"
|
|
6
|
+
import { renderString } from "silvery"
|
|
7
|
+
|
|
8
|
+
interface ProbeResult {
|
|
9
|
+
id: string
|
|
10
|
+
name: string
|
|
11
|
+
pass: boolean
|
|
12
|
+
note?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ReportProps {
|
|
16
|
+
terminal: string
|
|
17
|
+
terminalVersion: string
|
|
18
|
+
os: string
|
|
19
|
+
osVersion: string
|
|
20
|
+
probeCount: number
|
|
21
|
+
categoryCount: number
|
|
22
|
+
passed: number
|
|
23
|
+
total: number
|
|
24
|
+
categories: Map<string, ProbeResult[]>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** OSC 8 hyperlink wrapper */
|
|
28
|
+
function osc8(url: string, text: string): string {
|
|
29
|
+
return `\x1b]8;;${url}\x07${text}\x1b]8;;\x07`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function featureUrl(id: string, slug: string): string {
|
|
33
|
+
const cat = id.split(".")[0]!
|
|
34
|
+
return `https://terminfo.dev/${cat}/${slug}`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function Header({ terminal, terminalVersion, os, osVersion, probeCount, categoryCount, passed, total }: ReportProps) {
|
|
38
|
+
const pct = Math.round((passed / total) * 100)
|
|
39
|
+
return (
|
|
40
|
+
<Box flexDirection="column" marginBottom={1}>
|
|
41
|
+
<Text bold>{osc8("https://terminfo.dev", "terminfo.dev")}</Text>
|
|
42
|
+
<Text dimColor>Can your terminal do that?</Text>
|
|
43
|
+
<Text> </Text>
|
|
44
|
+
<Box flexDirection="row" gap={2}>
|
|
45
|
+
<Box flexDirection="column" width={12}>
|
|
46
|
+
<Text dimColor>Terminal</Text>
|
|
47
|
+
<Text dimColor>Platform</Text>
|
|
48
|
+
<Text dimColor>Probes</Text>
|
|
49
|
+
<Text dimColor>Score</Text>
|
|
50
|
+
</Box>
|
|
51
|
+
<Box flexDirection="column">
|
|
52
|
+
<Text bold>{terminal}{terminalVersion ? ` ${terminalVersion}` : ""}</Text>
|
|
53
|
+
<Text>{os} {osVersion}</Text>
|
|
54
|
+
<Text>{probeCount} features, {categoryCount} categories</Text>
|
|
55
|
+
<Text bold color={pct === 100 ? "green" : pct >= 90 ? "yellow" : "red"}>{passed}/{total} ({pct}%)</Text>
|
|
56
|
+
</Box>
|
|
57
|
+
</Box>
|
|
58
|
+
</Box>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function CategorySection({ name, probes, slugs }: { name: string; probes: ProbeResult[]; slugs: Record<string, string> }) {
|
|
63
|
+
const catPassed = probes.filter(p => p.pass).length
|
|
64
|
+
const allPassed = catPassed === probes.length
|
|
65
|
+
const catUrl = `https://terminfo.dev/${name}`
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<Box flexDirection="column">
|
|
69
|
+
<Text color={allPassed ? "green" : catPassed > 0 ? "yellow" : "red"}>
|
|
70
|
+
{osc8(catUrl, name)} ({catPassed}/{probes.length})
|
|
71
|
+
</Text>
|
|
72
|
+
{probes.map(p => {
|
|
73
|
+
const slug = slugs[p.id] ?? p.id.replaceAll(".", "-")
|
|
74
|
+
const url = featureUrl(p.id, slug)
|
|
75
|
+
const icon = p.pass ? "✓" : "✗"
|
|
76
|
+
return (
|
|
77
|
+
<Box key={p.id} flexDirection="row" paddingLeft={2}>
|
|
78
|
+
<Text color={p.pass ? "green" : "red"}>{icon} </Text>
|
|
79
|
+
<Text>{osc8(url, p.name)}</Text>
|
|
80
|
+
{p.note && <Text dimColor> — {p.note}</Text>}
|
|
81
|
+
</Box>
|
|
82
|
+
)
|
|
83
|
+
})}
|
|
84
|
+
</Box>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function Footer({ submitMode }: { submitMode: boolean }) {
|
|
89
|
+
if (submitMode) return null
|
|
90
|
+
return (
|
|
91
|
+
<Box flexDirection="column" marginTop={1}>
|
|
92
|
+
<Text dimColor>Submit: npx terminfo.dev --submit</Text>
|
|
93
|
+
<Text dimColor>JSON: npx terminfo.dev --json</Text>
|
|
94
|
+
</Box>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function Report(props: ReportProps & { slugs: Record<string, string>; submitMode: boolean }) {
|
|
99
|
+
return (
|
|
100
|
+
<Box flexDirection="column">
|
|
101
|
+
<Header {...props} />
|
|
102
|
+
{[...props.categories.entries()].map(([name, probes]) => (
|
|
103
|
+
<CategorySection key={name} name={name} probes={probes} slugs={props.slugs} />
|
|
104
|
+
))}
|
|
105
|
+
<Footer submitMode={props.submitMode} />
|
|
106
|
+
</Box>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function renderReport(props: ReportProps & { slugs: Record<string, string>; submitMode: boolean }): Promise<string> {
|
|
111
|
+
const width = process.stdout.columns ?? 80
|
|
112
|
+
return renderString(<Report {...props} />, { width })
|
|
113
|
+
}
|