Skip to content

Commit 1686dda

Browse files
authored
feat(plugin-jsdocs): add plugin-jsdocs to analyze documentation in ts/js projects (code-pushup#896)
1 parent 053d595 commit 1686dda

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2991
-0
lines changed

code-pushup.config.ts

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { z } from 'zod';
33
import {
44
coverageCoreConfigNx,
55
eslintCoreConfigNx,
6+
jsDocsCoreConfig,
67
jsPackagesCoreConfig,
78
lighthouseCoreConfig,
89
} from './code-pushup.preset.js';
@@ -39,4 +40,12 @@ export default mergeConfigs(
3940
'https://github.com/code-pushup/cli?tab=readme-ov-file#code-pushup-cli/',
4041
),
4142
await eslintCoreConfigNx(),
43+
jsDocsCoreConfig([
44+
'packages/**/src/**/*.ts',
45+
'!packages/**/node_modules',
46+
'!packages/**/{mocks,mock}',
47+
'!**/*.{spec,test}.ts',
48+
'!**/implementation/**',
49+
'!**/internal/**',
50+
]),
4251
);

code-pushup.preset.ts

+39
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ import eslintPlugin, {
1010
eslintConfigFromNxProject,
1111
} from './packages/plugin-eslint/src/index.js';
1212
import jsPackagesPlugin from './packages/plugin-js-packages/src/index.js';
13+
import jsDocsPlugin, {
14+
JsDocsPluginConfig,
15+
} from './packages/plugin-jsdocs/src/index.js';
16+
import {
17+
PLUGIN_SLUG,
18+
groups,
19+
} from './packages/plugin-jsdocs/src/lib/constants.js';
20+
import { filterGroupsByOnlyAudits } from './packages/plugin-jsdocs/src/lib/utils.js';
1321
import lighthousePlugin, {
1422
lighthouseGroupRef,
1523
} from './packages/plugin-lighthouse/src/index.js';
@@ -82,6 +90,24 @@ export const eslintCategories: CategoryConfig[] = [
8290
},
8391
];
8492

93+
export function getJsDocsCategories(
94+
config: JsDocsPluginConfig,
95+
): CategoryConfig[] {
96+
return [
97+
{
98+
slug: 'docs',
99+
title: 'Documentation',
100+
description: 'Measures how much of your code is **documented**.',
101+
refs: filterGroupsByOnlyAudits(groups, config).map(group => ({
102+
weight: 1,
103+
type: 'group',
104+
plugin: PLUGIN_SLUG,
105+
slug: group.slug,
106+
})),
107+
},
108+
];
109+
}
110+
85111
export const coverageCategories: CategoryConfig[] = [
86112
{
87113
slug: 'code-coverage',
@@ -114,6 +140,19 @@ export const lighthouseCoreConfig = async (
114140
};
115141
};
116142

143+
export const jsDocsCoreConfig = (
144+
config: JsDocsPluginConfig | string[],
145+
): CoreConfig => {
146+
return {
147+
plugins: [
148+
jsDocsPlugin(Array.isArray(config) ? { patterns: config } : config),
149+
],
150+
categories: getJsDocsCategories(
151+
Array.isArray(config) ? { patterns: config } : config,
152+
),
153+
};
154+
};
155+
117156
export const eslintCoreConfigNx = async (
118157
projectName?: string,
119158
): Promise<CoreConfig> => {
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import tseslint from 'typescript-eslint';
2+
import baseConfig from '../../eslint.config.js';
3+
4+
export default tseslint.config(...baseConfig, {
5+
files: ['**/*.ts'],
6+
languageOptions: {
7+
parserOptions: {
8+
projectService: true,
9+
tsconfigRootDir: import.meta.dirname,
10+
},
11+
},
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import jsDocsPlugin from '@code-pushup/jsdocs-plugin';
2+
3+
export default {
4+
plugins: [jsDocsPlugin(['**/*.ts'])],
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
h1 {
2+
color: #336699;
3+
text-align: center;
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>{{ title }}</h1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function notRealisticFunction() {
2+
return 'notRealisticFunction';
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Basic Angular component that displays a welcome message
3+
*/
4+
export class AppComponent {
5+
protected readonly title = 'My Angular App';
6+
7+
/**
8+
* Dummy method that returns a welcome message
9+
* @returns {string} - The welcome message
10+
*/
11+
getWelcomeMessage() {
12+
return 'Welcome to My Angular App!';
13+
}
14+
15+
sendEvent() {
16+
return 'Event sent';
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const someVariable = 'Hello World 1';
2+
3+
export function mapEventToCustomEvent(event: string) {
4+
return event;
5+
}
6+
7+
/** Commented */
8+
export function mapCustomEventToEvent(event: string) {
9+
return event;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import jsDocsPlugin from '@code-pushup/jsdocs-plugin';
2+
3+
export default {
4+
plugins: [jsDocsPlugin(['**/*.ts'])],
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function MyComponent() {
2+
return (
3+
<div>
4+
<h1>Hello World</h1>
5+
<p>This is a basic React component</p>
6+
</div>
7+
);
8+
}
9+
10+
export default MyComponent;

e2e/plugin-jsdocs-e2e/project.json

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "plugin-jsdocs-e2e",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "e2e/plugin-jsdocs-e2e/src",
5+
"projectType": "application",
6+
"tags": ["scope:plugin", "type:e2e"],
7+
"implicitDependencies": ["cli", "plugin-jsdocs"],
8+
"targets": {
9+
"lint": {
10+
"executor": "@nx/linter:eslint",
11+
"outputs": ["{options.outputFile}"],
12+
"options": {
13+
"lintFilePatterns": ["e2e/plugin-jsdocs-e2e/**/*.ts"]
14+
}
15+
},
16+
"e2e": {
17+
"executor": "@nx/vite:test",
18+
"options": {
19+
"configFile": "e2e/plugin-jsdocs-e2e/vite.config.e2e.ts"
20+
}
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
{
2+
"packageName": "@code-pushup/core",
3+
"plugins": [
4+
{
5+
"title": "JSDoc coverage",
6+
"slug": "jsdocs",
7+
"icon": "folder-docs",
8+
"description": "Official Code PushUp JSDoc coverage plugin.",
9+
"docsUrl": "https://www.npmjs.com/package/@code-pushup/jsdocs-plugin/",
10+
"groups": [
11+
{
12+
"slug": "documentation-coverage",
13+
"refs": [
14+
{
15+
"slug": "classes-coverage",
16+
"weight": 2
17+
},
18+
{
19+
"slug": "methods-coverage",
20+
"weight": 2
21+
},
22+
{
23+
"slug": "functions-coverage",
24+
"weight": 2
25+
},
26+
{
27+
"slug": "interfaces-coverage",
28+
"weight": 1
29+
},
30+
{
31+
"slug": "variables-coverage",
32+
"weight": 1
33+
},
34+
{
35+
"slug": "properties-coverage",
36+
"weight": 1
37+
},
38+
{
39+
"slug": "types-coverage",
40+
"weight": 1
41+
},
42+
{
43+
"slug": "enums-coverage",
44+
"weight": 1
45+
}
46+
],
47+
"title": "Documentation coverage",
48+
"description": "Documentation coverage"
49+
}
50+
],
51+
"audits": [
52+
{
53+
"slug": "enums-coverage",
54+
"displayValue": "0 undocumented enums",
55+
"value": 0,
56+
"score": 1,
57+
"details": {
58+
"issues": []
59+
},
60+
"title": "Enums coverage",
61+
"description": "Documentation coverage of enums"
62+
},
63+
{
64+
"slug": "interfaces-coverage",
65+
"displayValue": "0 undocumented interfaces",
66+
"value": 0,
67+
"score": 1,
68+
"details": {
69+
"issues": []
70+
},
71+
"title": "Interfaces coverage",
72+
"description": "Documentation coverage of interfaces"
73+
},
74+
{
75+
"slug": "types-coverage",
76+
"displayValue": "0 undocumented types",
77+
"value": 0,
78+
"score": 1,
79+
"details": {
80+
"issues": []
81+
},
82+
"title": "Types coverage",
83+
"description": "Documentation coverage of types"
84+
},
85+
{
86+
"slug": "functions-coverage",
87+
"displayValue": "2 undocumented functions",
88+
"value": 2,
89+
"score": 0.3333,
90+
"details": {
91+
"issues": [
92+
{
93+
"message": "Missing functions documentation for notRealisticFunction",
94+
"severity": "warning",
95+
"source": {
96+
"file": "tmp/e2e/plugin-jsdocs-e2e/__test__/angular/src/app.component.spec.ts",
97+
"position": {
98+
"startLine": 1
99+
}
100+
}
101+
},
102+
{
103+
"message": "Missing functions documentation for mapEventToCustomEvent",
104+
"severity": "warning",
105+
"source": {
106+
"file": "tmp/e2e/plugin-jsdocs-e2e/__test__/angular/src/map-event.function.ts",
107+
"position": {
108+
"startLine": 3
109+
}
110+
}
111+
}
112+
]
113+
},
114+
"title": "Functions coverage",
115+
"description": "Documentation coverage of functions"
116+
},
117+
{
118+
"slug": "variables-coverage",
119+
"displayValue": "1 undocumented variables",
120+
"value": 1,
121+
"score": 0,
122+
"details": {
123+
"issues": [
124+
{
125+
"message": "Missing variables documentation for someVariable",
126+
"severity": "warning",
127+
"source": {
128+
"file": "tmp/e2e/plugin-jsdocs-e2e/__test__/angular/src/map-event.function.ts",
129+
"position": {
130+
"startLine": 1
131+
}
132+
}
133+
}
134+
]
135+
},
136+
"title": "Variables coverage",
137+
"description": "Documentation coverage of variables"
138+
},
139+
{
140+
"slug": "classes-coverage",
141+
"displayValue": "0 undocumented classes",
142+
"value": 0,
143+
"score": 1,
144+
"details": {
145+
"issues": []
146+
},
147+
"title": "Classes coverage",
148+
"description": "Documentation coverage of classes"
149+
},
150+
{
151+
"slug": "methods-coverage",
152+
"displayValue": "1 undocumented methods",
153+
"value": 1,
154+
"score": 0.5,
155+
"details": {
156+
"issues": [
157+
{
158+
"message": "Missing methods documentation for sendEvent",
159+
"severity": "warning",
160+
"source": {
161+
"file": "tmp/e2e/plugin-jsdocs-e2e/__test__/angular/src/app.component.ts",
162+
"position": {
163+
"startLine": 15
164+
}
165+
}
166+
}
167+
]
168+
},
169+
"title": "Methods coverage",
170+
"description": "Documentation coverage of methods"
171+
},
172+
{
173+
"slug": "properties-coverage",
174+
"displayValue": "1 undocumented properties",
175+
"value": 1,
176+
"score": 0,
177+
"details": {
178+
"issues": [
179+
{
180+
"message": "Missing properties documentation for title",
181+
"severity": "warning",
182+
"source": {
183+
"file": "tmp/e2e/plugin-jsdocs-e2e/__test__/angular/src/app.component.ts",
184+
"position": {
185+
"startLine": 5
186+
}
187+
}
188+
}
189+
]
190+
},
191+
"title": "Properties coverage",
192+
"description": "Documentation coverage of properties"
193+
}
194+
]
195+
}
196+
]
197+
}

0 commit comments

Comments
 (0)