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 +22 -2
- package/dist/config-BSa1vlrn.js +118 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +1 -0
- package/dist/localbadge.d.ts +1 -0
- package/dist/localbadge.js +71 -0
- package/package.json +63 -4
package/README.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
-
#
|
|
1
|
+
# tsdown-starter
|
|
2
2
|
|
|
3
|
-
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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 };
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
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
|
+
}
|