localbadge 0.0.0-stage → 0.0.1

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/README.md CHANGED
@@ -1,3 +1,23 @@
1
- # Temporary Holding Version
1
+ # tsdown-starter
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A starter for creating a TypeScript package.
4
+
5
+ ## Development
6
+
7
+ - Install dependencies:
8
+
9
+ ```bash
10
+ npm install
11
+ ```
12
+
13
+ - Run the unit tests:
14
+
15
+ ```bash
16
+ npm run test
17
+ ```
18
+
19
+ - Build the library:
20
+
21
+ ```bash
22
+ npm run build
23
+ ```
@@ -0,0 +1,118 @@
1
+ import pc from "picocolors";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { makeBadge } from "badge-maker";
5
+ import boxen from "boxen";
6
+ import { startVitest } from "vitest/node";
7
+ import defu from "defu";
8
+ import { loadConfig } from "unconfig";
9
+ // src/coverage.ts
10
+ const getCoveragePercent = async (cwd = process.cwd()) => {
11
+ let linesPercent;
12
+ await startVitest([], {
13
+ root: cwd,
14
+ run: true,
15
+ reporters: ["dot", { onCoverage(coverage) {
16
+ const pct = coverage.getCoverageSummary().lines.pct;
17
+ if (typeof pct !== "number") throw new Error("Vitest coverage \"lines\": Unknown");
18
+ linesPercent = pct;
19
+ } }],
20
+ silent: true,
21
+ coverage: {
22
+ enabled: true,
23
+ clean: false,
24
+ reporter: [],
25
+ reportOnFailure: true
26
+ }
27
+ });
28
+ if (linesPercent === void 0) throw new Error("Vitest did not provide coverage data");
29
+ return linesPercent;
30
+ };
31
+ // src/badge.ts
32
+ const escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&#39;");
33
+ const generateBadge = async (options) => {
34
+ const pct = Math.floor(await getCoveragePercent(options.cwd));
35
+ const svg = makeBadge({
36
+ label: options.badge.label,
37
+ message: `${pct}%`,
38
+ color: options.badge.color,
39
+ labelColor: options.badge.labelColor,
40
+ style: options.badge.style
41
+ });
42
+ const dirParts = options.outputDir.split(/[\\/]+/).filter(Boolean);
43
+ if (dirParts.includes("..")) throw new Error("\"outputDir\" must not contain \"..\"");
44
+ const cwd = options.cwd || process.cwd();
45
+ const outputDir = path.join(cwd, ...dirParts);
46
+ const fileName = `${options.fileName}.svg`;
47
+ await mkdir(outputDir, { recursive: true });
48
+ await writeFile(path.join(outputDir, fileName), svg, "utf8");
49
+ if (options.silentMode) return;
50
+ const color = pc.createColors(!options.noColor);
51
+ const markdownPath = [...dirParts, fileName].join("/");
52
+ const safePath = escapeHtml(markdownPath);
53
+ const safeLabel = escapeHtml(options.badge.label);
54
+ const hint = `
55
+ Coverage badge created at:
56
+ ${color.cyan(color.underline(`${outputDir}/${fileName}`))}
57
+
58
+ ${color.gray("Markdown:")}
59
+ ${color.blue("!")}[${options.badge.label}]${color.cyan(`(${color.redBright(markdownPath)})`)}
60
+
61
+ ${color.gray("HTML:")}
62
+ <${color.blue("img")} ${color.red("src")}=${color.yellow(`"${safePath}"`)} ${color.red("alt")}=${color.yellow(`"${safeLabel}"`)}>
63
+ `;
64
+ console.log(boxen(hint, {
65
+ borderStyle: "round",
66
+ borderColor: "cyan",
67
+ padding: {
68
+ left: 2,
69
+ right: 2
70
+ }
71
+ }));
72
+ };
73
+ // src/config.ts
74
+ const defaultOptions = {
75
+ cwd: "",
76
+ silentMode: false,
77
+ noColor: false,
78
+ outputDir: "",
79
+ fileName: "coverage-badge",
80
+ badge: {
81
+ label: "coverage",
82
+ color: "green",
83
+ labelColor: "gray",
84
+ style: "flat"
85
+ }
86
+ };
87
+ const defineConfig = (options) => {
88
+ return options;
89
+ };
90
+ const resolveOptions = async (overrides = {}) => {
91
+ const cwd = overrides.cwd || process.cwd();
92
+ const { config } = await loadConfig({
93
+ cwd,
94
+ sources: [{
95
+ files: ["localbadge.config"],
96
+ extensions: [
97
+ "ts",
98
+ "mts",
99
+ "cts",
100
+ "js",
101
+ "mjs",
102
+ "cjs",
103
+ "json"
104
+ ]
105
+ }, {
106
+ files: [".localbadgerc"],
107
+ extensions: [
108
+ "json",
109
+ "yaml",
110
+ "yml",
111
+ ""
112
+ ]
113
+ }],
114
+ merge: true
115
+ });
116
+ return defu(overrides, config ?? {}, defaultOptions);
117
+ };
118
+ export { getCoveragePercent as a, generateBadge as i, defineConfig as n, resolveOptions as r, defaultOptions as t };
@@ -0,0 +1,33 @@
1
+ type DeepRequired<T> = T extends object ? { [K in keyof T]-?: NonNullable<T[K]> extends object ? DeepRequired<NonNullable<T[K]>> : T[K]; } : T;
2
+ type Options = {
3
+ cwd?: string;
4
+ silentMode?: boolean;
5
+ noColor?: boolean;
6
+ outputDir?: string;
7
+ fileName?: string;
8
+ badge?: {
9
+ label?: string;
10
+ color?: string;
11
+ labelColor?: string;
12
+ style?: 'flat' | 'plastic' | 'flat-square' | 'for-the-badge' | 'social';
13
+ };
14
+ };
15
+ type ResolvedOptions = DeepRequired<Options>;
16
+ export declare const generateBadge: (options: ResolvedOptions) => Promise<void>;
17
+ export declare const defaultOptions: {
18
+ cwd: string;
19
+ silentMode: false;
20
+ noColor: false;
21
+ outputDir: string;
22
+ fileName: string;
23
+ badge: {
24
+ label: string;
25
+ color: string;
26
+ labelColor: string;
27
+ style: "flat";
28
+ };
29
+ };
30
+ export declare const defineConfig: (options: Options) => Options;
31
+ export declare const resolveOptions: (overrides?: Options) => Promise<ResolvedOptions>;
32
+ export declare const getCoveragePercent: (cwd?: string) => Promise<number>;
33
+ export type { Options, ResolvedOptions };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { t as defaultOptions, n as defineConfig, i as generateBadge, a as getCoveragePercent, r as resolveOptions } from "./config-BSa1vlrn.js";
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ import { i as generateBadge, r as resolveOptions } from "./config-BSa1vlrn.js";
3
+ import { parseArgs } from "node:util";
4
+ import pc from "picocolors";
5
+ // src/cli.ts
6
+ /**
7
+ * добавить mode
8
+ * создать субкоманду coverage, основная localbadge
9
+ */
10
+ const { values } = parseArgs({
11
+ options: {
12
+ "output-dir": { type: "string" },
13
+ "file-name": { type: "string" },
14
+ cwd: { type: "string" },
15
+ silent: { type: "boolean" },
16
+ "no-color": { type: "boolean" },
17
+ label: { type: "string" },
18
+ color: { type: "string" },
19
+ "label-color": { type: "string" },
20
+ style: { type: "string" },
21
+ help: {
22
+ type: "boolean",
23
+ short: "h"
24
+ },
25
+ version: {
26
+ type: "boolean",
27
+ short: "v"
28
+ }
29
+ },
30
+ allowPositionals: false,
31
+ strict: true
32
+ });
33
+ if (values.help) {
34
+ console.log(`
35
+ Usage: coverage [options]
36
+
37
+ Options:
38
+ --output-dir <dir> Output directory (default: cwd)
39
+ --file-name <name> Output file name without extension (default: coverage-badge)
40
+ --cwd <dir> Project root (default: process.cwd())
41
+ --silent Suppress output
42
+ --no-color Disable colors
43
+ --label <text> Badge label
44
+ --color <color> Badge color
45
+ --label-color <color> Badge label color
46
+ --style <style> Badge style (flat|plastic|flat-square|for-the-badge|social)
47
+ --mode <mode> Badge mode (modern|shields-io)
48
+ `);
49
+ process.exit(0);
50
+ }
51
+ const overrides = {
52
+ cwd: values.cwd,
53
+ silentMode: values.silent,
54
+ noColor: values["no-color"],
55
+ outputDir: values["output-dir"],
56
+ fileName: values["file-name"],
57
+ badge: {
58
+ label: values.label,
59
+ color: values.color,
60
+ labelColor: values["label-color"],
61
+ style: values.style
62
+ }
63
+ };
64
+ try {
65
+ const options = await resolveOptions(overrides);
66
+ await generateBadge(options);
67
+ } catch (error) {
68
+ console.error(pc.red(`Error: ${error.message}`));
69
+ process.exit(1);
70
+ }
71
+ export {};
package/package.json CHANGED
@@ -1,6 +1,65 @@
1
1
  {
2
2
  "name": "localbadge",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "description": "",
6
+ "author": "Teplostanski Igor <hi@teplostanski.me> (https://teplostanski.me)",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/local-badges/coverage#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/local-badges/coverage.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/local-badges/coverage/issues"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsdown",
21
+ "dev": "tsdown --watch",
22
+ "test": "vitest",
23
+ "typecheck": "tsc --noEmit",
24
+ "prepublishOnly": "pnpm run build",
25
+ "prepack": "pnpm typecheck && pnpm build",
26
+ "check": "pnpm lint && pnpm typecheck",
27
+ "check:fix": "pnpm lint:fix && pnpm typecheck",
28
+ "lint": "biome check .",
29
+ "lint:fix": "biome check --write .",
30
+ "format": "biome format --write .",
31
+ "prepare": "husky"
32
+ },
33
+ "peerDependencies": {
34
+ "vitest": "^5.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^26.6.5",
38
+ "husky": "^9.1.7",
39
+ "tsdown": "^0.23.1",
40
+ "typescript": "^7.0.2"
41
+ },
42
+ "dependencies": {
43
+ "@biomejs/biome": "^2.6.7",
44
+ "@teplostanski/biome-config": "^2.0.3",
45
+ "@vitest/coverage-v8": "^5.1.0",
46
+ "@vitest/istanbul-lib-coverage": "^2.1.0",
47
+ "badge-maker": "^6.0.0",
48
+ "boxen": "^9.0.0",
49
+ "citty": "^0.2.2",
50
+ "defu": "^6.1.7",
51
+ "picocolors": "^1.1.1",
52
+ "unconfig": "^7.5.0"
53
+ },
54
+ "packageManager": "pnpm@12.18.0",
55
+ "bin": {
56
+ "localbadge": "dist/localbadge.js"
57
+ },
58
+ "exports": {
59
+ ".": {
60
+ "types": "./dist/index.d.ts",
61
+ "import": "./dist/index.js"
62
+ },
63
+ "./package.json": "./package.json"
64
+ }
65
+ }