@kt3k/tku 1.2.0 → 1.2.2
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/main.js +117 -4
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -163,10 +163,109 @@ function formatTable(result, omitted = 0) {
|
|
|
163
163
|
lines.push(`${totalDisplay.padStart(maxWidth)} total (${result.totalFiles} files)`);
|
|
164
164
|
return lines.join("\n");
|
|
165
165
|
}
|
|
166
|
+
function buildTree(files) {
|
|
167
|
+
const root = {
|
|
168
|
+
name: ".",
|
|
169
|
+
tokens: 0,
|
|
170
|
+
children: []
|
|
171
|
+
};
|
|
172
|
+
for (const file of files) {
|
|
173
|
+
const parts = file.path.split("/");
|
|
174
|
+
let node = root;
|
|
175
|
+
for (let i = 0; i < parts.length; i++) {
|
|
176
|
+
const name = parts[i];
|
|
177
|
+
const isFile = i === parts.length - 1;
|
|
178
|
+
let child = node.children.find((c) => c.name === name);
|
|
179
|
+
if (!child) {
|
|
180
|
+
child = {
|
|
181
|
+
name,
|
|
182
|
+
tokens: 0,
|
|
183
|
+
children: []
|
|
184
|
+
};
|
|
185
|
+
node.children.push(child);
|
|
186
|
+
}
|
|
187
|
+
if (isFile) {
|
|
188
|
+
child.tokens = file.tokens;
|
|
189
|
+
}
|
|
190
|
+
node = child;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function aggregate(node) {
|
|
194
|
+
if (node.children.length === 0) return node.tokens;
|
|
195
|
+
node.tokens = node.children.reduce((sum, c) => sum + aggregate(c), 0);
|
|
196
|
+
return node.tokens;
|
|
197
|
+
}
|
|
198
|
+
aggregate(root);
|
|
199
|
+
function sortChildren(node) {
|
|
200
|
+
for (const child of node.children) sortChildren(child);
|
|
201
|
+
const dirs = node.children.filter((c) => c.children.length > 0).sort((a, b) => b.tokens - a.tokens);
|
|
202
|
+
const leaves = node.children.filter((c) => c.children.length === 0).sort((a, b) => b.tokens - a.tokens);
|
|
203
|
+
node.children = [
|
|
204
|
+
...dirs,
|
|
205
|
+
...leaves
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
sortChildren(root);
|
|
209
|
+
return root;
|
|
210
|
+
}
|
|
211
|
+
function formatTree(result, options = {}) {
|
|
212
|
+
const tree = buildTree(result.files);
|
|
213
|
+
const dirsOnly = options.dirs ?? false;
|
|
214
|
+
const lines = [];
|
|
215
|
+
const allTokens = [];
|
|
216
|
+
function collectTokens(node) {
|
|
217
|
+
if (dirsOnly && node.children.length === 0) return;
|
|
218
|
+
allTokens.push(node.tokens);
|
|
219
|
+
for (const child of node.children) collectTokens(child);
|
|
220
|
+
}
|
|
221
|
+
collectTokens(tree);
|
|
222
|
+
const maxWidth = Math.max("tokens".length, ...allTokens.map((t) => formatTokenCount(t).length));
|
|
223
|
+
function render(node, prefix, isLast, isRoot) {
|
|
224
|
+
const display = formatTokenCount(node.tokens);
|
|
225
|
+
const connector = isRoot ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
226
|
+
const name = node.children.length > 0 && !isRoot ? `${node.name}/` : node.name;
|
|
227
|
+
lines.push(`${display.padStart(maxWidth)} ${prefix}${connector}${name}`);
|
|
228
|
+
const visibleChildren = dirsOnly ? node.children.filter((c) => c.children.length > 0) : node.children;
|
|
229
|
+
const childPrefix = isRoot ? "" : prefix + (isLast ? " " : "\u2502 ");
|
|
230
|
+
for (let i = 0; i < visibleChildren.length; i++) {
|
|
231
|
+
render(visibleChildren[i], childPrefix, i === visibleChildren.length - 1, false);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
lines.push(`${"tokens".padStart(maxWidth)} path`);
|
|
235
|
+
render(tree, "", true, true);
|
|
236
|
+
return lines.join("\n");
|
|
237
|
+
}
|
|
238
|
+
function summarizeByDir(result) {
|
|
239
|
+
const dirMap = /* @__PURE__ */ new Map();
|
|
240
|
+
for (const file of result.files) {
|
|
241
|
+
const parts = file.path.split("/");
|
|
242
|
+
if (parts.length < 2) continue;
|
|
243
|
+
for (let i = 1; i < parts.length; i++) {
|
|
244
|
+
const dir = parts.slice(0, i).join("/");
|
|
245
|
+
dirMap.set(dir, (dirMap.get(dir) ?? 0) + file.tokens);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const files = [
|
|
249
|
+
...dirMap.entries()
|
|
250
|
+
].map(([path, tokens]) => ({
|
|
251
|
+
path,
|
|
252
|
+
tokens
|
|
253
|
+
}));
|
|
254
|
+
return {
|
|
255
|
+
...result,
|
|
256
|
+
files
|
|
257
|
+
};
|
|
258
|
+
}
|
|
166
259
|
function formatResult(result, options = {}) {
|
|
167
|
-
const { json = false, top, sort = "tokens" } = options;
|
|
260
|
+
const { json = false, top, sort = "tokens", tree = false, dirs = false } = options;
|
|
261
|
+
if (tree) {
|
|
262
|
+
return formatTree(result, {
|
|
263
|
+
dirs
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
const effective = dirs ? summarizeByDir(result) : result;
|
|
168
267
|
const sorted = [
|
|
169
|
-
...
|
|
268
|
+
...effective.files
|
|
170
269
|
];
|
|
171
270
|
if (sort === "path") {
|
|
172
271
|
sorted.sort((a, b) => a.path.localeCompare(b.path));
|
|
@@ -176,7 +275,7 @@ function formatResult(result, options = {}) {
|
|
|
176
275
|
const filtered = top !== void 0 ? sorted.slice(0, top) : sorted;
|
|
177
276
|
const omitted = sorted.length - filtered.length;
|
|
178
277
|
const adjusted = {
|
|
179
|
-
...
|
|
278
|
+
...effective,
|
|
180
279
|
files: filtered
|
|
181
280
|
};
|
|
182
281
|
return json ? JSON.stringify(adjusted, null, 2) : formatTable(adjusted, omitted);
|
|
@@ -193,6 +292,9 @@ Options:
|
|
|
193
292
|
--json Output results as JSON
|
|
194
293
|
--top <n> Show only the top N files by token count
|
|
195
294
|
--sort <field> Sort by "tokens" or "path" (default: tokens)
|
|
295
|
+
-t, --tree Display results as a directory tree
|
|
296
|
+
(ignores --top, --json, --sort)
|
|
297
|
+
--dirs Summarize by directory (table or tree)
|
|
196
298
|
-h, --help Show this help message`);
|
|
197
299
|
}
|
|
198
300
|
async function main() {
|
|
@@ -223,6 +325,15 @@ async function main() {
|
|
|
223
325
|
type: "string",
|
|
224
326
|
default: "tokens"
|
|
225
327
|
},
|
|
328
|
+
tree: {
|
|
329
|
+
type: "boolean",
|
|
330
|
+
short: "t",
|
|
331
|
+
default: false
|
|
332
|
+
},
|
|
333
|
+
dirs: {
|
|
334
|
+
type: "boolean",
|
|
335
|
+
default: false
|
|
336
|
+
},
|
|
226
337
|
help: {
|
|
227
338
|
type: "boolean",
|
|
228
339
|
short: "h",
|
|
@@ -266,7 +377,9 @@ async function main() {
|
|
|
266
377
|
const output = formatResult(result, {
|
|
267
378
|
json: values.json,
|
|
268
379
|
top,
|
|
269
|
-
sort
|
|
380
|
+
sort,
|
|
381
|
+
tree: values.tree,
|
|
382
|
+
dirs: values.dirs
|
|
270
383
|
});
|
|
271
384
|
console.log(output);
|
|
272
385
|
} catch (e) {
|