@code-pushup/utils 0.56.0 → 0.58.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 (106) hide show
  1. package/package.json +13 -7
  2. package/src/index.d.ts +31 -29
  3. package/src/index.js +31 -0
  4. package/src/index.js.map +1 -0
  5. package/src/lib/create-runner-files.d.ts +8 -0
  6. package/src/lib/create-runner-files.js +22 -0
  7. package/src/lib/create-runner-files.js.map +1 -0
  8. package/src/lib/diff.js +38 -0
  9. package/src/lib/diff.js.map +1 -0
  10. package/src/lib/errors.js +14 -0
  11. package/src/lib/errors.js.map +1 -0
  12. package/src/lib/execute-process.d.ts +0 -1
  13. package/src/lib/execute-process.js +105 -0
  14. package/src/lib/execute-process.js.map +1 -0
  15. package/src/lib/file-system.d.ts +5 -5
  16. package/src/lib/file-system.js +113 -0
  17. package/src/lib/file-system.js.map +1 -0
  18. package/src/lib/filter.js +10 -0
  19. package/src/lib/filter.js.map +1 -0
  20. package/src/lib/formatting.js +83 -0
  21. package/src/lib/formatting.js.map +1 -0
  22. package/src/lib/git/git.commits-and-tags.js +148 -0
  23. package/src/lib/git/git.commits-and-tags.js.map +1 -0
  24. package/src/lib/git/git.d.ts +2 -2
  25. package/src/lib/git/git.js +58 -0
  26. package/src/lib/git/git.js.map +1 -0
  27. package/src/lib/group-by-status.js +6 -0
  28. package/src/lib/group-by-status.js.map +1 -0
  29. package/src/lib/guards.d.ts +2 -0
  30. package/src/lib/guards.js +10 -0
  31. package/src/lib/guards.js.map +1 -0
  32. package/src/lib/log-results.js +28 -0
  33. package/src/lib/log-results.js.map +1 -0
  34. package/src/lib/logging.js +33 -0
  35. package/src/lib/logging.js.map +1 -0
  36. package/src/lib/merge-configs.js +104 -0
  37. package/src/lib/merge-configs.js.map +1 -0
  38. package/src/lib/progress.js +57 -0
  39. package/src/lib/progress.js.map +1 -0
  40. package/src/lib/reports/constants.js +19 -0
  41. package/src/lib/reports/constants.js.map +1 -0
  42. package/src/lib/reports/environment-type.d.ts +1 -1
  43. package/src/lib/reports/environment-type.js +17 -0
  44. package/src/lib/reports/environment-type.js.map +1 -0
  45. package/src/lib/reports/flatten-plugins.js +8 -0
  46. package/src/lib/reports/flatten-plugins.js.map +1 -0
  47. package/src/lib/reports/formatting.d.ts +1 -1
  48. package/src/lib/reports/formatting.js +105 -0
  49. package/src/lib/reports/formatting.js.map +1 -0
  50. package/src/lib/reports/generate-md-report-categoy-section.d.ts +1 -1
  51. package/src/lib/reports/generate-md-report-categoy-section.js +63 -0
  52. package/src/lib/reports/generate-md-report-categoy-section.js.map +1 -0
  53. package/src/lib/reports/generate-md-report.d.ts +1 -1
  54. package/src/lib/reports/generate-md-report.js +116 -0
  55. package/src/lib/reports/generate-md-report.js.map +1 -0
  56. package/src/lib/reports/generate-md-reports-diff-utils.d.ts +1 -1
  57. package/src/lib/reports/generate-md-reports-diff-utils.js +117 -0
  58. package/src/lib/reports/generate-md-reports-diff-utils.js.map +1 -0
  59. package/src/lib/reports/generate-md-reports-diff.d.ts +1 -1
  60. package/src/lib/reports/generate-md-reports-diff.js +158 -0
  61. package/src/lib/reports/generate-md-reports-diff.js.map +1 -0
  62. package/src/lib/reports/load-report.js +15 -0
  63. package/src/lib/reports/load-report.js.map +1 -0
  64. package/src/lib/reports/log-stdout-summary.d.ts +1 -1
  65. package/src/lib/reports/log-stdout-summary.js +102 -0
  66. package/src/lib/reports/log-stdout-summary.js.map +1 -0
  67. package/src/lib/reports/scoring.d.ts +1 -1
  68. package/src/lib/reports/scoring.js +78 -0
  69. package/src/lib/reports/scoring.js.map +1 -0
  70. package/src/lib/reports/sorting.d.ts +1 -1
  71. package/src/lib/reports/sorting.js +91 -0
  72. package/src/lib/reports/sorting.js.map +1 -0
  73. package/src/lib/reports/types.js +7 -0
  74. package/src/lib/reports/types.js.map +1 -0
  75. package/src/lib/reports/utils.d.ts +1 -1
  76. package/src/lib/reports/utils.js +209 -0
  77. package/src/lib/reports/utils.js.map +1 -0
  78. package/src/lib/semver.js +17 -0
  79. package/src/lib/semver.js.map +1 -0
  80. package/src/lib/text-formats/constants.js +14 -0
  81. package/src/lib/text-formats/constants.js.map +1 -0
  82. package/src/lib/text-formats/html/details.js +20 -0
  83. package/src/lib/text-formats/html/details.js.map +1 -0
  84. package/src/lib/text-formats/html/font-style.js +13 -0
  85. package/src/lib/text-formats/html/font-style.js.map +1 -0
  86. package/src/lib/text-formats/html/link.js +4 -0
  87. package/src/lib/text-formats/html/link.js.map +1 -0
  88. package/src/lib/text-formats/html/table.js +27 -0
  89. package/src/lib/text-formats/html/table.js.map +1 -0
  90. package/src/lib/text-formats/index.d.ts +5 -5
  91. package/src/lib/text-formats/index.js +14 -0
  92. package/src/lib/text-formats/index.js.map +1 -0
  93. package/src/lib/text-formats/table.js +92 -0
  94. package/src/lib/text-formats/table.js.map +1 -0
  95. package/src/lib/transform.d.ts +2 -3
  96. package/src/lib/transform.js +111 -0
  97. package/src/lib/transform.js.map +1 -0
  98. package/src/lib/types.d.ts +3 -3
  99. package/src/lib/types.js +2 -0
  100. package/src/lib/types.js.map +1 -0
  101. package/src/lib/verbose-utils.js +20 -0
  102. package/src/lib/verbose-utils.js.map +1 -0
  103. package/src/lib/zod-validation.d.ts +11 -0
  104. package/src/lib/zod-validation.js +46 -0
  105. package/src/lib/zod-validation.js.map +1 -0
  106. 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