vue-sfc-inspector
Version:
Analyze Vue SFC script setup adoption
127 lines (124 loc) • 4.57 kB
JavaScript
import process from 'node:process';
import { defineCommand, runMain } from 'citty';
import consola from 'consola';
import { c as classifyVueFiles } from './shared/vue-sfc-inspector.B-iXU3RE.mjs';
import { colorize } from 'consola/utils';
import 'node:fs/promises';
import '@vue/compiler-sfc';
import 'fast-glob';
function createSegmentedProgressBar(segments, options = {}) {
const { width = 80, showLegend = true, showCounts = true } = options;
let bar = "";
for (const segment of segments) {
const segmentWidth = Math.round(segment.percentage / 100 * width);
if (segmentWidth > 0) {
const segmentBar = "\u2588".repeat(segmentWidth);
bar += colorize(segment.color, segmentBar);
}
}
let legend = "";
if (showLegend) {
const legendItems = segments.map((segment) => {
const count = showCounts ? ` (${segment.count})` : "";
const emoji = segment.emoji ? `${segment.emoji} ` : "";
return `${emoji}${segment.label}${count} ${segment.percentage.toFixed(1)}%`;
});
legend = legendItems.join(" ");
}
return { bar, legend };
}
const main = defineCommand({
meta: {
name: "vue-sfc-inspector",
version: "1.0.0",
description: "Analyze Vue SFC script setup adoption"
},
args: {
dir: {
type: "positional",
description: "Directory to scan",
default: ".",
required: false
},
details: {
type: "boolean",
description: "Show detailed file breakdown",
alias: "d"
}
},
async run({ args }) {
try {
consola.start("Analyzing Vue SFC files...");
const result = await classifyVueFiles(args.dir, { includeDetails: args.details });
consola.success("Analysis completed!");
consola.box("\u{1F4CA} Vue SFC Analysis Results");
consola.info(`\u{1F4DD} <script setup>: ${result.scriptSetup}`);
consola.info(`\u{1F527} Composition API (setup() in <script>): ${result.compositionAPI}`);
consola.info(`\u2699\uFE0F Options API: ${result.optionsAPI}`);
consola.info(`\u{1F4C1} Total Files: ${result.total}`);
if (result.total > 0) {
const scriptSetupRate = result.scriptSetup / result.total * 100;
const compositionAPIRate = result.compositionAPI / result.total * 100;
const optionsAPIRate = result.optionsAPI / result.total * 100;
consola.box("\u{1F4CA} Vue SFC Composition");
const segments = [
{
label: "<script setup>",
count: result.scriptSetup,
percentage: scriptSetupRate,
color: "blue",
emoji: "\u{1F4DD}"
},
{
label: "Composition API",
count: result.compositionAPI,
percentage: compositionAPIRate,
color: "green",
emoji: "\u{1F527}"
},
{
label: "Options API",
count: result.optionsAPI,
percentage: optionsAPIRate,
color: "yellow",
emoji: "\u2699\uFE0F"
}
];
const { bar, legend } = createSegmentedProgressBar(segments);
consola.log(bar);
consola.log(legend);
}
if (args.details && result.files) {
consola.box("\u{1F4CB} File Details");
const scriptSetupFiles = result.files.filter((f) => f.type === "scriptSetup");
if (scriptSetupFiles.length > 0) {
consola.info(` \u{1F4DD} <script setup> (${scriptSetupFiles.length} files):`);
scriptSetupFiles.forEach((file) => {
consola.info(` \u2022 ${file.path}`);
});
}
const compositionFiles = result.files.filter((f) => f.type === "compositionAPI");
if (compositionFiles.length > 0) {
consola.info(` \u{1F527} Composition API (${compositionFiles.length} files):`);
compositionFiles.forEach((file) => {
consola.info(` \u2022 ${file.path}`);
});
}
const optionsFiles = result.files.filter((f) => f.type === "optionsAPI");
if (optionsFiles.length > 0) {
consola.info(` \u2699\uFE0F Options API (${optionsFiles.length} files):`);
optionsFiles.forEach((file) => {
consola.info(` \u2022 ${file.path}`);
});
}
}
} catch (error) {
consola.error("Failed to analyze Vue files", error);
consola.info("\u{1F4A1} Make sure the directory contains .vue files");
consola.info("\u{1F4A1} Check file permissions");
process.exit(1);
}
}
});
runMain(main);