ccgather 2.0.35 → 2.0.37

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/dist/index.js +57 -43
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -67,6 +67,31 @@ var init_config = __esm({
67
67
  function hyperlink(text, url) {
68
68
  return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
69
69
  }
70
+ function interpolateHex(t) {
71
+ const r = Math.round(218 + 29 * t);
72
+ const g = Math.round(119 + 28 * t);
73
+ const b = Math.round(86 - 56 * t);
74
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
75
+ }
76
+ function renderChromeGradientLogo() {
77
+ const word = "CCGATHER";
78
+ const rows = [[], [], []];
79
+ for (let i = 0; i < word.length; i++) {
80
+ const ch = word[i];
81
+ const glyph = CHROME_FONT[ch];
82
+ if (!glyph) continue;
83
+ const color = import_chalk.default.hex(interpolateHex(i / (word.length - 1)));
84
+ for (let row = 0; row < 3; row++) {
85
+ if (rows[row].length > 0) rows[row].push(color(" "));
86
+ rows[row].push(color(glyph[row]));
87
+ }
88
+ }
89
+ return [rows[0].join(""), rows[1].join(""), rows[2].join("")];
90
+ }
91
+ function padLine(content) {
92
+ const w = getDisplayWidth(content);
93
+ return content + " ".repeat(Math.max(0, HEADER_WIDTH - w));
94
+ }
70
95
  function centerText(text, width) {
71
96
  const len = getDisplayWidth(text);
72
97
  const pad = width - len;
@@ -76,34 +101,33 @@ function createProfessionalHeader() {
76
101
  const lines = [];
77
102
  const v = boxRound.vertical;
78
103
  const h = boxRound.horizontal;
79
- lines.push(colors.dim(` ${boxRound.topLeft}${h.repeat(HEADER_WIDTH)}${boxRound.topRight}`));
80
- const logoLines = [
81
- `${colors.primary("\u2584\u2588\u2580\u2580 \u2584\u2588\u2580\u2580")} ${colors.secondary("\u2584\u2588\u2580\u2580 \u2584\u2588\u2580\u2588\u2584 \u2580\u2588\u2580 \u2588 \u2588 \u2588\u2580\u2580 \u2588\u2580\u2588")}`,
82
- `${colors.primary("\u2588 \u2588 ")} ${colors.secondary("\u2588 \u2580\u2588 \u2588\u2580\u2580\u2588\u2580 \u2588 \u2588\u2580\u2580\u2588 \u2588\u2580\u2580 \u2588\u2588\u2580")}`,
83
- `${colors.primary("\u2580\u2588\u2584\u2584 \u2580\u2588\u2584\u2584")} ${colors.secondary("\u2580\u2588\u2584\u2584\u2580 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588\u2584\u2584 \u2588 \u2588")}`
84
- ];
85
- for (const l of logoLines) {
86
- lines.push(colors.dim(` ${v}`) + centerText(l, HEADER_WIDTH) + colors.dim(v));
104
+ const dim = colors.dim;
105
+ lines.push(dim(` ${boxRound.topLeft}${h.repeat(HEADER_WIDTH)}${boxRound.topRight}`));
106
+ lines.push(dim(` ${v}`) + padLine("") + dim(v));
107
+ const logoRows = renderChromeGradientLogo();
108
+ const logoPadLeft = 7;
109
+ const logoPadRight = HEADER_WIDTH - logoPadLeft - 31;
110
+ for (const row of logoRows) {
111
+ lines.push(dim(` ${v}`) + " ".repeat(logoPadLeft) + row + " ".repeat(logoPadRight) + dim(v));
87
112
  }
88
113
  const versionStr = `v${VERSION}`;
89
- const versionPad = HEADER_WIDTH - versionStr.length - 2;
90
- lines.push(
91
- colors.dim(` ${v}`) + " ".repeat(versionPad) + colors.dim(versionStr) + " " + colors.dim(v)
92
- );
93
- lines.push(colors.dim(` ${boxRound.leftT}${h.repeat(HEADER_WIDTH)}${boxRound.rightT}`));
114
+ const versionPad = HEADER_WIDTH - getDisplayWidth(versionStr) - 2;
115
+ lines.push(dim(` ${v}`) + " ".repeat(Math.max(0, versionPad)) + dim(versionStr) + " " + dim(v));
116
+ lines.push(dim(` ${boxRound.leftT}${h.repeat(HEADER_WIDTH)}${boxRound.rightT}`));
94
117
  lines.push(
95
- colors.dim(` ${v}`) + centerText(colors.muted("Proof of your Claude Code dedication"), HEADER_WIDTH) + colors.dim(v)
118
+ dim(` ${v}`) + padLine(centerText(colors.muted("Proof of your Claude Code dedication"), HEADER_WIDTH)) + dim(v)
96
119
  );
97
120
  lines.push(
98
- colors.dim(` ${v}`) + centerText(colors.dim("Track \xB7 Prove \xB7 Rise"), HEADER_WIDTH) + colors.dim(v)
121
+ dim(` ${v}`) + padLine(centerText(colors.dim("Track \xB7 Prove \xB7 Rise"), HEADER_WIDTH)) + dim(v)
99
122
  );
100
- lines.push(colors.dim(` ${v}`) + " ".repeat(HEADER_WIDTH) + colors.dim(v));
123
+ lines.push(dim(` ${v}`) + padLine("") + dim(v));
101
124
  const siteLabel = " \u{1F310} ccgather.com ";
102
125
  const siteLink = hyperlink(colors.secondary(siteLabel), "https://ccgather.com");
126
+ const siteLabelWidth = getDisplayWidth(siteLabel);
103
127
  const leftDashes = 13;
104
- const rightDashes = HEADER_WIDTH - leftDashes - siteLabel.length;
128
+ const rightDashes = HEADER_WIDTH - leftDashes - siteLabelWidth;
105
129
  lines.push(
106
- colors.dim(` ${boxRound.bottomLeft}${h.repeat(leftDashes)}`) + siteLink + colors.dim(`${h.repeat(rightDashes)}${boxRound.bottomRight}`)
130
+ dim(` ${boxRound.bottomLeft}${h.repeat(leftDashes)}`) + siteLink + dim(`${h.repeat(Math.max(0, rightDashes))}${boxRound.bottomRight}`)
107
131
  );
108
132
  return lines;
109
133
  }
@@ -118,22 +142,11 @@ function createBox(lines, width = 47) {
118
142
  return [top, ...paddedLines.map((l) => colors.dim(" ") + l), bottom].join("\n");
119
143
  }
120
144
  function _stripAnsi(str) {
121
- return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
145
+ return str.replace(/\x1B\[[0-9;]*[a-zA-Z]|\x1B\]8;;[^\x07]*\x07/g, "");
122
146
  }
123
147
  function getDisplayWidth(str) {
124
148
  const stripped = _stripAnsi(str);
125
- let width = (0, import_string_width.default)(stripped);
126
- const emojiRegex = /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|✦/gu;
127
- const emojis = stripped.match(emojiRegex);
128
- if (emojis) {
129
- for (const emoji of emojis) {
130
- const emojiWidth = (0, import_string_width.default)(emoji);
131
- if (emojiWidth === 1) {
132
- width += 1;
133
- }
134
- }
135
- }
136
- return width;
149
+ return (0, import_string_width.default)(stripped);
137
150
  }
138
151
  function header(title, icon = "") {
139
152
  const iconPart = icon ? `${icon} ` : "";
@@ -247,13 +260,13 @@ async function printAnimatedWelcomeBox(user) {
247
260
  console.log(` \u{1F44B} ${colors.white.bold(`Welcome back, ${user.username}!`)}`);
248
261
  await sleep(50);
249
262
  }
250
- var import_chalk, import_string_width, VERSION, colors, LOGO, LOGO_COMPACT, TAGLINE, SLOGAN, boxRound, box, HEADER_WIDTH, LEVELS;
263
+ var import_chalk, import_string_width, VERSION, colors, LOGO_COMPACT, TAGLINE, SLOGAN, boxRound, box, HEADER_WIDTH, CHROME_FONT, LEVELS;
251
264
  var init_ui = __esm({
252
265
  "src/lib/ui.ts"() {
253
266
  "use strict";
254
267
  import_chalk = __toESM(require("chalk"));
255
268
  import_string_width = __toESM(require("string-width"));
256
- VERSION = true ? "2.0.35" : "0.0.0";
269
+ VERSION = true ? "2.0.37" : "0.0.0";
257
270
  colors = {
258
271
  primary: import_chalk.default.hex("#DA7756"),
259
272
  // Claude coral
@@ -282,14 +295,6 @@ var init_ui = __esm({
282
295
  free: import_chalk.default.hex("#6B7280")
283
296
  // Gray
284
297
  };
285
- LOGO = `
286
- ${colors.primary("\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557")} ${colors.secondary("\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}
287
- ${colors.primary("\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D")}${colors.secondary("\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557")}
288
- ${colors.primary("\u2588\u2588\u2551 \u2588\u2588\u2551 ")}${colors.secondary("\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D")}
289
- ${colors.primary("\u2588\u2588\u2551 \u2588\u2588\u2551 ")}${colors.secondary("\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557")}
290
- ${colors.primary("\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}${colors.secondary("\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551")}
291
- ${colors.primary("\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D")} ${colors.secondary("\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D")}
292
- `;
293
298
  LOGO_COMPACT = `
294
299
  ${colors.primary("CC")}${colors.secondary("gather")} ${colors.muted("- Proof of your Claude Code dedication")}
295
300
  `;
@@ -316,6 +321,15 @@ var init_ui = __esm({
316
321
  rightT: "\u2524"
317
322
  };
318
323
  HEADER_WIDTH = 46;
324
+ CHROME_FONT = {
325
+ C: ["\u2554\u2550\u2557", "\u2551 ", "\u255A\u2550\u255D"],
326
+ G: ["\u2554\u2550\u2557", "\u2551 \u2566", "\u255A\u2550\u255D"],
327
+ A: ["\u2554\u2550\u2557", "\u2560\u2550\u2563", "\u2569 \u2569"],
328
+ T: ["\u2554\u2566\u2557", " \u2551 ", " \u2569 "],
329
+ H: ["\u2566 \u2566", "\u2560\u2550\u2563", "\u2569 \u2569"],
330
+ E: ["\u2554\u2550\u2557", "\u2551\u2563 ", "\u255A\u2550\u255D"],
331
+ R: ["\u2566\u2550\u2557", "\u2560\u2566\u255D", "\u2569\u255A\u2550"]
332
+ };
319
333
  LEVELS = [
320
334
  { min: 0, level: 1, name: "Novice", icon: "\u{1F331}", color: colors.dim },
321
335
  { min: 5e7, level: 2, name: "Apprentice", icon: "\u{1F4DA}", color: colors.muted },
@@ -1419,7 +1433,7 @@ async function submit(options) {
1419
1433
  return `${yy}${mm}${dd}`;
1420
1434
  };
1421
1435
  const dateRange = usageData.firstUsed && usageData.lastUsed ? `${formatDate(usageData.firstUsed)} ~ ${formatDate(usageData.lastUsed)}` : "";
1422
- const daysTrackedDisplay = dateRange ? `${usageData.daysTracked} days ${colors.dim(`(${dateRange})`)}` : usageData.daysTracked.toString();
1436
+ const daysTrackedDisplay = dateRange ? `${usageData.daysTracked}d ${colors.dim(`(${dateRange})`)}` : usageData.daysTracked.toString();
1423
1437
  const summaryLines = [
1424
1438
  `${colors.muted("Total Cost")} \u{1F4B0} ${colors.warning(formatCost(usageData.totalCost))}`,
1425
1439
  `${colors.muted("Total Tokens")} \u26A1 ${colors.primary(formatNumber(usageData.totalTokens))}`,
@@ -1450,7 +1464,7 @@ async function submit(options) {
1450
1464
  summaryLines.push(
1451
1465
  `${colors.muted("Level")} ${currentLevel.icon} ${currentLevel.color(`${currentLevel.name}`)}`
1452
1466
  );
1453
- console.log(createBox(summaryLines, 52));
1467
+ console.log(createBox(summaryLines, 46));
1454
1468
  console.log(
1455
1469
  ` ${colors.dim(`Scanned ${projectCount} project(s), ${usageData.dailyUsage.length} day(s) of data`)}`
1456
1470
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccgather",
3
- "version": "2.0.35",
3
+ "version": "2.0.37",
4
4
  "description": "CLI tool for syncing Claude Code usage data to CCgather leaderboard",
5
5
  "bin": {
6
6
  "ccgather": "dist/index.js",