tailwint 1.1.3 → 1.1.4

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/dist/index.js CHANGED
@@ -92,10 +92,12 @@ export async function run(options = {}) {
92
92
  const fileContents = new Map();
93
93
  const fileVersions = new Map();
94
94
  const found = files.length;
95
- const foundText = `sent ${found} file${found === 1 ? "" : "s"} to lsp`;
96
- const foundPad = 54 - 2 - foundText.length - 1;
97
- console.error(` ${c.green}\u2714${c.reset} ${c.dim}${foundText}${c.reset} ${windTrail(foundPad)}`);
95
+ const skipped = prescan.unrelatedCssFiles.size;
96
+ let sent = 0;
98
97
  for (const filePath of files) {
98
+ // Skip CSS files with no Tailwind signals — sending them wastes server CPU
99
+ if (prescan.unrelatedCssFiles.has(filePath))
100
+ continue;
99
101
  let content;
100
102
  try {
101
103
  content = readFileSync(filePath, "utf-8");
@@ -113,6 +115,19 @@ export async function run(options = {}) {
113
115
  text: content,
114
116
  },
115
117
  });
118
+ sent++;
119
+ }
120
+ const sentText = `sent ${sent} file${sent === 1 ? "" : "s"} to lsp`;
121
+ const sentPad = 54 - 2 - sentText.length - 1;
122
+ console.error(` ${c.green}\u2714${c.reset} ${c.dim}${sentText}${c.reset} ${windTrail(sentPad)}`);
123
+ if (skipped > 0) {
124
+ const skipText = `${skipped} file${skipped === 1 ? "" : "s"} skipped`;
125
+ const skipPad = 54 - 2 - skipText.length - 1;
126
+ console.error(` ${c.dim}\u2500${c.reset} ${c.dim}${skipText}${c.reset} ${windTrail(skipPad)}`);
127
+ for (const f of prescan.unrelatedCssFiles) {
128
+ const rel = relative(cwd, f);
129
+ console.error(` ${c.dim}${fileBadge(rel)}${c.reset}`);
130
+ }
116
131
  }
117
132
  // Wait for all projects to be resolved (settled or broken)
118
133
  setTitle("tailwint ~ scanning...");
@@ -121,11 +136,20 @@ export async function run(options = {}) {
121
136
  const resolved = settledProjects + brokenProjects;
122
137
  const label = received > 0 ? "scanning" : "initializing";
123
138
  setTitle(`tailwint ~ ${label} ${resolved}/${prescan.maxProjects}`);
124
- const pct = found > 0 ? Math.round((received / found) * 100) : 0;
139
+ const pct = sent > 0 ? Math.round((received / sent) * 100) : 0;
125
140
  const bar = progressBar(pct, 18, true);
126
- const totalStr = String(found);
141
+ const totalStr = String(sent);
127
142
  const recvStr = String(received).padStart(totalStr.length);
128
- return ` ${braille()} ${bar} ${c.dim}${label}${dots()}${c.reset} ${c.bold}${recvStr}${c.reset}${c.dim}/${totalStr} scanned${c.reset} ${windTrail(12, tick)}`;
143
+ const usedCols = 2 + 1 + 1 + 20 + 1 + label.length + 3 + 1 - 2;
144
+ const waveCols = Math.max(0, 54 - usedCols);
145
+ // labelCol = 2(indent) + 1(braille) + 1(space) + 20(bar) + 1(space) = 25
146
+ // "received" starts at labelCol, numbers right-aligned before it
147
+ const countStr = `${recvStr}/${totalStr}`;
148
+ const countPad = " ".repeat(Math.max(0, 25 - countStr.length - 1));
149
+ const recvLabel = "files received";
150
+ const recvUsed = countPad.length + countStr.length + 1 + recvLabel.length + 1 - 2;
151
+ const recvWave = Math.max(0, 54 - recvUsed);
152
+ return ` ${braille()} ${bar} ${c.dim}${label}${dots()}${c.reset} ${windTrail(waveCols, tick)}\n${countPad}${c.bold}${countStr}${c.reset} ${c.dim}${recvLabel}${c.reset} ${windTrail(recvWave, tick + 3)}`;
129
153
  }, 80);
130
154
  await waitForAllProjects(prescan.predictedRoots, prescan.maxProjects);
131
155
  stopScan();
@@ -134,7 +158,7 @@ export async function run(options = {}) {
134
158
  console.error(` ${c.yellow}\u26A0${c.reset} ${c.dim}${w}${c.reset}`);
135
159
  }
136
160
  const scanned = diagnosticsReceived.size;
137
- const scannedText = `${scanned}/${found} files received`;
161
+ const scannedText = `${scanned}/${sent} files received`;
138
162
  const scannedPad = 54 - 2 - scannedText.length - 1;
139
163
  console.error(` ${c.green}\u2714${c.reset} ${c.dim}${scannedText}${c.reset} ${windTrail(scannedPad)}`);
140
164
  console.error("");
package/dist/lsp.js CHANGED
@@ -453,7 +453,7 @@ export async function shutdown() {
453
453
  return;
454
454
  await Promise.race([
455
455
  send("shutdown", {}).catch(() => { }),
456
- new Promise(r => setTimeout(r, 3000)),
456
+ new Promise(r => setTimeout(r, 500)),
457
457
  ]);
458
458
  notify("exit", {});
459
459
  serverDead = true;
package/dist/prescan.d.ts CHANGED
@@ -22,6 +22,8 @@ export interface PrescanResult {
22
22
  predictedUnrelated: number;
23
23
  /** Upper bound on projects the server might create */
24
24
  maxProjects: number;
25
+ /** Paths of CSS files with no Tailwind signals — safe to skip sending */
26
+ unrelatedCssFiles: Set<string>;
25
27
  }
26
28
  export declare function prescanCssFiles(files: string[]): PrescanResult;
27
29
  export {};
package/dist/prescan.js CHANGED
@@ -44,6 +44,7 @@ export function prescanCssFiles(files) {
44
44
  let predictedRoots = 0;
45
45
  let predictedNonRoots = 0;
46
46
  let predictedUnrelated = 0;
47
+ const unrelatedCssFiles = new Set();
47
48
  for (const filePath of files) {
48
49
  if (!filePath.endsWith(".css"))
49
50
  continue;
@@ -57,6 +58,7 @@ export function prescanCssFiles(files) {
57
58
  const result = analyzeStylesheet(content);
58
59
  if (result.versions.length === 0) {
59
60
  predictedUnrelated++;
61
+ unrelatedCssFiles.add(filePath);
60
62
  }
61
63
  else if (result.root) {
62
64
  predictedRoots++;
@@ -70,6 +72,7 @@ export function prescanCssFiles(files) {
70
72
  totalCssFiles,
71
73
  predictedRoots,
72
74
  predictedNonRoots,
75
+ unrelatedCssFiles,
73
76
  predictedUnrelated,
74
77
  maxProjects: predictedRoots + predictedNonRoots,
75
78
  };
package/dist/ui.js CHANGED
@@ -88,13 +88,25 @@ export function startSpinner(render, intervalMs = 100) {
88
88
  if (!isTTY)
89
89
  return () => { };
90
90
  process.stderr.write(c.hide);
91
+ let lastLines = 1;
91
92
  const id = setInterval(() => {
92
93
  tick++;
93
- process.stderr.write(`${c.clear}${render()}`);
94
+ const output = render();
95
+ const lines = output.split("\n").length;
96
+ // Move up and clear previous lines
97
+ let clear = "\x1b[2K\r";
98
+ for (let i = 1; i < lastLines; i++)
99
+ clear = `\x1b[A\x1b[2K` + clear;
100
+ process.stderr.write(`${clear}${output}`);
101
+ lastLines = lines;
94
102
  }, intervalMs);
95
103
  return () => {
96
104
  clearInterval(id);
97
- process.stderr.write(`${c.clear}${c.show}`);
105
+ // Move cursor to the first line of the spinner
106
+ for (let i = 1; i < lastLines; i++)
107
+ process.stderr.write("\x1b[A");
108
+ // Clear from cursor to end of screen (clears all spinner lines)
109
+ process.stderr.write(`\x1b[2K\x1b[J\r${c.show}`);
98
110
  };
99
111
  }
100
112
  // ---------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwint",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Tailwind CSS linter for CI — drives the official language server to catch class issues and auto-fix them",
5
5
  "license": "MIT",
6
6
  "author": "Peter Wang",