@ovh-ux/manager-static-analysis-kit 0.11.2 → 0.13.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.
Files changed (27) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +2 -2
  3. package/bin/cli-path-config.js +9 -8
  4. package/bin/code-duplication-tests-cli.js +9 -9
  5. package/bin/lint-cli.js +26 -10
  6. package/bin/perf-budgets-tests-cli.js +9 -9
  7. package/bin/tests-coverage-cli-tests.js +9 -9
  8. package/bin/types-coverage-cli.js +7 -0
  9. package/bin/types-coverage-tests-cli.js +9 -9
  10. package/bin/utils/args-parse-utils.js +3 -2
  11. package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.d.ts +1 -1
  12. package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.d.ts.map +1 -1
  13. package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.js +16 -146
  14. package/dist/adapters/code-duplication/helpers/code-duplication-reports-render.d.ts +4 -0
  15. package/dist/adapters/code-duplication/helpers/code-duplication-reports-render.d.ts.map +1 -0
  16. package/dist/adapters/code-duplication/helpers/code-duplication-reports-render.js +141 -0
  17. package/dist/adapters/eslint/rules/eslint-prettier.d.ts.map +1 -1
  18. package/dist/adapters/eslint/rules/eslint-prettier.js +3 -2
  19. package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.d.ts +2 -2
  20. package/dist/configs/code-formatter-config.d.ts +0 -1
  21. package/dist/configs/code-formatter-config.d.ts.map +1 -1
  22. package/dist/configs/code-formatter-config.js +0 -10
  23. package/dist/configs/shared-exclusion-patterns.d.ts +2 -0
  24. package/dist/configs/shared-exclusion-patterns.d.ts.map +1 -1
  25. package/dist/configs/shared-exclusion-patterns.js +40 -27
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +28 -28
package/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.13.0](https://github.com/ovh/manager/compare/@ovh-ux/manager-static-analysis-kit@0.12.0...@ovh-ux/manager-static-analysis-kit@0.13.0) (2025-11-16)
7
+
8
+
9
+ ### Features
10
+
11
+ * pnpm hybrid improvements ([3b45577](https://github.com/ovh/manager/commit/3b455770da0c7aeb7603f7c731abf6fac9eb4b3f))
12
+
13
+
14
+
15
+
16
+
17
+ # [0.12.0](https://github.com/ovh/manager/compare/@ovh-ux/manager-static-analysis-kit@0.11.2...@ovh-ux/manager-static-analysis-kit@0.12.0) (2025-11-02)
18
+
19
+
20
+ ### Features
21
+
22
+ * **muk:** static quality improvement ([2ca8694](https://github.com/ovh/manager/commit/2ca8694747cce2ea2901b6d04286ac07a65be03d))
23
+
24
+
25
+
26
+
27
+
6
28
  ## [0.11.2](https://github.com/ovh/manager/compare/@ovh-ux/manager-static-analysis-kit@0.11.1...@ovh-ux/manager-static-analysis-kit@0.11.2) (2025-10-23)
7
29
 
8
30
 
package/README.md CHANGED
@@ -101,13 +101,13 @@ yarn manager-types-coverage --package @ovh-ux/manager-container-app
101
101
  ### Analyze specific libraries (by `package.json` name)
102
102
 
103
103
  ```bash
104
- yarn manager-types-coverage --libraries @ovh-ux/manager-wiki,@ovh-ux/manager-react-components
104
+ yarn manager-types-coverage --libraries @ovh-ux/manager-wiki,@ovh-ux/muk
105
105
  ```
106
106
 
107
107
  or single library:
108
108
 
109
109
  ```bash
110
- yarn manager-types-coverage --library @ovh-ux/manager-react-components
110
+ yarn manager-types-coverage --library @ovh-ux/muk
111
111
  ```
112
112
 
113
113
  > In this mode:
@@ -58,13 +58,14 @@ export const combinedReportOutputRootDir = path.resolve(
58
58
 
59
59
  export const staticDiscoveredLibraries = [
60
60
  {
61
- fullPath: 'packages/manager-react-components',
62
- shortPath: 'manager-react-components',
63
- packageName: '@ovh-ux/manager-react-components',
64
- },
65
- {
66
- fullPath: 'packages/manager-wiki',
67
- shortPath: 'manager-wiki',
68
- packageName: '@ovh-ux/manager-wiki',
61
+ fullPath: 'packages/manager-ui-kit',
62
+ shortPath: 'manager-ui-kit',
63
+ packageName: '@ovh-ux/muk',
69
64
  },
70
65
  ];
66
+
67
+ export const typesSpecificIgnorePatterns = [
68
+ /(^|\/)(__tests__|tests?|spec|fixtures|stubs|mocks)\//i,
69
+ /\.(test|spec|stories?)\.(ts|tsx)$/i,
70
+ /(^|\/)i18n(\.ts|\.tsx)?$/i,
71
+ ];
@@ -22,13 +22,13 @@ const cases = [
22
22
  expect: 0,
23
23
  },
24
24
  {
25
- name: 'Single library static path by folder name (manager-react-components)',
26
- cmd: 'yarn manager-code-duplication --library manager-react-components',
25
+ name: 'Single library static path by folder name (manager-ui-kit)',
26
+ cmd: 'yarn manager-code-duplication --library manager-ui-kit',
27
27
  expect: 0,
28
28
  },
29
29
  {
30
- name: 'Single library static path by package name (manager-react-components)',
31
- cmd: 'yarn manager-code-duplication --library @ovh-ux/manager-react-components',
30
+ name: 'Single library static path by package name (manager-ui-kit)',
31
+ cmd: 'yarn manager-code-duplication --library @ovh-ux/muk',
32
32
  expect: 0,
33
33
  },
34
34
  {
@@ -42,13 +42,13 @@ const cases = [
42
42
  expect: 0,
43
43
  },
44
44
  {
45
- name: 'Multiple libraries by folder names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
46
- cmd: 'yarn manager-code-duplication --libraries manager-wiki,manager-react-components,shell-client,logs-to-customer',
45
+ name: 'Multiple libraries by folder names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
46
+ cmd: 'yarn manager-code-duplication --libraries manager-wiki,manager-ui-kit,shell-client,logs-to-customer',
47
47
  expect: 0,
48
48
  },
49
49
  {
50
- name: 'Multiple libraries by package names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
51
- cmd: 'yarn manager-code-duplication --libraries @ovh-ux/manager-wiki,@ovh-ux/manager-react-components,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
50
+ name: 'Multiple libraries by package names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
51
+ cmd: 'yarn manager-code-duplication --libraries @ovh-ux/manager-wiki,@ovh-ux/muk,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
52
52
  expect: 0,
53
53
  },
54
54
  {
@@ -58,7 +58,7 @@ const cases = [
58
58
  },
59
59
  {
60
60
  name: 'Mixed valid+invalid packages',
61
- cmd: 'yarn manager-code-duplication --packages @ovh-ux/manager-wiki,manager-react-components,@ovh-ux/manager-ghost-app',
61
+ cmd: 'yarn manager-code-duplication --packages @ovh-ux/manager-wiki,manager-ui-kit,@ovh-ux/manager-ghost-app',
62
62
  expect: 0,
63
63
  },
64
64
  {
package/bin/lint-cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawn } from 'node:child_process';
3
3
  import { existsSync } from 'node:fs';
4
+ import { createRequire } from 'node:module';
4
5
  import { dirname, join, resolve } from 'node:path';
5
6
  import process, { cwd, execPath } from 'node:process';
6
7
  import { fileURLToPath } from 'node:url';
7
- import { createRequire } from 'node:module';
8
8
 
9
9
  import { logError, logInfo } from './utils/log-utils.js';
10
10
 
@@ -44,16 +44,25 @@ const firstNonFlag = () => args.find((a) => !a.startsWith('--'));
44
44
 
45
45
  const hasExplicitConfig = hasFlag('--config');
46
46
  const localConfigCandidates = [
47
- 'eslint.config.ts', 'eslint.config.mts', 'eslint.config.cts',
48
- 'eslint.config.mjs', 'eslint.config.cjs', 'eslint.config.js',
47
+ 'eslint.config.ts',
48
+ 'eslint.config.mts',
49
+ 'eslint.config.cts',
50
+ 'eslint.config.mjs',
51
+ 'eslint.config.cjs',
52
+ 'eslint.config.js',
49
53
  ];
50
54
  const localConfigPath = localConfigCandidates
51
55
  .map((f) => join(userCwd, f))
52
56
  .find((p) => existsSync(p));
53
57
 
54
- const sharedDefaultPath = resolve(__dirname, '../dist/adapters/eslint/config/eslint-shared-config.js');
58
+ const sharedDefaultPath = resolve(
59
+ __dirname,
60
+ '../dist/adapters/eslint/config/eslint-shared-config.js',
61
+ );
55
62
 
56
- const configPath = hasExplicitConfig ? getFlagValue('--config') : (localConfigPath ?? sharedDefaultPath);
63
+ const configPath = hasExplicitConfig
64
+ ? getFlagValue('--config')
65
+ : (localConfigPath ?? sharedDefaultPath);
57
66
 
58
67
  // ---------------------------------------------------------------------------
59
68
  // Node preload for TS configs
@@ -67,14 +76,14 @@ if (needsTsx) {
67
76
  require.resolve('tsx');
68
77
  } catch {
69
78
  logError('[manager-lint] A TypeScript eslint config was detected, but "tsx" is not installed.');
70
- logError('Install it in @ovh-ux/manager-static-analysis-kit (or the invoking package) and retry.');
79
+ logError(
80
+ 'Install it in @ovh-ux/manager-static-analysis-kit (or the invoking package) and retry.',
81
+ );
71
82
  process.exit(1);
72
83
  }
73
84
  }
74
85
 
75
- const nodePreload = needsTsx
76
- ? (nodeMajor >= 20 ? ['--import', 'tsx'] : ['--loader', 'tsx'])
77
- : [];
86
+ const nodePreload = needsTsx ? (nodeMajor >= 20 ? ['--import', 'tsx'] : ['--loader', 'tsx']) : [];
78
87
 
79
88
  // ---------------------------------------------------------------------------
80
89
  // Build final ESLint argv
@@ -109,7 +118,14 @@ function run(procArgs) {
109
118
  if (hasFlag('--print-config')) {
110
119
  const target = firstNonFlag() ?? '.';
111
120
  logInfo('[manager-lint] Using config:', configPath);
112
- const code = await run([...nodePreload, eslintCli, '--config', configPath, '--print-config', target]);
121
+ const code = await run([
122
+ ...nodePreload,
123
+ eslintCli,
124
+ '--config',
125
+ configPath,
126
+ '--print-config',
127
+ target,
128
+ ]);
113
129
  process.exit(code);
114
130
  }
115
131
 
@@ -22,13 +22,13 @@ const cases = [
22
22
  expect: 0,
23
23
  },
24
24
  {
25
- name: 'Single library static path by folder name (manager-react-components)',
26
- cmd: 'yarn manager-perf-budgets --library manager-react-components',
25
+ name: 'Single library static path by folder name (manager-ui-kit)',
26
+ cmd: 'yarn manager-perf-budgets --library manager-ui-kit',
27
27
  expect: 0,
28
28
  },
29
29
  {
30
- name: 'Single library static path by package name (manager-react-components)',
31
- cmd: 'yarn manager-perf-budgets --library @ovh-ux/manager-react-components',
30
+ name: 'Single library static path by package name (manager-ui-kit)',
31
+ cmd: 'yarn manager-perf-budgets --library @ovh-ux/muk',
32
32
  expect: 0,
33
33
  },
34
34
  {
@@ -42,13 +42,13 @@ const cases = [
42
42
  expect: 0,
43
43
  },
44
44
  {
45
- name: 'Multiple libraries by folder names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
46
- cmd: 'yarn manager-perf-budgets --libraries manager-wiki,manager-react-components,shell-client,logs-to-customer',
45
+ name: 'Multiple libraries by folder names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
46
+ cmd: 'yarn manager-perf-budgets --libraries manager-wiki,manager-ui-kit,shell-client,logs-to-customer',
47
47
  expect: 0,
48
48
  },
49
49
  {
50
- name: 'Multiple libraries by package names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
51
- cmd: 'yarn manager-perf-budgets --libraries @ovh-ux/manager-wiki,@ovh-ux/manager-react-components,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
50
+ name: 'Multiple libraries by package names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
51
+ cmd: 'yarn manager-perf-budgets --libraries @ovh-ux/manager-wiki,@ovh-ux/muk,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
52
52
  expect: 0,
53
53
  },
54
54
  {
@@ -58,7 +58,7 @@ const cases = [
58
58
  },
59
59
  {
60
60
  name: 'Mixed valid+invalid packages',
61
- cmd: 'yarn manager-perf-budgets --packages @ovh-ux/manager-wiki,manager-react-components,@ovh-ux/manager-ghost-app',
61
+ cmd: 'yarn manager-perf-budgets --packages @ovh-ux/manager-wiki,manager-ui-kit,@ovh-ux/manager-ghost-app',
62
62
  expect: 0,
63
63
  },
64
64
  {
@@ -22,13 +22,13 @@ const cases = [
22
22
  expect: 0,
23
23
  },
24
24
  {
25
- name: 'Single library static path by folder name (manager-react-components)',
26
- cmd: 'yarn manager-tests-coverage --library manager-react-components',
25
+ name: 'Single library static path by folder name (manager-ui-kit)',
26
+ cmd: 'yarn manager-tests-coverage --library manager-ui-kit',
27
27
  expect: 0,
28
28
  },
29
29
  {
30
- name: 'Single library static path by package name (manager-react-components)',
31
- cmd: 'yarn manager-tests-coverage --library @ovh-ux/manager-react-components',
30
+ name: 'Single library static path by package name (manager-ui-kit)',
31
+ cmd: 'yarn manager-tests-coverage --library @ovh-ux/muk',
32
32
  expect: 0,
33
33
  },
34
34
  {
@@ -42,13 +42,13 @@ const cases = [
42
42
  expect: 0,
43
43
  },
44
44
  {
45
- name: 'Multiple libraries by folder names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
46
- cmd: 'yarn manager-tests-coverage --libraries manager-wiki,manager-react-components,shell-client,logs-to-customer',
45
+ name: 'Multiple libraries by folder names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
46
+ cmd: 'yarn manager-tests-coverage --libraries manager-wiki,manager-ui-kit,shell-client,logs-to-customer',
47
47
  expect: 0,
48
48
  },
49
49
  {
50
- name: 'Multiple libraries by package names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
51
- cmd: 'yarn manager-tests-coverage --libraries @ovh-ux/manager-wiki,@ovh-ux/manager-react-components,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
50
+ name: 'Multiple libraries by package names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
51
+ cmd: 'yarn manager-tests-coverage --libraries @ovh-ux/manager-wiki,@ovh-ux/muk,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
52
52
  expect: 0,
53
53
  },
54
54
  {
@@ -58,7 +58,7 @@ const cases = [
58
58
  },
59
59
  {
60
60
  name: 'Mixed valid+invalid packages',
61
- cmd: 'yarn manager-tests-coverage --packages @ovh-ux/manager-wiki,manager-react-components,@ovh-ux/manager-ghost-app',
61
+ cmd: 'yarn manager-tests-coverage --packages @ovh-ux/manager-wiki,manager-ui-kit,@ovh-ux/manager-ghost-app',
62
62
  expect: 0,
63
63
  },
64
64
  {
@@ -14,6 +14,7 @@ import {
14
14
  typesCoverageCombinedJsonReportName,
15
15
  typesCoverageOutputRootDir,
16
16
  typesCoverageReportsRootDirName,
17
+ typesSpecificIgnorePatterns,
17
18
  } from './cli-path-config.js';
18
19
  import { buildTypesCoverageArgs, parseCliTargets } from './utils/args-parse-utils.js';
19
20
  import { logError, logInfo, logWarn } from './utils/log-utils.js';
@@ -102,12 +103,18 @@ export function countLooseTypes(appDir) {
102
103
  visit(source);
103
104
  }
104
105
 
106
+ function shouldIgnore(filePath) {
107
+ return typesSpecificIgnorePatterns.some((re) => re.test(filePath));
108
+ }
109
+
105
110
  function walk(dir) {
106
111
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
107
112
  const fullPath = path.join(dir, entry.name);
108
113
  if (entry.isDirectory()) {
114
+ if (shouldIgnore(fullPath)) continue;
109
115
  walk(fullPath);
110
116
  } else if (/\.(ts|tsx)$/.test(entry.name)) {
117
+ if (shouldIgnore(fullPath)) continue;
111
118
  analyzeFile(fullPath);
112
119
  }
113
120
  }
@@ -22,13 +22,13 @@ const cases = [
22
22
  expect: 0,
23
23
  },
24
24
  {
25
- name: 'Single library static path by folder name (manager-react-components)',
26
- cmd: 'yarn manager-types-coverage --library manager-react-components',
25
+ name: 'Single library static path by folder name (manager-ui-kit)',
26
+ cmd: 'yarn manager-types-coverage --library manager-ui-kit',
27
27
  expect: 0,
28
28
  },
29
29
  {
30
- name: 'Single library static path by package name (manager-react-components)',
31
- cmd: 'yarn manager-types-coverage --library @ovh-ux/manager-react-components',
30
+ name: 'Single library static path by package name (manager-ui-kit)',
31
+ cmd: 'yarn manager-types-coverage --library @ovh-ux/muk',
32
32
  expect: 0,
33
33
  },
34
34
  {
@@ -42,13 +42,13 @@ const cases = [
42
42
  expect: 0,
43
43
  },
44
44
  {
45
- name: 'Multiple libraries by folder names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
46
- cmd: 'yarn manager-types-coverage --libraries manager-wiki,manager-react-components,shell-client,logs-to-customer',
45
+ name: 'Multiple libraries by folder names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
46
+ cmd: 'yarn manager-types-coverage --libraries manager-wiki,manager-ui-kit,shell-client,logs-to-customer',
47
47
  expect: 0,
48
48
  },
49
49
  {
50
- name: 'Multiple libraries by package names (manager-wiki,manager-react-components,shell-client,logs-to-customer)',
51
- cmd: 'yarn manager-types-coverage --libraries @ovh-ux/manager-wiki,@ovh-ux/manager-react-components,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
50
+ name: 'Multiple libraries by package names (manager-wiki,manager-ui-kit,shell-client,logs-to-customer)',
51
+ cmd: 'yarn manager-types-coverage --libraries @ovh-ux/manager-wiki,@ovh-ux/muk,@ovh-ux/manager-react-shell-client,@ovh-ux/logs-to-customer',
52
52
  expect: 0,
53
53
  },
54
54
  {
@@ -58,7 +58,7 @@ const cases = [
58
58
  },
59
59
  {
60
60
  name: 'Mixed valid+invalid packages',
61
- cmd: 'yarn manager-types-coverage --packages @ovh-ux/manager-wiki,manager-react-components,@ovh-ux/manager-ghost-app',
61
+ cmd: 'yarn manager-types-coverage --packages @ovh-ux/manager-wiki,manager-ui-kit,@ovh-ux/manager-ghost-app',
62
62
  expect: 0,
63
63
  },
64
64
  {
@@ -2,6 +2,7 @@ import process from 'node:process';
2
2
 
3
3
  import { codeDuplicationConfig } from '../../dist/configs/code-duplication-config.js';
4
4
  import { typesCoverageConfig } from '../../dist/configs/types-coverage-config.js';
5
+ import { staticDiscoveredLibraries } from '../cli-path-config.js';
5
6
  import { logError, logInfo } from './log-utils.js';
6
7
  import { discoverModules, getModule } from './module-utils.js';
7
8
 
@@ -44,7 +45,7 @@ import { discoverModules, getModule } from './module-utils.js';
44
45
  * parseArgs();
45
46
  * // → [
46
47
  * // { fullPath: "/.../packages/manager/core/core-shell", shortPath: "core-shell", packageName: "@ovh-ux/manager-core-shell" },
47
- * // { fullPath: "/.../packages/components/react-components", shortPath: "react-components", packageName: "@ovh-ux/manager-react-components" }
48
+ * // { fullPath: "/.../packages/components/react-components", shortPath: "react-components", packageName: "@ovh-ux/muk" }
48
49
  * // ]
49
50
  */
50
51
  export function parseArgs() {
@@ -54,7 +55,7 @@ export function parseArgs() {
54
55
 
55
56
  const moduleModeArgs = libsArg || packagesArg || appsArg;
56
57
 
57
- if (!moduleModeArgs) return discoverModules(false);
58
+ if (!moduleModeArgs) return [...discoverModules(false), ...staticDiscoveredLibraries];
58
59
 
59
60
  const index = process.argv.indexOf(moduleModeArgs);
60
61
  const rawValue = process.argv[index + 1] || '';
@@ -1,5 +1,5 @@
1
1
  import { CombinedCodeDuplicationSummary, JscpdReportV4, WorstCodeDuplicationFile } from '../types/CodeDuplication.js';
2
- export declare const extPriority: (file: string) => number;
2
+ export declare const buildExtensionPriority: (file: string) => number;
3
3
  export declare function extractWorstFiles(report: JscpdReportV4): {
4
4
  files: WorstCodeDuplicationFile[];
5
5
  fileCount: number;
@@ -1 +1 @@
1
- {"version":3,"file":"code-duplication-analysis-helper.d.ts","sourceRoot":"","sources":["../../../../src/adapters/code-duplication/helpers/code-duplication-analysis-helper.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,8BAA8B,EAC9B,aAAa,EACb,wBAAwB,EAEzB,MAAM,0BAA0B,CAAC;AAUlC,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,MAc1C,CAAC;AAmEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG;IACxD,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB,CAwEA;AA4ED,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,MAAM,GAAG,8BAA8B,CA+B9F;AAsGD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,8BAA8B,GAAG,MAAM,CAyD3F"}
1
+ {"version":3,"file":"code-duplication-analysis-helper.d.ts","sourceRoot":"","sources":["../../../../src/adapters/code-duplication/helpers/code-duplication-analysis-helper.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,8BAA8B,EAC9B,aAAa,EACb,wBAAwB,EAEzB,MAAM,0BAA0B,CAAC;AAelC,eAAO,MAAM,sBAAsB,GAAI,MAAM,MAAM,KAAG,MAMrD,CAAC;AAmBF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa;;;EAsDtD;AAyED,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,MAAM,GAAG,8BAA8B,CA+B9F;AAOD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,8BAA8B,GAAG,MAAM,CAQ3F"}
@@ -1,7 +1,8 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { codeDuplicationConfig } from '../../../configs/code-duplication-config.js';
4
- export const extPriority = (file) => {
4
+ import { buildDuplicationReportBody, buildDuplicationReportHead, } from './code-duplication-reports-render.js';
5
+ export const buildExtensionPriority = (file) => {
5
6
  const f = file.toLowerCase();
6
7
  if (/\.(d\.ts)$/.test(f))
7
8
  return 2;
@@ -11,7 +12,7 @@ export const extPriority = (file) => {
11
12
  return 1;
12
13
  return 2;
13
14
  };
14
- const safeCountLines = (file) => {
15
+ const countRealLines = (file) => {
15
16
  try {
16
17
  const txt = fs.readFileSync(file, 'utf8');
17
18
  return txt.split(/\r?\n/).length;
@@ -20,15 +21,6 @@ const safeCountLines = (file) => {
20
21
  return 0;
21
22
  }
22
23
  };
23
- function shortPathFromAppsRoot(filePath, app) {
24
- const norm = filePath.replace(/\\/g, '/');
25
- const appsIdx = norm.indexOf('/apps/');
26
- if (appsIdx >= 0) {
27
- return norm.slice(appsIdx + 1);
28
- }
29
- const parts = norm.split('/');
30
- return parts.slice(Math.max(0, parts.length - 5)).join('/');
31
- }
32
24
  export function extractWorstFiles(report) {
33
25
  const dups = Array.isArray(report?.duplicates) ? report.duplicates : [];
34
26
  if (dups.length === 0)
@@ -52,7 +44,7 @@ export function extractWorstFiles(report) {
52
44
  }
53
45
  }
54
46
  for (const file of Object.keys(fileMap)) {
55
- const realTotal = safeCountLines(file);
47
+ const realTotal = countRealLines(file);
56
48
  const estTotal = fileMap[file].estimatedTotal;
57
49
  fileMap[file].total = Math.max(realTotal || estTotal || 0, fileMap[file].dup);
58
50
  }
@@ -68,19 +60,17 @@ export function extractWorstFiles(report) {
68
60
  })
69
61
  .filter(([, s]) => s.percentage >= threshold)
70
62
  .sort((a, b) => {
71
- const pa = extPriority(a[0]);
72
- const pb = extPriority(b[0]);
63
+ const pa = buildExtensionPriority(a[0]);
64
+ const pb = buildExtensionPriority(b[0]);
73
65
  if (pa !== pb)
74
66
  return pa - pb;
75
67
  const pct = b[1].percentage - a[1].percentage;
76
68
  if (pct !== 0)
77
69
  return pct;
78
- if (b[1].duplicatedLines !== a[1].duplicatedLines) {
70
+ if (b[1].duplicatedLines !== a[1].duplicatedLines)
79
71
  return b[1].duplicatedLines - a[1].duplicatedLines;
80
- }
81
- if (b[1].totalLines !== a[1].totalLines) {
72
+ if (b[1].totalLines !== a[1].totalLines)
82
73
  return b[1].totalLines - a[1].totalLines;
83
- }
84
74
  return a[0].localeCompare(b[0]);
85
75
  })
86
76
  .slice(0, count);
@@ -126,7 +116,7 @@ function parseAppCodeDuplicationReport(jsonPath) {
126
116
  };
127
117
  }
128
118
  }
129
- function aggregateTotals(apps) {
119
+ function aggregateDuplicationTotals(apps) {
130
120
  return Object.values(apps).reduce((acc, app) => {
131
121
  acc.totalLines += app.totalLines;
132
122
  acc.totalTokens += app.totalTokens;
@@ -156,139 +146,19 @@ export function collectCodeDuplication(reportOutputDir) {
156
146
  apps[appDirName] = parseAppCodeDuplicationReport(jsonPath);
157
147
  }
158
148
  }
159
- const totals = aggregateTotals(apps);
149
+ const totals = aggregateDuplicationTotals(apps);
160
150
  return {
161
151
  apps,
162
152
  ...totals,
163
153
  percentage: totals.totalLines > 0 ? (totals.totalDuplicateLines / totals.totalLines) * 100 : 0,
164
154
  };
165
155
  }
166
- const getColorForDuplicationStatus = (pct) => {
167
- const green = codeDuplicationConfig.thresholds?.green ?? 10;
168
- const orange = codeDuplicationConfig.thresholds?.orange ?? 20;
169
- return pct < green ? 'green' : pct < orange ? 'orange' : 'red';
170
- };
171
- function renderWorstFiles(app, worstFiles = []) {
172
- const threshold = codeDuplicationConfig.worstFiles.threshold;
173
- if (!worstFiles.length) {
174
- return `
175
- <details class="coverage-details">
176
- <summary>📊 Duplication Overview for <strong>${app}</strong></summary>
177
- <p class="coverage-empty">No files above threshold 🎉</p>
178
- </details>`;
179
- }
180
- const rows = worstFiles
181
- .map(([file, f]) => {
182
- const short = shortPathFromAppsRoot(file, app);
183
- const color = getColorForDuplicationStatus(f.percentage);
184
- return `
185
- <tr>
186
- <td colspan="2" title="${file}">${short}</td>
187
- <td>${f.duplicatedLines}/${f.totalLines}</td>
188
- <td style="color:${color}">${f.percentage.toFixed(2)}%</td>
189
- </tr>`;
190
- })
191
- .join('');
192
- return `
193
- <details class="coverage-details">
194
- <summary>📊 Duplication Overview for <strong>${app}</strong> (≥ ${threshold}%)</summary>
195
- <table class="coverage-subtable">
196
- <tbody>${rows}</tbody>
197
- </table>
198
- </details>`;
199
- }
200
- function renderDuplicationCell(stats) {
201
- const min = stats.minPercentage ?? stats.percentage;
202
- const max = stats.maxPercentage ?? stats.percentage;
203
- if (stats.duplicateLines === 0) {
204
- return `<span style="color:${getColorForDuplicationStatus(0)}">0.00%</span>`;
205
- }
206
- if (min.toFixed(2) === max.toFixed(2)) {
207
- return `
208
- ${stats.percentage.toFixed(2)}% (${stats.filesWithDuplication} files cluster at
209
- <span style="color:${getColorForDuplicationStatus(min)}">${min.toFixed(2)}%</span>)
210
- `;
211
- }
212
- return `
213
- ${stats.percentage.toFixed(2)}% (range:
214
- <span style="color:${getColorForDuplicationStatus(min)}">${min.toFixed(2)}%</span> –
215
- <span style="color:${getColorForDuplicationStatus(max)}">${max.toFixed(2)}%</span>)
216
- `;
217
- }
218
- function buildAppRow(app, stats) {
219
- if (stats.error) {
220
- return `<tr style="background:#ffe0e0">
221
- <td>${app}</td>
222
- <td colspan="5" style="color:red">${stats.error}</td>
223
- </tr>`;
224
- }
225
- const max = stats.maxPercentage ?? stats.percentage;
226
- const rowColor = getColorForDuplicationStatus(max);
227
- const bg = rowColor === 'green' ? '#e6ffed' : rowColor === 'orange' ? '#fff8e1' : '#ffe6e6';
228
- return `
229
- <tr style="background:${bg}">
230
- <td>${app}</td>
231
- <td>${stats.totalLines}</td>
232
- <td>${stats.duplicateLines}</td>
233
- <td>${stats.clonesCount}</td>
234
- <td style="font-weight:bold;">${renderDuplicationCell(stats)}</td>
235
- </tr>
236
- <tr><td colspan="5">${renderWorstFiles(app, stats.worstFiles)}</td></tr>`;
237
- }
238
156
  export function generateCodeDuplicationHtml(summary) {
239
- const rows = Object.entries(summary.apps)
240
- .map(([app, stats]) => buildAppRow(app, stats))
241
- .join('');
242
- return `<!DOCTYPE html>
157
+ return `
158
+ <!DOCTYPE html>
243
159
  <html lang="en">
244
- <head>
245
- <meta charset="UTF-8"/>
246
- <title>Code Duplication Report</title>
247
- <style>
248
- body { font-family: Arial, sans-serif; margin: 2rem; }
249
- table { border-collapse: collapse; width: 100%; }
250
- th, td { border: 1px solid #ccc; padding: 0.5rem; text-align: left; }
251
- th { background: #f0f0f0; }
252
- .coverage-details {
253
- margin: 0.3rem 0 0.8rem 1.5rem;
254
- padding: 0.5rem;
255
- border-left: 3px solid #ccc;
256
- background: #fafafa;
257
- border-radius: 4px;
258
- }
259
- .coverage-details summary {
260
- font-weight: bold;
261
- cursor: pointer;
262
- }
263
- .coverage-subtable {
264
- margin-top: 0.5rem;
265
- border: 1px solid #ddd;
266
- width: 95%;
267
- font-size: 0.9em;
268
- }
269
- .coverage-empty {
270
- margin: 0.5rem 0;
271
- color: #888;
272
- font-style: italic;
273
- }
274
- </style>
275
- </head>
276
- <body>
277
- <h1>Code Duplication Report</h1>
278
- <p>Total lines: ${summary.totalLines}, Duplicate lines: ${summary.totalDuplicateLines},
279
- Percentage: ${summary.percentage.toFixed(2)}%</p>
280
- <table>
281
- <thead>
282
- <tr>
283
- <th>App</th>
284
- <th>Total lines</th>
285
- <th>Duplicate lines</th>
286
- <th>Clones</th>
287
- <th>Duplication %</th>
288
- </tr>
289
- </thead>
290
- <tbody>${rows}</tbody>
291
- </table>
292
- </body>
293
- </html>`;
160
+ ${buildDuplicationReportHead()}
161
+ ${buildDuplicationReportBody(summary)}
162
+ </html>
163
+ `.trim();
294
164
  }
@@ -0,0 +1,4 @@
1
+ import { CombinedCodeDuplicationSummary } from '../types/CodeDuplication.js';
2
+ export declare function buildDuplicationReportHead(): string;
3
+ export declare function buildDuplicationReportBody(summary: CombinedCodeDuplicationSummary): string;
4
+ //# sourceMappingURL=code-duplication-reports-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-duplication-reports-render.d.ts","sourceRoot":"","sources":["../../../../src/adapters/code-duplication/helpers/code-duplication-reports-render.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,8BAA8B,EAC/B,MAAM,0BAA0B,CAAC;AA4HlC,wBAAgB,0BAA0B,IAAI,MAAM,CAgCnD;AAOD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,8BAA8B,GAAG,MAAM,CA0B1F"}