From a6db0923b92458fd25682b903b123d372f9da9d1 Mon Sep 17 00:00:00 2001 From: ryu <114303361+ryuapp@users.noreply.github.com> Date: Fri, 5 Sep 2025 22:09:46 +0900 Subject: [PATCH] feat: add new loading text --- deno.json | 2 +- deno.lock | 8 +++---- src/animation.ts | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cli.ts | 16 ++++--------- 4 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 src/animation.ts diff --git a/deno.json b/deno.json index c96ea47..e2a44c3 100644 --- a/deno.json +++ b/deno.json @@ -18,7 +18,7 @@ "imports": { "playwright-core": "npm:playwright-core@^1.55.0", "@std/assert": "jsr:@std/assert@^1.0.13", - "@std/cli": "jsr:@std/cli@1.0.17", + "@std/cli": "jsr:@std/cli@^1.0.17", "@std/fmt": "jsr:@std/fmt@^1.0.7", "@std/front-matter": "jsr:@std/front-matter@^1.0.9", "@std/path": "jsr:@std/path@^1.0.9", diff --git a/deno.lock b/deno.lock index 4baf809..4240112 100644 --- a/deno.lock +++ b/deno.lock @@ -2,7 +2,7 @@ "version": "5", "specifiers": { "jsr:@std/assert@^1.0.13": "1.0.14", - "jsr:@std/cli@1.0.17": "1.0.17", + "jsr:@std/cli@^1.0.17": "1.0.22", "jsr:@std/collections@^1.1.1": "1.1.1", "jsr:@std/fmt@^1.0.7": "1.0.8", "jsr:@std/front-matter@^1.0.9": "1.0.9", @@ -24,8 +24,8 @@ "jsr:@std/internal@^1.0.10" ] }, - "@std/cli@1.0.17": { - "integrity": "e15b9abe629e17be90cc6216327f03a29eae613365f1353837fa749aad29ce7b" + "@std/cli@1.0.22": { + "integrity": "50d1e4f87887cb8a8afa29b88505ab5081188f5cad3985460c3b471fa49ff21a" }, "@std/collections@1.1.1": { "integrity": "eff6443fbd9d5a6697018fb39c5d13d5f662f0045f21392d640693d0008ab2af" @@ -385,7 +385,7 @@ "workspace": { "dependencies": [ "jsr:@std/assert@^1.0.13", - "jsr:@std/cli@1.0.17", + "jsr:@std/cli@^1.0.17", "jsr:@std/fmt@^1.0.7", "jsr:@std/front-matter@^1.0.9", "jsr:@std/path@^1.0.9", diff --git a/src/animation.ts b/src/animation.ts new file mode 100644 index 0000000..d4815ce --- /dev/null +++ b/src/animation.ts @@ -0,0 +1,60 @@ +import { brightCyan, brightWhite, cyan } from "@std/fmt/colors"; + +export function createWaveAnimation( + text: string, + filePath: string, +): { start: () => void; stop: () => void } { + const DEFAULT_SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; + const fullText = ` ${text} ${filePath}`; + let intervalId: number | null = null; + let frame = 0; + + const animate = () => { + const spinnerChar = DEFAULT_SPINNER[frame % DEFAULT_SPINNER.length]; + const waveWidth = 4; + const wavePosition = (frame * 0.8) % (fullText.length + waveWidth); + + // Spinner with cyan color, bright cyan in wave range + const spinnerDistance = Math.abs(0 - wavePosition); + let coloredText = ""; + if (spinnerDistance < waveWidth) { + coloredText = brightCyan(spinnerChar); + } else { + coloredText = cyan(spinnerChar); + } + + for (let i = 0; i < fullText.length; i++) { + const distance = Math.abs(i - wavePosition); + + if (distance < waveWidth) { + // highlight with bright white + coloredText += brightWhite(fullText[i]); + } else { + // default white color + coloredText += fullText[i]; + } + } + + const encoder = new TextEncoder(); + Deno.stdout.writeSync(encoder.encode(`\r${coloredText}`)); + frame++; + }; + + return { + start: () => { + if (!intervalId) { + intervalId = setInterval(animate, 40); + } + }, + stop: () => { + if (intervalId) { + clearInterval(intervalId); + intervalId = null; + const encoder = new TextEncoder(); + Deno.stdout.writeSync( + encoder.encode(`\r${" ".repeat(fullText.length + 2)}\r`), + ); + } + }, + }; +} diff --git a/src/cli.ts b/src/cli.ts index 4da0f1d..708bf0b 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -11,7 +11,6 @@ * @module */ -import { Spinner } from "@std/cli/unstable-spinner"; import { parseArgs } from "@std/cli/parse-args"; import { bgBlue, @@ -23,6 +22,7 @@ import { } from "@std/fmt/colors"; import { mdToPdf } from "./md-to-pdf.ts"; import { getFilename } from "./utils/filename.ts"; +import { createWaveAnimation } from "./animation.ts"; import type { MdToPdfOptions } from "./types.ts"; function printHelp(): void { @@ -42,16 +42,16 @@ ${yellow("Options:")} async function generatePdfFromMarkdown(path: string, options?: MdToPdfOptions) { const pdfName = getFilename(path) + ".pdf"; - spinner.message = " generating PDF from " + underline(path); - spinner.start(); + const waveAnimation = createWaveAnimation("generating PDF from", path); + waveAnimation.start(); await mdToPdf(path, options).then( (pdf) => { Deno.writeFileSync( pdfName, pdf, ); - spinner.stop(); - console.log("✅ generated " + underline(pdfName)); + waveAnimation.stop(); + console.log(green("✓") + " generated " + underline(pdfName)); }, ); } @@ -68,12 +68,6 @@ if (args.h || args.help) { Deno.exit(0); } -const spinner = new Spinner({ - message: "Loading...", - color: "yellow", - interval: 50, -}); - const paths: Array = []; if (args._) { for await (const path of args._) {