@code-pushup/coverage-plugin 0.44.4 → 0.45.1

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/bin.js CHANGED
@@ -3,301 +3,6 @@ import chalk5 from "chalk";
3
3
  import { writeFile } from "node:fs/promises";
4
4
  import { dirname } from "node:path";
5
5
 
6
- // packages/utils/src/lib/text-formats/constants.ts
7
- var NEW_LINE = "\n";
8
- var TAB = " ";
9
-
10
- // packages/utils/src/lib/text-formats/html/details.ts
11
- function details(title, content, cfg = { open: false }) {
12
- return `<details${cfg.open ? " open" : ""}>${NEW_LINE}<summary>${title}</summary>${NEW_LINE}${// ⚠️ The blank line is needed to ensure Markdown in content is rendered correctly.
13
- NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
14
- // ⚠️ The blank line ensure Markdown in content is rendered correctly.
15
- NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
16
- NEW_LINE}`;
17
- }
18
-
19
- // packages/utils/src/lib/text-formats/html/font-style.ts
20
- var boldElement = "b";
21
- function bold(text) {
22
- return `<${boldElement}>${text}</${boldElement}>`;
23
- }
24
- var italicElement = "i";
25
- function italic(text) {
26
- return `<${italicElement}>${text}</${italicElement}>`;
27
- }
28
- var codeElement = "code";
29
- function code(text) {
30
- return `<${codeElement}>${text}</${codeElement}>`;
31
- }
32
-
33
- // packages/utils/src/lib/text-formats/html/link.ts
34
- function link(href, text) {
35
- return `<a href="${href}">${text || href}"</a>`;
36
- }
37
-
38
- // packages/utils/src/lib/transform.ts
39
- import { platform } from "node:os";
40
- function toUnixNewlines(text) {
41
- return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
42
- }
43
- function capitalize(text) {
44
- return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
45
- 1
46
- )}`;
47
- }
48
- function toNumberPrecision(value, decimalPlaces) {
49
- return Number(
50
- `${Math.round(
51
- Number.parseFloat(`${value}e${decimalPlaces}`)
52
- )}e-${decimalPlaces}`
53
- );
54
- }
55
- function toOrdinal(value) {
56
- if (value % 10 === 1 && value % 100 !== 11) {
57
- return `${value}st`;
58
- }
59
- if (value % 10 === 2 && value % 100 !== 12) {
60
- return `${value}nd`;
61
- }
62
- if (value % 10 === 3 && value % 100 !== 13) {
63
- return `${value}rd`;
64
- }
65
- return `${value}th`;
66
- }
67
-
68
- // packages/utils/src/lib/table.ts
69
- function rowToStringArray({ rows, columns = [] }) {
70
- if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
71
- throw new TypeError(
72
- "Column can`t be object when rows are primitive values"
73
- );
74
- }
75
- return rows.map((row) => {
76
- if (Array.isArray(row)) {
77
- return row.map(String);
78
- }
79
- const objectRow = row;
80
- if (columns.length === 0 || typeof columns.at(0) === "string") {
81
- return Object.values(objectRow).map(String);
82
- }
83
- return columns.map(
84
- ({ key }) => String(objectRow[key])
85
- );
86
- });
87
- }
88
- function columnsToStringArray({ rows, columns = [] }) {
89
- const firstRow = rows.at(0);
90
- const primitiveRows = Array.isArray(firstRow);
91
- if (typeof columns.at(0) === "string" && !primitiveRows) {
92
- throw new Error("invalid union type. Caught by model parsing.");
93
- }
94
- if (columns.length === 0) {
95
- if (Array.isArray(firstRow)) {
96
- return firstRow.map((_, idx) => String(idx));
97
- }
98
- return Object.keys(firstRow);
99
- }
100
- if (typeof columns.at(0) === "string") {
101
- return columns.map(String);
102
- }
103
- const cols = columns;
104
- return cols.map(({ label, key }) => label ?? capitalize(key));
105
- }
106
- function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
107
- const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
108
- if (typeof column === "string") {
109
- return column;
110
- } else if (typeof column === "object") {
111
- return column.align ?? "center";
112
- } else {
113
- return "center";
114
- }
115
- }
116
- function getColumnAlignmentForIndex(targetIdx, columns = []) {
117
- const column = columns.at(targetIdx);
118
- if (column == null) {
119
- return "center";
120
- } else if (typeof column === "string") {
121
- return column;
122
- } else if (typeof column === "object") {
123
- return column.align ?? "center";
124
- } else {
125
- return "center";
126
- }
127
- }
128
- function getColumnAlignments({
129
- rows,
130
- columns = []
131
- }) {
132
- if (rows.at(0) == null) {
133
- throw new Error("first row can`t be undefined.");
134
- }
135
- if (Array.isArray(rows.at(0))) {
136
- const firstPrimitiveRow = rows.at(0);
137
- return Array.from({ length: firstPrimitiveRow.length }).map(
138
- (_, idx) => getColumnAlignmentForIndex(idx, columns)
139
- );
140
- }
141
- const firstObject = rows.at(0);
142
- return Object.keys(firstObject).map(
143
- (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
144
- );
145
- }
146
-
147
- // packages/utils/src/lib/text-formats/html/table.ts
148
- function wrap(elem, content) {
149
- return `<${elem}>${content}</${elem}>${NEW_LINE}`;
150
- }
151
- function wrapRow(content) {
152
- const elem = "tr";
153
- return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
154
- }
155
- function table(tableData) {
156
- if (tableData.rows.length === 0) {
157
- throw new Error("Data can't be empty");
158
- }
159
- const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
160
- const tableHeaderRow = wrapRow(tableHeaderCols);
161
- const tableBody = rowToStringArray(tableData).map((arr) => {
162
- const columns = arr.map((s) => wrap("td", s)).join("");
163
- return wrapRow(columns);
164
- }).join("");
165
- return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
166
- }
167
-
168
- // packages/utils/src/lib/text-formats/md/font-style.ts
169
- var boldWrap = "**";
170
- function bold2(text) {
171
- return `${boldWrap}${text}${boldWrap}`;
172
- }
173
- var italicWrap = "_";
174
- function italic2(text) {
175
- return `${italicWrap}${text}${italicWrap}`;
176
- }
177
- var strikeThroughWrap = "~";
178
- function strikeThrough(text) {
179
- return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
180
- }
181
- var codeWrap = "`";
182
- function code2(text) {
183
- return `${codeWrap}${text}${codeWrap}`;
184
- }
185
-
186
- // packages/utils/src/lib/text-formats/md/headline.ts
187
- function headline(text, hierarchy = 1) {
188
- return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
189
- }
190
- function h(text, hierarchy = 1) {
191
- return headline(text, hierarchy);
192
- }
193
- function h1(text) {
194
- return headline(text, 1);
195
- }
196
- function h2(text) {
197
- return headline(text, 2);
198
- }
199
- function h3(text) {
200
- return headline(text, 3);
201
- }
202
- function h4(text) {
203
- return headline(text, 4);
204
- }
205
- function h5(text) {
206
- return headline(text, 5);
207
- }
208
- function h6(text) {
209
- return headline(text, 6);
210
- }
211
-
212
- // packages/utils/src/lib/text-formats/md/image.ts
213
- function image(src, alt) {
214
- return `![${alt}](${src})`;
215
- }
216
-
217
- // packages/utils/src/lib/text-formats/md/link.ts
218
- function link2(href, text) {
219
- return `[${text || href}](${href})`;
220
- }
221
-
222
- // packages/utils/src/lib/text-formats/md/list.ts
223
- function li(text, order = "unordered") {
224
- const style = order === "unordered" ? "-" : "- [ ]";
225
- return `${style} ${text}`;
226
- }
227
- function indentation(text, level = 1) {
228
- return `${TAB.repeat(level)}${text}`;
229
- }
230
-
231
- // packages/utils/src/lib/text-formats/md/paragraphs.ts
232
- function paragraphs(...sections) {
233
- return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
234
- }
235
-
236
- // packages/utils/src/lib/text-formats/md/section.ts
237
- function section(...contents) {
238
- return `${lines(...contents)}${NEW_LINE}`;
239
- }
240
- function lines(...contents) {
241
- return `${contents.filter(Boolean).join(NEW_LINE)}`;
242
- }
243
-
244
- // packages/utils/src/lib/text-formats/md/table.ts
245
- var alignString = /* @__PURE__ */ new Map([
246
- ["left", ":--"],
247
- ["center", ":--:"],
248
- ["right", "--:"]
249
- ]);
250
- function tableRow(rows) {
251
- return `|${rows.join("|")}|`;
252
- }
253
- function table2(data) {
254
- if (data.rows.length === 0) {
255
- throw new Error("Data can't be empty");
256
- }
257
- const alignmentRow = getColumnAlignments(data).map(
258
- (s) => alignString.get(s) ?? String(alignString.get("center"))
259
- );
260
- return section(
261
- `${lines(
262
- tableRow(columnsToStringArray(data)),
263
- tableRow(alignmentRow),
264
- ...rowToStringArray(data).map(tableRow)
265
- )}`
266
- );
267
- }
268
-
269
- // packages/utils/src/lib/text-formats/index.ts
270
- var md = {
271
- bold: bold2,
272
- italic: italic2,
273
- strikeThrough,
274
- code: code2,
275
- link: link2,
276
- image,
277
- headline,
278
- h,
279
- h1,
280
- h2,
281
- h3,
282
- h4,
283
- h5,
284
- h6,
285
- indentation,
286
- lines,
287
- li,
288
- section,
289
- paragraphs,
290
- table: table2
291
- };
292
- var html = {
293
- bold,
294
- italic,
295
- code,
296
- link,
297
- details,
298
- table
299
- };
300
-
301
6
  // packages/models/src/lib/implementation/schemas.ts
302
7
  import { MATERIAL_ICONS } from "vscode-material-icons";
303
8
  import { z } from "zod";
@@ -407,6 +112,7 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
407
112
  }).min(1, { message: "file name is invalid" });
408
113
  var positiveIntSchema = z.number().int().positive();
409
114
  var nonnegativeIntSchema = z.number().int().nonnegative();
115
+ var nonnegativeNumberSchema = z.number().nonnegative();
410
116
  function packageVersionSchema(options) {
411
117
  const { versionDescription = "NPM version of the package", required } = options ?? {};
412
118
  const packageSchema = z.string({ description: "NPM package name" });
@@ -419,7 +125,7 @@ function packageVersionSchema(options) {
419
125
  { description: "NPM package name and version of a published package" }
420
126
  );
421
127
  }
422
- var weightSchema = nonnegativeIntSchema.describe(
128
+ var weightSchema = nonnegativeNumberSchema.describe(
423
129
  "Coefficient for the given score (use weight 0 if only for display)"
424
130
  );
425
131
  function weightedRefSchema(description, slugDescription) {
@@ -561,7 +267,7 @@ var tableObjectSchema = tableSharedSchema.merge(
561
267
  var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
562
268
 
563
269
  // packages/models/src/lib/audit-output.ts
564
- var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
270
+ var auditValueSchema = nonnegativeNumberSchema.describe("Raw numeric value");
565
271
  var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
566
272
  var auditDetailsSchema = z5.object(
567
273
  {
@@ -992,71 +698,366 @@ var reportsDiffSchema = z15.object({
992
698
  })
993
699
  );
994
700
 
995
- // packages/utils/src/lib/execute-process.ts
996
- import { spawn } from "node:child_process";
701
+ // packages/utils/src/lib/execute-process.ts
702
+ import { spawn } from "node:child_process";
703
+
704
+ // packages/utils/src/lib/file-system.ts
705
+ import { bundleRequire } from "bundle-require";
706
+ import chalk2 from "chalk";
707
+ import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
708
+ import { join } from "node:path";
709
+
710
+ // packages/utils/src/lib/logging.ts
711
+ import isaacs_cliui from "@isaacs/cliui";
712
+ import { cliui } from "@poppinss/cliui";
713
+ import chalk from "chalk";
714
+
715
+ // packages/utils/src/lib/reports/constants.ts
716
+ var TERMINAL_WIDTH = 80;
717
+
718
+ // packages/utils/src/lib/logging.ts
719
+ var singletonUiInstance;
720
+ function ui() {
721
+ if (singletonUiInstance === void 0) {
722
+ singletonUiInstance = cliui();
723
+ }
724
+ return {
725
+ ...singletonUiInstance,
726
+ row: (args) => {
727
+ logListItem(args);
728
+ }
729
+ };
730
+ }
731
+ var singletonisaacUi;
732
+ function logListItem(args) {
733
+ if (singletonisaacUi === void 0) {
734
+ singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
735
+ }
736
+ singletonisaacUi.div(...args);
737
+ const content = singletonisaacUi.toString();
738
+ singletonisaacUi.rows = [];
739
+ singletonUiInstance?.logger.log(content);
740
+ }
741
+
742
+ // packages/utils/src/lib/file-system.ts
743
+ async function readTextFile(path) {
744
+ const buffer = await readFile(path);
745
+ return buffer.toString();
746
+ }
747
+ async function readJsonFile(path) {
748
+ const text = await readTextFile(path);
749
+ return JSON.parse(text);
750
+ }
751
+ async function ensureDirectoryExists(baseDir) {
752
+ try {
753
+ await mkdir(baseDir, { recursive: true });
754
+ return;
755
+ } catch (error) {
756
+ ui().logger.info(error.message);
757
+ if (error.code !== "EEXIST") {
758
+ throw error;
759
+ }
760
+ }
761
+ }
762
+ function pluginWorkDir(slug) {
763
+ return join("node_modules", ".code-pushup", slug);
764
+ }
765
+
766
+ // packages/utils/src/lib/text-formats/constants.ts
767
+ var NEW_LINE = "\n";
768
+ var TAB = " ";
769
+
770
+ // packages/utils/src/lib/text-formats/html/details.ts
771
+ function details(title, content, cfg = { open: false }) {
772
+ return `<details${cfg.open ? " open" : ""}>${NEW_LINE}<summary>${title}</summary>${NEW_LINE}${// ⚠️ The blank line is needed to ensure Markdown in content is rendered correctly.
773
+ NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
774
+ // ⚠️ The blank line ensure Markdown in content is rendered correctly.
775
+ NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
776
+ NEW_LINE}`;
777
+ }
778
+
779
+ // packages/utils/src/lib/text-formats/html/font-style.ts
780
+ var boldElement = "b";
781
+ function bold(text) {
782
+ return `<${boldElement}>${text}</${boldElement}>`;
783
+ }
784
+ var italicElement = "i";
785
+ function italic(text) {
786
+ return `<${italicElement}>${text}</${italicElement}>`;
787
+ }
788
+ var codeElement = "code";
789
+ function code(text) {
790
+ return `<${codeElement}>${text}</${codeElement}>`;
791
+ }
792
+
793
+ // packages/utils/src/lib/text-formats/html/link.ts
794
+ function link(href, text) {
795
+ return `<a href="${href}">${text || href}"</a>`;
796
+ }
797
+
798
+ // packages/utils/src/lib/transform.ts
799
+ import { platform } from "node:os";
800
+ function toUnixNewlines(text) {
801
+ return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
802
+ }
803
+ function capitalize(text) {
804
+ return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
805
+ 1
806
+ )}`;
807
+ }
808
+ function toNumberPrecision(value, decimalPlaces) {
809
+ return Number(
810
+ `${Math.round(
811
+ Number.parseFloat(`${value}e${decimalPlaces}`)
812
+ )}e-${decimalPlaces}`
813
+ );
814
+ }
815
+ function toOrdinal(value) {
816
+ if (value % 10 === 1 && value % 100 !== 11) {
817
+ return `${value}st`;
818
+ }
819
+ if (value % 10 === 2 && value % 100 !== 12) {
820
+ return `${value}nd`;
821
+ }
822
+ if (value % 10 === 3 && value % 100 !== 13) {
823
+ return `${value}rd`;
824
+ }
825
+ return `${value}th`;
826
+ }
827
+
828
+ // packages/utils/src/lib/table.ts
829
+ function rowToStringArray({ rows, columns = [] }) {
830
+ if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
831
+ throw new TypeError(
832
+ "Column can`t be object when rows are primitive values"
833
+ );
834
+ }
835
+ return rows.map((row) => {
836
+ if (Array.isArray(row)) {
837
+ return row.map(String);
838
+ }
839
+ const objectRow = row;
840
+ if (columns.length === 0 || typeof columns.at(0) === "string") {
841
+ return Object.values(objectRow).map(String);
842
+ }
843
+ return columns.map(
844
+ ({ key }) => String(objectRow[key])
845
+ );
846
+ });
847
+ }
848
+ function columnsToStringArray({ rows, columns = [] }) {
849
+ const firstRow = rows.at(0);
850
+ const primitiveRows = Array.isArray(firstRow);
851
+ if (typeof columns.at(0) === "string" && !primitiveRows) {
852
+ throw new Error("invalid union type. Caught by model parsing.");
853
+ }
854
+ if (columns.length === 0) {
855
+ if (Array.isArray(firstRow)) {
856
+ return firstRow.map((_, idx) => String(idx));
857
+ }
858
+ return Object.keys(firstRow);
859
+ }
860
+ if (typeof columns.at(0) === "string") {
861
+ return columns.map(String);
862
+ }
863
+ const cols = columns;
864
+ return cols.map(({ label, key }) => label ?? capitalize(key));
865
+ }
866
+ function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
867
+ const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
868
+ if (typeof column === "string") {
869
+ return column;
870
+ } else if (typeof column === "object") {
871
+ return column.align ?? "center";
872
+ } else {
873
+ return "center";
874
+ }
875
+ }
876
+ function getColumnAlignmentForIndex(targetIdx, columns = []) {
877
+ const column = columns.at(targetIdx);
878
+ if (column == null) {
879
+ return "center";
880
+ } else if (typeof column === "string") {
881
+ return column;
882
+ } else if (typeof column === "object") {
883
+ return column.align ?? "center";
884
+ } else {
885
+ return "center";
886
+ }
887
+ }
888
+ function getColumnAlignments({
889
+ rows,
890
+ columns = []
891
+ }) {
892
+ if (rows.at(0) == null) {
893
+ throw new Error("first row can`t be undefined.");
894
+ }
895
+ if (Array.isArray(rows.at(0))) {
896
+ const firstPrimitiveRow = rows.at(0);
897
+ return Array.from({ length: firstPrimitiveRow.length }).map(
898
+ (_, idx) => getColumnAlignmentForIndex(idx, columns)
899
+ );
900
+ }
901
+ const firstObject = rows.at(0);
902
+ return Object.keys(firstObject).map(
903
+ (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
904
+ );
905
+ }
906
+
907
+ // packages/utils/src/lib/text-formats/html/table.ts
908
+ function wrap(elem, content) {
909
+ return `<${elem}>${content}</${elem}>${NEW_LINE}`;
910
+ }
911
+ function wrapRow(content) {
912
+ const elem = "tr";
913
+ return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
914
+ }
915
+ function table(tableData) {
916
+ if (tableData.rows.length === 0) {
917
+ throw new Error("Data can't be empty");
918
+ }
919
+ const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
920
+ const tableHeaderRow = wrapRow(tableHeaderCols);
921
+ const tableBody = rowToStringArray(tableData).map((arr) => {
922
+ const columns = arr.map((s) => wrap("td", s)).join("");
923
+ return wrapRow(columns);
924
+ }).join("");
925
+ return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
926
+ }
997
927
 
998
- // packages/utils/src/lib/file-system.ts
999
- import { bundleRequire } from "bundle-require";
1000
- import chalk2 from "chalk";
1001
- import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
1002
- import { join } from "node:path";
928
+ // packages/utils/src/lib/text-formats/md/font-style.ts
929
+ var boldWrap = "**";
930
+ function bold2(text) {
931
+ return `${boldWrap}${text}${boldWrap}`;
932
+ }
933
+ var italicWrap = "_";
934
+ function italic2(text) {
935
+ return `${italicWrap}${text}${italicWrap}`;
936
+ }
937
+ var strikeThroughWrap = "~";
938
+ function strikeThrough(text) {
939
+ return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
940
+ }
941
+ var codeWrap = "`";
942
+ function code2(text) {
943
+ return `${codeWrap}${text}${codeWrap}`;
944
+ }
1003
945
 
1004
- // packages/utils/src/lib/logging.ts
1005
- import isaacs_cliui from "@isaacs/cliui";
1006
- import { cliui } from "@poppinss/cliui";
1007
- import chalk from "chalk";
946
+ // packages/utils/src/lib/text-formats/md/headline.ts
947
+ function headline(text, hierarchy = 1) {
948
+ return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
949
+ }
950
+ function h(text, hierarchy = 1) {
951
+ return headline(text, hierarchy);
952
+ }
953
+ function h1(text) {
954
+ return headline(text, 1);
955
+ }
956
+ function h2(text) {
957
+ return headline(text, 2);
958
+ }
959
+ function h3(text) {
960
+ return headline(text, 3);
961
+ }
962
+ function h4(text) {
963
+ return headline(text, 4);
964
+ }
965
+ function h5(text) {
966
+ return headline(text, 5);
967
+ }
968
+ function h6(text) {
969
+ return headline(text, 6);
970
+ }
1008
971
 
1009
- // packages/utils/src/lib/reports/constants.ts
1010
- var TERMINAL_WIDTH = 80;
972
+ // packages/utils/src/lib/text-formats/md/image.ts
973
+ function image(src, alt) {
974
+ return `![${alt}](${src})`;
975
+ }
1011
976
 
1012
- // packages/utils/src/lib/logging.ts
1013
- var singletonUiInstance;
1014
- function ui() {
1015
- if (singletonUiInstance === void 0) {
1016
- singletonUiInstance = cliui();
1017
- }
1018
- return {
1019
- ...singletonUiInstance,
1020
- row: (args) => {
1021
- logListItem(args);
1022
- }
1023
- };
977
+ // packages/utils/src/lib/text-formats/md/link.ts
978
+ function link2(href, text) {
979
+ return `[${text || href}](${href})`;
1024
980
  }
1025
- var singletonisaacUi;
1026
- function logListItem(args) {
1027
- if (singletonisaacUi === void 0) {
1028
- singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
1029
- }
1030
- singletonisaacUi.div(...args);
1031
- const content = singletonisaacUi.toString();
1032
- singletonisaacUi.rows = [];
1033
- singletonUiInstance?.logger.log(content);
981
+
982
+ // packages/utils/src/lib/text-formats/md/list.ts
983
+ function li(text, order = "unordered") {
984
+ const style = order === "unordered" ? "-" : "- [ ]";
985
+ return `${style} ${text}`;
986
+ }
987
+ function indentation(text, level = 1) {
988
+ return `${TAB.repeat(level)}${text}`;
1034
989
  }
1035
990
 
1036
- // packages/utils/src/lib/file-system.ts
1037
- async function readTextFile(path) {
1038
- const buffer = await readFile(path);
1039
- return buffer.toString();
991
+ // packages/utils/src/lib/text-formats/md/paragraphs.ts
992
+ function paragraphs(...sections) {
993
+ return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
1040
994
  }
1041
- async function readJsonFile(path) {
1042
- const text = await readTextFile(path);
1043
- return JSON.parse(text);
995
+
996
+ // packages/utils/src/lib/text-formats/md/section.ts
997
+ function section(...contents) {
998
+ return `${lines(...contents)}${NEW_LINE}`;
1044
999
  }
1045
- async function ensureDirectoryExists(baseDir) {
1046
- try {
1047
- await mkdir(baseDir, { recursive: true });
1048
- return;
1049
- } catch (error) {
1050
- ui().logger.info(error.message);
1051
- if (error.code !== "EEXIST") {
1052
- throw error;
1053
- }
1054
- }
1000
+ function lines(...contents) {
1001
+ return `${contents.filter(Boolean).join(NEW_LINE)}`;
1055
1002
  }
1056
- function pluginWorkDir(slug) {
1057
- return join("node_modules", ".code-pushup", slug);
1003
+
1004
+ // packages/utils/src/lib/text-formats/md/table.ts
1005
+ var alignString = /* @__PURE__ */ new Map([
1006
+ ["left", ":--"],
1007
+ ["center", ":--:"],
1008
+ ["right", "--:"]
1009
+ ]);
1010
+ function tableRow(rows) {
1011
+ return `|${rows.join("|")}|`;
1012
+ }
1013
+ function table2(data) {
1014
+ if (data.rows.length === 0) {
1015
+ throw new Error("Data can't be empty");
1016
+ }
1017
+ const alignmentRow = getColumnAlignments(data).map(
1018
+ (s) => alignString.get(s) ?? String(alignString.get("center"))
1019
+ );
1020
+ return section(
1021
+ `${lines(
1022
+ tableRow(columnsToStringArray(data)),
1023
+ tableRow(alignmentRow),
1024
+ ...rowToStringArray(data).map(tableRow)
1025
+ )}`
1026
+ );
1058
1027
  }
1059
1028
 
1029
+ // packages/utils/src/lib/text-formats/index.ts
1030
+ var md = {
1031
+ bold: bold2,
1032
+ italic: italic2,
1033
+ strikeThrough,
1034
+ code: code2,
1035
+ link: link2,
1036
+ image,
1037
+ headline,
1038
+ h,
1039
+ h1,
1040
+ h2,
1041
+ h3,
1042
+ h4,
1043
+ h5,
1044
+ h6,
1045
+ indentation,
1046
+ lines,
1047
+ li,
1048
+ section,
1049
+ paragraphs,
1050
+ table: table2
1051
+ };
1052
+ var html = {
1053
+ bold,
1054
+ italic,
1055
+ code,
1056
+ link,
1057
+ details,
1058
+ table
1059
+ };
1060
+
1060
1061
  // packages/utils/src/lib/reports/utils.ts
1061
1062
  var { image: image2, bold: boldMd } = md;
1062
1063
  function calcDuration(start, stop) {
@@ -1156,10 +1157,134 @@ var PLUGIN_CONFIG_PATH = join2(
1156
1157
  WORKDIR,
1157
1158
  "plugin-config.json"
1158
1159
  );
1160
+ var INVALID_FUNCTION_NAME = "(empty-report)";
1159
1161
 
1160
1162
  // packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts
1161
1163
  import { join as join3 } from "node:path";
1162
1164
 
1165
+ // packages/plugin-coverage/src/lib/runner/lcov/merge-lcov.ts
1166
+ function mergeLcovResults(records) {
1167
+ const allFilenames = records.map((record) => record.file);
1168
+ if (allFilenames.length === new Set(allFilenames).size) {
1169
+ return records;
1170
+ }
1171
+ return records.reduce((accMerged, currRecord, currIndex) => {
1172
+ const filePath = currRecord.file;
1173
+ const lines6 = currRecord.lines.found;
1174
+ const duplicates = records.reduce(
1175
+ (acc, candidateRecord, candidateIndex) => {
1176
+ if (candidateRecord.file === filePath && candidateRecord.lines.found === lines6 && candidateIndex !== currIndex) {
1177
+ return [...acc, [candidateRecord, candidateIndex]];
1178
+ }
1179
+ return acc;
1180
+ },
1181
+ []
1182
+ );
1183
+ if (duplicates.map((duplicate) => duplicate[1]).some((index) => index < currIndex)) {
1184
+ return accMerged;
1185
+ }
1186
+ if (duplicates.length === 0) {
1187
+ return [...accMerged, currRecord];
1188
+ }
1189
+ return [
1190
+ ...accMerged,
1191
+ mergeDuplicateLcovRecords([
1192
+ currRecord,
1193
+ ...duplicates.map((duplicate) => duplicate[0])
1194
+ ])
1195
+ ];
1196
+ }, []);
1197
+ }
1198
+ function mergeDuplicateLcovRecords(records) {
1199
+ const linesDetails = mergeLcovLineDetails(
1200
+ records.map((record) => record.lines.details)
1201
+ );
1202
+ const linesHit = linesDetails.reduce(
1203
+ (acc, line) => acc + (line.hit > 0 ? 1 : 0),
1204
+ 0
1205
+ );
1206
+ const branchesDetails = mergeLcovBranchesDetails(
1207
+ records.map((record) => record.branches.details)
1208
+ );
1209
+ const branchesHit = branchesDetails.reduce(
1210
+ (acc, branch) => acc + (branch.taken > 0 ? 1 : 0),
1211
+ 0
1212
+ );
1213
+ const functionsDetails = mergeLcovFunctionsDetails(
1214
+ records.map((record) => record.functions.details)
1215
+ );
1216
+ const functionsHit = functionsDetails.reduce(
1217
+ (acc, func) => acc + (func.hit != null && func.hit > 0 ? 1 : 0),
1218
+ 0
1219
+ );
1220
+ const mergedRecord = {
1221
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1222
+ file: records[0].file,
1223
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1224
+ title: records[0].title,
1225
+ lines: {
1226
+ found: linesDetails.length,
1227
+ hit: linesHit,
1228
+ details: linesDetails
1229
+ },
1230
+ branches: {
1231
+ found: branchesDetails.length,
1232
+ hit: branchesHit,
1233
+ details: branchesDetails
1234
+ },
1235
+ functions: {
1236
+ found: functionsDetails.length,
1237
+ hit: functionsHit,
1238
+ details: functionsDetails
1239
+ }
1240
+ };
1241
+ return mergedRecord;
1242
+ }
1243
+ function mergeLcovLineDetails(details4) {
1244
+ const flatDetails = details4.flat();
1245
+ const uniqueLines = [
1246
+ ...new Set(flatDetails.map((flatDetail) => flatDetail.line))
1247
+ ];
1248
+ return uniqueLines.map((line) => {
1249
+ const hitSum = flatDetails.filter((lineDetail) => lineDetail.line === line).reduce((acc, lineDetail) => acc + lineDetail.hit, 0);
1250
+ return { line, hit: hitSum };
1251
+ });
1252
+ }
1253
+ function mergeLcovBranchesDetails(details4) {
1254
+ const flatDetails = details4.flat();
1255
+ const uniqueBranches = [
1256
+ ...new Set(
1257
+ flatDetails.map(
1258
+ ({ line, block, branch }) => JSON.stringify({ line, block, branch })
1259
+ )
1260
+ )
1261
+ ].map(
1262
+ (functionJSON) => JSON.parse(functionJSON)
1263
+ );
1264
+ return uniqueBranches.map(({ line, block, branch }) => {
1265
+ const takenSum = flatDetails.filter(
1266
+ (branchDetail) => branchDetail.line === line && branchDetail.block === block && branchDetail.branch === branch
1267
+ ).reduce((acc, branchDetail) => acc + branchDetail.taken, 0);
1268
+ return { line, block, branch, taken: takenSum };
1269
+ });
1270
+ }
1271
+ function mergeLcovFunctionsDetails(details4) {
1272
+ const flatDetails = details4.flat();
1273
+ const uniqueFunctions = [
1274
+ ...new Set(
1275
+ flatDetails.map(({ line, name }) => JSON.stringify({ line, name }))
1276
+ )
1277
+ ].map(
1278
+ (functionJSON) => JSON.parse(functionJSON)
1279
+ );
1280
+ return uniqueFunctions.map(({ line, name }) => {
1281
+ const hitSum = flatDetails.filter(
1282
+ (functionDetail) => functionDetail.line === line && functionDetail.name === name
1283
+ ).reduce((acc, functionDetail) => acc + (functionDetail.hit ?? 0), 0);
1284
+ return { line, name, hit: hitSum };
1285
+ });
1286
+ }
1287
+
1163
1288
  // packages/plugin-coverage/src/lib/runner/lcov/parse-lcov.ts
1164
1289
  import parseLcovExport from "parse-lcov";
1165
1290
  var godKnows = parseLcovExport;
@@ -1184,21 +1309,41 @@ function mergeConsecutiveNumbers(numberArr) {
1184
1309
 
1185
1310
  // packages/plugin-coverage/src/lib/runner/lcov/transform.ts
1186
1311
  function lcovReportToFunctionStat(record) {
1312
+ const validRecord = removeEmptyReport(record);
1187
1313
  return {
1188
- totalFound: record.functions.found,
1189
- totalHit: record.functions.hit,
1190
- issues: record.functions.hit < record.functions.found ? record.functions.details.filter((detail) => !detail.hit).map(
1314
+ totalFound: validRecord.functions.found,
1315
+ totalHit: validRecord.functions.hit,
1316
+ issues: validRecord.functions.hit < validRecord.functions.found ? validRecord.functions.details.filter((detail) => !detail.hit).map(
1191
1317
  (detail) => ({
1192
1318
  message: `Function ${detail.name} is not called in any test case.`,
1193
1319
  severity: "error",
1194
1320
  source: {
1195
- file: record.file,
1321
+ file: validRecord.file,
1196
1322
  position: { startLine: detail.line }
1197
1323
  }
1198
1324
  })
1199
1325
  ) : []
1200
1326
  };
1201
1327
  }
1328
+ function removeEmptyReport(record) {
1329
+ const validFunctions = record.functions.details.filter(
1330
+ (detail) => detail.name !== INVALID_FUNCTION_NAME
1331
+ );
1332
+ if (validFunctions.length === record.functions.found) {
1333
+ return record;
1334
+ }
1335
+ return {
1336
+ ...record,
1337
+ functions: {
1338
+ details: validFunctions,
1339
+ found: validFunctions.length,
1340
+ hit: validFunctions.reduce(
1341
+ (acc, fn) => acc + (fn.hit != null && fn.hit > 0 ? 1 : 0),
1342
+ 0
1343
+ )
1344
+ }
1345
+ };
1346
+ }
1202
1347
  function lcovReportToLineStat(record) {
1203
1348
  const missingCoverage = record.lines.hit < record.lines.found;
1204
1349
  const lines6 = missingCoverage ? record.lines.details.filter((detail) => !detail.hit).map((detail) => detail.line) : [];
@@ -1263,8 +1408,9 @@ function lcovCoverageToAuditOutput(stat2, coverageType) {
1263
1408
  // packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts
1264
1409
  async function lcovResultsToAuditOutputs(results, coverageTypes) {
1265
1410
  const lcovResults = await parseLcovFiles(results);
1411
+ const mergedResults = mergeLcovResults(lcovResults);
1266
1412
  const totalCoverageStats = getTotalCoverageFromLcovRecords(
1267
- lcovResults,
1413
+ mergedResults,
1268
1414
  coverageTypes
1269
1415
  );
1270
1416
  return coverageTypes.map((coverageType) => {
@@ -1280,6 +1426,11 @@ async function parseLcovFiles(results) {
1280
1426
  results.map(async (result) => {
1281
1427
  const resultsPath = typeof result === "string" ? result : result.resultsPath;
1282
1428
  const lcovFileContent = await readTextFile(resultsPath);
1429
+ if (lcovFileContent.trim() === "") {
1430
+ ui().logger.warning(
1431
+ `Coverage plugin: Empty lcov report file detected at ${resultsPath}.`
1432
+ );
1433
+ }
1283
1434
  const parsedRecords = parseLcov(toUnixNewlines(lcovFileContent));
1284
1435
  return parsedRecords.map((record) => ({
1285
1436
  ...record,