@mnaoumov/obsidian-dev-toolkit 2.1.0 → 3.1.0
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 +6 -2
- package/bin/archive-demo-vault.mjs +8 -0
- package/bin/generate-coverage-badge.mjs +8 -0
- package/bundlers/esbuild-impl/feature-options/package.json +6 -0
- package/bundlers/obsidian-cli-reload/package.json +6 -0
- package/bundlers/obsidian-plugin-build/package.json +6 -0
- package/bundlers/obsidian-plugin-features/package.json +6 -0
- package/bundlers/obsidian-plugin-transforms/package.json +6 -0
- package/bundlers/obsidian-plugin-webpack-loader/package.json +6 -0
- package/bundlers/obsidian-plugins-folder-deployment/package.json +6 -0
- package/bundlers/parcel/package.json +6 -0
- package/bundlers/rollup/package.json +6 -0
- package/bundlers/rollup-compatible/package.json +6 -0
- package/bundlers/rollup-compatible-features/package.json +6 -0
- package/bundlers/vite/package.json +6 -0
- package/bundlers/webpack/package.json +6 -0
- package/dist/demo-vault-helper/main.js +6 -442
- package/dist/integration-test-plugin/main.js +918 -4912
- package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.cjs +3 -188
- package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.cts +2 -18
- package/dist/lib/cjs/bundlers/esbuild-impl/feature-options.cjs +173 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/feature-options.d.cts +60 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/index.cjs +4 -1
- package/dist/lib/cjs/bundlers/esbuild-impl/index.d.cts +1 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.cjs +30 -82
- package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.d.cts +7 -24
- package/dist/lib/cjs/bundlers/index.cjs +39 -3
- package/dist/lib/cjs/bundlers/index.d.cts +12 -0
- package/dist/lib/cjs/bundlers/obsidian-cli-reload.cjs +182 -0
- package/dist/lib/cjs/bundlers/obsidian-cli-reload.d.cts +37 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-build.cjs +278 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-build.d.cts +217 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-features.cjs +242 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-features.d.cts +186 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-transforms.cjs +306 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-transforms.d.cts +231 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-webpack-loader.cjs +182 -0
- package/dist/lib/cjs/bundlers/obsidian-plugin-webpack-loader.d.cts +47 -0
- package/dist/lib/cjs/bundlers/obsidian-plugins-folder-deployment.cjs +320 -0
- package/dist/lib/cjs/bundlers/obsidian-plugins-folder-deployment.d.cts +44 -0
- package/dist/lib/cjs/bundlers/parcel.cjs +462 -0
- package/dist/lib/cjs/bundlers/parcel.d.cts +128 -0
- package/dist/lib/cjs/bundlers/rollup-compatible-features.cjs +181 -0
- package/dist/lib/cjs/bundlers/rollup-compatible-features.d.cts +128 -0
- package/dist/lib/cjs/bundlers/rollup-compatible.cjs +138 -0
- package/dist/lib/cjs/bundlers/rollup-compatible.d.cts +84 -0
- package/dist/lib/cjs/bundlers/rollup.cjs +218 -0
- package/dist/lib/cjs/bundlers/rollup.d.cts +99 -0
- package/dist/lib/cjs/bundlers/vite.cjs +229 -0
- package/dist/lib/cjs/bundlers/vite.d.cts +105 -0
- package/dist/lib/cjs/bundlers/webpack.cjs +354 -0
- package/dist/lib/cjs/bundlers/webpack.d.cts +133 -0
- package/dist/lib/cjs/demo-vault-cli.cjs +131 -0
- package/dist/lib/cjs/demo-vault-cli.d.cts +15 -0
- package/dist/lib/cjs/index.cjs +4 -1
- package/dist/lib/cjs/index.d.cts +1 -0
- package/dist/lib/cjs/test-runners/coverage-badge-cli.cjs +160 -0
- package/dist/lib/cjs/test-runners/coverage-badge-cli.d.cts +25 -0
- package/dist/lib/cjs/test-runners/coverage-badge.cjs +279 -0
- package/dist/lib/cjs/test-runners/coverage-badge.d.cts +143 -0
- package/dist/lib/cjs/test-runners/e2e-runner-support.cjs +170 -0
- package/dist/lib/cjs/test-runners/e2e-runner-support.d.cts +36 -0
- package/dist/lib/cjs/test-runners/index.cjs +18 -3
- package/dist/lib/cjs/test-runners/index.d.cts +5 -0
- package/dist/lib/cjs/test-runners/obsidian-test-runner.cjs +147 -0
- package/dist/lib/cjs/test-runners/obsidian-test-runner.d.cts +42 -0
- package/dist/lib/cjs/test-runners/wdio-obsidian.cjs +205 -0
- package/dist/lib/cjs/test-runners/wdio-obsidian.d.cts +199 -0
- package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.mts +2 -18
- package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.mjs +3 -192
- package/dist/lib/esm/bundlers/esbuild-impl/feature-options.d.mts +60 -0
- package/dist/lib/esm/bundlers/esbuild-impl/feature-options.mjs +82 -0
- package/dist/lib/esm/bundlers/esbuild-impl/index.d.mts +1 -0
- package/dist/lib/esm/bundlers/esbuild-impl/index.mjs +3 -1
- package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.d.mts +7 -24
- package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.mjs +41 -87
- package/dist/lib/esm/bundlers/index.d.mts +12 -0
- package/dist/lib/esm/bundlers/index.mjs +26 -2
- package/dist/lib/esm/bundlers/obsidian-cli-reload.d.mts +37 -0
- package/dist/lib/esm/bundlers/obsidian-cli-reload.mjs +83 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-build.d.mts +217 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-build.mjs +166 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-features.d.mts +186 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-features.mjs +126 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-transforms.d.mts +231 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-transforms.mjs +194 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-webpack-loader.d.mts +47 -0
- package/dist/lib/esm/bundlers/obsidian-plugin-webpack-loader.mjs +89 -0
- package/dist/lib/esm/bundlers/obsidian-plugins-folder-deployment.d.mts +44 -0
- package/dist/lib/esm/bundlers/obsidian-plugins-folder-deployment.mjs +228 -0
- package/dist/lib/esm/bundlers/parcel.d.mts +128 -0
- package/dist/lib/esm/bundlers/parcel.mjs +361 -0
- package/dist/lib/esm/bundlers/rollup-compatible-features.d.mts +128 -0
- package/dist/lib/esm/bundlers/rollup-compatible-features.mjs +93 -0
- package/dist/lib/esm/bundlers/rollup-compatible.d.mts +84 -0
- package/dist/lib/esm/bundlers/rollup-compatible.mjs +43 -0
- package/dist/lib/esm/bundlers/rollup.d.mts +99 -0
- package/dist/lib/esm/bundlers/rollup.mjs +130 -0
- package/dist/lib/esm/bundlers/vite.d.mts +105 -0
- package/dist/lib/esm/bundlers/vite.mjs +144 -0
- package/dist/lib/esm/bundlers/webpack.d.mts +133 -0
- package/dist/lib/esm/bundlers/webpack.mjs +259 -0
- package/dist/lib/esm/demo-vault-cli.d.mts +15 -0
- package/dist/lib/esm/demo-vault-cli.mjs +23 -0
- package/dist/lib/esm/index.d.mts +1 -0
- package/dist/lib/esm/index.mjs +3 -1
- package/dist/lib/esm/test-runners/coverage-badge-cli.d.mts +25 -0
- package/dist/lib/esm/test-runners/coverage-badge-cli.mjs +51 -0
- package/dist/lib/esm/test-runners/coverage-badge.d.mts +143 -0
- package/dist/lib/esm/test-runners/coverage-badge.mjs +181 -0
- package/dist/lib/esm/test-runners/e2e-runner-support.d.mts +36 -0
- package/dist/lib/esm/test-runners/e2e-runner-support.mjs +61 -0
- package/dist/lib/esm/test-runners/index.d.mts +5 -0
- package/dist/lib/esm/test-runners/index.mjs +12 -2
- package/dist/lib/esm/test-runners/obsidian-test-runner.d.mts +42 -0
- package/dist/lib/esm/test-runners/obsidian-test-runner.mjs +52 -0
- package/dist/lib/esm/test-runners/wdio-obsidian.d.mts +199 -0
- package/dist/lib/esm/test-runners/wdio-obsidian.mjs +110 -0
- package/package.json +104 -5
- package/test-runners/coverage-badge/package.json +6 -0
- package/test-runners/coverage-badge-cli/package.json +6 -0
- package/test-runners/e2e-runner-support/package.json +6 -0
- package/test-runners/obsidian-test-runner/package.json +6 -0
- package/test-runners/wdio-obsidian/package.json +6 -0
- package/tsconfig/preact.json +7 -0
- package/tsconfig/react.json +7 -0
- package/tsconfig/solid.json +7 -0
- package/tsconfig/svelte.json +7 -0
- package/tsconfig/vue.json +7 -0
- package/types/styles.d.ts +32 -0
- package/types/wasm.d.ts +11 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { archivePluginDemoVault } from "./demo-vault.mjs";
|
|
8
|
+
async function runArchiveDemoVaultCli() {
|
|
9
|
+
try {
|
|
10
|
+
const zipPath = await archivePluginDemoVault();
|
|
11
|
+
process.stdout.write(zipPath === null ? "No demo-vault/ folder: nothing to archive.\n" : `Archived the demo vault to ${zipPath}
|
|
12
|
+
`);
|
|
13
|
+
return 0;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}
|
|
16
|
+
`);
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
runArchiveDemoVaultCli
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2RlbW8tdmF1bHQtY2xpLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogVGhlIGBhcmNoaXZlLWRlbW8tdmF1bHRgIGNvbW1hbmQ6IHJ1bnMge0BsaW5rIGFyY2hpdmVQbHVnaW5EZW1vVmF1bHR9IG9uIHRoZSBidWlsdCBwbHVnaW4gYW5kIHR1cm5zIHRoZSByZXN1bHQgaW50b1xuICogYW4gZXhpdCBjb2RlLiBUaGUgYG9ic2lkaWFuLXBsdWdpbi1yZWxlYXNlLnltbGAgcmV1c2FibGUgd29ya2Zsb3cgcnVucyBpdCBhZnRlciB0aGUgYnVpbGQsIHNvIGEgcmVsZWFzZSBtYWRlIGluIENJXG4gKiBjYXJyaWVzIHRoZSBzYW1lIGRlbW8gdmF1bHQgYXJjaGl2ZSBhcyBvbmUgbWFkZSB3aXRoIGBucG0gcnVuIHZlcnNpb25gLlxuICovXG5cbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5cbmltcG9ydCB7IGFyY2hpdmVQbHVnaW5EZW1vVmF1bHQgfSBmcm9tICcuL2RlbW8tdmF1bHQudHMnO1xuXG4vKipcbiAqIFJ1bnMgYGFyY2hpdmUtZGVtby12YXVsdGAuIEEgcGx1Z2luIHdpdGhvdXQgYSBgZGVtby12YXVsdC9gIGZvbGRlciBpcyBub3QgYSBmYWlsdXJlOiB0aGVyZSBpcyBub3RoaW5nIHRvIGFyY2hpdmUuXG4gKlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB0byB0aGUgZXhpdCBjb2RlOiBgMGAgb25jZSB0aGUgYXJjaGl2ZSBpcyB3cml0dGVuIG9yIHdoZW4gdGhlcmUgaXMgbm8gZGVtb1xuICogICB2YXVsdCwgYDFgIG9uIGFueSBmYWlsdXJlLCB3aGljaCBpcyBwcmludGVkIHRvIHN0ZGVyci5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bkFyY2hpdmVEZW1vVmF1bHRDbGkoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCB6aXBQYXRoID0gYXdhaXQgYXJjaGl2ZVBsdWdpbkRlbW9WYXVsdCgpO1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKHppcFBhdGggPT09IG51bGwgPyAnTm8gZGVtby12YXVsdC8gZm9sZGVyOiBub3RoaW5nIHRvIGFyY2hpdmUuXFxuJyA6IGBBcmNoaXZlZCB0aGUgZGVtbyB2YXVsdCB0byAke3ppcFBhdGh9XFxuYCk7XG4gICAgcmV0dXJuIDA7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoYCR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfVxcbmApO1xuICAgIHJldHVybiAxO1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7OztBQVFBLE9BQU8sYUFBYTtBQUVwQixTQUFTLDhCQUE4QjtBQVF2QyxlQUFzQix5QkFBMEM7QUFDOUQsTUFBSTtBQUNGLFVBQU0sVUFBVSxNQUFNLHVCQUF1QjtBQUM3QyxZQUFRLE9BQU8sTUFBTSxZQUFZLE9BQU8saURBQWlELDhCQUE4QixPQUFPO0FBQUEsQ0FBSTtBQUNsSSxXQUFPO0FBQUEsRUFDVCxTQUFTLE9BQU87QUFDZCxZQUFRLE9BQU8sTUFBTSxHQUFHLGlCQUFpQixRQUFRLE1BQU0sVUFBVSxPQUFPLEtBQUssQ0FBQztBQUFBLENBQUk7QUFDbEYsV0FBTztBQUFBLEVBQ1Q7QUFDRjsiLAogICJuYW1lcyI6IFtdCn0K
|
package/dist/lib/esm/index.d.mts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
export * as 'bundlers' from './bundlers/index.mjs';
|
|
7
7
|
export * as 'demo-vault-app-json' from './demo-vault-app-json.mjs';
|
|
8
8
|
export * as 'demo-vault-buttons' from './demo-vault-buttons.mjs';
|
|
9
|
+
export * as 'demo-vault-cli' from './demo-vault-cli.mjs';
|
|
9
10
|
export * as 'demo-vault-coverage' from './demo-vault-coverage.mjs';
|
|
10
11
|
export * as 'demo-vault' from './demo-vault.mjs';
|
|
11
12
|
export * as 'docs-site' from './docs-site/index.mjs';
|
package/dist/lib/esm/index.mjs
CHANGED
|
@@ -6,6 +6,7 @@ if you want to view the source, please visit the github repository of this plugi
|
|
|
6
6
|
import * as bundlers from "./bundlers/index.mjs";
|
|
7
7
|
import * as demo_vault_app_json from "./demo-vault-app-json.mjs";
|
|
8
8
|
import * as demo_vault_buttons from "./demo-vault-buttons.mjs";
|
|
9
|
+
import * as demo_vault_cli from "./demo-vault-cli.mjs";
|
|
9
10
|
import * as demo_vault_coverage from "./demo-vault-coverage.mjs";
|
|
10
11
|
import * as demo_vault from "./demo-vault.mjs";
|
|
11
12
|
import * as docs_site from "./docs-site/index.mjs";
|
|
@@ -20,6 +21,7 @@ export {
|
|
|
20
21
|
demo_vault as "demo-vault",
|
|
21
22
|
demo_vault_app_json as "demo-vault-app-json",
|
|
22
23
|
demo_vault_buttons as "demo-vault-buttons",
|
|
24
|
+
demo_vault_cli as "demo-vault-cli",
|
|
23
25
|
demo_vault_coverage as "demo-vault-coverage",
|
|
24
26
|
docs_site as "docs-site",
|
|
25
27
|
formatters,
|
|
@@ -29,4 +31,4 @@ export {
|
|
|
29
31
|
test_runners as "test-runners",
|
|
30
32
|
version
|
|
31
33
|
};
|
|
32
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKiBUSElTIElTIEEgR0VORVJBVEVEL0JVTkRMRUQgRklMRSBCWSBCVUlMRCBTQ1JJUFQgKi9cblxuZXhwb3J0ICogYXMgJ2J1bmRsZXJzJyBmcm9tICcuL2J1bmRsZXJzL2luZGV4LnRzJztcbmV4cG9ydCAqIGFzICdkZW1vLXZhdWx0LWFwcC1qc29uJyBmcm9tICcuL2RlbW8tdmF1bHQtYXBwLWpzb24udHMnO1xuZXhwb3J0ICogYXMgJ2RlbW8tdmF1bHQtYnV0dG9ucycgZnJvbSAnLi9kZW1vLXZhdWx0LWJ1dHRvbnMudHMnO1xuZXhwb3J0ICogYXMgJ2RlbW8tdmF1bHQtY2xpJyBmcm9tICcuL2RlbW8tdmF1bHQtY2xpLnRzJztcbmV4cG9ydCAqIGFzICdkZW1vLXZhdWx0LWNvdmVyYWdlJyBmcm9tICcuL2RlbW8tdmF1bHQtY292ZXJhZ2UudHMnO1xuZXhwb3J0ICogYXMgJ2RlbW8tdmF1bHQnIGZyb20gJy4vZGVtby12YXVsdC50cyc7XG5leHBvcnQgKiBhcyAnZG9jcy1zaXRlJyBmcm9tICcuL2RvY3Mtc2l0ZS9pbmRleC50cyc7XG5leHBvcnQgKiBhcyAnZm9ybWF0dGVycycgZnJvbSAnLi9mb3JtYXR0ZXJzL2luZGV4LnRzJztcbmV4cG9ydCAqIGFzICdsaW50ZXJzJyBmcm9tICcuL2xpbnRlcnMvaW5kZXgudHMnO1xuZXhwb3J0ICogYXMgJ29ic2lkaWFuLXBsdWdpbi1yZXBvLXBhdGhzJyBmcm9tICcuL29ic2lkaWFuLXBsdWdpbi1yZXBvLXBhdGhzLnRzJztcbmV4cG9ydCAqIGFzICd0ZW1wbGF0ZXMnIGZyb20gJy4vdGVtcGxhdGVzLnRzJztcbmV4cG9ydCAqIGFzICd0ZXN0LXJ1bm5lcnMnIGZyb20gJy4vdGVzdC1ydW5uZXJzL2luZGV4LnRzJztcbmV4cG9ydCAqIGFzICd2ZXJzaW9uJyBmcm9tICcuL3ZlcnNpb24udHMnO1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7QUFFQSxZQUFZLGNBQWdCO0FBQzVCLFlBQVlBLHlCQUEyQjtBQUN2QyxZQUFZQyx3QkFBMEI7QUFDdEMsWUFBWUMsb0JBQXNCO0FBQ2xDLFlBQVlDLHlCQUEyQjtBQUN2QyxZQUFZQyxnQkFBa0I7QUFDOUIsWUFBWUMsZUFBaUI7QUFDN0IsWUFBWSxnQkFBa0I7QUFDOUIsWUFBWSxhQUFlO0FBQzNCLFlBQVlDLGdDQUFrQztBQUM5QyxZQUFZLGVBQWlCO0FBQzdCLFlBQVlDLGtCQUFvQjtBQUNoQyxZQUFZLGFBQWU7IiwKICAibmFtZXMiOiBbImRlbW8tdmF1bHQtYXBwLWpzb24iLCAiZGVtby12YXVsdC1idXR0b25zIiwgImRlbW8tdmF1bHQtY2xpIiwgImRlbW8tdmF1bHQtY292ZXJhZ2UiLCAiZGVtby12YXVsdCIsICJkb2NzLXNpdGUiLCAib2JzaWRpYW4tcGx1Z2luLXJlcG8tcGF0aHMiLCAidGVzdC1ydW5uZXJzIl0KfQo=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference path="../library-references.d.mts" />
|
|
2
|
+
/**
|
|
3
|
+
* @file
|
|
4
|
+
*
|
|
5
|
+
* The `generate-coverage-badge` command: reads its arguments, runs {@link generateCoverageBadge} and turns the result
|
|
6
|
+
* into an exit code. The `obsidian-plugin-ci.yml` reusable workflow runs it after the gate.
|
|
7
|
+
*/
|
|
8
|
+
import type { GenerateCoverageBadgeOptions } from './coverage-badge.mjs';
|
|
9
|
+
/**
|
|
10
|
+
* Parses the command line of `generate-coverage-badge`: `--lcov=<path>`, `--output=<path>`, `--metric=<metric>` and
|
|
11
|
+
* `--label=<text>`, each optional.
|
|
12
|
+
*
|
|
13
|
+
* @param $arguments - The arguments, without the node and script paths.
|
|
14
|
+
* @returns The {@link GenerateCoverageBadgeOptions}.
|
|
15
|
+
* @throws When an argument is unknown, or `--metric` is not a {@link CoverageBadgeMetric}.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseCoverageBadgeArguments($arguments: string[]): GenerateCoverageBadgeOptions;
|
|
18
|
+
/**
|
|
19
|
+
* Runs `generate-coverage-badge`.
|
|
20
|
+
*
|
|
21
|
+
* @param $arguments - The arguments, without the node and script paths.
|
|
22
|
+
* @returns A {@link Promise} that resolves to the exit code: `0` once the badge is written, `1` on any failure, which
|
|
23
|
+
* is printed to stderr.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runCoverageBadgeCli($arguments: string[]): Promise<number>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { parseArgs } from "node:util";
|
|
8
|
+
import { generateCoverageBadge } from "./coverage-badge.mjs";
|
|
9
|
+
const METRICS = ["branches", "functions", "lines", "lowest"];
|
|
10
|
+
function parseCoverageBadgeArguments($arguments) {
|
|
11
|
+
const { values } = parseArgs({
|
|
12
|
+
// eslint-disable-next-line unicorn/name-replacements -- `args` is the option name Node's `parseArgs` reads.
|
|
13
|
+
args: $arguments,
|
|
14
|
+
options: {
|
|
15
|
+
label: { type: "string" },
|
|
16
|
+
lcov: { type: "string" },
|
|
17
|
+
metric: { type: "string" },
|
|
18
|
+
output: { type: "string" }
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const { label, lcov, metric, output } = values;
|
|
22
|
+
if (metric !== void 0 && !isCoverageBadgeMetric(metric)) {
|
|
23
|
+
throw new Error(`Unknown --metric '${metric}'. Use one of: ${METRICS.join(", ")}.`);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
...label !== void 0 && { label },
|
|
27
|
+
...lcov !== void 0 && { lcovPath: lcov },
|
|
28
|
+
...metric !== void 0 && { metric },
|
|
29
|
+
...output !== void 0 && { outputPath: output }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function runCoverageBadgeCli($arguments) {
|
|
33
|
+
try {
|
|
34
|
+
const { outputPath, percent } = await generateCoverageBadge(parseCoverageBadgeArguments($arguments));
|
|
35
|
+
process.stdout.write(`Wrote the coverage badge (${String(percent)}%) to ${outputPath}
|
|
36
|
+
`);
|
|
37
|
+
return 0;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}
|
|
40
|
+
`);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isCoverageBadgeMetric(value) {
|
|
45
|
+
return METRICS.includes(value);
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
parseCoverageBadgeArguments,
|
|
49
|
+
runCoverageBadgeCli
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL3Rlc3QtcnVubmVycy9jb3ZlcmFnZS1iYWRnZS1jbGkudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBUaGUgYGdlbmVyYXRlLWNvdmVyYWdlLWJhZGdlYCBjb21tYW5kOiByZWFkcyBpdHMgYXJndW1lbnRzLCBydW5zIHtAbGluayBnZW5lcmF0ZUNvdmVyYWdlQmFkZ2V9IGFuZCB0dXJucyB0aGUgcmVzdWx0XG4gKiBpbnRvIGFuIGV4aXQgY29kZS4gVGhlIGBvYnNpZGlhbi1wbHVnaW4tY2kueW1sYCByZXVzYWJsZSB3b3JrZmxvdyBydW5zIGl0IGFmdGVyIHRoZSBnYXRlLlxuICovXG5cbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5pbXBvcnQgeyBwYXJzZUFyZ3MgfSBmcm9tICdub2RlOnV0aWwnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIENvdmVyYWdlQmFkZ2VNZXRyaWMsXG4gIEdlbmVyYXRlQ292ZXJhZ2VCYWRnZU9wdGlvbnNcbn0gZnJvbSAnLi9jb3ZlcmFnZS1iYWRnZS50cyc7XG5cbmltcG9ydCB7IGdlbmVyYXRlQ292ZXJhZ2VCYWRnZSB9IGZyb20gJy4vY292ZXJhZ2UtYmFkZ2UudHMnO1xuXG5jb25zdCBNRVRSSUNTOiByZWFkb25seSBDb3ZlcmFnZUJhZGdlTWV0cmljW10gPSBbJ2JyYW5jaGVzJywgJ2Z1bmN0aW9ucycsICdsaW5lcycsICdsb3dlc3QnXTtcblxuLyoqXG4gKiBQYXJzZXMgdGhlIGNvbW1hbmQgbGluZSBvZiBgZ2VuZXJhdGUtY292ZXJhZ2UtYmFkZ2VgOiBgLS1sY292PTxwYXRoPmAsIGAtLW91dHB1dD08cGF0aD5gLCBgLS1tZXRyaWM9PG1ldHJpYz5gIGFuZFxuICogYC0tbGFiZWw9PHRleHQ+YCwgZWFjaCBvcHRpb25hbC5cbiAqXG4gKiBAcGFyYW0gJGFyZ3VtZW50cyAtIFRoZSBhcmd1bWVudHMsIHdpdGhvdXQgdGhlIG5vZGUgYW5kIHNjcmlwdCBwYXRocy5cbiAqIEByZXR1cm5zIFRoZSB7QGxpbmsgR2VuZXJhdGVDb3ZlcmFnZUJhZGdlT3B0aW9uc30uXG4gKiBAdGhyb3dzIFdoZW4gYW4gYXJndW1lbnQgaXMgdW5rbm93biwgb3IgYC0tbWV0cmljYCBpcyBub3QgYSB7QGxpbmsgQ292ZXJhZ2VCYWRnZU1ldHJpY30uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUNvdmVyYWdlQmFkZ2VBcmd1bWVudHMoJGFyZ3VtZW50czogc3RyaW5nW10pOiBHZW5lcmF0ZUNvdmVyYWdlQmFkZ2VPcHRpb25zIHtcbiAgY29uc3QgeyB2YWx1ZXMgfSA9IHBhcnNlQXJncyh7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vbmFtZS1yZXBsYWNlbWVudHMgLS0gYGFyZ3NgIGlzIHRoZSBvcHRpb24gbmFtZSBOb2RlJ3MgYHBhcnNlQXJnc2AgcmVhZHMuXG4gICAgYXJnczogJGFyZ3VtZW50cyxcbiAgICBvcHRpb25zOiB7XG4gICAgICBsYWJlbDogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgbGNvdjogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgbWV0cmljOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICBvdXRwdXQ6IHsgdHlwZTogJ3N0cmluZycgfVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgeyBsYWJlbCwgbGNvdiwgbWV0cmljLCBvdXRwdXQgfSA9IHZhbHVlcztcbiAgaWYgKG1ldHJpYyAhPT0gdW5kZWZpbmVkICYmICFpc0NvdmVyYWdlQmFkZ2VNZXRyaWMobWV0cmljKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biAtLW1ldHJpYyAnJHttZXRyaWN9Jy4gVXNlIG9uZSBvZjogJHtNRVRSSUNTLmpvaW4oJywgJyl9LmApO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAuLi4obGFiZWwgIT09IHVuZGVmaW5lZCAmJiB7IGxhYmVsIH0pLFxuICAgIC4uLihsY292ICE9PSB1bmRlZmluZWQgJiYgeyBsY292UGF0aDogbGNvdiB9KSxcbiAgICAuLi4obWV0cmljICE9PSB1bmRlZmluZWQgJiYgeyBtZXRyaWMgfSksXG4gICAgLi4uKG91dHB1dCAhPT0gdW5kZWZpbmVkICYmIHsgb3V0cHV0UGF0aDogb3V0cHV0IH0pXG4gIH07XG59XG5cbi8qKlxuICogUnVucyBgZ2VuZXJhdGUtY292ZXJhZ2UtYmFkZ2VgLlxuICpcbiAqIEBwYXJhbSAkYXJndW1lbnRzIC0gVGhlIGFyZ3VtZW50cywgd2l0aG91dCB0aGUgbm9kZSBhbmQgc2NyaXB0IHBhdGhzLlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB0byB0aGUgZXhpdCBjb2RlOiBgMGAgb25jZSB0aGUgYmFkZ2UgaXMgd3JpdHRlbiwgYDFgIG9uIGFueSBmYWlsdXJlLCB3aGljaFxuICogICBpcyBwcmludGVkIHRvIHN0ZGVyci5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bkNvdmVyYWdlQmFkZ2VDbGkoJGFyZ3VtZW50czogc3RyaW5nW10pOiBQcm9taXNlPG51bWJlcj4ge1xuICB0cnkge1xuICAgIGNvbnN0IHsgb3V0cHV0UGF0aCwgcGVyY2VudCB9ID0gYXdhaXQgZ2VuZXJhdGVDb3ZlcmFnZUJhZGdlKHBhcnNlQ292ZXJhZ2VCYWRnZUFyZ3VtZW50cygkYXJndW1lbnRzKSk7XG4gICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoYFdyb3RlIHRoZSBjb3ZlcmFnZSBiYWRnZSAoJHtTdHJpbmcocGVyY2VudCl9JSkgdG8gJHtvdXRwdXRQYXRofVxcbmApO1xuICAgIHJldHVybiAwO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKGAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1cXG5gKTtcbiAgICByZXR1cm4gMTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0NvdmVyYWdlQmFkZ2VNZXRyaWModmFsdWU6IHN0cmluZyk6IHZhbHVlIGlzIENvdmVyYWdlQmFkZ2VNZXRyaWMge1xuICByZXR1cm4gKE1FVFJJQ1MgYXMgcmVhZG9ubHkgc3RyaW5nW10pLmluY2x1ZGVzKHZhbHVlKTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7O0FBT0EsT0FBTyxhQUFhO0FBQ3BCLFNBQVMsaUJBQWlCO0FBTzFCLFNBQVMsNkJBQTZCO0FBRXRDLE1BQU0sVUFBMEMsQ0FBQyxZQUFZLGFBQWEsU0FBUyxRQUFRO0FBVXBGLFNBQVMsNEJBQTRCLFlBQW9EO0FBQzlGLFFBQU0sRUFBRSxPQUFPLElBQUksVUFBVTtBQUFBO0FBQUEsSUFFM0IsTUFBTTtBQUFBLElBQ04sU0FBUztBQUFBLE1BQ1AsT0FBTyxFQUFFLE1BQU0sU0FBUztBQUFBLE1BQ3hCLE1BQU0sRUFBRSxNQUFNLFNBQVM7QUFBQSxNQUN2QixRQUFRLEVBQUUsTUFBTSxTQUFTO0FBQUEsTUFDekIsUUFBUSxFQUFFLE1BQU0sU0FBUztBQUFBLElBQzNCO0FBQUEsRUFDRixDQUFDO0FBRUQsUUFBTSxFQUFFLE9BQU8sTUFBTSxRQUFRLE9BQU8sSUFBSTtBQUN4QyxNQUFJLFdBQVcsVUFBYSxDQUFDLHNCQUFzQixNQUFNLEdBQUc7QUFDMUQsVUFBTSxJQUFJLE1BQU0scUJBQXFCLE1BQU0sa0JBQWtCLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRztBQUFBLEVBQ3BGO0FBRUEsU0FBTztBQUFBLElBQ0wsR0FBSSxVQUFVLFVBQWEsRUFBRSxNQUFNO0FBQUEsSUFDbkMsR0FBSSxTQUFTLFVBQWEsRUFBRSxVQUFVLEtBQUs7QUFBQSxJQUMzQyxHQUFJLFdBQVcsVUFBYSxFQUFFLE9BQU87QUFBQSxJQUNyQyxHQUFJLFdBQVcsVUFBYSxFQUFFLFlBQVksT0FBTztBQUFBLEVBQ25EO0FBQ0Y7QUFTQSxlQUFzQixvQkFBb0IsWUFBdUM7QUFDL0UsTUFBSTtBQUNGLFVBQU0sRUFBRSxZQUFZLFFBQVEsSUFBSSxNQUFNLHNCQUFzQiw0QkFBNEIsVUFBVSxDQUFDO0FBQ25HLFlBQVEsT0FBTyxNQUFNLDZCQUE2QixPQUFPLE9BQU8sQ0FBQyxTQUFTLFVBQVU7QUFBQSxDQUFJO0FBQ3hGLFdBQU87QUFBQSxFQUNULFNBQVMsT0FBTztBQUNkLFlBQVEsT0FBTyxNQUFNLEdBQUcsaUJBQWlCLFFBQVEsTUFBTSxVQUFVLE9BQU8sS0FBSyxDQUFDO0FBQUEsQ0FBSTtBQUNsRixXQUFPO0FBQUEsRUFDVDtBQUNGO0FBRUEsU0FBUyxzQkFBc0IsT0FBNkM7QUFDMUUsU0FBUSxRQUE4QixTQUFTLEtBQUs7QUFDdEQ7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/// <reference path="../library-references.d.mts" />
|
|
2
|
+
/**
|
|
3
|
+
* @file
|
|
4
|
+
*
|
|
5
|
+
* Renders a coverage badge from the `coverage/lcov.info` report `testCoverage` writes, as a self-contained SVG in
|
|
6
|
+
* the shields.io flat style, so a README can show the measured coverage with no external service. The
|
|
7
|
+
* `obsidian-plugin-ci.yml` reusable workflow publishes it to a `badges` branch; see the CI and release guide.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Which coverage figure the badge shows.
|
|
11
|
+
*
|
|
12
|
+
* - `lines`: the share of lines covered, the figure most coverage services show.
|
|
13
|
+
* - `functions`: the share of functions covered.
|
|
14
|
+
* - `branches`: the share of branches covered.
|
|
15
|
+
* - `lowest`: the lowest of the three, so the badge never shows a figure one of the others falls below.
|
|
16
|
+
*/
|
|
17
|
+
export type CoverageBadgeMetric = 'branches' | 'functions' | 'lines' | 'lowest';
|
|
18
|
+
/**
|
|
19
|
+
* A covered and a total count of one kind of coverage item.
|
|
20
|
+
*/
|
|
21
|
+
export interface CoverageCount {
|
|
22
|
+
/**
|
|
23
|
+
* How many items are covered.
|
|
24
|
+
*/
|
|
25
|
+
readonly covered: number;
|
|
26
|
+
/**
|
|
27
|
+
* How many items there are.
|
|
28
|
+
*/
|
|
29
|
+
readonly total: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The coverage totals of a whole lcov report.
|
|
33
|
+
*/
|
|
34
|
+
export interface CoverageTotals {
|
|
35
|
+
/**
|
|
36
|
+
* The branches (`BRF` / `BRH`).
|
|
37
|
+
*/
|
|
38
|
+
readonly branches: CoverageCount;
|
|
39
|
+
/**
|
|
40
|
+
* The functions (`FNF` / `FNH`).
|
|
41
|
+
*/
|
|
42
|
+
readonly functions: CoverageCount;
|
|
43
|
+
/**
|
|
44
|
+
* The lines (`LF` / `LH`).
|
|
45
|
+
*/
|
|
46
|
+
readonly lines: CoverageCount;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Options for {@link generateCoverageBadge}.
|
|
50
|
+
*/
|
|
51
|
+
export interface GenerateCoverageBadgeOptions {
|
|
52
|
+
/**
|
|
53
|
+
* The text on the left half of the badge.
|
|
54
|
+
*
|
|
55
|
+
* @default `'coverage'`
|
|
56
|
+
*/
|
|
57
|
+
readonly label?: string;
|
|
58
|
+
/**
|
|
59
|
+
* The lcov report to read, relative to the project root.
|
|
60
|
+
*
|
|
61
|
+
* @default `'coverage/lcov.info'`
|
|
62
|
+
*/
|
|
63
|
+
readonly lcovPath?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Which coverage figure the badge shows.
|
|
66
|
+
*
|
|
67
|
+
* @default `'lines'`
|
|
68
|
+
*/
|
|
69
|
+
readonly metric?: CoverageBadgeMetric;
|
|
70
|
+
/**
|
|
71
|
+
* Where to write the SVG, relative to the project root. The default sits beside the report, in a folder a
|
|
72
|
+
* project ignores, so a local coverage run never leaves a changed file behind.
|
|
73
|
+
*
|
|
74
|
+
* @default `'coverage/coverage-badge.svg'`
|
|
75
|
+
*/
|
|
76
|
+
readonly outputPath?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The result of {@link generateCoverageBadge}.
|
|
80
|
+
*/
|
|
81
|
+
export interface GenerateCoverageBadgeResult {
|
|
82
|
+
/**
|
|
83
|
+
* The absolute path of the SVG written.
|
|
84
|
+
*/
|
|
85
|
+
readonly outputPath: string;
|
|
86
|
+
/**
|
|
87
|
+
* The coverage figure the badge shows, in percents, rounded down to one decimal.
|
|
88
|
+
*/
|
|
89
|
+
readonly percent: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Parameters for {@link renderCoverageBadgeSvg}.
|
|
93
|
+
*/
|
|
94
|
+
export interface RenderCoverageBadgeSvgParams {
|
|
95
|
+
/**
|
|
96
|
+
* The text on the left half of the badge.
|
|
97
|
+
*/
|
|
98
|
+
readonly label: string;
|
|
99
|
+
/**
|
|
100
|
+
* The coverage figure, in percents.
|
|
101
|
+
*/
|
|
102
|
+
readonly percent: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Reads the lcov report, renders the badge and writes it.
|
|
106
|
+
*
|
|
107
|
+
* @param options - The {@link GenerateCoverageBadgeOptions}.
|
|
108
|
+
* @returns A {@link Promise} that resolves to the {@link GenerateCoverageBadgeResult}.
|
|
109
|
+
* @throws When the lcov report cannot be read; run the tests with coverage first.
|
|
110
|
+
*/
|
|
111
|
+
export declare function generateCoverageBadge(options?: GenerateCoverageBadgeOptions): Promise<GenerateCoverageBadgeResult>;
|
|
112
|
+
/**
|
|
113
|
+
* Picks the badge color of a coverage figure, on the shields.io scale.
|
|
114
|
+
*
|
|
115
|
+
* @param percent - The coverage figure, in percents.
|
|
116
|
+
* @returns The color, as a CSS hex color.
|
|
117
|
+
*/
|
|
118
|
+
export declare function getCoverageBadgeColor(percent: number): string;
|
|
119
|
+
/**
|
|
120
|
+
* Computes the figure a badge shows.
|
|
121
|
+
*
|
|
122
|
+
* A kind with nothing to cover counts as fully covered, as vitest's own summary reports it. The figure is rounded
|
|
123
|
+
* DOWN to one decimal, so a project at 99.96% never shows 100%.
|
|
124
|
+
*
|
|
125
|
+
* @param totals - The {@link CoverageTotals}.
|
|
126
|
+
* @param metric - The {@link CoverageBadgeMetric}.
|
|
127
|
+
* @returns The coverage figure, in percents.
|
|
128
|
+
*/
|
|
129
|
+
export declare function getCoveragePercent(totals: CoverageTotals, metric: CoverageBadgeMetric): number;
|
|
130
|
+
/**
|
|
131
|
+
* Sums the per-file counts of an lcov report.
|
|
132
|
+
*
|
|
133
|
+
* @param lcov - The text of the report.
|
|
134
|
+
* @returns The {@link CoverageTotals}.
|
|
135
|
+
*/
|
|
136
|
+
export declare function parseLcovTotals(lcov: string): CoverageTotals;
|
|
137
|
+
/**
|
|
138
|
+
* Renders a coverage badge in the shields.io flat style.
|
|
139
|
+
*
|
|
140
|
+
* @param params - The {@link RenderCoverageBadgeSvgParams}.
|
|
141
|
+
* @returns The SVG text.
|
|
142
|
+
*/
|
|
143
|
+
export declare function renderCoverageBadgeSvg(params: RenderCoverageBadgeSvgParams): string;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
(function () {
|
|
6
|
+
function ensureBrowserProcess() {
|
|
7
|
+
const browserProcess = {
|
|
8
|
+
browser: true,
|
|
9
|
+
cwd() {
|
|
10
|
+
return "/";
|
|
11
|
+
},
|
|
12
|
+
env: {},
|
|
13
|
+
platform: "android"
|
|
14
|
+
};
|
|
15
|
+
const existingProcess = globalThis.process;
|
|
16
|
+
if (!existingProcess) {
|
|
17
|
+
globalThis.process = browserProcess;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (existingProcess.versions?.node) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const existingProcessRecord = existingProcess;
|
|
24
|
+
for (const [key, value] of Object.entries(browserProcess)) {
|
|
25
|
+
existingProcessRecord[key] ??= value;
|
|
26
|
+
}
|
|
27
|
+
existingProcessRecord["browser"] = true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
ensureBrowserProcess();
|
|
31
|
+
})();
|
|
32
|
+
|
|
33
|
+
import { resolvePathFromRootSafe } from "@mnaoumov/typescript-dev-toolkit/root";
|
|
34
|
+
import {
|
|
35
|
+
mkdir,
|
|
36
|
+
readFile,
|
|
37
|
+
writeFile
|
|
38
|
+
} from "node:fs/promises";
|
|
39
|
+
import { dirname } from "node:path";
|
|
40
|
+
const DEFAULT_LABEL = "coverage";
|
|
41
|
+
const DEFAULT_LCOV_PATH = "coverage/lcov.info";
|
|
42
|
+
const DEFAULT_OUTPUT_PATH = "coverage/coverage-badge.svg";
|
|
43
|
+
const FULL_PERCENT = 100;
|
|
44
|
+
const PERCENT_PRECISION = 10;
|
|
45
|
+
const GREEN_MIN_PERCENT = 90;
|
|
46
|
+
const YELLOW_GREEN_MIN_PERCENT = 80;
|
|
47
|
+
const YELLOW_MIN_PERCENT = 70;
|
|
48
|
+
const ORANGE_MIN_PERCENT = 60;
|
|
49
|
+
const RED = "#e05d44";
|
|
50
|
+
const BADGE_COLOR_THRESHOLDS = [
|
|
51
|
+
{ color: "#4c1", minPercent: FULL_PERCENT },
|
|
52
|
+
{ color: "#97ca00", minPercent: GREEN_MIN_PERCENT },
|
|
53
|
+
{ color: "#a4a61d", minPercent: YELLOW_GREEN_MIN_PERCENT },
|
|
54
|
+
{ color: "#dfb317", minPercent: YELLOW_MIN_PERCENT },
|
|
55
|
+
{ color: "#fe7d37", minPercent: ORANGE_MIN_PERCENT },
|
|
56
|
+
{ color: RED, minPercent: 0 }
|
|
57
|
+
];
|
|
58
|
+
const BADGE_HEIGHT = 20;
|
|
59
|
+
const TEXT_PADDING = 12;
|
|
60
|
+
const HALF = 0.5;
|
|
61
|
+
const TEXT_BASELINE = 14;
|
|
62
|
+
const TEXT_SHADOW_BASELINE = 15;
|
|
63
|
+
const NARROW_CHARACTER_WIDTH = 3.9;
|
|
64
|
+
const DEFAULT_CHARACTER_WIDTH = 7;
|
|
65
|
+
const WIDE_CHARACTER_WIDTH = 9.5;
|
|
66
|
+
const PERCENT_SIGN_WIDTH = 11.9;
|
|
67
|
+
const NARROW_CHARACTERS = /* @__PURE__ */ new Set([" ", "-", ",", ";", ":", "!", ".", "'", "(", ")", "/", "f", "I", "i", "j", "l", "r", "t"]);
|
|
68
|
+
const WIDE_CHARACTERS = /* @__PURE__ */ new Set(["M", "m", "W", "w"]);
|
|
69
|
+
async function generateCoverageBadge(options = {}) {
|
|
70
|
+
const {
|
|
71
|
+
label = DEFAULT_LABEL,
|
|
72
|
+
lcovPath = DEFAULT_LCOV_PATH,
|
|
73
|
+
metric = "lines",
|
|
74
|
+
outputPath = DEFAULT_OUTPUT_PATH
|
|
75
|
+
} = options;
|
|
76
|
+
const resolvedLcovPath = resolvePathFromRootSafe({ path: lcovPath });
|
|
77
|
+
let lcov;
|
|
78
|
+
try {
|
|
79
|
+
lcov = await readFile(resolvedLcovPath, "utf-8");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw new Error(`Could not read the lcov report '${resolvedLcovPath}'. Run the tests with coverage first.`, { cause: error });
|
|
82
|
+
}
|
|
83
|
+
const percent = getCoveragePercent(parseLcovTotals(lcov), metric);
|
|
84
|
+
const resolvedOutputPath = resolvePathFromRootSafe({ path: outputPath });
|
|
85
|
+
await mkdir(dirname(resolvedOutputPath), { recursive: true });
|
|
86
|
+
await writeFile(resolvedOutputPath, renderCoverageBadgeSvg({ label, percent }));
|
|
87
|
+
return { outputPath: resolvedOutputPath, percent };
|
|
88
|
+
}
|
|
89
|
+
function getCoverageBadgeColor(percent) {
|
|
90
|
+
const threshold = BADGE_COLOR_THRESHOLDS.find((candidate) => percent >= candidate.minPercent);
|
|
91
|
+
return threshold?.color ?? RED;
|
|
92
|
+
}
|
|
93
|
+
function getCoveragePercent(totals, metric) {
|
|
94
|
+
const percents = {
|
|
95
|
+
branches: toPercent(totals.branches),
|
|
96
|
+
functions: toPercent(totals.functions),
|
|
97
|
+
lines: toPercent(totals.lines)
|
|
98
|
+
};
|
|
99
|
+
const percent = metric === "lowest" ? Math.min(percents.branches, percents.functions, percents.lines) : percents[metric];
|
|
100
|
+
return Math.floor(percent * PERCENT_PRECISION) / PERCENT_PRECISION;
|
|
101
|
+
}
|
|
102
|
+
function parseLcovTotals(lcov) {
|
|
103
|
+
const sums = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const line of lcov.split(/\r?\n/u)) {
|
|
105
|
+
const match = /^(?<key>BRF|BRH|FNF|FNH|LF|LH):(?<value>\d+)$/u.exec(line.trim());
|
|
106
|
+
if (!match?.groups) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const { key = "", value = "" } = match.groups;
|
|
110
|
+
sums.set(key, (sums.get(key) ?? 0) + Number(value));
|
|
111
|
+
}
|
|
112
|
+
function count(coveredKey, totalKey) {
|
|
113
|
+
return { covered: sums.get(coveredKey) ?? 0, total: sums.get(totalKey) ?? 0 };
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
branches: count("BRH", "BRF"),
|
|
117
|
+
functions: count("FNH", "FNF"),
|
|
118
|
+
lines: count("LH", "LF")
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function renderCoverageBadgeSvg(params) {
|
|
122
|
+
const { label, percent } = params;
|
|
123
|
+
const value = `${String(percent)}%`;
|
|
124
|
+
const labelTextWidth = measureText(label);
|
|
125
|
+
const valueTextWidth = measureText(value);
|
|
126
|
+
const labelWidth = labelTextWidth + TEXT_PADDING;
|
|
127
|
+
const valueWidth = valueTextWidth + TEXT_PADDING;
|
|
128
|
+
const width = labelWidth + valueWidth;
|
|
129
|
+
const labelCenter = labelWidth * HALF;
|
|
130
|
+
const valueCenter = labelWidth + valueWidth * HALF;
|
|
131
|
+
const color = getCoverageBadgeColor(percent);
|
|
132
|
+
const title = escapeXml(`${label}: ${value}`);
|
|
133
|
+
const escapedLabel = escapeXml(label);
|
|
134
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${String(width)}" height="${String(BADGE_HEIGHT)}" role="img" aria-label="${title}">
|
|
135
|
+
<title>${title}</title>
|
|
136
|
+
<linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient>
|
|
137
|
+
<clipPath id="r"><rect width="${String(width)}" height="${String(BADGE_HEIGHT)}" rx="3" fill="#fff"/></clipPath>
|
|
138
|
+
<g clip-path="url(#r)">
|
|
139
|
+
<rect width="${String(labelWidth)}" height="${String(BADGE_HEIGHT)}" fill="#555"/>
|
|
140
|
+
<rect x="${String(labelWidth)}" width="${String(valueWidth)}" height="${String(BADGE_HEIGHT)}" fill="${color}"/>
|
|
141
|
+
<rect width="${String(width)}" height="${String(BADGE_HEIGHT)}" fill="url(#s)"/>
|
|
142
|
+
</g>
|
|
143
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11" text-rendering="geometricPrecision">
|
|
144
|
+
<text x="${String(labelCenter)}" y="${String(TEXT_SHADOW_BASELINE)}" fill="#010101" fill-opacity=".3" textLength="${String(labelTextWidth)}">${escapedLabel}</text>
|
|
145
|
+
<text x="${String(labelCenter)}" y="${String(TEXT_BASELINE)}" textLength="${String(labelTextWidth)}">${escapedLabel}</text>
|
|
146
|
+
<text x="${String(valueCenter)}" y="${String(TEXT_SHADOW_BASELINE)}" fill="#010101" fill-opacity=".3" textLength="${String(valueTextWidth)}">${value}</text>
|
|
147
|
+
<text x="${String(valueCenter)}" y="${String(TEXT_BASELINE)}" textLength="${String(valueTextWidth)}">${value}</text>
|
|
148
|
+
</g>
|
|
149
|
+
</svg>
|
|
150
|
+
`;
|
|
151
|
+
}
|
|
152
|
+
function escapeXml(text) {
|
|
153
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
154
|
+
}
|
|
155
|
+
function measureCharacter(character) {
|
|
156
|
+
if (character === "%") {
|
|
157
|
+
return PERCENT_SIGN_WIDTH;
|
|
158
|
+
}
|
|
159
|
+
if (NARROW_CHARACTERS.has(character)) {
|
|
160
|
+
return NARROW_CHARACTER_WIDTH;
|
|
161
|
+
}
|
|
162
|
+
return WIDE_CHARACTERS.has(character) ? WIDE_CHARACTER_WIDTH : DEFAULT_CHARACTER_WIDTH;
|
|
163
|
+
}
|
|
164
|
+
function measureText(text) {
|
|
165
|
+
let width = 0;
|
|
166
|
+
for (const character of text) {
|
|
167
|
+
width += measureCharacter(character);
|
|
168
|
+
}
|
|
169
|
+
return Math.round(width);
|
|
170
|
+
}
|
|
171
|
+
function toPercent(count) {
|
|
172
|
+
return count.total === 0 ? FULL_PERCENT : count.covered / count.total * FULL_PERCENT;
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
generateCoverageBadge,
|
|
176
|
+
getCoverageBadgeColor,
|
|
177
|
+
getCoveragePercent,
|
|
178
|
+
parseLcovTotals,
|
|
179
|
+
renderCoverageBadgeSvg
|
|
180
|
+
};
|
|
181
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy90ZXN0LXJ1bm5lcnMvY292ZXJhZ2UtYmFkZ2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFJlbmRlcnMgYSBjb3ZlcmFnZSBiYWRnZSBmcm9tIHRoZSBgY292ZXJhZ2UvbGNvdi5pbmZvYCByZXBvcnQgYHRlc3RDb3ZlcmFnZWAgd3JpdGVzLCBhcyBhIHNlbGYtY29udGFpbmVkIFNWRyBpblxuICogdGhlIHNoaWVsZHMuaW8gZmxhdCBzdHlsZSwgc28gYSBSRUFETUUgY2FuIHNob3cgdGhlIG1lYXN1cmVkIGNvdmVyYWdlIHdpdGggbm8gZXh0ZXJuYWwgc2VydmljZS4gVGhlXG4gKiBgb2JzaWRpYW4tcGx1Z2luLWNpLnltbGAgcmV1c2FibGUgd29ya2Zsb3cgcHVibGlzaGVzIGl0IHRvIGEgYGJhZGdlc2AgYnJhbmNoOyBzZWUgdGhlIENJIGFuZCByZWxlYXNlIGd1aWRlLlxuICovXG5cbmltcG9ydCB7IHJlc29sdmVQYXRoRnJvbVJvb3RTYWZlIH0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtZGV2LXRvb2xraXQvcm9vdCc7XG5pbXBvcnQge1xuICBta2RpcixcbiAgcmVhZEZpbGUsXG4gIHdyaXRlRmlsZVxufSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IGRpcm5hbWUgfSBmcm9tICdub2RlOnBhdGgnO1xuXG4vKipcbiAqIFdoaWNoIGNvdmVyYWdlIGZpZ3VyZSB0aGUgYmFkZ2Ugc2hvd3MuXG4gKlxuICogLSBgbGluZXNgOiB0aGUgc2hhcmUgb2YgbGluZXMgY292ZXJlZCwgdGhlIGZpZ3VyZSBtb3N0IGNvdmVyYWdlIHNlcnZpY2VzIHNob3cuXG4gKiAtIGBmdW5jdGlvbnNgOiB0aGUgc2hhcmUgb2YgZnVuY3Rpb25zIGNvdmVyZWQuXG4gKiAtIGBicmFuY2hlc2A6IHRoZSBzaGFyZSBvZiBicmFuY2hlcyBjb3ZlcmVkLlxuICogLSBgbG93ZXN0YDogdGhlIGxvd2VzdCBvZiB0aGUgdGhyZWUsIHNvIHRoZSBiYWRnZSBuZXZlciBzaG93cyBhIGZpZ3VyZSBvbmUgb2YgdGhlIG90aGVycyBmYWxscyBiZWxvdy5cbiAqL1xuZXhwb3J0IHR5cGUgQ292ZXJhZ2VCYWRnZU1ldHJpYyA9ICdicmFuY2hlcycgfCAnZnVuY3Rpb25zJyB8ICdsaW5lcycgfCAnbG93ZXN0JztcblxuLyoqXG4gKiBBIGNvdmVyZWQgYW5kIGEgdG90YWwgY291bnQgb2Ygb25lIGtpbmQgb2YgY292ZXJhZ2UgaXRlbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb3ZlcmFnZUNvdW50IHtcbiAgLyoqXG4gICAqIEhvdyBtYW55IGl0ZW1zIGFyZSBjb3ZlcmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgY292ZXJlZDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBIb3cgbWFueSBpdGVtcyB0aGVyZSBhcmUuXG4gICAqL1xuICByZWFkb25seSB0b3RhbDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFRoZSBjb3ZlcmFnZSB0b3RhbHMgb2YgYSB3aG9sZSBsY292IHJlcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb3ZlcmFnZVRvdGFscyB7XG4gIC8qKlxuICAgKiBUaGUgYnJhbmNoZXMgKGBCUkZgIC8gYEJSSGApLlxuICAgKi9cbiAgcmVhZG9ubHkgYnJhbmNoZXM6IENvdmVyYWdlQ291bnQ7XG5cbiAgLyoqXG4gICAqIFRoZSBmdW5jdGlvbnMgKGBGTkZgIC8gYEZOSGApLlxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25zOiBDb3ZlcmFnZUNvdW50O1xuXG4gIC8qKlxuICAgKiBUaGUgbGluZXMgKGBMRmAgLyBgTEhgKS5cbiAgICovXG4gIHJlYWRvbmx5IGxpbmVzOiBDb3ZlcmFnZUNvdW50O1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHtAbGluayBnZW5lcmF0ZUNvdmVyYWdlQmFkZ2V9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVyYXRlQ292ZXJhZ2VCYWRnZU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHRleHQgb24gdGhlIGxlZnQgaGFsZiBvZiB0aGUgYmFkZ2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IGAnY292ZXJhZ2UnYFxuICAgKi9cbiAgcmVhZG9ubHkgbGFiZWw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBsY292IHJlcG9ydCB0byByZWFkLCByZWxhdGl2ZSB0byB0aGUgcHJvamVjdCByb290LlxuICAgKlxuICAgKiBAZGVmYXVsdCBgJ2NvdmVyYWdlL2xjb3YuaW5mbydgXG4gICAqL1xuICByZWFkb25seSBsY292UGF0aD86IHN0cmluZztcblxuICAvKipcbiAgICogV2hpY2ggY292ZXJhZ2UgZmlndXJlIHRoZSBiYWRnZSBzaG93cy5cbiAgICpcbiAgICogQGRlZmF1bHQgYCdsaW5lcydgXG4gICAqL1xuICByZWFkb25seSBtZXRyaWM/OiBDb3ZlcmFnZUJhZGdlTWV0cmljO1xuXG4gIC8qKlxuICAgKiBXaGVyZSB0byB3cml0ZSB0aGUgU1ZHLCByZWxhdGl2ZSB0byB0aGUgcHJvamVjdCByb290LiBUaGUgZGVmYXVsdCBzaXRzIGJlc2lkZSB0aGUgcmVwb3J0LCBpbiBhIGZvbGRlciBhXG4gICAqIHByb2plY3QgaWdub3Jlcywgc28gYSBsb2NhbCBjb3ZlcmFnZSBydW4gbmV2ZXIgbGVhdmVzIGEgY2hhbmdlZCBmaWxlIGJlaGluZC5cbiAgICpcbiAgICogQGRlZmF1bHQgYCdjb3ZlcmFnZS9jb3ZlcmFnZS1iYWRnZS5zdmcnYFxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0UGF0aD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgcmVzdWx0IG9mIHtAbGluayBnZW5lcmF0ZUNvdmVyYWdlQmFkZ2V9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVyYXRlQ292ZXJhZ2VCYWRnZVJlc3VsdCB7XG4gIC8qKlxuICAgKiBUaGUgYWJzb2x1dGUgcGF0aCBvZiB0aGUgU1ZHIHdyaXR0ZW4uXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRQYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBjb3ZlcmFnZSBmaWd1cmUgdGhlIGJhZGdlIHNob3dzLCBpbiBwZXJjZW50cywgcm91bmRlZCBkb3duIHRvIG9uZSBkZWNpbWFsLlxuICAgKi9cbiAgcmVhZG9ubHkgcGVyY2VudDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayByZW5kZXJDb3ZlcmFnZUJhZGdlU3ZnfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZW5kZXJDb3ZlcmFnZUJhZGdlU3ZnUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSB0ZXh0IG9uIHRoZSBsZWZ0IGhhbGYgb2YgdGhlIGJhZGdlLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFiZWw6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGNvdmVyYWdlIGZpZ3VyZSwgaW4gcGVyY2VudHMuXG4gICAqL1xuICByZWFkb25seSBwZXJjZW50OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBCYWRnZUNvbG9yVGhyZXNob2xkIHtcbiAgcmVhZG9ubHkgY29sb3I6IHN0cmluZztcbiAgcmVhZG9ubHkgbWluUGVyY2VudDogbnVtYmVyO1xufVxuXG5jb25zdCBERUZBVUxUX0xBQkVMID0gJ2NvdmVyYWdlJztcbmNvbnN0IERFRkFVTFRfTENPVl9QQVRIID0gJ2NvdmVyYWdlL2xjb3YuaW5mbyc7XG5jb25zdCBERUZBVUxUX09VVFBVVF9QQVRIID0gJ2NvdmVyYWdlL2NvdmVyYWdlLWJhZGdlLnN2Zyc7XG5jb25zdCBGVUxMX1BFUkNFTlQgPSAxMDA7XG5jb25zdCBQRVJDRU5UX1BSRUNJU0lPTiA9IDEwO1xuXG5jb25zdCBHUkVFTl9NSU5fUEVSQ0VOVCA9IDkwO1xuY29uc3QgWUVMTE9XX0dSRUVOX01JTl9QRVJDRU5UID0gODA7XG5jb25zdCBZRUxMT1dfTUlOX1BFUkNFTlQgPSA3MDtcbmNvbnN0IE9SQU5HRV9NSU5fUEVSQ0VOVCA9IDYwO1xuY29uc3QgUkVEID0gJyNlMDVkNDQnO1xuXG4vLyBUaGUgc2hpZWxkcy5pbyBjb2xvciBzY2FsZSwgZnJvbSB0aGUgdG9wIGRvd247IHRoZSBsYXN0IGVudHJ5IGNhdGNoZXMgZXZlcnl0aGluZyBiZWxvdyBpdC5cbmNvbnN0IEJBREdFX0NPTE9SX1RIUkVTSE9MRFM6IHJlYWRvbmx5IEJhZGdlQ29sb3JUaHJlc2hvbGRbXSA9IFtcbiAgeyBjb2xvcjogJyM0YzEnLCBtaW5QZXJjZW50OiBGVUxMX1BFUkNFTlQgfSxcbiAgeyBjb2xvcjogJyM5N2NhMDAnLCBtaW5QZXJjZW50OiBHUkVFTl9NSU5fUEVSQ0VOVCB9LFxuICB7IGNvbG9yOiAnI2E0YTYxZCcsIG1pblBlcmNlbnQ6IFlFTExPV19HUkVFTl9NSU5fUEVSQ0VOVCB9LFxuICB7IGNvbG9yOiAnI2RmYjMxNycsIG1pblBlcmNlbnQ6IFlFTExPV19NSU5fUEVSQ0VOVCB9LFxuICB7IGNvbG9yOiAnI2ZlN2QzNycsIG1pblBlcmNlbnQ6IE9SQU5HRV9NSU5fUEVSQ0VOVCB9LFxuICB7IGNvbG9yOiBSRUQsIG1pblBlcmNlbnQ6IDAgfVxuXTtcblxuY29uc3QgQkFER0VfSEVJR0hUID0gMjA7XG4vLyBUaGUgcGFkZGluZyBvbiBib3RoIHNpZGVzIG9mIGEgdGV4dCB0b2dldGhlci5cbmNvbnN0IFRFWFRfUEFERElORyA9IDEyO1xuY29uc3QgSEFMRiA9IDAuNTtcbmNvbnN0IFRFWFRfQkFTRUxJTkUgPSAxNDtcbmNvbnN0IFRFWFRfU0hBRE9XX0JBU0VMSU5FID0gMTU7XG5cbi8vIEFwcHJveGltYXRlIGFkdmFuY2Ugd2lkdGhzIG9mIDExcHggVmVyZGFuYSwgdGhlIGZhY2Ugc2hpZWxkcy5pbyBtZWFzdXJlcyB3aXRoLiBUaGUgcmVuZGVyZWQgdGV4dCBpcyBzdHJldGNoZWQgdG9cbi8vIHRoZSBjb21wdXRlZCB3aWR0aCB0aHJvdWdoIGB0ZXh0TGVuZ3RoYCwgc28gYW4gZXN0aW1hdGUgYSBwaXhlbCBvZmYgbW92ZXMgdGhlIHBhZGRpbmcsIG5ldmVyIGNsaXBzIHRoZSB0ZXh0LlxuY29uc3QgTkFSUk9XX0NIQVJBQ1RFUl9XSURUSCA9IDMuOTtcbmNvbnN0IERFRkFVTFRfQ0hBUkFDVEVSX1dJRFRIID0gNztcbmNvbnN0IFdJREVfQ0hBUkFDVEVSX1dJRFRIID0gOS41O1xuY29uc3QgUEVSQ0VOVF9TSUdOX1dJRFRIID0gMTEuOTtcbmNvbnN0IE5BUlJPV19DSEFSQUNURVJTID0gbmV3IFNldChbJyAnLCAnLScsICcsJywgJzsnLCAnOicsICchJywgJy4nLCAnXFwnJywgJygnLCAnKScsICcvJywgJ2YnLCAnSScsICdpJywgJ2onLCAnbCcsICdyJywgJ3QnXSk7XG5jb25zdCBXSURFX0NIQVJBQ1RFUlMgPSBuZXcgU2V0KFsnTScsICdtJywgJ1cnLCAndyddKTtcblxuLyoqXG4gKiBSZWFkcyB0aGUgbGNvdiByZXBvcnQsIHJlbmRlcnMgdGhlIGJhZGdlIGFuZCB3cml0ZXMgaXQuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBUaGUge0BsaW5rIEdlbmVyYXRlQ292ZXJhZ2VCYWRnZU9wdGlvbnN9LlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB0byB0aGUge0BsaW5rIEdlbmVyYXRlQ292ZXJhZ2VCYWRnZVJlc3VsdH0uXG4gKiBAdGhyb3dzIFdoZW4gdGhlIGxjb3YgcmVwb3J0IGNhbm5vdCBiZSByZWFkOyBydW4gdGhlIHRlc3RzIHdpdGggY292ZXJhZ2UgZmlyc3QuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUNvdmVyYWdlQmFkZ2Uob3B0aW9uczogR2VuZXJhdGVDb3ZlcmFnZUJhZGdlT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxHZW5lcmF0ZUNvdmVyYWdlQmFkZ2VSZXN1bHQ+IHtcbiAgY29uc3Qge1xuICAgIGxhYmVsID0gREVGQVVMVF9MQUJFTCxcbiAgICBsY292UGF0aCA9IERFRkFVTFRfTENPVl9QQVRILFxuICAgIG1ldHJpYyA9ICdsaW5lcycsXG4gICAgb3V0cHV0UGF0aCA9IERFRkFVTFRfT1VUUFVUX1BBVEhcbiAgfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgcmVzb2x2ZWRMY292UGF0aCA9IHJlc29sdmVQYXRoRnJvbVJvb3RTYWZlKHsgcGF0aDogbGNvdlBhdGggfSk7XG4gIGxldCBsY292OiBzdHJpbmc7XG4gIHRyeSB7XG4gICAgbGNvdiA9IGF3YWl0IHJlYWRGaWxlKHJlc29sdmVkTGNvdlBhdGgsICd1dGYtOCcpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHJlYWQgdGhlIGxjb3YgcmVwb3J0ICcke3Jlc29sdmVkTGNvdlBhdGh9Jy4gUnVuIHRoZSB0ZXN0cyB3aXRoIGNvdmVyYWdlIGZpcnN0LmAsIHsgY2F1c2U6IGVycm9yIH0pO1xuICB9XG5cbiAgY29uc3QgcGVyY2VudCA9IGdldENvdmVyYWdlUGVyY2VudChwYXJzZUxjb3ZUb3RhbHMobGNvdiksIG1ldHJpYyk7XG4gIGNvbnN0IHJlc29sdmVkT3V0cHV0UGF0aCA9IHJlc29sdmVQYXRoRnJvbVJvb3RTYWZlKHsgcGF0aDogb3V0cHV0UGF0aCB9KTtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShyZXNvbHZlZE91dHB1dFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgYXdhaXQgd3JpdGVGaWxlKHJlc29sdmVkT3V0cHV0UGF0aCwgcmVuZGVyQ292ZXJhZ2VCYWRnZVN2Zyh7IGxhYmVsLCBwZXJjZW50IH0pKTtcbiAgcmV0dXJuIHsgb3V0cHV0UGF0aDogcmVzb2x2ZWRPdXRwdXRQYXRoLCBwZXJjZW50IH07XG59XG5cbi8qKlxuICogUGlja3MgdGhlIGJhZGdlIGNvbG9yIG9mIGEgY292ZXJhZ2UgZmlndXJlLCBvbiB0aGUgc2hpZWxkcy5pbyBzY2FsZS5cbiAqXG4gKiBAcGFyYW0gcGVyY2VudCAtIFRoZSBjb3ZlcmFnZSBmaWd1cmUsIGluIHBlcmNlbnRzLlxuICogQHJldHVybnMgVGhlIGNvbG9yLCBhcyBhIENTUyBoZXggY29sb3IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb3ZlcmFnZUJhZGdlQ29sb3IocGVyY2VudDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgdGhyZXNob2xkID0gQkFER0VfQ09MT1JfVEhSRVNIT0xEUy5maW5kKChjYW5kaWRhdGUpID0+IHBlcmNlbnQgPj0gY2FuZGlkYXRlLm1pblBlcmNlbnQpO1xuICByZXR1cm4gdGhyZXNob2xkPy5jb2xvciA/PyBSRUQ7XG59XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGZpZ3VyZSBhIGJhZGdlIHNob3dzLlxuICpcbiAqIEEga2luZCB3aXRoIG5vdGhpbmcgdG8gY292ZXIgY291bnRzIGFzIGZ1bGx5IGNvdmVyZWQsIGFzIHZpdGVzdCdzIG93biBzdW1tYXJ5IHJlcG9ydHMgaXQuIFRoZSBmaWd1cmUgaXMgcm91bmRlZFxuICogRE9XTiB0byBvbmUgZGVjaW1hbCwgc28gYSBwcm9qZWN0IGF0IDk5Ljk2JSBuZXZlciBzaG93cyAxMDAlLlxuICpcbiAqIEBwYXJhbSB0b3RhbHMgLSBUaGUge0BsaW5rIENvdmVyYWdlVG90YWxzfS5cbiAqIEBwYXJhbSBtZXRyaWMgLSBUaGUge0BsaW5rIENvdmVyYWdlQmFkZ2VNZXRyaWN9LlxuICogQHJldHVybnMgVGhlIGNvdmVyYWdlIGZpZ3VyZSwgaW4gcGVyY2VudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb3ZlcmFnZVBlcmNlbnQodG90YWxzOiBDb3ZlcmFnZVRvdGFscywgbWV0cmljOiBDb3ZlcmFnZUJhZGdlTWV0cmljKTogbnVtYmVyIHtcbiAgY29uc3QgcGVyY2VudHMgPSB7XG4gICAgYnJhbmNoZXM6IHRvUGVyY2VudCh0b3RhbHMuYnJhbmNoZXMpLFxuICAgIGZ1bmN0aW9uczogdG9QZXJjZW50KHRvdGFscy5mdW5jdGlvbnMpLFxuICAgIGxpbmVzOiB0b1BlcmNlbnQodG90YWxzLmxpbmVzKVxuICB9O1xuICBjb25zdCBwZXJjZW50ID0gbWV0cmljID09PSAnbG93ZXN0JyA/IE1hdGgubWluKHBlcmNlbnRzLmJyYW5jaGVzLCBwZXJjZW50cy5mdW5jdGlvbnMsIHBlcmNlbnRzLmxpbmVzKSA6IHBlcmNlbnRzW21ldHJpY107XG4gIHJldHVybiBNYXRoLmZsb29yKHBlcmNlbnQgKiBQRVJDRU5UX1BSRUNJU0lPTikgLyBQRVJDRU5UX1BSRUNJU0lPTjtcbn1cblxuLyoqXG4gKiBTdW1zIHRoZSBwZXItZmlsZSBjb3VudHMgb2YgYW4gbGNvdiByZXBvcnQuXG4gKlxuICogQHBhcmFtIGxjb3YgLSBUaGUgdGV4dCBvZiB0aGUgcmVwb3J0LlxuICogQHJldHVybnMgVGhlIHtAbGluayBDb3ZlcmFnZVRvdGFsc30uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUxjb3ZUb3RhbHMobGNvdjogc3RyaW5nKTogQ292ZXJhZ2VUb3RhbHMge1xuICBjb25zdCBzdW1zID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIGxjb3Yuc3BsaXQoL1xccj9cXG4vdSkpIHtcbiAgICBjb25zdCBtYXRjaCA9IC9eKD88a2V5PkJSRnxCUkh8Rk5GfEZOSHxMRnxMSCk6KD88dmFsdWU+XFxkKykkL3UuZXhlYyhsaW5lLnRyaW0oKSk7XG4gICAgaWYgKCFtYXRjaD8uZ3JvdXBzKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgeyBrZXkgPSAnJywgdmFsdWUgPSAnJyB9ID0gbWF0Y2guZ3JvdXBzO1xuICAgIHN1bXMuc2V0KGtleSwgKHN1bXMuZ2V0KGtleSkgPz8gMCkgKyBOdW1iZXIodmFsdWUpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvdW50KGNvdmVyZWRLZXk6IHN0cmluZywgdG90YWxLZXk6IHN0cmluZyk6IENvdmVyYWdlQ291bnQge1xuICAgIHJldHVybiB7IGNvdmVyZWQ6IHN1bXMuZ2V0KGNvdmVyZWRLZXkpID8/IDAsIHRvdGFsOiBzdW1zLmdldCh0b3RhbEtleSkgPz8gMCB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBicmFuY2hlczogY291bnQoJ0JSSCcsICdCUkYnKSxcbiAgICBmdW5jdGlvbnM6IGNvdW50KCdGTkgnLCAnRk5GJyksXG4gICAgbGluZXM6IGNvdW50KCdMSCcsICdMRicpXG4gIH07XG59XG5cbi8qKlxuICogUmVuZGVycyBhIGNvdmVyYWdlIGJhZGdlIGluIHRoZSBzaGllbGRzLmlvIGZsYXQgc3R5bGUuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSB7QGxpbmsgUmVuZGVyQ292ZXJhZ2VCYWRnZVN2Z1BhcmFtc30uXG4gKiBAcmV0dXJucyBUaGUgU1ZHIHRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJDb3ZlcmFnZUJhZGdlU3ZnKHBhcmFtczogUmVuZGVyQ292ZXJhZ2VCYWRnZVN2Z1BhcmFtcyk6IHN0cmluZyB7XG4gIGNvbnN0IHsgbGFiZWwsIHBlcmNlbnQgfSA9IHBhcmFtcztcbiAgY29uc3QgdmFsdWUgPSBgJHtTdHJpbmcocGVyY2VudCl9JWA7XG4gIGNvbnN0IGxhYmVsVGV4dFdpZHRoID0gbWVhc3VyZVRleHQobGFiZWwpO1xuICBjb25zdCB2YWx1ZVRleHRXaWR0aCA9IG1lYXN1cmVUZXh0KHZhbHVlKTtcbiAgY29uc3QgbGFiZWxXaWR0aCA9IGxhYmVsVGV4dFdpZHRoICsgVEVYVF9QQURESU5HO1xuICBjb25zdCB2YWx1ZVdpZHRoID0gdmFsdWVUZXh0V2lkdGggKyBURVhUX1BBRERJTkc7XG4gIGNvbnN0IHdpZHRoID0gbGFiZWxXaWR0aCArIHZhbHVlV2lkdGg7XG4gIGNvbnN0IGxhYmVsQ2VudGVyID0gbGFiZWxXaWR0aCAqIEhBTEY7XG4gIGNvbnN0IHZhbHVlQ2VudGVyID0gbGFiZWxXaWR0aCArIHZhbHVlV2lkdGggKiBIQUxGO1xuICBjb25zdCBjb2xvciA9IGdldENvdmVyYWdlQmFkZ2VDb2xvcihwZXJjZW50KTtcbiAgY29uc3QgdGl0bGUgPSBlc2NhcGVYbWwoYCR7bGFiZWx9OiAke3ZhbHVlfWApO1xuICBjb25zdCBlc2NhcGVkTGFiZWwgPSBlc2NhcGVYbWwobGFiZWwpO1xuXG4gIHJldHVybiBgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIke1N0cmluZyh3aWR0aCl9XCIgaGVpZ2h0PVwiJHtTdHJpbmcoQkFER0VfSEVJR0hUKX1cIiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIiR7dGl0bGV9XCI+XG4gIDx0aXRsZT4ke3RpdGxlfTwvdGl0bGU+XG4gIDxsaW5lYXJHcmFkaWVudCBpZD1cInNcIiB4Mj1cIjBcIiB5Mj1cIjEwMCVcIj48c3RvcCBvZmZzZXQ9XCIwXCIgc3RvcC1jb2xvcj1cIiNiYmJcIiBzdG9wLW9wYWNpdHk9XCIuMVwiLz48c3RvcCBvZmZzZXQ9XCIxXCIgc3RvcC1vcGFjaXR5PVwiLjFcIi8+PC9saW5lYXJHcmFkaWVudD5cbiAgPGNsaXBQYXRoIGlkPVwiclwiPjxyZWN0IHdpZHRoPVwiJHtTdHJpbmcod2lkdGgpfVwiIGhlaWdodD1cIiR7U3RyaW5nKEJBREdFX0hFSUdIVCl9XCIgcng9XCIzXCIgZmlsbD1cIiNmZmZcIi8+PC9jbGlwUGF0aD5cbiAgPGcgY2xpcC1wYXRoPVwidXJsKCNyKVwiPlxuICAgIDxyZWN0IHdpZHRoPVwiJHtTdHJpbmcobGFiZWxXaWR0aCl9XCIgaGVpZ2h0PVwiJHtTdHJpbmcoQkFER0VfSEVJR0hUKX1cIiBmaWxsPVwiIzU1NVwiLz5cbiAgICA8cmVjdCB4PVwiJHtTdHJpbmcobGFiZWxXaWR0aCl9XCIgd2lkdGg9XCIke1N0cmluZyh2YWx1ZVdpZHRoKX1cIiBoZWlnaHQ9XCIke1N0cmluZyhCQURHRV9IRUlHSFQpfVwiIGZpbGw9XCIke2NvbG9yfVwiLz5cbiAgICA8cmVjdCB3aWR0aD1cIiR7U3RyaW5nKHdpZHRoKX1cIiBoZWlnaHQ9XCIke1N0cmluZyhCQURHRV9IRUlHSFQpfVwiIGZpbGw9XCJ1cmwoI3MpXCIvPlxuICA8L2c+XG4gIDxnIGZpbGw9XCIjZmZmXCIgdGV4dC1hbmNob3I9XCJtaWRkbGVcIiBmb250LWZhbWlseT1cIlZlcmRhbmEsR2VuZXZhLERlamFWdSBTYW5zLHNhbnMtc2VyaWZcIiBmb250LXNpemU9XCIxMVwiIHRleHQtcmVuZGVyaW5nPVwiZ2VvbWV0cmljUHJlY2lzaW9uXCI+XG4gICAgPHRleHQgeD1cIiR7U3RyaW5nKGxhYmVsQ2VudGVyKX1cIiB5PVwiJHtTdHJpbmcoVEVYVF9TSEFET1dfQkFTRUxJTkUpfVwiIGZpbGw9XCIjMDEwMTAxXCIgZmlsbC1vcGFjaXR5PVwiLjNcIiB0ZXh0TGVuZ3RoPVwiJHtTdHJpbmcobGFiZWxUZXh0V2lkdGgpfVwiPiR7ZXNjYXBlZExhYmVsfTwvdGV4dD5cbiAgICA8dGV4dCB4PVwiJHtTdHJpbmcobGFiZWxDZW50ZXIpfVwiIHk9XCIke1N0cmluZyhURVhUX0JBU0VMSU5FKX1cIiB0ZXh0TGVuZ3RoPVwiJHtTdHJpbmcobGFiZWxUZXh0V2lkdGgpfVwiPiR7ZXNjYXBlZExhYmVsfTwvdGV4dD5cbiAgICA8dGV4dCB4PVwiJHtTdHJpbmcodmFsdWVDZW50ZXIpfVwiIHk9XCIke1N0cmluZyhURVhUX1NIQURPV19CQVNFTElORSl9XCIgZmlsbD1cIiMwMTAxMDFcIiBmaWxsLW9wYWNpdHk9XCIuM1wiIHRleHRMZW5ndGg9XCIke1N0cmluZyh2YWx1ZVRleHRXaWR0aCl9XCI+JHt2YWx1ZX08L3RleHQ+XG4gICAgPHRleHQgeD1cIiR7U3RyaW5nKHZhbHVlQ2VudGVyKX1cIiB5PVwiJHtTdHJpbmcoVEVYVF9CQVNFTElORSl9XCIgdGV4dExlbmd0aD1cIiR7U3RyaW5nKHZhbHVlVGV4dFdpZHRoKX1cIj4ke3ZhbHVlfTwvdGV4dD5cbiAgPC9nPlxuPC9zdmc+XG5gO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVYbWwodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRleHQucmVwbGFjZUFsbCgnJicsICcmYW1wOycpLnJlcGxhY2VBbGwoJzwnLCAnJmx0OycpLnJlcGxhY2VBbGwoJz4nLCAnJmd0OycpLnJlcGxhY2VBbGwoJ1wiJywgJyZxdW90OycpO1xufVxuXG5mdW5jdGlvbiBtZWFzdXJlQ2hhcmFjdGVyKGNoYXJhY3Rlcjogc3RyaW5nKTogbnVtYmVyIHtcbiAgaWYgKGNoYXJhY3RlciA9PT0gJyUnKSB7XG4gICAgcmV0dXJuIFBFUkNFTlRfU0lHTl9XSURUSDtcbiAgfVxuICBpZiAoTkFSUk9XX0NIQVJBQ1RFUlMuaGFzKGNoYXJhY3RlcikpIHtcbiAgICByZXR1cm4gTkFSUk9XX0NIQVJBQ1RFUl9XSURUSDtcbiAgfVxuICByZXR1cm4gV0lERV9DSEFSQUNURVJTLmhhcyhjaGFyYWN0ZXIpID8gV0lERV9DSEFSQUNURVJfV0lEVEggOiBERUZBVUxUX0NIQVJBQ1RFUl9XSURUSDtcbn1cblxuZnVuY3Rpb24gbWVhc3VyZVRleHQodGV4dDogc3RyaW5nKTogbnVtYmVyIHtcbiAgbGV0IHdpZHRoID0gMDtcbiAgZm9yIChjb25zdCBjaGFyYWN0ZXIgb2YgdGV4dCkge1xuICAgIHdpZHRoICs9IG1lYXN1cmVDaGFyYWN0ZXIoY2hhcmFjdGVyKTtcbiAgfVxuICByZXR1cm4gTWF0aC5yb3VuZCh3aWR0aCk7XG59XG5cbmZ1bmN0aW9uIHRvUGVyY2VudChjb3VudDogQ292ZXJhZ2VDb3VudCk6IG51bWJlciB7XG4gIHJldHVybiBjb3VudC50b3RhbCA9PT0gMCA/IEZVTExfUEVSQ0VOVCA6IGNvdW50LmNvdmVyZWQgLyBjb3VudC50b3RhbCAqIEZVTExfUEVSQ0VOVDtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRQSxTQUFTLCtCQUErQjtBQUN4QztBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFDUCxTQUFTLGVBQWU7QUFvSHhCLE1BQU0sZ0JBQWdCO0FBQ3RCLE1BQU0sb0JBQW9CO0FBQzFCLE1BQU0sc0JBQXNCO0FBQzVCLE1BQU0sZUFBZTtBQUNyQixNQUFNLG9CQUFvQjtBQUUxQixNQUFNLG9CQUFvQjtBQUMxQixNQUFNLDJCQUEyQjtBQUNqQyxNQUFNLHFCQUFxQjtBQUMzQixNQUFNLHFCQUFxQjtBQUMzQixNQUFNLE1BQU07QUFHWixNQUFNLHlCQUF5RDtBQUFBLEVBQzdE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
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// <reference path="../library-references.d.mts" />
|
|
2
|
+
/**
|
|
3
|
+
* @file
|
|
4
|
+
*
|
|
5
|
+
* What the end-to-end runners share: where the specs live, and the check that the packages a runner drives are
|
|
6
|
+
* installed in the project, so a missing one is reported with the `npm install` line that fixes it instead of as a
|
|
7
|
+
* shell's `command not found`.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The spec files the end-to-end runners run by default.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_END_TO_END_SPECS = "./e2e/**/*.spec.ts";
|
|
13
|
+
/**
|
|
14
|
+
* Parameters for {@link assertProjectPackagesInstalled}.
|
|
15
|
+
*/
|
|
16
|
+
export interface AssertProjectPackagesInstalledParams {
|
|
17
|
+
/**
|
|
18
|
+
* The packages the runner needs.
|
|
19
|
+
*/
|
|
20
|
+
readonly packageNames: readonly string[];
|
|
21
|
+
/**
|
|
22
|
+
* The folder whose `node_modules` the packages are resolved from. Defaults to the project root.
|
|
23
|
+
*/
|
|
24
|
+
readonly projectFolder?: string;
|
|
25
|
+
/**
|
|
26
|
+
* What needs the packages, as the error message names it, e.g. `testEndToEndWithWdioObsidian()`.
|
|
27
|
+
*/
|
|
28
|
+
readonly requester: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Throws when any of the packages is not installed in the project, naming the `npm install` line.
|
|
32
|
+
*
|
|
33
|
+
* @param params - The {@link AssertProjectPackagesInstalledParams}.
|
|
34
|
+
* @throws When a package is missing.
|
|
35
|
+
*/
|
|
36
|
+
export declare function assertProjectPackagesInstalled(params: AssertProjectPackagesInstalledParams): void;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
(function () {
|
|
6
|
+
function ensureBrowserProcess() {
|
|
7
|
+
const browserProcess = {
|
|
8
|
+
browser: true,
|
|
9
|
+
cwd() {
|
|
10
|
+
return "/";
|
|
11
|
+
},
|
|
12
|
+
env: {},
|
|
13
|
+
platform: "android"
|
|
14
|
+
};
|
|
15
|
+
const existingProcess = globalThis.process;
|
|
16
|
+
if (!existingProcess) {
|
|
17
|
+
globalThis.process = browserProcess;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (existingProcess.versions?.node) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const existingProcessRecord = existingProcess;
|
|
24
|
+
for (const [key, value] of Object.entries(browserProcess)) {
|
|
25
|
+
existingProcessRecord[key] ??= value;
|
|
26
|
+
}
|
|
27
|
+
existingProcessRecord["browser"] = true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
ensureBrowserProcess();
|
|
31
|
+
})();
|
|
32
|
+
|
|
33
|
+
import { getRootFolder } from "@mnaoumov/typescript-dev-toolkit/root";
|
|
34
|
+
import { join } from "@mnaoumov/typescript-lib/path";
|
|
35
|
+
import { createRequire } from "node:module";
|
|
36
|
+
import process from "node:process";
|
|
37
|
+
const DEFAULT_END_TO_END_SPECS = "./e2e/**/*.spec.ts";
|
|
38
|
+
function assertProjectPackagesInstalled(params) {
|
|
39
|
+
const projectFolder = params.projectFolder ?? getRootFolder() ?? process.cwd();
|
|
40
|
+
const require2 = createRequire(join(projectFolder, "package.json"));
|
|
41
|
+
const missingPackageNames = params.packageNames.filter((packageName) => !isPackageInstalled(require2, packageName));
|
|
42
|
+
if (missingPackageNames.length === 0) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
throw new Error(
|
|
46
|
+
`${params.requester} needs ${missingPackageNames.map((packageName) => `\`${packageName}\``).join(", ")}, which the project does not have. Install with: npm install --save-dev ${missingPackageNames.join(" ")}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function isPackageInstalled(require2, packageName) {
|
|
50
|
+
try {
|
|
51
|
+
require2.resolve(`${packageName}/package.json`);
|
|
52
|
+
return true;
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return error.code === "ERR_PACKAGE_PATH_NOT_EXPORTED";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
DEFAULT_END_TO_END_SPECS,
|
|
59
|
+
assertProjectPackagesInstalled
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy90ZXN0LXJ1bm5lcnMvZTJlLXJ1bm5lci1zdXBwb3J0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBXaGF0IHRoZSBlbmQtdG8tZW5kIHJ1bm5lcnMgc2hhcmU6IHdoZXJlIHRoZSBzcGVjcyBsaXZlLCBhbmQgdGhlIGNoZWNrIHRoYXQgdGhlIHBhY2thZ2VzIGEgcnVubmVyIGRyaXZlcyBhcmVcbiAqIGluc3RhbGxlZCBpbiB0aGUgcHJvamVjdCwgc28gYSBtaXNzaW5nIG9uZSBpcyByZXBvcnRlZCB3aXRoIHRoZSBgbnBtIGluc3RhbGxgIGxpbmUgdGhhdCBmaXhlcyBpdCBpbnN0ZWFkIG9mIGFzIGFcbiAqIHNoZWxsJ3MgYGNvbW1hbmQgbm90IGZvdW5kYC5cbiAqL1xuXG5pbXBvcnQgeyBnZXRSb290Rm9sZGVyIH0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtZGV2LXRvb2xraXQvcm9vdCc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtbGliL3BhdGgnO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5cbi8qKlxuICogVGhlIHNwZWMgZmlsZXMgdGhlIGVuZC10by1lbmQgcnVubmVycyBydW4gYnkgZGVmYXVsdC5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRU5EX1RPX0VORF9TUEVDUyA9ICcuL2UyZS8qKi8qLnNwZWMudHMnO1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBhc3NlcnRQcm9qZWN0UGFja2FnZXNJbnN0YWxsZWR9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFzc2VydFByb2plY3RQYWNrYWdlc0luc3RhbGxlZFBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgcGFja2FnZXMgdGhlIHJ1bm5lciBuZWVkcy5cbiAgICovXG4gIHJlYWRvbmx5IHBhY2thZ2VOYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBmb2xkZXIgd2hvc2UgYG5vZGVfbW9kdWxlc2AgdGhlIHBhY2thZ2VzIGFyZSByZXNvbHZlZCBmcm9tLiBEZWZhdWx0cyB0byB0aGUgcHJvamVjdCByb290LlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvamVjdEZvbGRlcj86IHN0cmluZztcblxuICAvKipcbiAgICogV2hhdCBuZWVkcyB0aGUgcGFja2FnZXMsIGFzIHRoZSBlcnJvciBtZXNzYWdlIG5hbWVzIGl0LCBlLmcuIGB0ZXN0RW5kVG9FbmRXaXRoV2Rpb09ic2lkaWFuKClgLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVxdWVzdGVyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhyb3dzIHdoZW4gYW55IG9mIHRoZSBwYWNrYWdlcyBpcyBub3QgaW5zdGFsbGVkIGluIHRoZSBwcm9qZWN0LCBuYW1pbmcgdGhlIGBucG0gaW5zdGFsbGAgbGluZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHtAbGluayBBc3NlcnRQcm9qZWN0UGFja2FnZXNJbnN0YWxsZWRQYXJhbXN9LlxuICogQHRocm93cyBXaGVuIGEgcGFja2FnZSBpcyBtaXNzaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0UHJvamVjdFBhY2thZ2VzSW5zdGFsbGVkKHBhcmFtczogQXNzZXJ0UHJvamVjdFBhY2thZ2VzSW5zdGFsbGVkUGFyYW1zKTogdm9pZCB7XG4gIGNvbnN0IHByb2plY3RGb2xkZXIgPSBwYXJhbXMucHJvamVjdEZvbGRlciA/PyBnZXRSb290Rm9sZGVyKCkgPz8gcHJvY2Vzcy5jd2QoKTtcbiAgY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoam9pbihwcm9qZWN0Rm9sZGVyLCAncGFja2FnZS5qc29uJykpO1xuICBjb25zdCBtaXNzaW5nUGFja2FnZU5hbWVzID0gcGFyYW1zLnBhY2thZ2VOYW1lcy5maWx0ZXIoKHBhY2thZ2VOYW1lKSA9PiAhaXNQYWNrYWdlSW5zdGFsbGVkKHJlcXVpcmUsIHBhY2thZ2VOYW1lKSk7XG4gIGlmIChtaXNzaW5nUGFja2FnZU5hbWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgJHtwYXJhbXMucmVxdWVzdGVyfSBuZWVkcyAke21pc3NpbmdQYWNrYWdlTmFtZXMubWFwKChwYWNrYWdlTmFtZSkgPT4gYFxcYCR7cGFja2FnZU5hbWV9XFxgYCkuam9pbignLCAnKX0sIHdoaWNoIHRoZSBwcm9qZWN0IGRvZXMgbm90IGhhdmUuIGBcbiAgICAgICsgYEluc3RhbGwgd2l0aDogbnBtIGluc3RhbGwgLS1zYXZlLWRldiAke21pc3NpbmdQYWNrYWdlTmFtZXMuam9pbignICcpfWBcbiAgKTtcbn1cblxuZnVuY3Rpb24gaXNQYWNrYWdlSW5zdGFsbGVkKHJlcXVpcmU6IE5vZGVKUy5SZXF1aXJlLCBwYWNrYWdlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgcmVxdWlyZS5yZXNvbHZlKGAke3BhY2thZ2VOYW1lfS9wYWNrYWdlLmpzb25gKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBBIHBhY2thZ2Ugd2hvc2UgYGV4cG9ydHNgIG1hcCBkb2VzIG5vdCBsaXN0IGAuL3BhY2thZ2UuanNvbmAgaXMgaW5zdGFsbGVkIGFsbCB0aGUgc2FtZS5cbiAgICByZXR1cm4gKGVycm9yIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSA9PT0gJ0VSUl9QQUNLQUdFX1BBVEhfTk9UX0VYUE9SVEVEJztcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVFBLFNBQVMscUJBQXFCO0FBQzlCLFNBQVMsWUFBWTtBQUNyQixTQUFTLHFCQUFxQjtBQUM5QixPQUFPLGFBQWE7QUFLYixNQUFNLDJCQUEyQjtBQTRCakMsU0FBUywrQkFBK0IsUUFBb0Q7QUFDakcsUUFBTSxnQkFBZ0IsT0FBTyxpQkFBaUIsY0FBYyxLQUFLLFFBQVEsSUFBSTtBQUM3RSxRQUFNQSxXQUFVLGNBQWMsS0FBSyxlQUFlLGNBQWMsQ0FBQztBQUNqRSxRQUFNLHNCQUFzQixPQUFPLGFBQWEsT0FBTyxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQkEsVUFBUyxXQUFXLENBQUM7QUFDakgsTUFBSSxvQkFBb0IsV0FBVyxHQUFHO0FBQ3BDO0FBQUEsRUFDRjtBQUVBLFFBQU0sSUFBSTtBQUFBLElBQ1IsR0FBRyxPQUFPLFNBQVMsVUFBVSxvQkFBb0IsSUFBSSxDQUFDLGdCQUFnQixLQUFLLFdBQVcsSUFBSSxFQUFFLEtBQUssSUFBSSxDQUFDLDJFQUMxRCxvQkFBb0IsS0FBSyxHQUFHLENBQUM7QUFBQSxFQUMzRTtBQUNGO0FBRUEsU0FBUyxtQkFBbUJBLFVBQXlCLGFBQThCO0FBQ2pGLE1BQUk7QUFDRixJQUFBQSxTQUFRLFFBQVEsR0FBRyxXQUFXLGVBQWU7QUFDN0MsV0FBTztBQUFBLEVBQ1QsU0FBUyxPQUFPO0FBRWQsV0FBUSxNQUFnQyxTQUFTO0FBQUEsRUFDbkQ7QUFDRjsiLCJuYW1lcyI6WyJyZXF1aXJlIl19
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
/// <reference path="../library-references.d.mts" />
|
|
2
|
+
export * as 'coverage-badge-cli' from './coverage-badge-cli.mjs';
|
|
3
|
+
export * as 'coverage-badge' from './coverage-badge.mjs';
|
|
4
|
+
export * as 'e2e-runner-support' from './e2e-runner-support.mjs';
|
|
2
5
|
export * as 'integration-test-plugin' from './integration-test-plugin.mjs';
|
|
6
|
+
export * as 'obsidian-test-runner' from './obsidian-test-runner.mjs';
|
|
3
7
|
export * as 'performance-eval-cap' from './performance-eval-cap.mjs';
|
|
4
8
|
export * as 'vitest-config' from './vitest-config.mjs';
|
|
9
|
+
export * as 'wdio-obsidian' from './wdio-obsidian.mjs';
|