terminfo.dev 1.5.0 → 1.6.1
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 +1 -1
- package/src/index.ts +30 -5
- package/src/submit.ts +15 -54
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -76,7 +76,8 @@ async function runProbes(): Promise<ProbeResults> {
|
|
|
76
76
|
notes[probe.id] = `error: ${err instanceof Error ? err.message : String(err)}`
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
//
|
|
79
|
+
// Reset all SGR attributes + drain pending responses before exiting alt screen
|
|
80
|
+
process.stdout.write("\x1b[0m\x1b[2J\x1b[H")
|
|
80
81
|
await drainStdin(500)
|
|
81
82
|
process.stdout.write("\x1b[?1049l")
|
|
82
83
|
})
|
|
@@ -173,21 +174,45 @@ program
|
|
|
173
174
|
program
|
|
174
175
|
.command("submit")
|
|
175
176
|
.description("Run all probes and submit results to terminfo.dev via GitHub issue")
|
|
176
|
-
.
|
|
177
|
+
.option("--terminal-name <name>", "Override detected terminal name")
|
|
178
|
+
.option("--terminal-version <version>", "Override detected terminal version")
|
|
179
|
+
.action(async (opts) => {
|
|
180
|
+
// Confirm details BEFORE probes (stdin is still clean)
|
|
181
|
+
const terminal = detectTerminal()
|
|
182
|
+
const name = opts.terminalName ?? terminal.name
|
|
183
|
+
const version = opts.terminalVersion ?? terminal.version
|
|
184
|
+
|
|
185
|
+
printHeader(terminal)
|
|
186
|
+
console.log(``)
|
|
187
|
+
console.log(` Will submit results for \x1b[1m${name}${version ? ` ${version}` : ""}\x1b[0m on ${terminal.os}`)
|
|
188
|
+
if (!version) {
|
|
189
|
+
console.log(` \x1b[33m⚠ No version detected. Use --terminal-version to specify.\x1b[0m`)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const { createInterface } = await import("node:readline")
|
|
193
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
194
|
+
const proceed = await new Promise<string>((resolve) => {
|
|
195
|
+
rl.question(`\n Press Enter to run probes and submit (or Ctrl+C to cancel) `, (answer) => {
|
|
196
|
+
rl.close()
|
|
197
|
+
resolve(answer)
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// Now run probes (stdin goes to raw mode, no conflict)
|
|
177
202
|
const data = await runProbes()
|
|
178
203
|
printResults(data)
|
|
179
204
|
|
|
180
205
|
console.log(`\nSubmitting results to terminfo.dev...`)
|
|
181
206
|
const url = await submitResults({
|
|
182
|
-
terminal:
|
|
183
|
-
terminalVersion:
|
|
207
|
+
terminal: name,
|
|
208
|
+
terminalVersion: version,
|
|
184
209
|
os: data.terminal.os,
|
|
185
210
|
osVersion: data.terminal.osVersion,
|
|
186
211
|
results: data.results,
|
|
187
212
|
notes: data.notes,
|
|
188
213
|
responses: data.responses,
|
|
189
214
|
generated: new Date().toISOString(),
|
|
190
|
-
cliVersion: "1.
|
|
215
|
+
cliVersion: "1.6.0",
|
|
191
216
|
probeCount: ALL_PROBES.length,
|
|
192
217
|
})
|
|
193
218
|
if (url) {
|
package/src/submit.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { writeFileSync, unlinkSync } from "node:fs"
|
|
|
6
6
|
import { tmpdir } from "node:os"
|
|
7
7
|
import { join } from "node:path"
|
|
8
8
|
import { execFileSync } from "node:child_process"
|
|
9
|
-
import { createInterface } from "node:readline"
|
|
10
9
|
|
|
11
10
|
const REPO = "beorn/terminfo.dev"
|
|
12
11
|
|
|
@@ -23,65 +22,28 @@ interface SubmitData {
|
|
|
23
22
|
probeCount?: number
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
/** Drain any leftover bytes from stdin (e.g., late-arriving escape sequence responses) */
|
|
27
|
-
async function drainStdin(): Promise<void> {
|
|
28
|
-
return new Promise((resolve) => {
|
|
29
|
-
if (!process.stdin.readable) { resolve(); return }
|
|
30
|
-
process.stdin.resume()
|
|
31
|
-
const timer = setTimeout(() => {
|
|
32
|
-
process.stdin.pause()
|
|
33
|
-
process.stdin.removeAllListeners("readable")
|
|
34
|
-
resolve()
|
|
35
|
-
}, 200)
|
|
36
|
-
process.stdin.on("readable", () => {
|
|
37
|
-
while (process.stdin.read() !== null) {} // discard
|
|
38
|
-
})
|
|
39
|
-
timer.unref()
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function prompt(question: string, defaultValue?: string): Promise<string> {
|
|
44
|
-
await drainStdin()
|
|
45
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
46
|
-
const suffix = defaultValue ? ` [${defaultValue}]` : ""
|
|
47
|
-
return new Promise((resolve) => {
|
|
48
|
-
rl.question(`${question}${suffix}: `, (answer) => {
|
|
49
|
-
rl.close()
|
|
50
|
-
resolve(answer.trim() || defaultValue || "")
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
25
|
export async function submitResults(data: SubmitData): Promise<string | null> {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
data.terminalVersion
|
|
60
|
-
|
|
26
|
+
const passed = Object.values(data.results).filter(Boolean).length
|
|
27
|
+
const total = Object.keys(data.results).length
|
|
28
|
+
const pct = Math.round((passed / total) * 100)
|
|
29
|
+
const ver = data.terminalVersion ? ` ${data.terminalVersion}` : ""
|
|
30
|
+
|
|
31
|
+
console.log(`\n Submitting: \x1b[1m${data.terminal}${ver}\x1b[0m on ${data.os} — ${pct}% (${passed}/${total})`)
|
|
61
32
|
|
|
62
33
|
if (!data.terminalVersion) {
|
|
63
|
-
console.log(
|
|
34
|
+
console.log(` \x1b[33m⚠ No version detected — use --terminal-version to specify\x1b[0m`)
|
|
64
35
|
}
|
|
65
36
|
|
|
66
37
|
// Check for duplicates
|
|
67
38
|
if (hasGhCli()) {
|
|
68
39
|
const existing = checkDuplicate(data.terminal, data.terminalVersion, data.os)
|
|
69
40
|
if (existing) {
|
|
70
|
-
console.log(
|
|
71
|
-
console.log(`
|
|
72
|
-
const proceed = await prompt(" Submit anyway? (y/N)", "N")
|
|
73
|
-
if (proceed.toLowerCase() !== "y") {
|
|
74
|
-
console.log(`Skipped.`)
|
|
75
|
-
return null
|
|
76
|
-
}
|
|
41
|
+
console.log(` \x1b[33m⚠ Similar submission exists: ${existing}\x1b[0m`)
|
|
42
|
+
console.log(` Submitting anyway (different probe version may have new results)`)
|
|
77
43
|
}
|
|
78
44
|
}
|
|
79
45
|
|
|
80
|
-
const
|
|
81
|
-
const total = Object.keys(data.results).length
|
|
82
|
-
const pct = Math.round((passed / total) * 100)
|
|
83
|
-
|
|
84
|
-
const title = `[census] ${data.terminal}${data.terminalVersion ? ` ${data.terminalVersion}` : ""} on ${data.os} — ${pct}% (${passed}/${total})`
|
|
46
|
+
const title = `[census] ${data.terminal}${ver} on ${data.os} — ${pct}% (${passed}/${total})`
|
|
85
47
|
|
|
86
48
|
const body = `## Community Census Result
|
|
87
49
|
|
|
@@ -114,8 +76,8 @@ ${JSON.stringify(data, null, 2)}
|
|
|
114
76
|
if (!hasGhCli()) {
|
|
115
77
|
const filename = `terminfo-${data.terminal}-${data.os}-${Date.now()}.json`
|
|
116
78
|
writeFileSync(filename, JSON.stringify(data, null, 2))
|
|
117
|
-
console.log(`\n\x1b[33mgh CLI not found. Results saved to ${filename}\x1b[0m`)
|
|
118
|
-
console.log(`To submit: https://github.com/${REPO}/issues/new`)
|
|
79
|
+
console.log(`\n \x1b[33mgh CLI not found. Results saved to ${filename}\x1b[0m`)
|
|
80
|
+
console.log(` To submit: https://github.com/${REPO}/issues/new`)
|
|
119
81
|
return null
|
|
120
82
|
}
|
|
121
83
|
|
|
@@ -130,8 +92,8 @@ ${JSON.stringify(data, null, 2)}
|
|
|
130
92
|
], { encoding: "utf-8", timeout: 30000 })
|
|
131
93
|
return result.trim()
|
|
132
94
|
} catch (err) {
|
|
133
|
-
console.error(
|
|
134
|
-
console.error(err instanceof Error ? err.message : String(err))
|
|
95
|
+
console.error(` \x1b[31mFailed to create issue\x1b[0m`)
|
|
96
|
+
console.error(` ${err instanceof Error ? err.message : String(err)}`)
|
|
135
97
|
return null
|
|
136
98
|
} finally {
|
|
137
99
|
try { unlinkSync(bodyFile) } catch {}
|
|
@@ -159,8 +121,7 @@ function checkDuplicate(terminal: string, version: string, os: string): string |
|
|
|
159
121
|
"--json", "url,title",
|
|
160
122
|
"--jq", ".[0] | .title + \" \" + .url",
|
|
161
123
|
], { encoding: "utf-8", timeout: 10000 })
|
|
162
|
-
|
|
163
|
-
return trimmed || null
|
|
124
|
+
return result.trim() || null
|
|
164
125
|
} catch {
|
|
165
126
|
return null
|
|
166
127
|
}
|