From c4ce50514e3f17f833a503efa62a57ed4a6c8b55 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 17:49:09 +0000 Subject: [PATCH 1/2] build(deps): replace ora with picospinner picospinner has no runtime dependencies, so this drops ora and its 16 transitive packages from the dependency tree. picospinner does not detect non-interactive output itself, so bin.ts only animates when stderr is an interactive terminal and otherwise prints the start and final lines, matching ora's previous behaviour in CI and when piped. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01R1iLgtNj9JZPkuSQCZbGfR --- package.json | 2 +- src/bin.ts | 46 ++++++++++++++- yarn.lock | 154 +++------------------------------------------------ 3 files changed, 52 insertions(+), 150 deletions(-) diff --git a/package.json b/package.json index 7041a4a..78dadfa 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "chalk": "^5.3.0", "lodash.camelcase": "^4.3.0", "markdown-it": "^14.1.0", - "ora": "^8.1.0", + "picospinner": "^3.1.2", "pretty-ms": "^9.1.0" }, "lint-staged": { diff --git a/src/bin.ts b/src/bin.ts index f9e6ff5..6c6bf96 100755 --- a/src/bin.ts +++ b/src/bin.ts @@ -3,8 +3,8 @@ import chalk from 'chalk'; import fs from 'node:fs'; import { parseArgs } from 'node:util'; -import ora from 'ora'; import * as path from 'node:path'; +import { Spinner } from 'picospinner'; import pretty from 'pretty-ms'; import { parseDocs } from './index.js'; @@ -50,7 +50,7 @@ if (help) { process.exit(0); } -const runner = ora(chalk.yellow('Checking argv')).start(); +const runner = startSpinner(chalk.yellow('Checking argv')); if (typeof dir !== 'string') { runner.fail(chalk.red('Missing required --dir argument. "--dir ../electron"')); @@ -75,7 +75,7 @@ const resolvedOutDir = : path.resolve(process.cwd(), outDir) : process.cwd(); -runner.text = chalk.cyan(`Generating API in directory: ${chalk.yellow(`"${resolvedOutDir}"`)}`); +runner.setText(chalk.cyan(`Generating API in directory: ${chalk.yellow(`"${resolvedOutDir}"`)}`)); const start = Date.now(); @@ -105,3 +105,43 @@ void fs.promises.mkdir(resolvedOutDir, { recursive: true }).then(() => process.exit(1); }), ); + +function startSpinner(text: string) { + const symbols = { succeed: chalk.green('✔'), fail: chalk.red('✖') }; + // picospinner animates unconditionally, which would flood logs when stderr is + // not a terminal (e.g. in CI), so only animate when interactive and otherwise + // just print the start and final lines. + const interactive = process.stderr.isTTY && process.env.TERM !== 'dumb' && !('CI' in process.env); + + if (interactive) { + const spinner = new Spinner( + { text, stream: process.stderr }, + { + colors: false, + frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'].map((frame) => + chalk.cyan(frame), + ), + symbols, + }, + ); + spinner.start(80); + return { + setText: (newText: string) => spinner.setText(newText), + succeed: (newText: string) => spinner.succeed(newText), + fail: (newText?: string) => spinner.fail(newText), + }; + } + + process.stderr.write(`- ${text}\n`); + return { + setText: (newText: string) => { + text = newText; + }, + succeed: (newText: string) => { + process.stderr.write(`${symbols.succeed} ${newText}\n`); + }, + fail: (newText = text) => { + process.stderr.write(`${symbols.fail} ${newText}\n`); + }, + }; +} diff --git a/yarn.lock b/yarn.lock index 71a87ad..fc994e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,10 +64,10 @@ __metadata: lint-staged: "npm:^17.4.1" lodash.camelcase: "npm:^4.3.0" markdown-it: "npm:^14.1.0" - ora: "npm:^8.1.0" oxfmt: "npm:^0.71.0" oxlint: "npm:^1.82.0" oxlint-tsgolint: "npm:^7.0.2001" + picospinner: "npm:^3.1.2" pretty-ms: "npm:^9.1.0" typescript: "npm:^6.0.2" vite: "npm:^8.0.16" @@ -697,13 +697,6 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -763,22 +756,6 @@ __metadata: languageName: node linkType: hard -"cli-cursor@npm:^5.0.0": - version: 5.0.0 - resolution: "cli-cursor@npm:5.0.0" - dependencies: - restore-cursor: "npm:^5.0.0" - checksum: 10c0/7ec62f69b79f6734ab209a3e4dbdc8af7422d44d360a7cb1efa8a0887bbe466a6e625650c466fe4359aee44dbe2dc0b6994b583d40a05d0808a5cb193641d220 - languageName: node - linkType: hard - -"cli-spinners@npm:^2.9.2": - version: 2.9.2 - resolution: "cli-spinners@npm:2.9.2" - checksum: 10c0/907a1c227ddf0d7a101e7ab8b300affc742ead4b4ebe920a5bf1bc6d45dce2958fcd195eb28fa25275062fe6fa9b109b93b63bc8033396ed3bcb50297008b3a3 - languageName: node - linkType: hard - "deep-eql@npm:^5.0.1": version: 5.0.2 resolution: "deep-eql@npm:5.0.2" @@ -793,13 +770,6 @@ __metadata: languageName: node linkType: hard -"emoji-regex@npm:^10.3.0": - version: 10.4.0 - resolution: "emoji-regex@npm:10.4.0" - checksum: 10c0/a3fcedfc58bfcce21a05a5f36a529d81e88d602100145fcca3dc6f795e3c8acc4fc18fe773fbf9b6d6e9371205edb3afa2668ec3473fa2aa7fd47d2a9d46482d - languageName: node - linkType: hard - "entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" @@ -857,13 +827,6 @@ __metadata: languageName: node linkType: hard -"get-east-asian-width@npm:^1.0.0": - version: 1.2.0 - resolution: "get-east-asian-width@npm:1.2.0" - checksum: 10c0/914b1e217cf38436c24b4c60b4c45289e39a45bf9e65ef9fd343c2815a1a02b8a0215aeec8bf9c07c516089004b6e3826332481f40a09529fcadbf6e579f286b - languageName: node - linkType: hard - "get-func-name@npm:^2.0.1": version: 2.0.2 resolution: "get-func-name@npm:2.0.2" @@ -880,27 +843,6 @@ __metadata: languageName: node linkType: hard -"is-interactive@npm:^2.0.0": - version: 2.0.0 - resolution: "is-interactive@npm:2.0.0" - checksum: 10c0/801c8f6064f85199dc6bf99b5dd98db3282e930c3bc197b32f2c5b89313bb578a07d1b8a01365c4348c2927229234f3681eb861b9c2c92bee72ff397390fa600 - languageName: node - linkType: hard - -"is-unicode-supported@npm:^1.3.0": - version: 1.3.0 - resolution: "is-unicode-supported@npm:1.3.0" - checksum: 10c0/b8674ea95d869f6faabddc6a484767207058b91aea0250803cbf1221345cb0c56f466d4ecea375dc77f6633d248d33c47bd296fb8f4cdba0b4edba8917e83d8a - languageName: node - linkType: hard - -"is-unicode-supported@npm:^2.0.0": - version: 2.1.0 - resolution: "is-unicode-supported@npm:2.1.0" - checksum: 10c0/a0f53e9a7c1fdbcf2d2ef6e40d4736fdffff1c9f8944c75e15425118ff3610172c87bf7bc6c34d3903b04be59790bb2212ddbe21ee65b5a97030fc50370545a5 - languageName: node - linkType: hard - "js-tokens@npm:^10.0.0": version: 10.0.0 resolution: "js-tokens@npm:10.0.0" @@ -1061,16 +1003,6 @@ __metadata: languageName: node linkType: hard -"log-symbols@npm:^6.0.0": - version: 6.0.0 - resolution: "log-symbols@npm:6.0.0" - dependencies: - chalk: "npm:^5.3.0" - is-unicode-supported: "npm:^1.3.0" - checksum: 10c0/36636cacedba8f067d2deb4aad44e91a89d9efb3ead27e1846e7b82c9a10ea2e3a7bd6ce28a7ca616bebc60954ff25c67b0f92d20a6a746bb3cc52c3701891f6 - languageName: node - linkType: hard - "loupe@npm:^3.1.0": version: 3.1.1 resolution: "loupe@npm:3.1.1" @@ -1123,13 +1055,6 @@ __metadata: languageName: node linkType: hard -"mimic-function@npm:^5.0.0": - version: 5.0.1 - resolution: "mimic-function@npm:5.0.1" - checksum: 10c0/f3d9464dd1816ecf6bdf2aec6ba32c0728022039d992f178237d8e289b48764fee4131319e72eedd4f7f094e22ded0af836c3187a7edc4595d28dd74368fd81d - languageName: node - linkType: hard - "nanoid@npm:^3.3.18": version: 3.3.19 resolution: "nanoid@npm:3.3.19" @@ -1146,32 +1071,6 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^7.0.0": - version: 7.0.0 - resolution: "onetime@npm:7.0.0" - dependencies: - mimic-function: "npm:^5.0.0" - checksum: 10c0/5cb9179d74b63f52a196a2e7037ba2b9a893245a5532d3f44360012005c9cadb60851d56716ebff18a6f47129dab7168022445df47c2aff3b276d92585ed1221 - languageName: node - linkType: hard - -"ora@npm:^8.1.0": - version: 8.1.0 - resolution: "ora@npm:8.1.0" - dependencies: - chalk: "npm:^5.3.0" - cli-cursor: "npm:^5.0.0" - cli-spinners: "npm:^2.9.2" - is-interactive: "npm:^2.0.0" - is-unicode-supported: "npm:^2.0.0" - log-symbols: "npm:^6.0.0" - stdin-discarder: "npm:^0.2.2" - string-width: "npm:^7.2.0" - strip-ansi: "npm:^7.1.0" - checksum: 10c0/4ac9a6dd7fe915a354680f33ced21ee96d13d3c5ab0dc00b3c3ba9e3695ed141b1d045222990f5a71a9a91f801042a0b0d32e58dfc5509ff9b81efdd3fcf6339 - languageName: node - linkType: hard - "oxfmt@npm:^0.71.0": version: 0.71.0 resolution: "oxfmt@npm:0.71.0" @@ -1396,6 +1295,13 @@ __metadata: languageName: node linkType: hard +"picospinner@npm:^3.1.2": + version: 3.1.2 + resolution: "picospinner@npm:3.1.2" + checksum: 10c0/395de8ac018a30bd3097c3eea634bc2930ebfb3a31bcc85f6dee11e91d95fb4b82c8b569430406c3839691d6041277dd29feb4623d88a6e5a9d397022e5e64de + languageName: node + linkType: hard + "postcss@npm:^8.5.28": version: 8.5.28 resolution: "postcss@npm:8.5.28" @@ -1432,16 +1338,6 @@ __metadata: languageName: node linkType: hard -"restore-cursor@npm:^5.0.0": - version: 5.1.0 - resolution: "restore-cursor@npm:5.1.0" - dependencies: - onetime: "npm:^7.0.0" - signal-exit: "npm:^4.1.0" - checksum: 10c0/c2ba89131eea791d1b25205bdfdc86699767e2b88dee2a590b1a6caa51737deac8bad0260a5ded2f7c074b7db2f3a626bcf1fcf3cdf35974cbeea5e2e6764f60 - languageName: node - linkType: hard - "rolldown@npm:~1.2.6": version: 1.2.9 resolution: "rolldown@npm:1.2.9" @@ -1507,13 +1403,6 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.1.0": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - "source-map-js@npm:^1.2.1": version: 1.2.2 resolution: "source-map-js@npm:1.2.2" @@ -1535,13 +1424,6 @@ __metadata: languageName: node linkType: hard -"stdin-discarder@npm:^0.2.2": - version: 0.2.2 - resolution: "stdin-discarder@npm:0.2.2" - checksum: 10c0/c78375e82e956d7a64be6e63c809c7f058f5303efcaf62ea48350af072bacdb99c06cba39209b45a071c1acbd49116af30df1df9abb448df78a6005b72f10537 - languageName: node - linkType: hard - "string-argv@npm:^0.3.2": version: 0.3.2 resolution: "string-argv@npm:0.3.2" @@ -1549,26 +1431,6 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^7.2.0": - version: 7.2.0 - resolution: "string-width@npm:7.2.0" - dependencies: - emoji-regex: "npm:^10.3.0" - get-east-asian-width: "npm:^1.0.0" - strip-ansi: "npm:^7.1.0" - checksum: 10c0/eb0430dd43f3199c7a46dcbf7a0b34539c76fe3aa62763d0b0655acdcbdf360b3f66f3d58ca25ba0205f42ea3491fa00f09426d3b7d3040e506878fc7664c9b9 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.1.0": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - "tinybench@npm:6.1.4": version: 6.1.4 resolution: "tinybench@npm:6.1.4" From c3f4281d332aaa43f5a5e5f5dadb8a6fac4d56f6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 17:56:09 +0000 Subject: [PATCH 2/2] build(deps): use yocto-spinner instead of picospinner yocto-spinner handles non-interactive output itself, so the custom fallback helper in bin.ts is no longer needed and the port maps directly onto ora's API. Its only dependency is yoctocolors, which has no dependencies of its own. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01R1iLgtNj9JZPkuSQCZbGfR --- package.json | 4 ++-- src/bin.ts | 56 ++++++++-------------------------------------------- yarn.lock | 25 +++++++++++++++-------- 3 files changed, 27 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index 78dadfa..812b433 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "chalk": "^5.3.0", "lodash.camelcase": "^4.3.0", "markdown-it": "^14.1.0", - "picospinner": "^3.1.2", - "pretty-ms": "^9.1.0" + "pretty-ms": "^9.1.0", + "yocto-spinner": "^1.2.2" }, "lint-staged": { "*.{js,ts}": [ diff --git a/src/bin.ts b/src/bin.ts index 6c6bf96..d836ab1 100755 --- a/src/bin.ts +++ b/src/bin.ts @@ -4,7 +4,7 @@ import chalk from 'chalk'; import fs from 'node:fs'; import { parseArgs } from 'node:util'; import * as path from 'node:path'; -import { Spinner } from 'picospinner'; +import yoctoSpinner from 'yocto-spinner'; import pretty from 'pretty-ms'; import { parseDocs } from './index.js'; @@ -50,21 +50,21 @@ if (help) { process.exit(0); } -const runner = startSpinner(chalk.yellow('Checking argv')); +const runner = yoctoSpinner({ text: chalk.yellow('Checking argv') }).start(); if (typeof dir !== 'string') { - runner.fail(chalk.red('Missing required --dir argument. "--dir ../electron"')); + runner.error(chalk.red('Missing required --dir argument. "--dir ../electron"')); process.exit(1); } if (typeof moduleVersion !== 'string') { - runner.fail(chalk.red('Missing required --moduleVersion argument. "--moduleVersion 1.2.3"')); + runner.error(chalk.red('Missing required --moduleVersion argument. "--moduleVersion 1.2.3"')); process.exit(1); } const resolvedDir = path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir); if (!fs.existsSync(resolvedDir)) { - runner.fail(`${chalk.red('Resolved directory does not exist:')} ${chalk.cyan(resolvedDir)}`); + runner.error(`${chalk.red('Resolved directory does not exist:')} ${chalk.cyan(resolvedDir)}`); process.exit(1); } @@ -75,7 +75,7 @@ const resolvedOutDir = : path.resolve(process.cwd(), outDir) : process.cwd(); -runner.setText(chalk.cyan(`Generating API in directory: ${chalk.yellow(`"${resolvedOutDir}"`)}`)); +runner.text = chalk.cyan(`Generating API in directory: ${chalk.yellow(`"${resolvedOutDir}"`)}`); const start = Date.now(); @@ -93,55 +93,15 @@ void fs.promises.mkdir(resolvedOutDir, { recursive: true }).then(() => ), ) .then(() => - runner.succeed( + runner.success( `${chalk.green('Electron API generated in')} ${chalk.yellow( `"${resolvedOutDir}"`, )} took ${chalk.cyan(pretty(Date.now() - start))}`, ), ) .catch((err) => { - runner.fail(); + runner.error(); console.error(err); process.exit(1); }), ); - -function startSpinner(text: string) { - const symbols = { succeed: chalk.green('✔'), fail: chalk.red('✖') }; - // picospinner animates unconditionally, which would flood logs when stderr is - // not a terminal (e.g. in CI), so only animate when interactive and otherwise - // just print the start and final lines. - const interactive = process.stderr.isTTY && process.env.TERM !== 'dumb' && !('CI' in process.env); - - if (interactive) { - const spinner = new Spinner( - { text, stream: process.stderr }, - { - colors: false, - frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'].map((frame) => - chalk.cyan(frame), - ), - symbols, - }, - ); - spinner.start(80); - return { - setText: (newText: string) => spinner.setText(newText), - succeed: (newText: string) => spinner.succeed(newText), - fail: (newText?: string) => spinner.fail(newText), - }; - } - - process.stderr.write(`- ${text}\n`); - return { - setText: (newText: string) => { - text = newText; - }, - succeed: (newText: string) => { - process.stderr.write(`${symbols.succeed} ${newText}\n`); - }, - fail: (newText = text) => { - process.stderr.write(`${symbols.fail} ${newText}\n`); - }, - }; -} diff --git a/yarn.lock b/yarn.lock index fc994e3..356d110 100644 --- a/yarn.lock +++ b/yarn.lock @@ -67,11 +67,11 @@ __metadata: oxfmt: "npm:^0.71.0" oxlint: "npm:^1.82.0" oxlint-tsgolint: "npm:^7.0.2001" - picospinner: "npm:^3.1.2" pretty-ms: "npm:^9.1.0" typescript: "npm:^6.0.2" vite: "npm:^8.0.16" vitest: "npm:^5.0.1" + yocto-spinner: "npm:^1.2.2" bin: electron-docs-linter: ./dist/bin.js electron-docs-parser: ./dist/bin.js @@ -1295,13 +1295,6 @@ __metadata: languageName: node linkType: hard -"picospinner@npm:^3.1.2": - version: 3.1.2 - resolution: "picospinner@npm:3.1.2" - checksum: 10c0/395de8ac018a30bd3097c3eea634bc2930ebfb3a31bcc85f6dee11e91d95fb4b82c8b569430406c3839691d6041277dd29feb4623d88a6e5a9d397022e5e64de - languageName: node - linkType: hard - "postcss@npm:^8.5.28": version: 8.5.28 resolution: "postcss@npm:8.5.28" @@ -1641,3 +1634,19 @@ __metadata: checksum: 10c0/f340718df45e97a9551b9bf9dac61c80050bc464513b710debfb5067c380c8472e3b67809cffacb4ab5ffb5e66ef9310816c88b05f371cec60abfedd8c88e0a2 languageName: node linkType: hard + +"yocto-spinner@npm:^1.2.2": + version: 1.2.2 + resolution: "yocto-spinner@npm:1.2.2" + dependencies: + yoctocolors: "npm:^2.1.1" + checksum: 10c0/d1cf681e3057884d038bbafc568e572baba03f52ef1c435e3de1a2fef6d7aff671d44eeb9452315e5322a638e0c9b6de22be3d81539f9e4234725e49eb75a015 + languageName: node + linkType: hard + +"yoctocolors@npm:^2.1.1": + version: 2.2.0 + resolution: "yoctocolors@npm:2.2.0" + checksum: 10c0/ca179aa83401aa0711f268fda38145a44c828e612a5f5265439efb5796cd63c46ca6b786bae3b74c75440a48518c36b5b23cba7fbb76ea8af5a9f85f830a5754 + languageName: node + linkType: hard