@code-pushup/utils 0.56.0 → 0.57.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/package.json +12 -7
- package/src/index.d.ts +30 -29
- package/src/index.js +30 -0
- package/src/index.js.map +1 -0
- package/src/lib/diff.js +38 -0
- package/src/lib/diff.js.map +1 -0
- package/src/lib/errors.js +14 -0
- package/src/lib/errors.js.map +1 -0
- package/src/lib/execute-process.d.ts +0 -1
- package/src/lib/execute-process.js +101 -0
- package/src/lib/execute-process.js.map +1 -0
- package/src/lib/file-system.d.ts +5 -5
- package/src/lib/file-system.js +113 -0
- package/src/lib/file-system.js.map +1 -0
- package/src/lib/filter.js +10 -0
- package/src/lib/filter.js.map +1 -0
- package/src/lib/formatting.js +83 -0
- package/src/lib/formatting.js.map +1 -0
- package/src/lib/git/git.commits-and-tags.js +148 -0
- package/src/lib/git/git.commits-and-tags.js.map +1 -0
- package/src/lib/git/git.d.ts +2 -2
- package/src/lib/git/git.js +58 -0
- package/src/lib/git/git.js.map +1 -0
- package/src/lib/group-by-status.js +6 -0
- package/src/lib/group-by-status.js.map +1 -0
- package/src/lib/guards.d.ts +2 -0
- package/src/lib/guards.js +10 -0
- package/src/lib/guards.js.map +1 -0
- package/src/lib/log-results.js +28 -0
- package/src/lib/log-results.js.map +1 -0
- package/src/lib/logging.js +33 -0
- package/src/lib/logging.js.map +1 -0
- package/src/lib/merge-configs.js +104 -0
- package/src/lib/merge-configs.js.map +1 -0
- package/src/lib/progress.js +57 -0
- package/src/lib/progress.js.map +1 -0
- package/src/lib/reports/constants.js +19 -0
- package/src/lib/reports/constants.js.map +1 -0
- package/src/lib/reports/environment-type.d.ts +1 -1
- package/src/lib/reports/environment-type.js +17 -0
- package/src/lib/reports/environment-type.js.map +1 -0
- package/src/lib/reports/flatten-plugins.js +8 -0
- package/src/lib/reports/flatten-plugins.js.map +1 -0
- package/src/lib/reports/formatting.d.ts +1 -1
- package/src/lib/reports/formatting.js +105 -0
- package/src/lib/reports/formatting.js.map +1 -0
- package/src/lib/reports/generate-md-report-categoy-section.d.ts +1 -1
- package/src/lib/reports/generate-md-report-categoy-section.js +63 -0
- package/src/lib/reports/generate-md-report-categoy-section.js.map +1 -0
- package/src/lib/reports/generate-md-report.d.ts +1 -1
- package/src/lib/reports/generate-md-report.js +116 -0
- package/src/lib/reports/generate-md-report.js.map +1 -0
- package/src/lib/reports/generate-md-reports-diff-utils.d.ts +1 -1
- package/src/lib/reports/generate-md-reports-diff-utils.js +117 -0
- package/src/lib/reports/generate-md-reports-diff-utils.js.map +1 -0
- package/src/lib/reports/generate-md-reports-diff.d.ts +1 -1
- package/src/lib/reports/generate-md-reports-diff.js +158 -0
- package/src/lib/reports/generate-md-reports-diff.js.map +1 -0
- package/src/lib/reports/load-report.js +15 -0
- package/src/lib/reports/load-report.js.map +1 -0
- package/src/lib/reports/log-stdout-summary.d.ts +1 -1
- package/src/lib/reports/log-stdout-summary.js +102 -0
- package/src/lib/reports/log-stdout-summary.js.map +1 -0
- package/src/lib/reports/scoring.d.ts +1 -1
- package/src/lib/reports/scoring.js +78 -0
- package/src/lib/reports/scoring.js.map +1 -0
- package/src/lib/reports/sorting.d.ts +1 -1
- package/src/lib/reports/sorting.js +91 -0
- package/src/lib/reports/sorting.js.map +1 -0
- package/src/lib/reports/types.js +7 -0
- package/src/lib/reports/types.js.map +1 -0
- package/src/lib/reports/utils.d.ts +1 -1
- package/src/lib/reports/utils.js +209 -0
- package/src/lib/reports/utils.js.map +1 -0
- package/src/lib/semver.js +17 -0
- package/src/lib/semver.js.map +1 -0
- package/src/lib/text-formats/constants.js +14 -0
- package/src/lib/text-formats/constants.js.map +1 -0
- package/src/lib/text-formats/html/details.js +20 -0
- package/src/lib/text-formats/html/details.js.map +1 -0
- package/src/lib/text-formats/html/font-style.js +13 -0
- package/src/lib/text-formats/html/font-style.js.map +1 -0
- package/src/lib/text-formats/html/link.js +4 -0
- package/src/lib/text-formats/html/link.js.map +1 -0
- package/src/lib/text-formats/html/table.js +27 -0
- package/src/lib/text-formats/html/table.js.map +1 -0
- package/src/lib/text-formats/index.d.ts +5 -5
- package/src/lib/text-formats/index.js +14 -0
- package/src/lib/text-formats/index.js.map +1 -0
- package/src/lib/text-formats/table.js +92 -0
- package/src/lib/text-formats/table.js.map +1 -0
- package/src/lib/transform.d.ts +1 -2
- package/src/lib/transform.js +111 -0
- package/src/lib/transform.js.map +1 -0
- package/src/lib/types.d.ts +3 -3
- package/src/lib/types.js +2 -0
- package/src/lib/types.js.map +1 -0
- package/src/lib/verbose-utils.js +20 -0
- package/src/lib/verbose-utils.js.map +1 -0
- package/src/lib/zod-validation.d.ts +3 -0
- package/src/lib/zod-validation.js +22 -0
- package/src/lib/zod-validation.js.map +1 -0
- package/index.js +0 -2980
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { MarkdownDocument, md, } from 'build-md';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { HIERARCHY } from '../text-formats/index.js';
|
|
4
|
+
import { columnsToStringArray, getColumnAlignments, rowToStringArray, } from '../text-formats/table.js';
|
|
5
|
+
import { getEnvironmentType, getGitHubBaseUrl, getGitLabBaseUrl, } from './environment-type.js';
|
|
6
|
+
export function tableSection(tableData, options) {
|
|
7
|
+
if (tableData.rows.length === 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const { level = HIERARCHY.level_4 } = options ?? {};
|
|
11
|
+
const columns = columnsToStringArray(tableData);
|
|
12
|
+
const alignments = getColumnAlignments(tableData);
|
|
13
|
+
const rows = rowToStringArray(tableData);
|
|
14
|
+
return new MarkdownDocument().heading(level, tableData.title).table(columns.map((heading, i) => {
|
|
15
|
+
const alignment = alignments[i];
|
|
16
|
+
if (alignment) {
|
|
17
|
+
return { heading, alignment };
|
|
18
|
+
}
|
|
19
|
+
return heading;
|
|
20
|
+
}), rows);
|
|
21
|
+
}
|
|
22
|
+
// @TODO extract `Pick<AuditReport, 'docsUrl' | 'description'>` to a reusable schema and type
|
|
23
|
+
export function metaDescription(audit) {
|
|
24
|
+
const docsUrl = audit.docsUrl;
|
|
25
|
+
const description = audit.description?.trim();
|
|
26
|
+
if (docsUrl) {
|
|
27
|
+
const docsLink = md.link(docsUrl, '📖 Docs');
|
|
28
|
+
if (!description) {
|
|
29
|
+
return docsLink;
|
|
30
|
+
}
|
|
31
|
+
const parsedDescription = description.endsWith('```')
|
|
32
|
+
? `${description}\n\n`
|
|
33
|
+
: `${description} `;
|
|
34
|
+
return md `${parsedDescription}${docsLink}`;
|
|
35
|
+
}
|
|
36
|
+
if (description && description.trim().length > 0) {
|
|
37
|
+
return description;
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Link to local source for IDE
|
|
43
|
+
* @param source
|
|
44
|
+
* @param reportLocation
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* linkToLocalSourceInIde({ file: 'src/index.ts' }, { outputDir: '.code-pushup' }) // [`src/index.ts`](../src/index.ts)
|
|
48
|
+
*/
|
|
49
|
+
export function linkToLocalSourceForIde(source, options) {
|
|
50
|
+
const { file, position } = source;
|
|
51
|
+
const { outputDir } = options ?? {};
|
|
52
|
+
// NOT linkable
|
|
53
|
+
if (!outputDir) {
|
|
54
|
+
return md.code(file);
|
|
55
|
+
}
|
|
56
|
+
return md.link(formatFileLink(file, position, outputDir), md.code(file));
|
|
57
|
+
}
|
|
58
|
+
export function formatSourceLine(position) {
|
|
59
|
+
if (!position) {
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
62
|
+
const { startLine, endLine } = position;
|
|
63
|
+
return endLine && startLine !== endLine
|
|
64
|
+
? `${startLine}-${endLine}`
|
|
65
|
+
: `${startLine}`;
|
|
66
|
+
}
|
|
67
|
+
export function formatGitHubLink(file, position) {
|
|
68
|
+
const baseUrl = getGitHubBaseUrl();
|
|
69
|
+
if (!position) {
|
|
70
|
+
return `${baseUrl}/${file}`;
|
|
71
|
+
}
|
|
72
|
+
const { startLine, endLine, startColumn, endColumn } = position;
|
|
73
|
+
const start = startColumn ? `L${startLine}C${startColumn}` : `L${startLine}`;
|
|
74
|
+
const end = endLine
|
|
75
|
+
? endColumn
|
|
76
|
+
? `L${endLine}C${endColumn}`
|
|
77
|
+
: `L${endLine}`
|
|
78
|
+
: '';
|
|
79
|
+
const lineRange = end && start !== end ? `${start}-${end}` : start;
|
|
80
|
+
return `${baseUrl}/${file}#${lineRange}`;
|
|
81
|
+
}
|
|
82
|
+
export function formatGitLabLink(file, position) {
|
|
83
|
+
const baseUrl = getGitLabBaseUrl();
|
|
84
|
+
if (!position) {
|
|
85
|
+
return `${baseUrl}/${file}`;
|
|
86
|
+
}
|
|
87
|
+
const { startLine, endLine } = position;
|
|
88
|
+
const lineRange = endLine && startLine !== endLine ? `${startLine}-${endLine}` : startLine;
|
|
89
|
+
return `${baseUrl}/${file}#L${lineRange}`;
|
|
90
|
+
}
|
|
91
|
+
export function formatFileLink(file, position, outputDir) {
|
|
92
|
+
const relativePath = path.posix.relative(outputDir, file);
|
|
93
|
+
const env = getEnvironmentType();
|
|
94
|
+
switch (env) {
|
|
95
|
+
case 'vscode':
|
|
96
|
+
return position ? `${relativePath}#L${position.startLine}` : relativePath;
|
|
97
|
+
case 'github':
|
|
98
|
+
return formatGitHubLink(file, position);
|
|
99
|
+
case 'gitlab':
|
|
100
|
+
return formatGitLabLink(file, position);
|
|
101
|
+
default:
|
|
102
|
+
return relativePath;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=formatting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatting.js","sourceRoot":"","sources":["../../../../../../packages/utils/src/lib/reports/formatting.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type InlineText, MarkdownDocument } from 'build-md';
|
|
2
2
|
import type { AuditReport } from '@code-pushup/models';
|
|
3
|
-
import type { ScoredGroup, ScoredReport } from './types';
|
|
3
|
+
import type { ScoredGroup, ScoredReport } from './types.js';
|
|
4
4
|
export declare function categoriesOverviewSection(report: Required<Pick<ScoredReport, 'plugins' | 'categories'>>): MarkdownDocument;
|
|
5
5
|
export declare function categoriesDetailsSection(report: Required<Pick<ScoredReport, 'plugins' | 'categories'>>): MarkdownDocument;
|
|
6
6
|
export declare function categoryRef({ title, score, value, displayValue }: AuditReport, pluginTitle: string): InlineText;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { MarkdownDocument, md } from 'build-md';
|
|
2
|
+
import { slugify } from '../formatting.js';
|
|
3
|
+
import { HIERARCHY } from '../text-formats/index.js';
|
|
4
|
+
import { metaDescription } from './formatting.js';
|
|
5
|
+
import { getSortableAuditByRef, getSortableGroupByRef } from './sorting.js';
|
|
6
|
+
import { countCategoryAudits, formatReportScore, getPluginNameFromSlug, scoreMarker, targetScoreIcon, } from './utils.js';
|
|
7
|
+
export function categoriesOverviewSection(report) {
|
|
8
|
+
const { categories, plugins } = report;
|
|
9
|
+
return new MarkdownDocument().table([
|
|
10
|
+
{ heading: '🏷 Category', alignment: 'left' },
|
|
11
|
+
{ heading: '⭐ Score', alignment: 'center' },
|
|
12
|
+
{ heading: '🛡 Audits', alignment: 'center' },
|
|
13
|
+
], categories.map(({ title, refs, score, isBinary }) => [
|
|
14
|
+
// @TODO refactor `isBinary: boolean` to `targetScore: number` #713
|
|
15
|
+
// The heading "ID" is inferred from the heading text in Markdown.
|
|
16
|
+
md.link(`#${slugify(title)}`, title),
|
|
17
|
+
md `${scoreMarker(score)} ${md.bold(formatReportScore(score))}${binaryIconSuffix(score, isBinary)}`,
|
|
18
|
+
countCategoryAudits(refs, plugins).toString(),
|
|
19
|
+
]));
|
|
20
|
+
}
|
|
21
|
+
export function categoriesDetailsSection(report) {
|
|
22
|
+
const { categories, plugins } = report;
|
|
23
|
+
return new MarkdownDocument()
|
|
24
|
+
.heading(HIERARCHY.level_2, '🏷 Categories')
|
|
25
|
+
.$foreach(categories, (doc, category) => doc
|
|
26
|
+
.heading(HIERARCHY.level_3, category.title)
|
|
27
|
+
.paragraph(metaDescription(category))
|
|
28
|
+
.paragraph(md `${scoreMarker(category.score)} Score: ${md.bold(formatReportScore(category.score))}${binaryIconSuffix(category.score, category.isBinary)}`)
|
|
29
|
+
.list(category.refs.map(ref => {
|
|
30
|
+
// Add group details
|
|
31
|
+
if (ref.type === 'group') {
|
|
32
|
+
const group = getSortableGroupByRef(ref, plugins);
|
|
33
|
+
const groupAudits = group.refs.map(groupRef => getSortableAuditByRef({ ...groupRef, plugin: group.plugin, type: 'audit' }, plugins));
|
|
34
|
+
const pluginTitle = getPluginNameFromSlug(ref.plugin, plugins);
|
|
35
|
+
return categoryGroupItem(group, groupAudits, pluginTitle);
|
|
36
|
+
}
|
|
37
|
+
// Add audit details
|
|
38
|
+
else {
|
|
39
|
+
const audit = getSortableAuditByRef(ref, plugins);
|
|
40
|
+
const pluginTitle = getPluginNameFromSlug(ref.plugin, plugins);
|
|
41
|
+
return categoryRef(audit, pluginTitle);
|
|
42
|
+
}
|
|
43
|
+
})));
|
|
44
|
+
}
|
|
45
|
+
export function categoryRef({ title, score, value, displayValue }, pluginTitle) {
|
|
46
|
+
const auditTitleAsLink = md.link(`#${slugify(title)}-${slugify(pluginTitle)}`, title);
|
|
47
|
+
const marker = scoreMarker(score, 'square');
|
|
48
|
+
return md `${marker} ${auditTitleAsLink} (${md.italic(pluginTitle)}) - ${md.bold((displayValue || value).toString())}`;
|
|
49
|
+
}
|
|
50
|
+
export function categoryGroupItem({ score = 0, title }, groupAudits, pluginTitle) {
|
|
51
|
+
const groupTitle = md `${scoreMarker(score)} ${title} (${md.italic(pluginTitle)})`;
|
|
52
|
+
const auditsList = md.list(groupAudits.map(({ title: auditTitle, score: auditScore, value, displayValue }) => {
|
|
53
|
+
const auditTitleLink = md.link(`#${slugify(auditTitle)}-${slugify(pluginTitle)}`, auditTitle);
|
|
54
|
+
const marker = scoreMarker(auditScore, 'square');
|
|
55
|
+
return md `${marker} ${auditTitleLink} - ${md.bold(String(displayValue ?? value))}`;
|
|
56
|
+
}));
|
|
57
|
+
return md `${groupTitle}${auditsList}`;
|
|
58
|
+
}
|
|
59
|
+
export function binaryIconSuffix(score, isBinary) {
|
|
60
|
+
// @TODO refactor `isBinary: boolean` to `targetScore: number` #713
|
|
61
|
+
return targetScoreIcon(score, isBinary ? 1 : undefined, { prefix: ' ' });
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=generate-md-report-categoy-section.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-md-report-categoy-section.js","sourceRoot":"","sources":["../../../../../../packages/utils/src/lib/reports/generate-md-report-categoy-section.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type InlineText, MarkdownDocument } from 'build-md';
|
|
2
2
|
import type { AuditReport, Issue, Report } from '@code-pushup/models';
|
|
3
|
-
import type { MdReportOptions, ScoredReport } from './types';
|
|
3
|
+
import type { MdReportOptions, ScoredReport } from './types.js';
|
|
4
4
|
export declare function auditDetailsAuditValue({ score, value, displayValue, }: AuditReport): InlineText;
|
|
5
5
|
export declare function generateMdReport(report: ScoredReport, options?: MdReportOptions): string;
|
|
6
6
|
export declare function auditDetailsIssues(issues?: Issue[], options?: MdReportOptions): MarkdownDocument | null;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { MarkdownDocument, md } from 'build-md';
|
|
2
|
+
import { formatDate, formatDuration } from '../formatting.js';
|
|
3
|
+
import { HIERARCHY } from '../text-formats/index.js';
|
|
4
|
+
import { FOOTER_PREFIX, README_LINK, REPORT_HEADLINE_TEXT, } from './constants.js';
|
|
5
|
+
import { formatSourceLine, linkToLocalSourceForIde, metaDescription, tableSection, } from './formatting.js';
|
|
6
|
+
import { categoriesDetailsSection, categoriesOverviewSection, } from './generate-md-report-categoy-section.js';
|
|
7
|
+
import { formatReportScore, scoreMarker, severityMarker } from './utils.js';
|
|
8
|
+
export function auditDetailsAuditValue({ score, value, displayValue, }) {
|
|
9
|
+
return md `${scoreMarker(score, 'square')} ${md.bold(String(displayValue ?? value))} (score: ${formatReportScore(score)})`;
|
|
10
|
+
}
|
|
11
|
+
function hasCategories(report) {
|
|
12
|
+
return !!report.categories && report.categories.length > 0;
|
|
13
|
+
}
|
|
14
|
+
export function generateMdReport(report, options) {
|
|
15
|
+
return new MarkdownDocument()
|
|
16
|
+
.heading(HIERARCHY.level_1, REPORT_HEADLINE_TEXT)
|
|
17
|
+
.$concat(...(hasCategories(report)
|
|
18
|
+
? [categoriesOverviewSection(report), categoriesDetailsSection(report)]
|
|
19
|
+
: []), auditsSection(report, options), aboutSection(report))
|
|
20
|
+
.rule()
|
|
21
|
+
.paragraph(md `${FOOTER_PREFIX} ${md.link(README_LINK, 'Code PushUp')}`)
|
|
22
|
+
.toString();
|
|
23
|
+
}
|
|
24
|
+
export function auditDetailsIssues(issues = [], options) {
|
|
25
|
+
if (issues.length === 0) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return new MarkdownDocument().heading(HIERARCHY.level_4, 'Issues').table([
|
|
29
|
+
{ heading: 'Severity', alignment: 'center' },
|
|
30
|
+
{ heading: 'Message', alignment: 'left' },
|
|
31
|
+
{ heading: 'Source file', alignment: 'left' },
|
|
32
|
+
{ heading: 'Line(s)', alignment: 'center' },
|
|
33
|
+
], issues.map(({ severity: level, message, source }) => {
|
|
34
|
+
const severity = md `${severityMarker(level)} ${md.italic(level)}`;
|
|
35
|
+
if (!source) {
|
|
36
|
+
return [severity, message];
|
|
37
|
+
}
|
|
38
|
+
const file = linkToLocalSourceForIde(source, options);
|
|
39
|
+
if (!source.position) {
|
|
40
|
+
return [severity, message, file];
|
|
41
|
+
}
|
|
42
|
+
const line = formatSourceLine(source.position);
|
|
43
|
+
return [severity, message, file, line];
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
export function auditDetails(audit, options) {
|
|
47
|
+
const { table, issues = [] } = audit.details ?? {};
|
|
48
|
+
const detailsValue = auditDetailsAuditValue(audit);
|
|
49
|
+
// undefined details OR empty details (undefined issues OR empty issues AND empty table)
|
|
50
|
+
if (issues.length === 0 && !table?.rows.length) {
|
|
51
|
+
return new MarkdownDocument().paragraph(detailsValue);
|
|
52
|
+
}
|
|
53
|
+
const tableSectionContent = table && tableSection(table);
|
|
54
|
+
const issuesSectionContent = issues.length > 0 && auditDetailsIssues(issues, options);
|
|
55
|
+
return new MarkdownDocument().details(detailsValue, new MarkdownDocument().$concat(tableSectionContent, issuesSectionContent));
|
|
56
|
+
}
|
|
57
|
+
export function auditsSection({ plugins }, options) {
|
|
58
|
+
return new MarkdownDocument()
|
|
59
|
+
.heading(HIERARCHY.level_2, '🛡️ Audits')
|
|
60
|
+
.$foreach(plugins.flatMap(plugin => plugin.audits.map(audit => ({ ...audit, plugin }))), (doc, { plugin, ...audit }) => {
|
|
61
|
+
const auditTitle = `${audit.title} (${plugin.title})`;
|
|
62
|
+
const detailsContent = auditDetails(audit, options);
|
|
63
|
+
const descriptionContent = metaDescription(audit);
|
|
64
|
+
return doc
|
|
65
|
+
.heading(HIERARCHY.level_3, auditTitle)
|
|
66
|
+
.$concat(detailsContent)
|
|
67
|
+
.paragraph(descriptionContent);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export function aboutSection(report) {
|
|
71
|
+
const { date, plugins } = report;
|
|
72
|
+
return new MarkdownDocument()
|
|
73
|
+
.heading(HIERARCHY.level_2, 'About')
|
|
74
|
+
.paragraph(md `Report was created by ${md.link(README_LINK, 'Code PushUp')} on ${formatDate(new Date(date))}.`)
|
|
75
|
+
.table(...pluginMetaTable({ plugins }))
|
|
76
|
+
.table(...reportMetaTable(report));
|
|
77
|
+
}
|
|
78
|
+
export function pluginMetaTable({ plugins, }) {
|
|
79
|
+
return [
|
|
80
|
+
[
|
|
81
|
+
{ heading: 'Plugin', alignment: 'left' },
|
|
82
|
+
{ heading: 'Audits', alignment: 'center' },
|
|
83
|
+
{ heading: 'Version', alignment: 'center' },
|
|
84
|
+
{ heading: 'Duration', alignment: 'right' },
|
|
85
|
+
],
|
|
86
|
+
plugins.map(({ title, audits, version = '', duration }) => [
|
|
87
|
+
title,
|
|
88
|
+
audits.length.toString(),
|
|
89
|
+
version && md.code(version),
|
|
90
|
+
formatDuration(duration),
|
|
91
|
+
]),
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
export function reportMetaTable({ commit, version, duration, plugins, categories, }) {
|
|
95
|
+
return [
|
|
96
|
+
[
|
|
97
|
+
{ heading: 'Commit', alignment: 'left' },
|
|
98
|
+
{ heading: 'Version', alignment: 'center' },
|
|
99
|
+
{ heading: 'Duration', alignment: 'right' },
|
|
100
|
+
{ heading: 'Plugins', alignment: 'center' },
|
|
101
|
+
{ heading: 'Categories', alignment: 'center' },
|
|
102
|
+
{ heading: 'Audits', alignment: 'center' },
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
[
|
|
106
|
+
commit ? `${commit.message} (${commit.hash})` : 'N/A',
|
|
107
|
+
md.code(version),
|
|
108
|
+
formatDuration(duration),
|
|
109
|
+
plugins.length.toString(),
|
|
110
|
+
(categories?.length ?? 0).toString(),
|
|
111
|
+
plugins.reduce((acc, { audits }) => acc + audits.length, 0).toString(),
|
|
112
|
+
],
|
|
113
|
+
],
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=generate-md-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-md-report.js","sourceRoot":"","sources":["../../../../../../packages/utils/src/lib/reports/generate-md-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type InlineText, MarkdownDocument } from 'build-md';
|
|
2
2
|
import type { ReportsDiff } from '@code-pushup/models';
|
|
3
|
-
import type { DiffOutcome } from './types';
|
|
3
|
+
import type { DiffOutcome } from './types.js';
|
|
4
4
|
export declare function summarizeUnchanged(token: string, { changed, unchanged }: {
|
|
5
5
|
changed: unknown[];
|
|
6
6
|
unchanged: unknown[];
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { MarkdownDocument, md } from 'build-md';
|
|
2
|
+
import { pluralize, pluralizeToken } from '../formatting.js';
|
|
3
|
+
import { objectToEntries } from '../transform.js';
|
|
4
|
+
// to prevent exceeding Markdown comment character limit
|
|
5
|
+
const MAX_ROWS = 100;
|
|
6
|
+
export function summarizeUnchanged(token, { changed, unchanged }) {
|
|
7
|
+
const pluralizedCount = changed.length > 0
|
|
8
|
+
? pluralizeToken(`other ${token}`, unchanged.length)
|
|
9
|
+
: `All of ${pluralizeToken(token, unchanged.length)}`;
|
|
10
|
+
const pluralizedVerb = unchanged.length === 1 ? 'is' : 'are';
|
|
11
|
+
return `${pluralizedCount} ${pluralizedVerb} unchanged.`;
|
|
12
|
+
}
|
|
13
|
+
export function summarizeDiffOutcomes(outcomes, token) {
|
|
14
|
+
return objectToEntries(countDiffOutcomes(outcomes))
|
|
15
|
+
.filter((entry) => entry[0] !== 'unchanged' && entry[1] > 0)
|
|
16
|
+
.map(([outcome, count]) => {
|
|
17
|
+
const formattedCount = `<strong>${count}</strong> ${pluralize(token, count)}`;
|
|
18
|
+
switch (outcome) {
|
|
19
|
+
case 'positive':
|
|
20
|
+
return `👍 ${formattedCount} improved`;
|
|
21
|
+
case 'negative':
|
|
22
|
+
return `👎 ${formattedCount} regressed`;
|
|
23
|
+
case 'mixed':
|
|
24
|
+
return `${formattedCount} changed without impacting score`;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
.join(', ');
|
|
28
|
+
}
|
|
29
|
+
export function createGroupsOrAuditsDetails(token, { changed, unchanged }, ...[columns, rows]) {
|
|
30
|
+
if (changed.length === 0) {
|
|
31
|
+
return new MarkdownDocument().paragraph(summarizeUnchanged(token, { changed, unchanged }));
|
|
32
|
+
}
|
|
33
|
+
return new MarkdownDocument()
|
|
34
|
+
.table(columns, rows.slice(0, MAX_ROWS))
|
|
35
|
+
.paragraph(changed.length > MAX_ROWS &&
|
|
36
|
+
md.italic(`Only the ${MAX_ROWS} most affected ${pluralize(token)} are listed above for brevity.`))
|
|
37
|
+
.paragraph(unchanged.length > 0 && summarizeUnchanged(token, { changed, unchanged }));
|
|
38
|
+
}
|
|
39
|
+
export function formatTitle({ title, docsUrl, }) {
|
|
40
|
+
if (docsUrl) {
|
|
41
|
+
return md.link(docsUrl, title);
|
|
42
|
+
}
|
|
43
|
+
return title;
|
|
44
|
+
}
|
|
45
|
+
export function formatPortalLink(portalUrl) {
|
|
46
|
+
return (portalUrl &&
|
|
47
|
+
md.link(portalUrl, '🕵️ See full comparison in Code PushUp portal 🔍'));
|
|
48
|
+
}
|
|
49
|
+
export function sortChanges(changes) {
|
|
50
|
+
return changes.toSorted((a, b) => Math.abs(b.scores.diff) - Math.abs(a.scores.diff) ||
|
|
51
|
+
Math.abs(b.values?.diff ?? 0) - Math.abs(a.values?.diff ?? 0));
|
|
52
|
+
}
|
|
53
|
+
export function getDiffChanges(diff) {
|
|
54
|
+
return [
|
|
55
|
+
...diff.categories.changed,
|
|
56
|
+
...diff.groups.changed,
|
|
57
|
+
...diff.audits.changed,
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
export function changesToDiffOutcomes(changes) {
|
|
61
|
+
return changes.map((change) => {
|
|
62
|
+
if (change.scores.diff > 0) {
|
|
63
|
+
return 'positive';
|
|
64
|
+
}
|
|
65
|
+
if (change.scores.diff < 0) {
|
|
66
|
+
return 'negative';
|
|
67
|
+
}
|
|
68
|
+
if (change.values != null && change.values.diff !== 0) {
|
|
69
|
+
return 'mixed';
|
|
70
|
+
}
|
|
71
|
+
return 'unchanged';
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export function mergeDiffOutcomes(outcomes) {
|
|
75
|
+
if (outcomes.every(outcome => outcome === 'unchanged')) {
|
|
76
|
+
return 'unchanged';
|
|
77
|
+
}
|
|
78
|
+
if (outcomes.includes('positive') && !outcomes.includes('negative')) {
|
|
79
|
+
return 'positive';
|
|
80
|
+
}
|
|
81
|
+
if (outcomes.includes('negative') && !outcomes.includes('positive')) {
|
|
82
|
+
return 'negative';
|
|
83
|
+
}
|
|
84
|
+
return 'mixed';
|
|
85
|
+
}
|
|
86
|
+
function countDiffOutcomes(outcomes) {
|
|
87
|
+
return {
|
|
88
|
+
positive: outcomes.filter(outcome => outcome === 'positive').length,
|
|
89
|
+
negative: outcomes.filter(outcome => outcome === 'negative').length,
|
|
90
|
+
mixed: outcomes.filter(outcome => outcome === 'mixed').length,
|
|
91
|
+
unchanged: outcomes.filter(outcome => outcome === 'unchanged').length,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export function formatReportOutcome(outcome, commits) {
|
|
95
|
+
const outcomeTexts = {
|
|
96
|
+
positive: md `🥳 Code PushUp report has ${md.bold('improved')}`,
|
|
97
|
+
negative: md `😟 Code PushUp report has ${md.bold('regressed')}`,
|
|
98
|
+
mixed: md `🤨 Code PushUp report has both ${md.bold('improvements and regressions')}`,
|
|
99
|
+
unchanged: md `😐 Code PushUp report is ${md.bold('unchanged')}`,
|
|
100
|
+
};
|
|
101
|
+
if (commits) {
|
|
102
|
+
const commitsText = `compared target commit ${commits.after.hash} with source commit ${commits.before.hash}`;
|
|
103
|
+
return md `${outcomeTexts[outcome]} – ${commitsText}.`;
|
|
104
|
+
}
|
|
105
|
+
return md `${outcomeTexts[outcome]}.`;
|
|
106
|
+
}
|
|
107
|
+
export function compareDiffsBy(type, a, b) {
|
|
108
|
+
return (sumScoreChanges(b[type].changed) - sumScoreChanges(a[type].changed) ||
|
|
109
|
+
sumConfigChanges(b[type]) - sumConfigChanges(a[type]));
|
|
110
|
+
}
|
|
111
|
+
function sumScoreChanges(changes) {
|
|
112
|
+
return changes.reduce((acc, { scores }) => acc + Math.abs(scores.diff), 0);
|
|
113
|
+
}
|
|
114
|
+
function sumConfigChanges({ added, removed, }) {
|
|
115
|
+
return added.length + removed.length;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=generate-md-reports-diff-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-md-reports-diff-utils.js","sourceRoot":"","sources":["../../../../../../packages/utils/src/lib/reports/generate-md-reports-diff-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReportsDiff } from '@code-pushup/models';
|
|
2
|
-
import type { WithRequired } from '../types';
|
|
2
|
+
import type { WithRequired } from '../types.js';
|
|
3
3
|
export declare function generateMdReportsDiff(diff: ReportsDiff): string;
|
|
4
4
|
export type LabeledDiff = WithRequired<ReportsDiff, 'label'>;
|
|
5
5
|
export declare function generateMdReportsDiffForMonorepo(diffs: LabeledDiff[]): string;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { MarkdownDocument, md, } from 'build-md';
|
|
2
|
+
import { HIERARCHY } from '../text-formats/index.js';
|
|
3
|
+
import { toArray } from '../transform.js';
|
|
4
|
+
import { changesToDiffOutcomes, compareDiffsBy, createGroupsOrAuditsDetails, formatPortalLink, formatReportOutcome, formatTitle, getDiffChanges, mergeDiffOutcomes, sortChanges, summarizeDiffOutcomes, summarizeUnchanged, } from './generate-md-reports-diff-utils.js';
|
|
5
|
+
import { formatScoreChange, formatScoreWithColor, formatValueChange, scoreMarker, } from './utils.js';
|
|
6
|
+
export function generateMdReportsDiff(diff) {
|
|
7
|
+
return new MarkdownDocument()
|
|
8
|
+
.$concat(createDiffHeaderSection(diff), createDiffCategoriesSection(diff), createDiffDetailsSection(diff))
|
|
9
|
+
.toString();
|
|
10
|
+
}
|
|
11
|
+
export function generateMdReportsDiffForMonorepo(diffs) {
|
|
12
|
+
const diffsWithOutcomes = diffs
|
|
13
|
+
.map(diff => ({
|
|
14
|
+
...diff,
|
|
15
|
+
outcome: mergeDiffOutcomes(changesToDiffOutcomes(getDiffChanges(diff))),
|
|
16
|
+
}))
|
|
17
|
+
.sort((a, b) => compareDiffsBy('categories', a, b) ||
|
|
18
|
+
compareDiffsBy('groups', a, b) ||
|
|
19
|
+
compareDiffsBy('audits', a, b) ||
|
|
20
|
+
a.label.localeCompare(b.label));
|
|
21
|
+
const unchanged = diffsWithOutcomes.filter(({ outcome }) => outcome === 'unchanged');
|
|
22
|
+
const changed = diffsWithOutcomes.filter(diff => !unchanged.includes(diff));
|
|
23
|
+
return new MarkdownDocument()
|
|
24
|
+
.$concat(createDiffHeaderSection(diffs), ...changed.map(createDiffProjectSection))
|
|
25
|
+
.$if(unchanged.length > 0, doc => doc
|
|
26
|
+
.rule()
|
|
27
|
+
.paragraph(summarizeUnchanged('project', { unchanged, changed })))
|
|
28
|
+
.toString();
|
|
29
|
+
}
|
|
30
|
+
function createDiffHeaderSection(diff) {
|
|
31
|
+
const outcome = mergeDiffOutcomes(changesToDiffOutcomes(toArray(diff).flatMap(getDiffChanges)));
|
|
32
|
+
// TODO: what if array contains different commit pairs?
|
|
33
|
+
const commits = Array.isArray(diff) ? diff[0]?.commits : diff.commits;
|
|
34
|
+
const portalUrl = Array.isArray(diff) ? undefined : diff.portalUrl;
|
|
35
|
+
return new MarkdownDocument()
|
|
36
|
+
.heading(HIERARCHY.level_1, 'Code PushUp')
|
|
37
|
+
.paragraph(formatReportOutcome(outcome, commits))
|
|
38
|
+
.paragraph(formatPortalLink(portalUrl));
|
|
39
|
+
}
|
|
40
|
+
function createDiffProjectSection(diff) {
|
|
41
|
+
return new MarkdownDocument()
|
|
42
|
+
.heading(HIERARCHY.level_2, md `💼 Project ${md.code(diff.label)}`)
|
|
43
|
+
.paragraph(formatReportOutcome(diff.outcome))
|
|
44
|
+
.paragraph(formatPortalLink(diff.portalUrl))
|
|
45
|
+
.$concat(createDiffCategoriesSection(diff, {
|
|
46
|
+
skipHeading: true,
|
|
47
|
+
skipUnchanged: true,
|
|
48
|
+
}), createDiffDetailsSection(diff, HIERARCHY.level_3));
|
|
49
|
+
}
|
|
50
|
+
function createDiffCategoriesSection(diff, options) {
|
|
51
|
+
const { changed, unchanged, added } = diff.categories;
|
|
52
|
+
const { skipHeading, skipUnchanged } = options ?? {};
|
|
53
|
+
const categoriesCount = changed.length + unchanged.length + added.length;
|
|
54
|
+
const hasChanges = unchanged.length < categoriesCount;
|
|
55
|
+
if (categoriesCount === 0) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const [columns, rows] = createCategoriesTable(diff, {
|
|
59
|
+
hasChanges,
|
|
60
|
+
skipUnchanged,
|
|
61
|
+
});
|
|
62
|
+
return new MarkdownDocument()
|
|
63
|
+
.heading(HIERARCHY.level_2, !skipHeading && '🏷️ Categories')
|
|
64
|
+
.table(columns, rows)
|
|
65
|
+
.paragraph(added.length > 0 && md.italic(String.raw `(\*) New category.`))
|
|
66
|
+
.paragraph(skipUnchanged &&
|
|
67
|
+
unchanged.length > 0 &&
|
|
68
|
+
summarizeUnchanged('category', { changed, unchanged }));
|
|
69
|
+
}
|
|
70
|
+
function createCategoriesTable(diff, options) {
|
|
71
|
+
const { changed, unchanged, added } = diff.categories;
|
|
72
|
+
const { hasChanges, skipUnchanged } = options;
|
|
73
|
+
const rows = [
|
|
74
|
+
...sortChanges(changed).map(category => [
|
|
75
|
+
formatTitle(category),
|
|
76
|
+
formatScoreWithColor(category.scores.before, {
|
|
77
|
+
skipBold: true,
|
|
78
|
+
}),
|
|
79
|
+
formatScoreWithColor(category.scores.after),
|
|
80
|
+
formatScoreChange(category.scores.diff),
|
|
81
|
+
]),
|
|
82
|
+
...added.map(category => [
|
|
83
|
+
formatTitle(category),
|
|
84
|
+
md.italic(String.raw `n/a (\*)`),
|
|
85
|
+
formatScoreWithColor(category.score),
|
|
86
|
+
md.italic(String.raw `n/a (\*)`),
|
|
87
|
+
]),
|
|
88
|
+
...(skipUnchanged
|
|
89
|
+
? []
|
|
90
|
+
: unchanged.map(category => [
|
|
91
|
+
formatTitle(category),
|
|
92
|
+
formatScoreWithColor(category.score, { skipBold: true }),
|
|
93
|
+
formatScoreWithColor(category.score),
|
|
94
|
+
'–',
|
|
95
|
+
])),
|
|
96
|
+
];
|
|
97
|
+
if (rows.length === 0) {
|
|
98
|
+
return [[], []];
|
|
99
|
+
}
|
|
100
|
+
const columns = [
|
|
101
|
+
{ heading: '🏷️ Category', alignment: 'left' },
|
|
102
|
+
{
|
|
103
|
+
heading: hasChanges ? '⭐ Previous score' : '⭐ Score',
|
|
104
|
+
alignment: 'center',
|
|
105
|
+
},
|
|
106
|
+
{ heading: '⭐ Current score', alignment: 'center' },
|
|
107
|
+
{ heading: '🔄 Score change', alignment: 'center' },
|
|
108
|
+
];
|
|
109
|
+
return [
|
|
110
|
+
hasChanges ? columns : columns.slice(0, 2),
|
|
111
|
+
rows.map(row => (hasChanges ? row : row.slice(0, 2))),
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
function createDiffDetailsSection(diff, level = HIERARCHY.level_2) {
|
|
115
|
+
if (diff.groups.changed.length + diff.audits.changed.length === 0) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const summary = ['group', 'audit']
|
|
119
|
+
.map(token => summarizeDiffOutcomes(changesToDiffOutcomes(diff[`${token}s`].changed), token))
|
|
120
|
+
.filter(Boolean)
|
|
121
|
+
.join(', ');
|
|
122
|
+
const details = new MarkdownDocument().$concat(createDiffGroupsSection(diff, level), createDiffAuditsSection(diff, level));
|
|
123
|
+
return new MarkdownDocument().details(summary, details);
|
|
124
|
+
}
|
|
125
|
+
function createDiffGroupsSection(diff, level) {
|
|
126
|
+
if (diff.groups.changed.length + diff.groups.unchanged.length === 0) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return new MarkdownDocument().heading(level, '🗃️ Groups').$concat(createGroupsOrAuditsDetails('group', diff.groups, [
|
|
130
|
+
{ heading: '🔌 Plugin', alignment: 'left' },
|
|
131
|
+
{ heading: '🗃️ Group', alignment: 'left' },
|
|
132
|
+
{ heading: '⭐ Previous score', alignment: 'center' },
|
|
133
|
+
{ heading: '⭐ Current score', alignment: 'center' },
|
|
134
|
+
{ heading: '🔄 Score change', alignment: 'center' },
|
|
135
|
+
], sortChanges(diff.groups.changed).map(group => [
|
|
136
|
+
formatTitle(group.plugin),
|
|
137
|
+
formatTitle(group),
|
|
138
|
+
formatScoreWithColor(group.scores.before, { skipBold: true }),
|
|
139
|
+
formatScoreWithColor(group.scores.after),
|
|
140
|
+
formatScoreChange(group.scores.diff),
|
|
141
|
+
])));
|
|
142
|
+
}
|
|
143
|
+
function createDiffAuditsSection(diff, level) {
|
|
144
|
+
return new MarkdownDocument().heading(level, '🛡️ Audits').$concat(createGroupsOrAuditsDetails('audit', diff.audits, [
|
|
145
|
+
{ heading: '🔌 Plugin', alignment: 'left' },
|
|
146
|
+
{ heading: '🛡️ Audit', alignment: 'left' },
|
|
147
|
+
{ heading: '📏 Previous value', alignment: 'center' },
|
|
148
|
+
{ heading: '📏 Current value', alignment: 'center' },
|
|
149
|
+
{ heading: '🔄 Value change', alignment: 'center' },
|
|
150
|
+
], sortChanges(diff.audits.changed).map(audit => [
|
|
151
|
+
formatTitle(audit.plugin),
|
|
152
|
+
formatTitle(audit),
|
|
153
|
+
`${scoreMarker(audit.scores.before, 'square')} ${audit.displayValues.before || audit.values.before.toString()}`,
|
|
154
|
+
md `${scoreMarker(audit.scores.after, 'square')} ${md.bold(audit.displayValues.after || audit.values.after.toString())}`,
|
|
155
|
+
formatValueChange(audit),
|
|
156
|
+
])));
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=generate-md-reports-diff.js.map
|