terminfo.dev 0.5.0 → 0.7.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +49 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminfo.dev",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Test your terminal's feature support and contribute to terminfo.dev",
5
5
  "keywords": [
6
6
  "ansi",
package/src/index.ts CHANGED
@@ -13,11 +13,42 @@
13
13
  * ```
14
14
  */
15
15
 
16
+ import { readFileSync } from "node:fs"
17
+ import { dirname, join } from "node:path"
18
+ import { fileURLToPath } from "node:url"
16
19
  import { detectTerminal } from "./detect.ts"
17
20
  import { ALL_PROBES } from "./probes/index.ts"
18
21
  import { withRawMode } from "./tty.ts"
19
22
  import { submitResults } from "./submit.ts"
20
23
 
24
+ const __dirname = dirname(fileURLToPath(import.meta.url))
25
+
26
+ /** Load feature slugs from features.json for OSC 8 hyperlinks */
27
+ function loadFeatureSlugs(): Record<string, string> {
28
+ // Try repo-local path first, then npm-installed path
29
+ const candidates = [
30
+ join(__dirname, "..", "..", "features.json"), // repo: cli/src/ -> features.json
31
+ join(__dirname, "..", "..", "..", "features.json"), // npm: node_modules/terminfo.dev/src/ -> features.json
32
+ ]
33
+ for (const path of candidates) {
34
+ try {
35
+ const raw = JSON.parse(readFileSync(path, "utf-8"))
36
+ delete raw.$comment
37
+ const slugs: Record<string, string> = {}
38
+ for (const [id, entry] of Object.entries(raw) as [string, any][]) {
39
+ slugs[id] = entry.slug ?? id.replaceAll(".", "-")
40
+ }
41
+ return slugs
42
+ } catch {}
43
+ }
44
+ return {} // fallback: featureSlug() will use id.replaceAll(".", "-")
45
+ }
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
+
21
52
  interface ResultEntry {
22
53
  terminal: string
23
54
  terminalVersion: string
@@ -39,11 +70,16 @@ async function main() {
39
70
  const terminal = detectTerminal()
40
71
 
41
72
  if (!jsonMode) {
42
- console.log(`\x1b[1mterminfo\x1b[0m — terminal feature testing for terminfo.dev\n`)
43
- console.log(
44
- `Detected: \x1b[1m${terminal.name}\x1b[0m${terminal.version ? ` ${terminal.version}` : ""} on ${terminal.os}${terminal.osVersion ? ` ${terminal.osVersion}` : ""}`,
45
- )
46
- console.log(`Running ${ALL_PROBES.length} probes...\n`)
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...`)
47
83
  }
48
84
 
49
85
  const results: Record<string, boolean> = {}
@@ -101,7 +137,8 @@ async function main() {
101
137
  // Display results
102
138
  console.log(`\n\x1b[1mResults: ${passed}/${total} (${pct}%)\x1b[0m\n`)
103
139
 
104
- // Show categories
140
+ // Show categories with OSC 8 hyperlinks
141
+ const slugs = loadFeatureSlugs()
105
142
  const categories = new Map<string, Array<{ id: string; name: string; pass: boolean; note?: string }>>()
106
143
  for (const probe of ALL_PROBES) {
107
144
  const cat = probe.id.split(".")[0]!
@@ -117,11 +154,15 @@ async function main() {
117
154
  for (const [cat, probes] of categories) {
118
155
  const catPassed = probes.filter((p) => p.pass).length
119
156
  const color = catPassed === probes.length ? "\x1b[32m" : catPassed > 0 ? "\x1b[33m" : "\x1b[31m"
120
- console.log(`${color}${cat}\x1b[0m (${catPassed}/${probes.length})`)
157
+ const catLink = link(`https://terminfo.dev/${cat}`, cat)
158
+ console.log(`${color}${catLink}\x1b[0m (${catPassed}/${probes.length})`)
121
159
  for (const p of probes) {
122
160
  const icon = p.pass ? "\x1b[32m✓\x1b[0m" : "\x1b[31m✗\x1b[0m"
123
161
  const note = p.note ? ` \x1b[2m— ${p.note}\x1b[0m` : ""
124
- console.log(` ${icon} ${p.name}${note}`)
162
+ const slug = slugs[p.id] ?? p.id.replaceAll(".", "-")
163
+ const cat = p.id.split(".")[0]!
164
+ const featureLink = link(`https://terminfo.dev/${cat}/${slug}`, p.name)
165
+ console.log(` ${icon} ${featureLink}${note}`)
125
166
  }
126
167
  }
127
168