Skip to content

Commit b9b0524

Browse files
committed
feat: implement new list output format
1 parent d12b52e commit b9b0524

File tree

2 files changed

+115
-10
lines changed

2 files changed

+115
-10
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ react-component-usage-finder -c ComponentName
6868

6969
- `-c, --component`: Name of the component to analyze (required)
7070
- `-d, --directory`: Root directory to scan (defaults to current directory)
71+
- `-m, --markdown`: Output as markdown list
7172
- `-h, --help`: Show help
7273

7374
## Output Example

main.js

+114-10
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,69 @@ class TreeFormatter {
177177
0
178178
);
179179
}
180+
181+
getMarkdownList(hierarchy, parentPath = "") {
182+
let result = "";
183+
const currentPath = parentPath
184+
? `${parentPath} -> ${hierarchy.name}`
185+
: hierarchy.name;
186+
187+
// If this is a leaf node (no further usages), add a list item
188+
if (!hierarchy.usedIn || hierarchy.usedIn.length === 0) {
189+
result += `- ${currentPath}\n`;
190+
}
191+
192+
// Recursively process children
193+
if (hierarchy.usedIn && hierarchy.usedIn.length > 0) {
194+
hierarchy.usedIn.forEach((child) => {
195+
result += this.getMarkdownList(child, currentPath);
196+
});
197+
}
198+
199+
return result;
200+
}
201+
202+
getStatistics(hierarchy) {
203+
const stats = {
204+
totalComponents: new Set(),
205+
maxDepth: 0,
206+
leafNodes: 0,
207+
uniqueFiles: new Set(),
208+
};
209+
210+
this.calculateStats(hierarchy, 1, stats);
211+
212+
return {
213+
totalComponents: stats.totalComponents.size,
214+
maxDepth: stats.maxDepth,
215+
leafNodes: stats.leafNodes,
216+
uniqueFiles: stats.uniqueFiles.size,
217+
};
218+
}
219+
220+
calculateStats(node, depth, stats) {
221+
stats.totalComponents.add(node.name);
222+
stats.maxDepth = Math.max(stats.maxDepth, depth);
223+
if (node.definedIn) {
224+
stats.uniqueFiles.add(node.definedIn);
225+
}
226+
227+
if (!node.usedIn || node.usedIn.length === 0) {
228+
stats.leafNodes++;
229+
} else {
230+
node.usedIn.forEach((child) => {
231+
this.calculateStats(child, depth + 1, stats);
232+
});
233+
}
234+
}
235+
236+
formatSummary(stats) {
237+
return `Summary:
238+
• Total unique components: ${stats.totalComponents}
239+
• Maximum depth: ${stats.maxDepth}
240+
• Leaf usages: ${stats.leafNodes}
241+
• Files involved: ${stats.uniqueFiles}\n`;
242+
}
180243
}
181244

182245
const argv = yargs(hideBin(process.argv))
@@ -193,33 +256,74 @@ const argv = yargs(hideBin(process.argv))
193256
demandOption: true,
194257
type: "string",
195258
})
259+
.option("m", {
260+
alias: "markdown",
261+
describe: "Output as markdown list",
262+
type: "boolean",
263+
default: false,
264+
})
196265
.help("h")
197266
.alias("h", "help").argv;
198267

199268
async function main() {
200269
try {
201270
const analyzer = new ComponentAnalyzer(argv.directory);
202271
const hierarchy = await analyzer.analyze(argv.component);
203-
204-
console.log("\nComponent Usage Tree:");
205272
const formatter = new TreeFormatter();
206-
const treeOutput = formatter.formatHierarchy(hierarchy);
207-
console.log(treeOutput);
208273

209-
const totalUsages = formatter.getLeafUsages(hierarchy);
210-
console.log(`\nTotal leaf usages found: ${totalUsages}`);
274+
// Calculate and display statistics
275+
const stats = formatter.getStatistics(hierarchy);
276+
console.log("\n" + formatter.formatSummary(stats));
277+
278+
// Prompt for viewing the list
279+
const viewResponse = await prompts([
280+
{
281+
type: "confirm",
282+
name: "viewList",
283+
message: "Would you like to see the detailed usage list?",
284+
initial: true,
285+
},
286+
{
287+
type: (prev) => (prev ? "select" : null),
288+
name: "format",
289+
message: "Select output format:",
290+
choices: [
291+
{ title: "Tree view", value: "tree" },
292+
{ title: "Markdown list", value: "markdown" },
293+
],
294+
initial: 0,
295+
},
296+
]);
297+
298+
let output = "";
299+
if (viewResponse.viewList) {
300+
if (viewResponse.format === "markdown") {
301+
output = formatter.getMarkdownList(hierarchy);
302+
console.log("\nComponent Usage List:");
303+
} else {
304+
output = formatter.formatHierarchy(hierarchy);
305+
console.log("\nComponent Usage Tree:");
306+
}
307+
console.log(output);
308+
}
211309

212-
const response = await prompts({
310+
const clipboardResponse = await prompts({
213311
type: "confirm",
214312
name: "copyToClipboard",
215313
message: "Copy output to clipboard?",
216314
initial: false,
217315
});
218316

219-
if (response.copyToClipboard) {
220-
const markdownOutput = `\`\`\`text\n${treeOutput}\`\`\``;
317+
if (clipboardResponse.copyToClipboard) {
318+
const markdownOutput =
319+
viewResponse.format === "markdown"
320+
? `${formatter.formatSummary(stats)}\n${output}`
321+
: `\`\`\`text\n${formatter.formatSummary(stats)}\n${output}\`\`\``;
221322
await clipboardy.write(markdownOutput);
222-
console.log("\n✓ Copied to clipboard in markdown format");
323+
console.log(
324+
"\n✓ Copied to clipboard" +
325+
(viewResponse.format === "markdown" ? "" : " in markdown format")
326+
);
223327
}
224328
} catch (error) {
225329
console.error("Error:", error);

0 commit comments

Comments
 (0)