codesnap-analyzer
Version:
Create comprehensive snapshots of your codebase with token counting for LLMs
121 lines (120 loc) • 4.69 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputFormatter = void 0;
// src/services/formatter.ts
const path_1 = __importDefault(require("path"));
const token_counter_1 = require("../utils/token-counter");
const inspector_1 = require("inspector");
class OutputFormatter {
static createSummary(directory, stats, tokenCounts) {
const summary = token_counter_1.TokenCounter.formatTokenCounts(tokenCounts);
const lines = [
`Project Directory: ${path_1.default.basename(directory)}`,
`Total Files Analyzed: ${stats.totalFiles}`,
`Total Size: ${(stats.totalSize / 1024 / 1024).toFixed(2)} MB`,
`Date: ${new Date().toISOString()}`,
"",
summary,
];
return lines.join("\n");
}
static formatNumber(num) {
if (num >= 1000000) {
return `${(num / 1000000).toFixed(2)}M`;
}
if (num >= 1000) {
return `${(num / 1000).toFixed(1)}K`;
}
return num.toString();
}
static createTree(files) {
const tree = this.buildFileTree(files);
const lines = ["Directory structure:", ...this.renderTree(tree)];
return lines.join("\n");
}
static buildFileTree(files) {
const root = {
name: "",
type: "directory",
children: [],
path: "",
};
// Sort files to ensure consistent ordering
const sortedFiles = [...files].sort((a, b) => a.path.localeCompare(b.path));
for (const file of sortedFiles) {
const parts = file.path.split(/[\\/]/);
let currentNode = root;
// Process each part of the path
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
const isFile = i === parts.length - 1;
const nodePath = parts.slice(0, i + 1).join("/");
// Find existing node or create new one
let node = currentNode.children.find((n) => n.name === part);
if (!node) {
node = {
name: part,
type: isFile ? "file" : "directory",
children: [],
path: nodePath,
};
currentNode.children.push(node);
// Sort children after adding new node
currentNode.children.sort((a, b) => {
// Directories come first
if (a.type !== b.type) {
return a.type === "directory" ? -1 : 1;
}
// Then sort alphabetically
return a.name.localeCompare(b.name);
});
}
currentNode = node;
}
}
return root;
}
static renderTree(node, prefix = "", isLast = true, level = 0) {
const lines = [];
if (node.name) {
const line = prefix +
(isLast ? "└── " : "├── ") +
node.name +
(node.type === "directory" ? "/" : "");
lines.push(line);
}
const childPrefix = node.name ? prefix + (isLast ? " " : "│ ") : "";
if (node.type === "directory") {
node.children.forEach((child, index) => {
const isLastChild = index === node.children.length - 1;
lines.push(...this.renderTree(child, childPrefix, isLastChild, level + 1));
});
}
return lines;
}
static createContent(files) {
const output = [];
const separator = "=" + "=".repeat(47) + "\n";
// Add README.md first if it exists
const readme = files.find((f) => f.path.toLowerCase() === "readme.md");
if (readme?.content) {
output.push(separator +
`File: ${readme.path}\n` +
separator +
readme.content +
"\n");
}
// Add all other files
files.forEach((file) => {
inspector_1.console.log("createContent from", file.path);
if (file.content && file.path.toLowerCase() !== "readme.md") {
output.push(separator + `File: ${file.path}\n` + separator + file.content + "\n");
}
});
return output.join("\n");
}
}
exports.OutputFormatter = OutputFormatter;