ortoni-report 4.0.0 → 4.0.2-beta.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.
@@ -0,0 +1,2134 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
31
+
32
+ // src/ortoni-report.ts
33
+ var ortoni_report_exports = {};
34
+ __export(ortoni_report_exports, {
35
+ OrtoniReport: () => OrtoniReport,
36
+ default: () => OrtoniReport
37
+ });
38
+ module.exports = __toCommonJS(ortoni_report_exports);
39
+
40
+ // src/helpers/fileManager.ts
41
+ var import_fs = __toESM(require("fs"), 1);
42
+ var import_path = __toESM(require("path"), 1);
43
+ var import_url = require("url");
44
+ var import_meta = {};
45
+ var __filename = (0, import_url.fileURLToPath)(import_meta.url);
46
+ var __dirname = (0, import_path.dirname)(__filename);
47
+ var FileManager = class {
48
+ constructor(folderPath) {
49
+ this.folderPath = folderPath;
50
+ }
51
+ ensureReportDirectory() {
52
+ const ortoniDataFolder = import_path.default.join(this.folderPath, "ortoni-data");
53
+ if (!import_fs.default.existsSync(this.folderPath)) {
54
+ import_fs.default.mkdirSync(this.folderPath, { recursive: true });
55
+ } else {
56
+ if (import_fs.default.existsSync(ortoniDataFolder)) {
57
+ import_fs.default.rmSync(ortoniDataFolder, { recursive: true, force: true });
58
+ }
59
+ }
60
+ }
61
+ writeReportFile(filename, data) {
62
+ const templatePath = import_path.default.resolve(__dirname, "../index.html");
63
+ let html = import_fs.default.readFileSync(templatePath, "utf-8");
64
+ const reportJSON = JSON.stringify({
65
+ data
66
+ });
67
+ html = html.replace("__ORTONI_TEST_REPORTDATA__", reportJSON);
68
+ const outputPath = import_path.default.join(process.cwd(), this.folderPath, filename);
69
+ import_fs.default.writeFileSync(outputPath, html);
70
+ return outputPath;
71
+ }
72
+ writeRawFile(filename, data) {
73
+ const outputPath = import_path.default.join(process.cwd(), this.folderPath, filename);
74
+ import_fs.default.mkdirSync(import_path.default.dirname(outputPath), { recursive: true });
75
+ const content = typeof data === "string" ? data : JSON.stringify(data, null, 2);
76
+ import_fs.default.writeFileSync(outputPath, content, "utf-8");
77
+ return outputPath;
78
+ }
79
+ copyTraceViewerAssets(skip) {
80
+ if (skip) return;
81
+ const traceViewerFolder = import_path.default.join(
82
+ require.resolve("playwright-core"),
83
+ "..",
84
+ "lib",
85
+ "vite",
86
+ "traceViewer"
87
+ );
88
+ const traceViewerTargetFolder = import_path.default.join(this.folderPath, "trace");
89
+ const traceViewerAssetsTargetFolder = import_path.default.join(
90
+ traceViewerTargetFolder,
91
+ "assets"
92
+ );
93
+ import_fs.default.mkdirSync(traceViewerAssetsTargetFolder, { recursive: true });
94
+ for (const file of import_fs.default.readdirSync(traceViewerFolder)) {
95
+ if (file.endsWith(".map") || file.includes("watch") || file.includes("assets"))
96
+ continue;
97
+ import_fs.default.copyFileSync(
98
+ import_path.default.join(traceViewerFolder, file),
99
+ import_path.default.join(traceViewerTargetFolder, file)
100
+ );
101
+ }
102
+ const assetsFolder = import_path.default.join(traceViewerFolder, "assets");
103
+ for (const file of import_fs.default.readdirSync(assetsFolder)) {
104
+ if (file.endsWith(".map") || file.includes("xtermModule")) continue;
105
+ import_fs.default.copyFileSync(
106
+ import_path.default.join(assetsFolder, file),
107
+ import_path.default.join(traceViewerAssetsTargetFolder, file)
108
+ );
109
+ }
110
+ }
111
+ };
112
+
113
+ // src/utils/groupProjects.ts
114
+ function groupResults(config, results) {
115
+ if (config.showProject) {
116
+ const groupedResults = results.reduce((acc, result, index) => {
117
+ const testId = `${result.filePath}:${result.projectName}:${result.title}`;
118
+ const key = `${testId}-${result.key}-${result.retryAttemptCount}`;
119
+ const { filePath, suite, projectName } = result;
120
+ acc[filePath] = acc[filePath] || {};
121
+ acc[filePath][suite] = acc[filePath][suite] || {};
122
+ acc[filePath][suite][projectName] = acc[filePath][suite][projectName] || [];
123
+ acc[filePath][suite][projectName].push({ ...result, index, testId, key });
124
+ return acc;
125
+ }, {});
126
+ return groupedResults;
127
+ } else {
128
+ const groupedResults = results.reduce((acc, result, index) => {
129
+ const testId = `${result.filePath}:${result.projectName}:${result.title}`;
130
+ const key = `${testId}-${result.key}-${result.retryAttemptCount}`;
131
+ const { filePath, suite } = result;
132
+ acc[filePath] = acc[filePath] || {};
133
+ acc[filePath][suite] = acc[filePath][suite] || [];
134
+ acc[filePath][suite].push({ ...result, index, testId, key });
135
+ return acc;
136
+ }, {});
137
+ return groupedResults;
138
+ }
139
+ }
140
+
141
+ // src/helpers/HTMLGenerator.ts
142
+ var HTMLGenerator = class {
143
+ constructor(ortoniConfig, dbManager) {
144
+ this.ortoniConfig = ortoniConfig;
145
+ this.dbManager = dbManager;
146
+ }
147
+ async generateFinalReport(filteredResults, totalDuration, results, projectSet) {
148
+ const data = await this.prepareReportData(
149
+ filteredResults,
150
+ totalDuration,
151
+ results,
152
+ projectSet
153
+ );
154
+ return data;
155
+ }
156
+ async getReportData() {
157
+ return {
158
+ summary: await this.dbManager.getSummaryData(),
159
+ trends: await this.dbManager.getTrends(),
160
+ flakyTests: await this.dbManager.getFlakyTests(),
161
+ slowTests: await this.dbManager.getSlowTests()
162
+ };
163
+ }
164
+ async prepareReportData(filteredResults, totalDuration, results, projectSet) {
165
+ const totalTests = filteredResults.length;
166
+ const passedTests = results.filter((r) => r.status === "passed").length;
167
+ const flakyTests = results.filter((r) => r.status === "flaky").length;
168
+ const failed = filteredResults.filter(
169
+ (r) => r.status === "failed" || r.status === "timedOut"
170
+ ).length;
171
+ const successRate = ((passedTests + flakyTests) / totalTests * 100).toFixed(2);
172
+ const allTags = /* @__PURE__ */ new Set();
173
+ results.forEach(
174
+ (result) => result.testTags.forEach((tag) => allTags.add(tag))
175
+ );
176
+ const projectResults = this.calculateProjectResults(
177
+ filteredResults,
178
+ results,
179
+ projectSet
180
+ );
181
+ const lastRunDate = (/* @__PURE__ */ new Date()).toLocaleString();
182
+ const testHistories = await Promise.all(
183
+ results.map(async (result) => {
184
+ const testId = `${result.filePath}:${result.projectName}:${result.title}`;
185
+ const history = await this.dbManager.getTestHistory(testId);
186
+ return {
187
+ testId,
188
+ history
189
+ };
190
+ })
191
+ );
192
+ return {
193
+ summary: {
194
+ overAllResult: {
195
+ pass: passedTests,
196
+ fail: failed,
197
+ skip: results.filter((r) => r.status === "skipped").length,
198
+ retry: results.filter((r) => r.retryAttemptCount).length,
199
+ flaky: flakyTests,
200
+ total: filteredResults.length
201
+ },
202
+ successRate,
203
+ lastRunDate,
204
+ totalDuration,
205
+ stats: this.extractProjectStats(projectResults)
206
+ },
207
+ testResult: {
208
+ tests: groupResults(this.ortoniConfig, results),
209
+ testHistories,
210
+ allTags: Array.from(allTags),
211
+ set: projectSet
212
+ },
213
+ userConfig: {
214
+ projectName: this.ortoniConfig.projectName,
215
+ authorName: this.ortoniConfig.authorName,
216
+ type: this.ortoniConfig.testType,
217
+ title: this.ortoniConfig.title
218
+ },
219
+ userMeta: {
220
+ meta: this.ortoniConfig.meta
221
+ },
222
+ preferences: {
223
+ logo: this.ortoniConfig.logo || void 0,
224
+ showProject: this.ortoniConfig.showProject || false
225
+ },
226
+ analytics: {
227
+ reportData: await this.getReportData()
228
+ }
229
+ };
230
+ }
231
+ calculateProjectResults(filteredResults, results, projectSet) {
232
+ return Array.from(projectSet).map((projectName) => {
233
+ const projectTests = filteredResults.filter(
234
+ (r) => r.projectName === projectName
235
+ );
236
+ const allProjectTests = results.filter(
237
+ (r) => r.projectName === projectName
238
+ );
239
+ return {
240
+ projectName,
241
+ passedTests: projectTests.filter((r) => r.status === "passed").length,
242
+ failedTests: projectTests.filter(
243
+ (r) => r.status === "failed" || r.status === "timedOut"
244
+ ).length,
245
+ skippedTests: allProjectTests.filter((r) => r.status === "skipped").length,
246
+ retryTests: allProjectTests.filter((r) => r.retryAttemptCount).length,
247
+ flakyTests: allProjectTests.filter((r) => r.status === "flaky").length,
248
+ totalTests: projectTests.length
249
+ };
250
+ });
251
+ }
252
+ extractProjectStats(projectResults) {
253
+ return {
254
+ projectNames: projectResults.map((result) => result.projectName),
255
+ totalTests: projectResults.map((result) => result.totalTests),
256
+ passedTests: projectResults.map((result) => result.passedTests),
257
+ failedTests: projectResults.map((result) => result.failedTests),
258
+ skippedTests: projectResults.map((result) => result.skippedTests),
259
+ retryTests: projectResults.map((result) => result.retryTests),
260
+ flakyTests: projectResults.map((result) => result.flakyTests)
261
+ };
262
+ }
263
+ };
264
+
265
+ // src/helpers/resultProcessor .ts
266
+ var import_ansi_to_html = __toESM(require("ansi-to-html"), 1);
267
+ var import_path4 = __toESM(require("path"), 1);
268
+
269
+ // src/utils/attachFiles.ts
270
+ var import_path2 = __toESM(require("path"), 1);
271
+ var import_fs3 = __toESM(require("fs"), 1);
272
+
273
+ // src/helpers/markdownConverter.ts
274
+ var import_fs2 = __toESM(require("fs"), 1);
275
+
276
+ // node_modules/marked/lib/marked.esm.js
277
+ function M() {
278
+ return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
279
+ }
280
+ var w = M();
281
+ function H(a3) {
282
+ w = a3;
283
+ }
284
+ var C = { exec: () => null };
285
+ function h(a3, e = "") {
286
+ let t = typeof a3 == "string" ? a3 : a3.source, n = { replace: (s, i) => {
287
+ let r = typeof i == "string" ? i : i.source;
288
+ return r = r.replace(m.caret, "$1"), t = t.replace(s, r), n;
289
+ }, getRegex: () => new RegExp(t, e) };
290
+ return n;
291
+ }
292
+ var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceTabs: /^\t+/, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] /, listReplaceTask: /^\[[ xX]\] +/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (a3) => new RegExp(`^( {0,3}${a3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: (a3) => new RegExp(`^ {0,${Math.min(3, a3 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), hrRegex: (a3) => new RegExp(`^ {0,${Math.min(3, a3 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), fencesBeginRegex: (a3) => new RegExp(`^ {0,${Math.min(3, a3 - 1)}}(?:\`\`\`|~~~)`), headingBeginRegex: (a3) => new RegExp(`^ {0,${Math.min(3, a3 - 1)}}#`), htmlBeginRegex: (a3) => new RegExp(`^ {0,${Math.min(3, a3 - 1)}}<(?:[a-z].*>|!--)`, "i") };
293
+ var xe = /^(?:[ \t]*(?:\n|$))+/;
294
+ var be = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
295
+ var Te = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
296
+ var I = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
297
+ var we = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
298
+ var j = /(?:[*+-]|\d{1,9}[.)])/;
299
+ var re = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
300
+ var ie = h(re).replace(/bull/g, j).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
301
+ var ye = h(re).replace(/bull/g, j).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
302
+ var F = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
303
+ var Re = /^[^\n]+/;
304
+ var Q = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
305
+ var Se = h(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", Q).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
306
+ var $e = h(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, j).getRegex();
307
+ var v = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
308
+ var U = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
309
+ var _e = h("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", U).replace("tag", v).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
310
+ var oe = h(F).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
311
+ var Le = h(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", oe).getRegex();
312
+ var K = { blockquote: Le, code: be, def: Se, fences: Te, heading: we, hr: I, html: _e, lheading: ie, list: $e, newline: xe, paragraph: oe, table: C, text: Re };
313
+ var se = h("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
314
+ var ze = { ...K, lheading: ye, table: se, paragraph: h(F).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex() };
315
+ var Me = { ...K, html: h(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", U).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: C, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: h(F).replace("hr", I).replace("heading", ` *#{1,6} *[^
316
+ ]`).replace("lheading", ie).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
317
+ var Pe = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
318
+ var Ae = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
319
+ var le = /^( {2,}|\\)\n(?!\s*$)/;
320
+ var Ee = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
321
+ var D = /[\p{P}\p{S}]/u;
322
+ var X = /[\s\p{P}\p{S}]/u;
323
+ var ae = /[^\s\p{P}\p{S}]/u;
324
+ var Ce = h(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, X).getRegex();
325
+ var ce = /(?!~)[\p{P}\p{S}]/u;
326
+ var Ie = /(?!~)[\s\p{P}\p{S}]/u;
327
+ var Oe = /(?:[^\s\p{P}\p{S}]|~)/u;
328
+ var Be = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g;
329
+ var pe = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/;
330
+ var qe = h(pe, "u").replace(/punct/g, D).getRegex();
331
+ var ve = h(pe, "u").replace(/punct/g, ce).getRegex();
332
+ var ue = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
333
+ var De = h(ue, "gu").replace(/notPunctSpace/g, ae).replace(/punctSpace/g, X).replace(/punct/g, D).getRegex();
334
+ var Ze = h(ue, "gu").replace(/notPunctSpace/g, Oe).replace(/punctSpace/g, Ie).replace(/punct/g, ce).getRegex();
335
+ var Ge = h("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, ae).replace(/punctSpace/g, X).replace(/punct/g, D).getRegex();
336
+ var He = h(/\\(punct)/, "gu").replace(/punct/g, D).getRegex();
337
+ var Ne = h(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
338
+ var je = h(U).replace("(?:-->|$)", "-->").getRegex();
339
+ var Fe = h("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", je).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
340
+ var q = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
341
+ var Qe = h(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label", q).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
342
+ var he = h(/^!?\[(label)\]\[(ref)\]/).replace("label", q).replace("ref", Q).getRegex();
343
+ var ke = h(/^!?\[(ref)\](?:\[\])?/).replace("ref", Q).getRegex();
344
+ var Ue = h("reflink|nolink(?!\\()", "g").replace("reflink", he).replace("nolink", ke).getRegex();
345
+ var W = { _backpedal: C, anyPunctuation: He, autolink: Ne, blockSkip: Be, br: le, code: Ae, del: C, emStrongLDelim: qe, emStrongRDelimAst: De, emStrongRDelimUnd: Ge, escape: Pe, link: Qe, nolink: ke, punctuation: Ce, reflink: he, reflinkSearch: Ue, tag: Fe, text: Ee, url: C };
346
+ var Ke = { ...W, link: h(/^!?\[(label)\]\((.*?)\)/).replace("label", q).getRegex(), reflink: h(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", q).getRegex() };
347
+ var N = { ...W, emStrongRDelimAst: Ze, emStrongLDelim: ve, url: h(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, "i").replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/, text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/ };
348
+ var Xe = { ...N, br: h(le).replace("{2,}", "*").getRegex(), text: h(N.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
349
+ var O = { normal: K, gfm: ze, pedantic: Me };
350
+ var P = { normal: W, gfm: N, breaks: Xe, pedantic: Ke };
351
+ var We = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
352
+ var ge = (a3) => We[a3];
353
+ function R(a3, e) {
354
+ if (e) {
355
+ if (m.escapeTest.test(a3)) return a3.replace(m.escapeReplace, ge);
356
+ } else if (m.escapeTestNoEncode.test(a3)) return a3.replace(m.escapeReplaceNoEncode, ge);
357
+ return a3;
358
+ }
359
+ function J(a3) {
360
+ try {
361
+ a3 = encodeURI(a3).replace(m.percentDecode, "%");
362
+ } catch {
363
+ return null;
364
+ }
365
+ return a3;
366
+ }
367
+ function V(a3, e) {
368
+ let t = a3.replace(m.findPipe, (i, r, o) => {
369
+ let l = false, c = r;
370
+ for (; --c >= 0 && o[c] === "\\"; ) l = !l;
371
+ return l ? "|" : " |";
372
+ }), n = t.split(m.splitPipe), s = 0;
373
+ if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
374
+ else for (; n.length < e; ) n.push("");
375
+ for (; s < n.length; s++) n[s] = n[s].trim().replace(m.slashPipe, "|");
376
+ return n;
377
+ }
378
+ function A(a3, e, t) {
379
+ let n = a3.length;
380
+ if (n === 0) return "";
381
+ let s = 0;
382
+ for (; s < n; ) {
383
+ let i = a3.charAt(n - s - 1);
384
+ if (i === e && !t) s++;
385
+ else if (i !== e && t) s++;
386
+ else break;
387
+ }
388
+ return a3.slice(0, n - s);
389
+ }
390
+ function fe(a3, e) {
391
+ if (a3.indexOf(e[1]) === -1) return -1;
392
+ let t = 0;
393
+ for (let n = 0; n < a3.length; n++) if (a3[n] === "\\") n++;
394
+ else if (a3[n] === e[0]) t++;
395
+ else if (a3[n] === e[1] && (t--, t < 0)) return n;
396
+ return t > 0 ? -2 : -1;
397
+ }
398
+ function de(a3, e, t, n, s) {
399
+ let i = e.href, r = e.title || null, o = a3[1].replace(s.other.outputLinkReplace, "$1");
400
+ n.state.inLink = true;
401
+ let l = { type: a3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: i, title: r, text: o, tokens: n.inlineTokens(o) };
402
+ return n.state.inLink = false, l;
403
+ }
404
+ function Je(a3, e, t) {
405
+ let n = a3.match(t.other.indentCodeCompensation);
406
+ if (n === null) return e;
407
+ let s = n[1];
408
+ return e.split(`
409
+ `).map((i) => {
410
+ let r = i.match(t.other.beginningSpace);
411
+ if (r === null) return i;
412
+ let [o] = r;
413
+ return o.length >= s.length ? i.slice(s.length) : i;
414
+ }).join(`
415
+ `);
416
+ }
417
+ var S = class {
418
+ constructor(e) {
419
+ __publicField(this, "options");
420
+ __publicField(this, "rules");
421
+ __publicField(this, "lexer");
422
+ this.options = e || w;
423
+ }
424
+ space(e) {
425
+ let t = this.rules.block.newline.exec(e);
426
+ if (t && t[0].length > 0) return { type: "space", raw: t[0] };
427
+ }
428
+ code(e) {
429
+ let t = this.rules.block.code.exec(e);
430
+ if (t) {
431
+ let n = t[0].replace(this.rules.other.codeRemoveIndent, "");
432
+ return { type: "code", raw: t[0], codeBlockStyle: "indented", text: this.options.pedantic ? n : A(n, `
433
+ `) };
434
+ }
435
+ }
436
+ fences(e) {
437
+ let t = this.rules.block.fences.exec(e);
438
+ if (t) {
439
+ let n = t[0], s = Je(n, t[3] || "", this.rules);
440
+ return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
441
+ }
442
+ }
443
+ heading(e) {
444
+ let t = this.rules.block.heading.exec(e);
445
+ if (t) {
446
+ let n = t[2].trim();
447
+ if (this.rules.other.endingHash.test(n)) {
448
+ let s = A(n, "#");
449
+ (this.options.pedantic || !s || this.rules.other.endingSpaceChar.test(s)) && (n = s.trim());
450
+ }
451
+ return { type: "heading", raw: t[0], depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
452
+ }
453
+ }
454
+ hr(e) {
455
+ let t = this.rules.block.hr.exec(e);
456
+ if (t) return { type: "hr", raw: A(t[0], `
457
+ `) };
458
+ }
459
+ blockquote(e) {
460
+ let t = this.rules.block.blockquote.exec(e);
461
+ if (t) {
462
+ let n = A(t[0], `
463
+ `).split(`
464
+ `), s = "", i = "", r = [];
465
+ for (; n.length > 0; ) {
466
+ let o = false, l = [], c;
467
+ for (c = 0; c < n.length; c++) if (this.rules.other.blockquoteStart.test(n[c])) l.push(n[c]), o = true;
468
+ else if (!o) l.push(n[c]);
469
+ else break;
470
+ n = n.slice(c);
471
+ let p = l.join(`
472
+ `), u = p.replace(this.rules.other.blockquoteSetextReplace, `
473
+ $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
474
+ s = s ? `${s}
475
+ ${p}` : p, i = i ? `${i}
476
+ ${u}` : u;
477
+ let d = this.lexer.state.top;
478
+ if (this.lexer.state.top = true, this.lexer.blockTokens(u, r, true), this.lexer.state.top = d, n.length === 0) break;
479
+ let g = r.at(-1);
480
+ if (g?.type === "code") break;
481
+ if (g?.type === "blockquote") {
482
+ let x = g, f = x.raw + `
483
+ ` + n.join(`
484
+ `), y = this.blockquote(f);
485
+ r[r.length - 1] = y, s = s.substring(0, s.length - x.raw.length) + y.raw, i = i.substring(0, i.length - x.text.length) + y.text;
486
+ break;
487
+ } else if (g?.type === "list") {
488
+ let x = g, f = x.raw + `
489
+ ` + n.join(`
490
+ `), y = this.list(f);
491
+ r[r.length - 1] = y, s = s.substring(0, s.length - g.raw.length) + y.raw, i = i.substring(0, i.length - x.raw.length) + y.raw, n = f.substring(r.at(-1).raw.length).split(`
492
+ `);
493
+ continue;
494
+ }
495
+ }
496
+ return { type: "blockquote", raw: s, tokens: r, text: i };
497
+ }
498
+ }
499
+ list(e) {
500
+ let t = this.rules.block.list.exec(e);
501
+ if (t) {
502
+ let n = t[1].trim(), s = n.length > 1, i = { type: "list", raw: "", ordered: s, start: s ? +n.slice(0, -1) : "", loose: false, items: [] };
503
+ n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]");
504
+ let r = this.rules.other.listItemRegex(n), o = false;
505
+ for (; e; ) {
506
+ let c = false, p = "", u = "";
507
+ if (!(t = r.exec(e)) || this.rules.block.hr.test(e)) break;
508
+ p = t[0], e = e.substring(p.length);
509
+ let d = t[2].split(`
510
+ `, 1)[0].replace(this.rules.other.listReplaceTabs, (Z) => " ".repeat(3 * Z.length)), g = e.split(`
511
+ `, 1)[0], x = !d.trim(), f = 0;
512
+ if (this.options.pedantic ? (f = 2, u = d.trimStart()) : x ? f = t[1].length + 1 : (f = t[2].search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, u = d.slice(f), f += t[1].length), x && this.rules.other.blankLine.test(g) && (p += g + `
513
+ `, e = e.substring(g.length + 1), c = true), !c) {
514
+ let Z = this.rules.other.nextBulletRegex(f), ee = this.rules.other.hrRegex(f), te = this.rules.other.fencesBeginRegex(f), ne = this.rules.other.headingBeginRegex(f), me = this.rules.other.htmlBeginRegex(f);
515
+ for (; e; ) {
516
+ let G = e.split(`
517
+ `, 1)[0], E;
518
+ if (g = G, this.options.pedantic ? (g = g.replace(this.rules.other.listReplaceNesting, " "), E = g) : E = g.replace(this.rules.other.tabCharGlobal, " "), te.test(g) || ne.test(g) || me.test(g) || Z.test(g) || ee.test(g)) break;
519
+ if (E.search(this.rules.other.nonSpaceChar) >= f || !g.trim()) u += `
520
+ ` + E.slice(f);
521
+ else {
522
+ if (x || d.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || te.test(d) || ne.test(d) || ee.test(d)) break;
523
+ u += `
524
+ ` + g;
525
+ }
526
+ !x && !g.trim() && (x = true), p += G + `
527
+ `, e = e.substring(G.length + 1), d = E.slice(f);
528
+ }
529
+ }
530
+ i.loose || (o ? i.loose = true : this.rules.other.doubleBlankLine.test(p) && (o = true));
531
+ let y = null, Y;
532
+ this.options.gfm && (y = this.rules.other.listIsTask.exec(u), y && (Y = y[0] !== "[ ] ", u = u.replace(this.rules.other.listReplaceTask, ""))), i.items.push({ type: "list_item", raw: p, task: !!y, checked: Y, loose: false, text: u, tokens: [] }), i.raw += p;
533
+ }
534
+ let l = i.items.at(-1);
535
+ if (l) l.raw = l.raw.trimEnd(), l.text = l.text.trimEnd();
536
+ else return;
537
+ i.raw = i.raw.trimEnd();
538
+ for (let c = 0; c < i.items.length; c++) if (this.lexer.state.top = false, i.items[c].tokens = this.lexer.blockTokens(i.items[c].text, []), !i.loose) {
539
+ let p = i.items[c].tokens.filter((d) => d.type === "space"), u = p.length > 0 && p.some((d) => this.rules.other.anyLine.test(d.raw));
540
+ i.loose = u;
541
+ }
542
+ if (i.loose) for (let c = 0; c < i.items.length; c++) i.items[c].loose = true;
543
+ return i;
544
+ }
545
+ }
546
+ html(e) {
547
+ let t = this.rules.block.html.exec(e);
548
+ if (t) return { type: "html", block: true, raw: t[0], pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: t[0] };
549
+ }
550
+ def(e) {
551
+ let t = this.rules.block.def.exec(e);
552
+ if (t) {
553
+ let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), s = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", i = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
554
+ return { type: "def", tag: n, raw: t[0], href: s, title: i };
555
+ }
556
+ }
557
+ table(e) {
558
+ let t = this.rules.block.table.exec(e);
559
+ if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
560
+ let n = V(t[1]), s = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), i = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
561
+ `) : [], r = { type: "table", raw: t[0], header: [], align: [], rows: [] };
562
+ if (n.length === s.length) {
563
+ for (let o of s) this.rules.other.tableAlignRight.test(o) ? r.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? r.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? r.align.push("left") : r.align.push(null);
564
+ for (let o = 0; o < n.length; o++) r.header.push({ text: n[o], tokens: this.lexer.inline(n[o]), header: true, align: r.align[o] });
565
+ for (let o of i) r.rows.push(V(o, r.header.length).map((l, c) => ({ text: l, tokens: this.lexer.inline(l), header: false, align: r.align[c] })));
566
+ return r;
567
+ }
568
+ }
569
+ lheading(e) {
570
+ let t = this.rules.block.lheading.exec(e);
571
+ if (t) return { type: "heading", raw: t[0], depth: t[2].charAt(0) === "=" ? 1 : 2, text: t[1], tokens: this.lexer.inline(t[1]) };
572
+ }
573
+ paragraph(e) {
574
+ let t = this.rules.block.paragraph.exec(e);
575
+ if (t) {
576
+ let n = t[1].charAt(t[1].length - 1) === `
577
+ ` ? t[1].slice(0, -1) : t[1];
578
+ return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
579
+ }
580
+ }
581
+ text(e) {
582
+ let t = this.rules.block.text.exec(e);
583
+ if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
584
+ }
585
+ escape(e) {
586
+ let t = this.rules.inline.escape.exec(e);
587
+ if (t) return { type: "escape", raw: t[0], text: t[1] };
588
+ }
589
+ tag(e) {
590
+ let t = this.rules.inline.tag.exec(e);
591
+ if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
592
+ }
593
+ link(e) {
594
+ let t = this.rules.inline.link.exec(e);
595
+ if (t) {
596
+ let n = t[2].trim();
597
+ if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
598
+ if (!this.rules.other.endAngleBracket.test(n)) return;
599
+ let r = A(n.slice(0, -1), "\\");
600
+ if ((n.length - r.length) % 2 === 0) return;
601
+ } else {
602
+ let r = fe(t[2], "()");
603
+ if (r === -2) return;
604
+ if (r > -1) {
605
+ let l = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + r;
606
+ t[2] = t[2].substring(0, r), t[0] = t[0].substring(0, l).trim(), t[3] = "";
607
+ }
608
+ }
609
+ let s = t[2], i = "";
610
+ if (this.options.pedantic) {
611
+ let r = this.rules.other.pedanticHrefTitle.exec(s);
612
+ r && (s = r[1], i = r[3]);
613
+ } else i = t[3] ? t[3].slice(1, -1) : "";
614
+ return s = s.trim(), this.rules.other.startAngleBracket.test(s) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), de(t, { href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), title: i && i.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules);
615
+ }
616
+ }
617
+ reflink(e, t) {
618
+ let n;
619
+ if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
620
+ let s = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), i = t[s.toLowerCase()];
621
+ if (!i) {
622
+ let r = n[0].charAt(0);
623
+ return { type: "text", raw: r, text: r };
624
+ }
625
+ return de(n, i, n[0], this.lexer, this.rules);
626
+ }
627
+ }
628
+ emStrong(e, t, n = "") {
629
+ let s = this.rules.inline.emStrongLDelim.exec(e);
630
+ if (!s || s[3] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
631
+ if (!(s[1] || s[2] || "") || !n || this.rules.inline.punctuation.exec(n)) {
632
+ let r = [...s[0]].length - 1, o, l, c = r, p = 0, u = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
633
+ for (u.lastIndex = 0, t = t.slice(-1 * e.length + r); (s = u.exec(t)) != null; ) {
634
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) continue;
635
+ if (l = [...o].length, s[3] || s[4]) {
636
+ c += l;
637
+ continue;
638
+ } else if ((s[5] || s[6]) && r % 3 && !((r + l) % 3)) {
639
+ p += l;
640
+ continue;
641
+ }
642
+ if (c -= l, c > 0) continue;
643
+ l = Math.min(l, l + c + p);
644
+ let d = [...s[0]][0].length, g = e.slice(0, r + s.index + d + l);
645
+ if (Math.min(r, l) % 2) {
646
+ let f = g.slice(1, -1);
647
+ return { type: "em", raw: g, text: f, tokens: this.lexer.inlineTokens(f) };
648
+ }
649
+ let x = g.slice(2, -2);
650
+ return { type: "strong", raw: g, text: x, tokens: this.lexer.inlineTokens(x) };
651
+ }
652
+ }
653
+ }
654
+ codespan(e) {
655
+ let t = this.rules.inline.code.exec(e);
656
+ if (t) {
657
+ let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), s = this.rules.other.nonSpaceChar.test(n), i = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n);
658
+ return s && i && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
659
+ }
660
+ }
661
+ br(e) {
662
+ let t = this.rules.inline.br.exec(e);
663
+ if (t) return { type: "br", raw: t[0] };
664
+ }
665
+ del(e) {
666
+ let t = this.rules.inline.del.exec(e);
667
+ if (t) return { type: "del", raw: t[0], text: t[2], tokens: this.lexer.inlineTokens(t[2]) };
668
+ }
669
+ autolink(e) {
670
+ let t = this.rules.inline.autolink.exec(e);
671
+ if (t) {
672
+ let n, s;
673
+ return t[2] === "@" ? (n = t[1], s = "mailto:" + n) : (n = t[1], s = n), { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
674
+ }
675
+ }
676
+ url(e) {
677
+ let t;
678
+ if (t = this.rules.inline.url.exec(e)) {
679
+ let n, s;
680
+ if (t[2] === "@") n = t[0], s = "mailto:" + n;
681
+ else {
682
+ let i;
683
+ do
684
+ i = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
685
+ while (i !== t[0]);
686
+ n = t[0], t[1] === "www." ? s = "http://" + t[0] : s = t[0];
687
+ }
688
+ return { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
689
+ }
690
+ }
691
+ inlineText(e) {
692
+ let t = this.rules.inline.text.exec(e);
693
+ if (t) {
694
+ let n = this.lexer.state.inRawBlock;
695
+ return { type: "text", raw: t[0], text: t[0], escaped: n };
696
+ }
697
+ }
698
+ };
699
+ var b = class a {
700
+ constructor(e) {
701
+ __publicField(this, "tokens");
702
+ __publicField(this, "options");
703
+ __publicField(this, "state");
704
+ __publicField(this, "tokenizer");
705
+ __publicField(this, "inlineQueue");
706
+ this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || w, this.options.tokenizer = this.options.tokenizer || new S(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true };
707
+ let t = { other: m, block: O.normal, inline: P.normal };
708
+ this.options.pedantic ? (t.block = O.pedantic, t.inline = P.pedantic) : this.options.gfm && (t.block = O.gfm, this.options.breaks ? t.inline = P.breaks : t.inline = P.gfm), this.tokenizer.rules = t;
709
+ }
710
+ static get rules() {
711
+ return { block: O, inline: P };
712
+ }
713
+ static lex(e, t) {
714
+ return new a(t).lex(e);
715
+ }
716
+ static lexInline(e, t) {
717
+ return new a(t).inlineTokens(e);
718
+ }
719
+ lex(e) {
720
+ e = e.replace(m.carriageReturn, `
721
+ `), this.blockTokens(e, this.tokens);
722
+ for (let t = 0; t < this.inlineQueue.length; t++) {
723
+ let n = this.inlineQueue[t];
724
+ this.inlineTokens(n.src, n.tokens);
725
+ }
726
+ return this.inlineQueue = [], this.tokens;
727
+ }
728
+ blockTokens(e, t = [], n = false) {
729
+ for (this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, "")); e; ) {
730
+ let s;
731
+ if (this.options.extensions?.block?.some((r) => (s = r.call({ lexer: this }, e, t)) ? (e = e.substring(s.raw.length), t.push(s), true) : false)) continue;
732
+ if (s = this.tokenizer.space(e)) {
733
+ e = e.substring(s.raw.length);
734
+ let r = t.at(-1);
735
+ s.raw.length === 1 && r !== void 0 ? r.raw += `
736
+ ` : t.push(s);
737
+ continue;
738
+ }
739
+ if (s = this.tokenizer.code(e)) {
740
+ e = e.substring(s.raw.length);
741
+ let r = t.at(-1);
742
+ r?.type === "paragraph" || r?.type === "text" ? (r.raw += `
743
+ ` + s.raw, r.text += `
744
+ ` + s.text, this.inlineQueue.at(-1).src = r.text) : t.push(s);
745
+ continue;
746
+ }
747
+ if (s = this.tokenizer.fences(e)) {
748
+ e = e.substring(s.raw.length), t.push(s);
749
+ continue;
750
+ }
751
+ if (s = this.tokenizer.heading(e)) {
752
+ e = e.substring(s.raw.length), t.push(s);
753
+ continue;
754
+ }
755
+ if (s = this.tokenizer.hr(e)) {
756
+ e = e.substring(s.raw.length), t.push(s);
757
+ continue;
758
+ }
759
+ if (s = this.tokenizer.blockquote(e)) {
760
+ e = e.substring(s.raw.length), t.push(s);
761
+ continue;
762
+ }
763
+ if (s = this.tokenizer.list(e)) {
764
+ e = e.substring(s.raw.length), t.push(s);
765
+ continue;
766
+ }
767
+ if (s = this.tokenizer.html(e)) {
768
+ e = e.substring(s.raw.length), t.push(s);
769
+ continue;
770
+ }
771
+ if (s = this.tokenizer.def(e)) {
772
+ e = e.substring(s.raw.length);
773
+ let r = t.at(-1);
774
+ r?.type === "paragraph" || r?.type === "text" ? (r.raw += `
775
+ ` + s.raw, r.text += `
776
+ ` + s.raw, this.inlineQueue.at(-1).src = r.text) : this.tokens.links[s.tag] || (this.tokens.links[s.tag] = { href: s.href, title: s.title });
777
+ continue;
778
+ }
779
+ if (s = this.tokenizer.table(e)) {
780
+ e = e.substring(s.raw.length), t.push(s);
781
+ continue;
782
+ }
783
+ if (s = this.tokenizer.lheading(e)) {
784
+ e = e.substring(s.raw.length), t.push(s);
785
+ continue;
786
+ }
787
+ let i = e;
788
+ if (this.options.extensions?.startBlock) {
789
+ let r = 1 / 0, o = e.slice(1), l;
790
+ this.options.extensions.startBlock.forEach((c) => {
791
+ l = c.call({ lexer: this }, o), typeof l == "number" && l >= 0 && (r = Math.min(r, l));
792
+ }), r < 1 / 0 && r >= 0 && (i = e.substring(0, r + 1));
793
+ }
794
+ if (this.state.top && (s = this.tokenizer.paragraph(i))) {
795
+ let r = t.at(-1);
796
+ n && r?.type === "paragraph" ? (r.raw += `
797
+ ` + s.raw, r.text += `
798
+ ` + s.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = r.text) : t.push(s), n = i.length !== e.length, e = e.substring(s.raw.length);
799
+ continue;
800
+ }
801
+ if (s = this.tokenizer.text(e)) {
802
+ e = e.substring(s.raw.length);
803
+ let r = t.at(-1);
804
+ r?.type === "text" ? (r.raw += `
805
+ ` + s.raw, r.text += `
806
+ ` + s.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = r.text) : t.push(s);
807
+ continue;
808
+ }
809
+ if (e) {
810
+ let r = "Infinite loop on byte: " + e.charCodeAt(0);
811
+ if (this.options.silent) {
812
+ console.error(r);
813
+ break;
814
+ } else throw new Error(r);
815
+ }
816
+ }
817
+ return this.state.top = true, t;
818
+ }
819
+ inline(e, t = []) {
820
+ return this.inlineQueue.push({ src: e, tokens: t }), t;
821
+ }
822
+ inlineTokens(e, t = []) {
823
+ let n = e, s = null;
824
+ if (this.tokens.links) {
825
+ let o = Object.keys(this.tokens.links);
826
+ if (o.length > 0) for (; (s = this.tokenizer.rules.inline.reflinkSearch.exec(n)) != null; ) o.includes(s[0].slice(s[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, s.index) + "[" + "a".repeat(s[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
827
+ }
828
+ for (; (s = this.tokenizer.rules.inline.anyPunctuation.exec(n)) != null; ) n = n.slice(0, s.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
829
+ for (; (s = this.tokenizer.rules.inline.blockSkip.exec(n)) != null; ) n = n.slice(0, s.index) + "[" + "a".repeat(s[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
830
+ let i = false, r = "";
831
+ for (; e; ) {
832
+ i || (r = ""), i = false;
833
+ let o;
834
+ if (this.options.extensions?.inline?.some((c) => (o = c.call({ lexer: this }, e, t)) ? (e = e.substring(o.raw.length), t.push(o), true) : false)) continue;
835
+ if (o = this.tokenizer.escape(e)) {
836
+ e = e.substring(o.raw.length), t.push(o);
837
+ continue;
838
+ }
839
+ if (o = this.tokenizer.tag(e)) {
840
+ e = e.substring(o.raw.length), t.push(o);
841
+ continue;
842
+ }
843
+ if (o = this.tokenizer.link(e)) {
844
+ e = e.substring(o.raw.length), t.push(o);
845
+ continue;
846
+ }
847
+ if (o = this.tokenizer.reflink(e, this.tokens.links)) {
848
+ e = e.substring(o.raw.length);
849
+ let c = t.at(-1);
850
+ o.type === "text" && c?.type === "text" ? (c.raw += o.raw, c.text += o.text) : t.push(o);
851
+ continue;
852
+ }
853
+ if (o = this.tokenizer.emStrong(e, n, r)) {
854
+ e = e.substring(o.raw.length), t.push(o);
855
+ continue;
856
+ }
857
+ if (o = this.tokenizer.codespan(e)) {
858
+ e = e.substring(o.raw.length), t.push(o);
859
+ continue;
860
+ }
861
+ if (o = this.tokenizer.br(e)) {
862
+ e = e.substring(o.raw.length), t.push(o);
863
+ continue;
864
+ }
865
+ if (o = this.tokenizer.del(e)) {
866
+ e = e.substring(o.raw.length), t.push(o);
867
+ continue;
868
+ }
869
+ if (o = this.tokenizer.autolink(e)) {
870
+ e = e.substring(o.raw.length), t.push(o);
871
+ continue;
872
+ }
873
+ if (!this.state.inLink && (o = this.tokenizer.url(e))) {
874
+ e = e.substring(o.raw.length), t.push(o);
875
+ continue;
876
+ }
877
+ let l = e;
878
+ if (this.options.extensions?.startInline) {
879
+ let c = 1 / 0, p = e.slice(1), u;
880
+ this.options.extensions.startInline.forEach((d) => {
881
+ u = d.call({ lexer: this }, p), typeof u == "number" && u >= 0 && (c = Math.min(c, u));
882
+ }), c < 1 / 0 && c >= 0 && (l = e.substring(0, c + 1));
883
+ }
884
+ if (o = this.tokenizer.inlineText(l)) {
885
+ e = e.substring(o.raw.length), o.raw.slice(-1) !== "_" && (r = o.raw.slice(-1)), i = true;
886
+ let c = t.at(-1);
887
+ c?.type === "text" ? (c.raw += o.raw, c.text += o.text) : t.push(o);
888
+ continue;
889
+ }
890
+ if (e) {
891
+ let c = "Infinite loop on byte: " + e.charCodeAt(0);
892
+ if (this.options.silent) {
893
+ console.error(c);
894
+ break;
895
+ } else throw new Error(c);
896
+ }
897
+ }
898
+ return t;
899
+ }
900
+ };
901
+ var $ = class {
902
+ constructor(e) {
903
+ __publicField(this, "options");
904
+ __publicField(this, "parser");
905
+ this.options = e || w;
906
+ }
907
+ space(e) {
908
+ return "";
909
+ }
910
+ code({ text: e, lang: t, escaped: n }) {
911
+ let s = (t || "").match(m.notSpaceStart)?.[0], i = e.replace(m.endingNewline, "") + `
912
+ `;
913
+ return s ? '<pre><code class="language-' + R(s) + '">' + (n ? i : R(i, true)) + `</code></pre>
914
+ ` : "<pre><code>" + (n ? i : R(i, true)) + `</code></pre>
915
+ `;
916
+ }
917
+ blockquote({ tokens: e }) {
918
+ return `<blockquote>
919
+ ${this.parser.parse(e)}</blockquote>
920
+ `;
921
+ }
922
+ html({ text: e }) {
923
+ return e;
924
+ }
925
+ heading({ tokens: e, depth: t }) {
926
+ return `<h${t}>${this.parser.parseInline(e)}</h${t}>
927
+ `;
928
+ }
929
+ hr(e) {
930
+ return `<hr>
931
+ `;
932
+ }
933
+ list(e) {
934
+ let t = e.ordered, n = e.start, s = "";
935
+ for (let o = 0; o < e.items.length; o++) {
936
+ let l = e.items[o];
937
+ s += this.listitem(l);
938
+ }
939
+ let i = t ? "ol" : "ul", r = t && n !== 1 ? ' start="' + n + '"' : "";
940
+ return "<" + i + r + `>
941
+ ` + s + "</" + i + `>
942
+ `;
943
+ }
944
+ listitem(e) {
945
+ let t = "";
946
+ if (e.task) {
947
+ let n = this.checkbox({ checked: !!e.checked });
948
+ e.loose ? e.tokens[0]?.type === "paragraph" ? (e.tokens[0].text = n + " " + e.tokens[0].text, e.tokens[0].tokens && e.tokens[0].tokens.length > 0 && e.tokens[0].tokens[0].type === "text" && (e.tokens[0].tokens[0].text = n + " " + R(e.tokens[0].tokens[0].text), e.tokens[0].tokens[0].escaped = true)) : e.tokens.unshift({ type: "text", raw: n + " ", text: n + " ", escaped: true }) : t += n + " ";
949
+ }
950
+ return t += this.parser.parse(e.tokens, !!e.loose), `<li>${t}</li>
951
+ `;
952
+ }
953
+ checkbox({ checked: e }) {
954
+ return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox">';
955
+ }
956
+ paragraph({ tokens: e }) {
957
+ return `<p>${this.parser.parseInline(e)}</p>
958
+ `;
959
+ }
960
+ table(e) {
961
+ let t = "", n = "";
962
+ for (let i = 0; i < e.header.length; i++) n += this.tablecell(e.header[i]);
963
+ t += this.tablerow({ text: n });
964
+ let s = "";
965
+ for (let i = 0; i < e.rows.length; i++) {
966
+ let r = e.rows[i];
967
+ n = "";
968
+ for (let o = 0; o < r.length; o++) n += this.tablecell(r[o]);
969
+ s += this.tablerow({ text: n });
970
+ }
971
+ return s && (s = `<tbody>${s}</tbody>`), `<table>
972
+ <thead>
973
+ ` + t + `</thead>
974
+ ` + s + `</table>
975
+ `;
976
+ }
977
+ tablerow({ text: e }) {
978
+ return `<tr>
979
+ ${e}</tr>
980
+ `;
981
+ }
982
+ tablecell(e) {
983
+ let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
984
+ return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
985
+ `;
986
+ }
987
+ strong({ tokens: e }) {
988
+ return `<strong>${this.parser.parseInline(e)}</strong>`;
989
+ }
990
+ em({ tokens: e }) {
991
+ return `<em>${this.parser.parseInline(e)}</em>`;
992
+ }
993
+ codespan({ text: e }) {
994
+ return `<code>${R(e, true)}</code>`;
995
+ }
996
+ br(e) {
997
+ return "<br>";
998
+ }
999
+ del({ tokens: e }) {
1000
+ return `<del>${this.parser.parseInline(e)}</del>`;
1001
+ }
1002
+ link({ href: e, title: t, tokens: n }) {
1003
+ let s = this.parser.parseInline(n), i = J(e);
1004
+ if (i === null) return s;
1005
+ e = i;
1006
+ let r = '<a href="' + e + '"';
1007
+ return t && (r += ' title="' + R(t) + '"'), r += ">" + s + "</a>", r;
1008
+ }
1009
+ image({ href: e, title: t, text: n, tokens: s }) {
1010
+ s && (n = this.parser.parseInline(s, this.parser.textRenderer));
1011
+ let i = J(e);
1012
+ if (i === null) return R(n);
1013
+ e = i;
1014
+ let r = `<img src="${e}" alt="${n}"`;
1015
+ return t && (r += ` title="${R(t)}"`), r += ">", r;
1016
+ }
1017
+ text(e) {
1018
+ return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : R(e.text);
1019
+ }
1020
+ };
1021
+ var _ = class {
1022
+ strong({ text: e }) {
1023
+ return e;
1024
+ }
1025
+ em({ text: e }) {
1026
+ return e;
1027
+ }
1028
+ codespan({ text: e }) {
1029
+ return e;
1030
+ }
1031
+ del({ text: e }) {
1032
+ return e;
1033
+ }
1034
+ html({ text: e }) {
1035
+ return e;
1036
+ }
1037
+ text({ text: e }) {
1038
+ return e;
1039
+ }
1040
+ link({ text: e }) {
1041
+ return "" + e;
1042
+ }
1043
+ image({ text: e }) {
1044
+ return "" + e;
1045
+ }
1046
+ br() {
1047
+ return "";
1048
+ }
1049
+ };
1050
+ var T = class a2 {
1051
+ constructor(e) {
1052
+ __publicField(this, "options");
1053
+ __publicField(this, "renderer");
1054
+ __publicField(this, "textRenderer");
1055
+ this.options = e || w, this.options.renderer = this.options.renderer || new $(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new _();
1056
+ }
1057
+ static parse(e, t) {
1058
+ return new a2(t).parse(e);
1059
+ }
1060
+ static parseInline(e, t) {
1061
+ return new a2(t).parseInline(e);
1062
+ }
1063
+ parse(e, t = true) {
1064
+ let n = "";
1065
+ for (let s = 0; s < e.length; s++) {
1066
+ let i = e[s];
1067
+ if (this.options.extensions?.renderers?.[i.type]) {
1068
+ let o = i, l = this.options.extensions.renderers[o.type].call({ parser: this }, o);
1069
+ if (l !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "paragraph", "text"].includes(o.type)) {
1070
+ n += l || "";
1071
+ continue;
1072
+ }
1073
+ }
1074
+ let r = i;
1075
+ switch (r.type) {
1076
+ case "space": {
1077
+ n += this.renderer.space(r);
1078
+ continue;
1079
+ }
1080
+ case "hr": {
1081
+ n += this.renderer.hr(r);
1082
+ continue;
1083
+ }
1084
+ case "heading": {
1085
+ n += this.renderer.heading(r);
1086
+ continue;
1087
+ }
1088
+ case "code": {
1089
+ n += this.renderer.code(r);
1090
+ continue;
1091
+ }
1092
+ case "table": {
1093
+ n += this.renderer.table(r);
1094
+ continue;
1095
+ }
1096
+ case "blockquote": {
1097
+ n += this.renderer.blockquote(r);
1098
+ continue;
1099
+ }
1100
+ case "list": {
1101
+ n += this.renderer.list(r);
1102
+ continue;
1103
+ }
1104
+ case "html": {
1105
+ n += this.renderer.html(r);
1106
+ continue;
1107
+ }
1108
+ case "paragraph": {
1109
+ n += this.renderer.paragraph(r);
1110
+ continue;
1111
+ }
1112
+ case "text": {
1113
+ let o = r, l = this.renderer.text(o);
1114
+ for (; s + 1 < e.length && e[s + 1].type === "text"; ) o = e[++s], l += `
1115
+ ` + this.renderer.text(o);
1116
+ t ? n += this.renderer.paragraph({ type: "paragraph", raw: l, text: l, tokens: [{ type: "text", raw: l, text: l, escaped: true }] }) : n += l;
1117
+ continue;
1118
+ }
1119
+ default: {
1120
+ let o = 'Token with "' + r.type + '" type was not found.';
1121
+ if (this.options.silent) return console.error(o), "";
1122
+ throw new Error(o);
1123
+ }
1124
+ }
1125
+ }
1126
+ return n;
1127
+ }
1128
+ parseInline(e, t = this.renderer) {
1129
+ let n = "";
1130
+ for (let s = 0; s < e.length; s++) {
1131
+ let i = e[s];
1132
+ if (this.options.extensions?.renderers?.[i.type]) {
1133
+ let o = this.options.extensions.renderers[i.type].call({ parser: this }, i);
1134
+ if (o !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(i.type)) {
1135
+ n += o || "";
1136
+ continue;
1137
+ }
1138
+ }
1139
+ let r = i;
1140
+ switch (r.type) {
1141
+ case "escape": {
1142
+ n += t.text(r);
1143
+ break;
1144
+ }
1145
+ case "html": {
1146
+ n += t.html(r);
1147
+ break;
1148
+ }
1149
+ case "link": {
1150
+ n += t.link(r);
1151
+ break;
1152
+ }
1153
+ case "image": {
1154
+ n += t.image(r);
1155
+ break;
1156
+ }
1157
+ case "strong": {
1158
+ n += t.strong(r);
1159
+ break;
1160
+ }
1161
+ case "em": {
1162
+ n += t.em(r);
1163
+ break;
1164
+ }
1165
+ case "codespan": {
1166
+ n += t.codespan(r);
1167
+ break;
1168
+ }
1169
+ case "br": {
1170
+ n += t.br(r);
1171
+ break;
1172
+ }
1173
+ case "del": {
1174
+ n += t.del(r);
1175
+ break;
1176
+ }
1177
+ case "text": {
1178
+ n += t.text(r);
1179
+ break;
1180
+ }
1181
+ default: {
1182
+ let o = 'Token with "' + r.type + '" type was not found.';
1183
+ if (this.options.silent) return console.error(o), "";
1184
+ throw new Error(o);
1185
+ }
1186
+ }
1187
+ }
1188
+ return n;
1189
+ }
1190
+ };
1191
+ var _a;
1192
+ var L = (_a = class {
1193
+ constructor(e) {
1194
+ __publicField(this, "options");
1195
+ __publicField(this, "block");
1196
+ this.options = e || w;
1197
+ }
1198
+ preprocess(e) {
1199
+ return e;
1200
+ }
1201
+ postprocess(e) {
1202
+ return e;
1203
+ }
1204
+ processAllTokens(e) {
1205
+ return e;
1206
+ }
1207
+ provideLexer() {
1208
+ return this.block ? b.lex : b.lexInline;
1209
+ }
1210
+ provideParser() {
1211
+ return this.block ? T.parse : T.parseInline;
1212
+ }
1213
+ }, __publicField(_a, "passThroughHooks", /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"])), _a);
1214
+ var B = class {
1215
+ constructor(...e) {
1216
+ __publicField(this, "defaults", M());
1217
+ __publicField(this, "options", this.setOptions);
1218
+ __publicField(this, "parse", this.parseMarkdown(true));
1219
+ __publicField(this, "parseInline", this.parseMarkdown(false));
1220
+ __publicField(this, "Parser", T);
1221
+ __publicField(this, "Renderer", $);
1222
+ __publicField(this, "TextRenderer", _);
1223
+ __publicField(this, "Lexer", b);
1224
+ __publicField(this, "Tokenizer", S);
1225
+ __publicField(this, "Hooks", L);
1226
+ this.use(...e);
1227
+ }
1228
+ walkTokens(e, t) {
1229
+ let n = [];
1230
+ for (let s of e) switch (n = n.concat(t.call(this, s)), s.type) {
1231
+ case "table": {
1232
+ let i = s;
1233
+ for (let r of i.header) n = n.concat(this.walkTokens(r.tokens, t));
1234
+ for (let r of i.rows) for (let o of r) n = n.concat(this.walkTokens(o.tokens, t));
1235
+ break;
1236
+ }
1237
+ case "list": {
1238
+ let i = s;
1239
+ n = n.concat(this.walkTokens(i.items, t));
1240
+ break;
1241
+ }
1242
+ default: {
1243
+ let i = s;
1244
+ this.defaults.extensions?.childTokens?.[i.type] ? this.defaults.extensions.childTokens[i.type].forEach((r) => {
1245
+ let o = i[r].flat(1 / 0);
1246
+ n = n.concat(this.walkTokens(o, t));
1247
+ }) : i.tokens && (n = n.concat(this.walkTokens(i.tokens, t)));
1248
+ }
1249
+ }
1250
+ return n;
1251
+ }
1252
+ use(...e) {
1253
+ let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
1254
+ return e.forEach((n) => {
1255
+ let s = { ...n };
1256
+ if (s.async = this.defaults.async || s.async || false, n.extensions && (n.extensions.forEach((i) => {
1257
+ if (!i.name) throw new Error("extension name required");
1258
+ if ("renderer" in i) {
1259
+ let r = t.renderers[i.name];
1260
+ r ? t.renderers[i.name] = function(...o) {
1261
+ let l = i.renderer.apply(this, o);
1262
+ return l === false && (l = r.apply(this, o)), l;
1263
+ } : t.renderers[i.name] = i.renderer;
1264
+ }
1265
+ if ("tokenizer" in i) {
1266
+ if (!i.level || i.level !== "block" && i.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
1267
+ let r = t[i.level];
1268
+ r ? r.unshift(i.tokenizer) : t[i.level] = [i.tokenizer], i.start && (i.level === "block" ? t.startBlock ? t.startBlock.push(i.start) : t.startBlock = [i.start] : i.level === "inline" && (t.startInline ? t.startInline.push(i.start) : t.startInline = [i.start]));
1269
+ }
1270
+ "childTokens" in i && i.childTokens && (t.childTokens[i.name] = i.childTokens);
1271
+ }), s.extensions = t), n.renderer) {
1272
+ let i = this.defaults.renderer || new $(this.defaults);
1273
+ for (let r in n.renderer) {
1274
+ if (!(r in i)) throw new Error(`renderer '${r}' does not exist`);
1275
+ if (["options", "parser"].includes(r)) continue;
1276
+ let o = r, l = n.renderer[o], c = i[o];
1277
+ i[o] = (...p) => {
1278
+ let u = l.apply(i, p);
1279
+ return u === false && (u = c.apply(i, p)), u || "";
1280
+ };
1281
+ }
1282
+ s.renderer = i;
1283
+ }
1284
+ if (n.tokenizer) {
1285
+ let i = this.defaults.tokenizer || new S(this.defaults);
1286
+ for (let r in n.tokenizer) {
1287
+ if (!(r in i)) throw new Error(`tokenizer '${r}' does not exist`);
1288
+ if (["options", "rules", "lexer"].includes(r)) continue;
1289
+ let o = r, l = n.tokenizer[o], c = i[o];
1290
+ i[o] = (...p) => {
1291
+ let u = l.apply(i, p);
1292
+ return u === false && (u = c.apply(i, p)), u;
1293
+ };
1294
+ }
1295
+ s.tokenizer = i;
1296
+ }
1297
+ if (n.hooks) {
1298
+ let i = this.defaults.hooks || new L();
1299
+ for (let r in n.hooks) {
1300
+ if (!(r in i)) throw new Error(`hook '${r}' does not exist`);
1301
+ if (["options", "block"].includes(r)) continue;
1302
+ let o = r, l = n.hooks[o], c = i[o];
1303
+ L.passThroughHooks.has(r) ? i[o] = (p) => {
1304
+ if (this.defaults.async) return Promise.resolve(l.call(i, p)).then((d) => c.call(i, d));
1305
+ let u = l.call(i, p);
1306
+ return c.call(i, u);
1307
+ } : i[o] = (...p) => {
1308
+ let u = l.apply(i, p);
1309
+ return u === false && (u = c.apply(i, p)), u;
1310
+ };
1311
+ }
1312
+ s.hooks = i;
1313
+ }
1314
+ if (n.walkTokens) {
1315
+ let i = this.defaults.walkTokens, r = n.walkTokens;
1316
+ s.walkTokens = function(o) {
1317
+ let l = [];
1318
+ return l.push(r.call(this, o)), i && (l = l.concat(i.call(this, o))), l;
1319
+ };
1320
+ }
1321
+ this.defaults = { ...this.defaults, ...s };
1322
+ }), this;
1323
+ }
1324
+ setOptions(e) {
1325
+ return this.defaults = { ...this.defaults, ...e }, this;
1326
+ }
1327
+ lexer(e, t) {
1328
+ return b.lex(e, t ?? this.defaults);
1329
+ }
1330
+ parser(e, t) {
1331
+ return T.parse(e, t ?? this.defaults);
1332
+ }
1333
+ parseMarkdown(e) {
1334
+ return (n, s) => {
1335
+ let i = { ...s }, r = { ...this.defaults, ...i }, o = this.onError(!!r.silent, !!r.async);
1336
+ if (this.defaults.async === true && i.async === false) return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
1337
+ if (typeof n > "u" || n === null) return o(new Error("marked(): input parameter is undefined or null"));
1338
+ if (typeof n != "string") return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
1339
+ r.hooks && (r.hooks.options = r, r.hooks.block = e);
1340
+ let l = r.hooks ? r.hooks.provideLexer() : e ? b.lex : b.lexInline, c = r.hooks ? r.hooks.provideParser() : e ? T.parse : T.parseInline;
1341
+ if (r.async) return Promise.resolve(r.hooks ? r.hooks.preprocess(n) : n).then((p) => l(p, r)).then((p) => r.hooks ? r.hooks.processAllTokens(p) : p).then((p) => r.walkTokens ? Promise.all(this.walkTokens(p, r.walkTokens)).then(() => p) : p).then((p) => c(p, r)).then((p) => r.hooks ? r.hooks.postprocess(p) : p).catch(o);
1342
+ try {
1343
+ r.hooks && (n = r.hooks.preprocess(n));
1344
+ let p = l(n, r);
1345
+ r.hooks && (p = r.hooks.processAllTokens(p)), r.walkTokens && this.walkTokens(p, r.walkTokens);
1346
+ let u = c(p, r);
1347
+ return r.hooks && (u = r.hooks.postprocess(u)), u;
1348
+ } catch (p) {
1349
+ return o(p);
1350
+ }
1351
+ };
1352
+ }
1353
+ onError(e, t) {
1354
+ return (n) => {
1355
+ if (n.message += `
1356
+ Please report this to https://github.com/markedjs/marked.`, e) {
1357
+ let s = "<p>An error occurred:</p><pre>" + R(n.message + "", true) + "</pre>";
1358
+ return t ? Promise.resolve(s) : s;
1359
+ }
1360
+ if (t) return Promise.reject(n);
1361
+ throw n;
1362
+ };
1363
+ }
1364
+ };
1365
+ var z = new B();
1366
+ function k(a3, e) {
1367
+ return z.parse(a3, e);
1368
+ }
1369
+ k.options = k.setOptions = function(a3) {
1370
+ return z.setOptions(a3), k.defaults = z.defaults, H(k.defaults), k;
1371
+ };
1372
+ k.getDefaults = M;
1373
+ k.defaults = w;
1374
+ k.use = function(...a3) {
1375
+ return z.use(...a3), k.defaults = z.defaults, H(k.defaults), k;
1376
+ };
1377
+ k.walkTokens = function(a3, e) {
1378
+ return z.walkTokens(a3, e);
1379
+ };
1380
+ k.parseInline = z.parseInline;
1381
+ k.Parser = T;
1382
+ k.parser = T.parse;
1383
+ k.Renderer = $;
1384
+ k.TextRenderer = _;
1385
+ k.Lexer = b;
1386
+ k.lexer = b.lex;
1387
+ k.Tokenizer = S;
1388
+ k.Hooks = L;
1389
+ k.parse = k;
1390
+ var Dt = k.options;
1391
+ var Zt = k.setOptions;
1392
+ var Gt = k.use;
1393
+ var Ht = k.walkTokens;
1394
+ var Nt = k.parseInline;
1395
+ var Ft = T.parse;
1396
+ var Qt = b.lex;
1397
+
1398
+ // src/helpers/markdownConverter.ts
1399
+ function convertMarkdownToHtml(markdownPath, htmlOutputPath) {
1400
+ const hasMarkdown = import_fs2.default.existsSync(markdownPath);
1401
+ const markdownContent = hasMarkdown ? import_fs2.default.readFileSync(markdownPath, "utf-8") : "";
1402
+ const markdownHtml = hasMarkdown ? k(markdownContent) : "";
1403
+ const drawerHtml = `${markdownHtml || ""}`;
1404
+ import_fs2.default.writeFileSync(htmlOutputPath, drawerHtml.trim(), "utf-8");
1405
+ if (hasMarkdown) {
1406
+ import_fs2.default.unlinkSync(markdownPath);
1407
+ }
1408
+ }
1409
+
1410
+ // src/utils/attachFiles.ts
1411
+ function attachFiles(subFolder, result, testResult, config, steps, errors) {
1412
+ const folderPath = config.folderPath || "ortoni-report";
1413
+ const attachmentsFolder = import_path2.default.join(
1414
+ folderPath,
1415
+ "ortoni-data",
1416
+ "attachments",
1417
+ subFolder
1418
+ );
1419
+ if (!import_fs3.default.existsSync(attachmentsFolder)) {
1420
+ import_fs3.default.mkdirSync(attachmentsFolder, { recursive: true });
1421
+ }
1422
+ if (!result.attachments) return;
1423
+ const { base64Image } = config;
1424
+ testResult.screenshots = [];
1425
+ testResult.videoPath = [];
1426
+ result.attachments.forEach((attachment) => {
1427
+ const { contentType, name, path: attachmentPath, body } = attachment;
1428
+ if (!attachmentPath && !body) return;
1429
+ const fileName = attachmentPath ? import_path2.default.basename(attachmentPath) : `${name}.${getFileExtension(contentType)}`;
1430
+ const relativePath = import_path2.default.join(
1431
+ "ortoni-data",
1432
+ "attachments",
1433
+ subFolder,
1434
+ fileName
1435
+ );
1436
+ const fullPath = import_path2.default.join(attachmentsFolder, fileName);
1437
+ if (contentType === "image/png") {
1438
+ handleImage(
1439
+ attachmentPath,
1440
+ body,
1441
+ base64Image,
1442
+ fullPath,
1443
+ relativePath,
1444
+ testResult
1445
+ );
1446
+ } else if (name === "video") {
1447
+ handleAttachment(
1448
+ attachmentPath,
1449
+ fullPath,
1450
+ relativePath,
1451
+ "videoPath",
1452
+ testResult
1453
+ );
1454
+ } else if (name === "trace") {
1455
+ handleAttachment(
1456
+ attachmentPath,
1457
+ fullPath,
1458
+ relativePath,
1459
+ "tracePath",
1460
+ testResult
1461
+ );
1462
+ } else if (name === "error-context") {
1463
+ handleAttachment(
1464
+ attachmentPath,
1465
+ fullPath,
1466
+ relativePath,
1467
+ "markdownPath",
1468
+ testResult,
1469
+ steps,
1470
+ errors
1471
+ );
1472
+ }
1473
+ });
1474
+ }
1475
+ function handleImage(attachmentPath, body, base64Image, fullPath, relativePath, testResult) {
1476
+ let screenshotPath = "";
1477
+ if (attachmentPath) {
1478
+ try {
1479
+ const screenshotContent = import_fs3.default.readFileSync(
1480
+ attachmentPath,
1481
+ base64Image ? "base64" : void 0
1482
+ );
1483
+ screenshotPath = base64Image ? `data:image/png;base64,${screenshotContent}` : relativePath;
1484
+ if (!base64Image) {
1485
+ import_fs3.default.copyFileSync(attachmentPath, fullPath);
1486
+ }
1487
+ } catch (error) {
1488
+ console.error(
1489
+ `OrtoniReport: Failed to read screenshot file: ${attachmentPath}`,
1490
+ error
1491
+ );
1492
+ }
1493
+ } else if (body) {
1494
+ screenshotPath = `data:image/png;base64,${body.toString("base64")}`;
1495
+ }
1496
+ if (screenshotPath) {
1497
+ testResult.screenshots?.push(screenshotPath);
1498
+ }
1499
+ }
1500
+ function handleAttachment(attachmentPath, fullPath, relativePath, resultKey, testResult, steps, errors) {
1501
+ if (attachmentPath) {
1502
+ import_fs3.default.copyFileSync(attachmentPath, fullPath);
1503
+ if (resultKey === "videoPath") {
1504
+ testResult[resultKey]?.push(relativePath);
1505
+ } else if (resultKey === "tracePath") {
1506
+ testResult[resultKey] = relativePath;
1507
+ }
1508
+ }
1509
+ if (resultKey === "markdownPath" && errors) {
1510
+ const htmlPath = fullPath.replace(/\.md$/, ".html");
1511
+ const htmlRelativePath = relativePath.replace(/\.md$/, ".html");
1512
+ convertMarkdownToHtml(fullPath, htmlPath);
1513
+ testResult[resultKey] = htmlRelativePath;
1514
+ return;
1515
+ }
1516
+ }
1517
+ function getFileExtension(contentType) {
1518
+ const extensions = {
1519
+ "image/png": "png",
1520
+ "video/webm": "webm",
1521
+ "application/zip": "zip",
1522
+ "text/markdown": "md"
1523
+ };
1524
+ return extensions[contentType] || "unknown";
1525
+ }
1526
+
1527
+ // src/utils/utils.ts
1528
+ var import_path3 = __toESM(require("path"), 1);
1529
+ function normalizeFilePath(filePath) {
1530
+ const normalizedPath = import_path3.default.normalize(filePath);
1531
+ return import_path3.default.basename(normalizedPath);
1532
+ }
1533
+ function ensureHtmlExtension(filename) {
1534
+ const ext = import_path3.default.extname(filename);
1535
+ if (ext && ext.toLowerCase() === ".html") {
1536
+ return filename;
1537
+ }
1538
+ return `${filename}.html`;
1539
+ }
1540
+ function escapeHtml(unsafe) {
1541
+ if (typeof unsafe !== "string") {
1542
+ return String(unsafe);
1543
+ }
1544
+ return unsafe.replace(/[&<"']/g, function(match) {
1545
+ const escapeMap = {
1546
+ "&": "&amp;",
1547
+ "<": "&lt;",
1548
+ ">": "&gt;",
1549
+ '"': "&quot;",
1550
+ "'": "&#039;"
1551
+ };
1552
+ return escapeMap[match] || match;
1553
+ });
1554
+ }
1555
+ function formatDateLocal(dateInput) {
1556
+ const date = typeof dateInput === "string" ? new Date(dateInput) : dateInput;
1557
+ const options = {
1558
+ year: "numeric",
1559
+ month: "short",
1560
+ day: "2-digit",
1561
+ hour: "2-digit",
1562
+ minute: "2-digit",
1563
+ hour12: true,
1564
+ timeZoneName: "short"
1565
+ // or "Asia/Kolkata"
1566
+ };
1567
+ return new Intl.DateTimeFormat(void 0, options).format(date);
1568
+ }
1569
+ function extractSuites(titlePath) {
1570
+ const tagPattern = /@[\w]+/g;
1571
+ const suiteParts = titlePath.slice(3, titlePath.length - 1).map((p) => p.replace(tagPattern, "").trim());
1572
+ return {
1573
+ hierarchy: suiteParts.join(" > "),
1574
+ // full hierarchy
1575
+ topLevelSuite: suiteParts[0] ?? "",
1576
+ // first suite
1577
+ parentSuite: suiteParts[suiteParts.length - 1] ?? ""
1578
+ // last suite
1579
+ };
1580
+ }
1581
+
1582
+ // src/helpers/resultProcessor .ts
1583
+ var TestResultProcessor = class {
1584
+ constructor(projectRoot) {
1585
+ this.ansiToHtml = new import_ansi_to_html.default({ fg: "var(--snippet-color)" });
1586
+ this.projectRoot = projectRoot;
1587
+ }
1588
+ processTestResult(test, result, projectSet, ortoniConfig) {
1589
+ const status = test.outcome() === "flaky" ? "flaky" : result.status;
1590
+ const projectName = test.titlePath()[1];
1591
+ projectSet.add(projectName);
1592
+ const location = test.location;
1593
+ const filePath = normalizeFilePath(test.titlePath()[2]);
1594
+ const tagPattern = /@[\w]+/g;
1595
+ const title = test.title.replace(tagPattern, "").trim();
1596
+ const suite = test.titlePath()[3].replace(tagPattern, "").trim();
1597
+ const suiteAndTitle = extractSuites(test.titlePath());
1598
+ const suiteHierarchy = suiteAndTitle.hierarchy;
1599
+ const testResult = {
1600
+ suiteHierarchy,
1601
+ key: test.id,
1602
+ annotations: test.annotations,
1603
+ testTags: test.tags,
1604
+ location: `${filePath}:${location.line}:${location.column}`,
1605
+ retryAttemptCount: result.retry,
1606
+ projectName,
1607
+ suite,
1608
+ title,
1609
+ status,
1610
+ flaky: test.outcome(),
1611
+ duration: result.duration,
1612
+ errors: result.errors.map(
1613
+ (e) => this.ansiToHtml.toHtml(escapeHtml(e.stack || e.toString()))
1614
+ ),
1615
+ steps: this.processSteps(result.steps),
1616
+ logs: this.ansiToHtml.toHtml(
1617
+ escapeHtml(
1618
+ result.stdout.concat(result.stderr).map((log) => log).join("\n")
1619
+ )
1620
+ ),
1621
+ filePath,
1622
+ filters: projectSet,
1623
+ base64Image: ortoniConfig.base64Image,
1624
+ testId: `${filePath}:${projectName}:${title}`
1625
+ };
1626
+ attachFiles(
1627
+ test.id,
1628
+ result,
1629
+ testResult,
1630
+ ortoniConfig,
1631
+ testResult.steps,
1632
+ testResult.errors
1633
+ );
1634
+ return testResult;
1635
+ }
1636
+ processSteps(steps) {
1637
+ return steps.map((step) => {
1638
+ const stepLocation = step.location ? `${import_path4.default.relative(this.projectRoot, step.location.file)}:${step.location.line}:${step.location.column}` : "";
1639
+ return {
1640
+ snippet: this.ansiToHtml.toHtml(escapeHtml(step.error?.snippet || "")),
1641
+ title: step.title,
1642
+ location: step.error ? stepLocation : ""
1643
+ };
1644
+ });
1645
+ }
1646
+ };
1647
+
1648
+ // src/utils/expressServer.ts
1649
+ var import_express = __toESM(require("express"), 1);
1650
+ var import_path5 = __toESM(require("path"), 1);
1651
+ var import_child_process = require("child_process");
1652
+ function startReportServer(reportFolder, reportFilename, port = 2004, open2) {
1653
+ const app = (0, import_express.default)();
1654
+ app.use(import_express.default.static(reportFolder));
1655
+ app.get("/", (_req, res) => {
1656
+ try {
1657
+ res.sendFile(import_path5.default.resolve(reportFolder, reportFilename));
1658
+ } catch (error) {
1659
+ console.error("Ortoni-Report: Error sending report file:", error);
1660
+ res.status(500).send("Error loading report");
1661
+ }
1662
+ });
1663
+ try {
1664
+ const server = app.listen(port, () => {
1665
+ console.log(
1666
+ `Server is running at http://localhost:${port}
1667
+ Press Ctrl+C to stop.`
1668
+ );
1669
+ if (open2 === "always" || open2 === "on-failure") {
1670
+ try {
1671
+ openBrowser(`http://localhost:${port}`);
1672
+ } catch (error) {
1673
+ console.error("Ortoni-Report: Error opening browser:", error);
1674
+ }
1675
+ }
1676
+ });
1677
+ server.on("error", (error) => {
1678
+ if (error.code === "EADDRINUSE") {
1679
+ console.error(
1680
+ `Ortoni-Report: Port ${port} is already in use. Trying a different port...`
1681
+ );
1682
+ } else {
1683
+ console.error("Ortoni-Report: Server error:", error);
1684
+ }
1685
+ });
1686
+ } catch (error) {
1687
+ console.error("Ortoni-Report: Error starting the server:", error);
1688
+ }
1689
+ }
1690
+ function openBrowser(url) {
1691
+ const platform = process.platform;
1692
+ let command;
1693
+ try {
1694
+ if (platform === "win32") {
1695
+ command = "cmd";
1696
+ (0, import_child_process.spawn)(command, ["/c", "start", url]);
1697
+ } else if (platform === "darwin") {
1698
+ command = "open";
1699
+ (0, import_child_process.spawn)(command, [url]);
1700
+ } else {
1701
+ command = "xdg-open";
1702
+ (0, import_child_process.spawn)(command, [url]);
1703
+ }
1704
+ } catch (error) {
1705
+ console.error("Ortoni-Report: Error opening the browser:", error);
1706
+ }
1707
+ }
1708
+
1709
+ // src/helpers/serverManager.ts
1710
+ var ServerManager = class {
1711
+ constructor(ortoniConfig) {
1712
+ this.ortoniConfig = ortoniConfig;
1713
+ }
1714
+ startServer(folderPath, outputFilename, overAllStatus) {
1715
+ const openOption = this.ortoniConfig.open || "never";
1716
+ const hasFailures = overAllStatus === "failed";
1717
+ if (openOption === "always" || openOption === "on-failure" && hasFailures) {
1718
+ startReportServer(
1719
+ folderPath,
1720
+ outputFilename,
1721
+ this.ortoniConfig.port,
1722
+ openOption
1723
+ );
1724
+ }
1725
+ }
1726
+ };
1727
+
1728
+ // src/helpers/databaseManager.ts
1729
+ var import_sqlite = require("sqlite");
1730
+ var import_sqlite3 = __toESM(require("sqlite3"), 1);
1731
+ var DatabaseManager = class {
1732
+ constructor() {
1733
+ this.db = null;
1734
+ }
1735
+ async initialize(dbPath) {
1736
+ try {
1737
+ this.db = await (0, import_sqlite.open)({
1738
+ filename: dbPath,
1739
+ driver: import_sqlite3.default.Database
1740
+ });
1741
+ await this.createTables();
1742
+ await this.createIndexes();
1743
+ } catch (error) {
1744
+ console.error("OrtoniReport: Error initializing database:", error);
1745
+ }
1746
+ }
1747
+ async createTables() {
1748
+ if (!this.db) {
1749
+ console.error("OrtoniReport: Database not initialized");
1750
+ return;
1751
+ }
1752
+ try {
1753
+ await this.db.exec(`
1754
+ CREATE TABLE IF NOT EXISTS test_runs (
1755
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
1756
+ run_date TEXT
1757
+ );
1758
+
1759
+ CREATE TABLE IF NOT EXISTS test_results (
1760
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
1761
+ run_id INTEGER,
1762
+ test_id TEXT,
1763
+ status TEXT,
1764
+ duration INTEGER, -- store duration as raw ms
1765
+ error_message TEXT,
1766
+ FOREIGN KEY (run_id) REFERENCES test_runs (id)
1767
+ );
1768
+ `);
1769
+ } catch (error) {
1770
+ console.error("OrtoniReport: Error creating tables:", error);
1771
+ }
1772
+ }
1773
+ async createIndexes() {
1774
+ if (!this.db) {
1775
+ console.error("OrtoniReport: Database not initialized");
1776
+ return;
1777
+ }
1778
+ try {
1779
+ await this.db.exec(`
1780
+ CREATE INDEX IF NOT EXISTS idx_test_id ON test_results (test_id);
1781
+ CREATE INDEX IF NOT EXISTS idx_run_id ON test_results (run_id);
1782
+ `);
1783
+ } catch (error) {
1784
+ console.error("OrtoniReport: Error creating indexes:", error);
1785
+ }
1786
+ }
1787
+ async saveTestRun() {
1788
+ if (!this.db) {
1789
+ console.error("OrtoniReport: Database not initialized");
1790
+ return null;
1791
+ }
1792
+ try {
1793
+ const runDate = (/* @__PURE__ */ new Date()).toISOString();
1794
+ const { lastID } = await this.db.run(
1795
+ `
1796
+ INSERT INTO test_runs (run_date)
1797
+ VALUES (?)
1798
+ `,
1799
+ [runDate]
1800
+ );
1801
+ return lastID;
1802
+ } catch (error) {
1803
+ console.error("OrtoniReport: Error saving test run:", error);
1804
+ return null;
1805
+ }
1806
+ }
1807
+ async saveTestResults(runId, results) {
1808
+ if (!this.db) {
1809
+ console.error("OrtoniReport: Database not initialized");
1810
+ return;
1811
+ }
1812
+ try {
1813
+ await this.db.exec("BEGIN TRANSACTION;");
1814
+ const stmt = await this.db.prepare(`
1815
+ INSERT INTO test_results (run_id, test_id, status, duration, error_message)
1816
+ VALUES (?, ?, ?, ?, ?)
1817
+ `);
1818
+ for (const result of results) {
1819
+ await stmt.run([
1820
+ runId,
1821
+ `${result.filePath}:${result.projectName}:${result.title}`,
1822
+ result.status,
1823
+ result.duration,
1824
+ // store raw ms
1825
+ result.errors.join("\n")
1826
+ ]);
1827
+ }
1828
+ await stmt.finalize();
1829
+ await this.db.exec("COMMIT;");
1830
+ } catch (error) {
1831
+ await this.db.exec("ROLLBACK;");
1832
+ console.error("OrtoniReport: Error saving test results:", error);
1833
+ }
1834
+ }
1835
+ async getTestHistory(testId, limit = 10) {
1836
+ if (!this.db) {
1837
+ console.error("OrtoniReport: Database not initialized");
1838
+ return [];
1839
+ }
1840
+ try {
1841
+ const results = await this.db.all(
1842
+ `
1843
+ SELECT tr.status, tr.duration, tr.error_message, trun.run_date
1844
+ FROM test_results tr
1845
+ JOIN test_runs trun ON tr.run_id = trun.id
1846
+ WHERE tr.test_id = ?
1847
+ ORDER BY trun.run_date DESC
1848
+ LIMIT ?
1849
+ `,
1850
+ [testId, limit]
1851
+ );
1852
+ return results.map((result) => ({
1853
+ ...result,
1854
+ run_date: formatDateLocal(result.run_date)
1855
+ }));
1856
+ } catch (error) {
1857
+ console.error("OrtoniReport: Error getting test history:", error);
1858
+ return [];
1859
+ }
1860
+ }
1861
+ async close() {
1862
+ if (this.db) {
1863
+ try {
1864
+ await this.db.close();
1865
+ } catch (error) {
1866
+ console.error("OrtoniReport: Error closing database:", error);
1867
+ } finally {
1868
+ this.db = null;
1869
+ }
1870
+ }
1871
+ }
1872
+ async getSummaryData() {
1873
+ if (!this.db) {
1874
+ console.error("OrtoniReport: Database not initialized");
1875
+ return {
1876
+ totalRuns: 0,
1877
+ totalTests: 0,
1878
+ passed: 0,
1879
+ failed: 0,
1880
+ passRate: 0,
1881
+ avgDuration: 0
1882
+ };
1883
+ }
1884
+ try {
1885
+ const summary = await this.db.get(`
1886
+ SELECT
1887
+ (SELECT COUNT(*) FROM test_runs) as totalRuns,
1888
+ (SELECT COUNT(*) FROM test_results) as totalTests,
1889
+ (SELECT COUNT(*) FROM test_results WHERE status = 'passed') as passed,
1890
+ (SELECT COUNT(*) FROM test_results WHERE status = 'failed') as failed,
1891
+ (SELECT AVG(duration) FROM test_results) as avgDuration
1892
+ `);
1893
+ const passRate = summary.totalTests ? (summary.passed / summary.totalTests * 100).toFixed(2) : 0;
1894
+ return {
1895
+ totalRuns: summary.totalRuns,
1896
+ totalTests: summary.totalTests,
1897
+ passed: summary.passed,
1898
+ failed: summary.failed,
1899
+ passRate: parseFloat(passRate.toString()),
1900
+ avgDuration: Math.round(summary.avgDuration || 0)
1901
+ // raw ms avg
1902
+ };
1903
+ } catch (error) {
1904
+ console.error("OrtoniReport: Error getting summary data:", error);
1905
+ return {
1906
+ totalRuns: 0,
1907
+ totalTests: 0,
1908
+ passed: 0,
1909
+ failed: 0,
1910
+ passRate: 0,
1911
+ avgDuration: 0
1912
+ };
1913
+ }
1914
+ }
1915
+ async getTrends(limit = 100) {
1916
+ if (!this.db) {
1917
+ console.error("OrtoniReport: Database not initialized");
1918
+ return [];
1919
+ }
1920
+ try {
1921
+ const rows = await this.db.all(
1922
+ `
1923
+ SELECT trun.run_date,
1924
+ SUM(CASE WHEN tr.status = 'passed' THEN 1 ELSE 0 END) AS passed,
1925
+ SUM(CASE WHEN tr.status = 'failed' THEN 1 ELSE 0 END) AS failed,
1926
+ AVG(tr.duration) AS avg_duration
1927
+ FROM test_results tr
1928
+ JOIN test_runs trun ON tr.run_id = trun.id
1929
+ GROUP BY trun.run_date
1930
+ ORDER BY trun.run_date DESC
1931
+ LIMIT ?
1932
+ `,
1933
+ [limit]
1934
+ );
1935
+ return rows.reverse().map((row) => ({
1936
+ ...row,
1937
+ run_date: formatDateLocal(row.run_date),
1938
+ avg_duration: Math.round(row.avg_duration || 0)
1939
+ // raw ms avg
1940
+ }));
1941
+ } catch (error) {
1942
+ console.error("OrtoniReport: Error getting trends data:", error);
1943
+ return [];
1944
+ }
1945
+ }
1946
+ async getFlakyTests(limit = 10) {
1947
+ if (!this.db) {
1948
+ console.error("OrtoniReport: Database not initialized");
1949
+ return [];
1950
+ }
1951
+ try {
1952
+ return await this.db.all(
1953
+ `
1954
+ SELECT
1955
+ test_id,
1956
+ COUNT(*) AS total,
1957
+ SUM(CASE WHEN status = 'flaky' THEN 1 ELSE 0 END) AS flaky,
1958
+ AVG(duration) AS avg_duration
1959
+ FROM test_results
1960
+ GROUP BY test_id
1961
+ HAVING flaky > 0
1962
+ ORDER BY flaky DESC
1963
+ LIMIT ?
1964
+ `,
1965
+ [limit]
1966
+ );
1967
+ } catch (error) {
1968
+ console.error("OrtoniReport: Error getting flaky tests:", error);
1969
+ return [];
1970
+ }
1971
+ }
1972
+ async getSlowTests(limit = 10) {
1973
+ if (!this.db) {
1974
+ console.error("OrtoniReport: Database not initialized");
1975
+ return [];
1976
+ }
1977
+ try {
1978
+ const rows = await this.db.all(
1979
+ `
1980
+ SELECT
1981
+ test_id,
1982
+ AVG(duration) AS avg_duration
1983
+ FROM test_results
1984
+ GROUP BY test_id
1985
+ ORDER BY avg_duration DESC
1986
+ LIMIT ?
1987
+ `,
1988
+ [limit]
1989
+ );
1990
+ return rows.map((row) => ({
1991
+ test_id: row.test_id,
1992
+ avg_duration: Math.round(row.avg_duration || 0)
1993
+ // raw ms avg
1994
+ }));
1995
+ } catch (error) {
1996
+ console.error("OrtoniReport: Error getting slow tests:", error);
1997
+ return [];
1998
+ }
1999
+ }
2000
+ };
2001
+
2002
+ // src/ortoni-report.ts
2003
+ var import_path6 = __toESM(require("path"), 1);
2004
+ var OrtoniReport = class {
2005
+ constructor(ortoniConfig = {}) {
2006
+ this.ortoniConfig = ortoniConfig;
2007
+ this.results = [];
2008
+ this.projectSet = /* @__PURE__ */ new Set();
2009
+ this.shouldGenerateReport = true;
2010
+ this.showConsoleLogs = true;
2011
+ this.skipTraceViewer = false;
2012
+ this.reportsCount = 0;
2013
+ this.folderPath = ortoniConfig.folderPath || "ortoni-report";
2014
+ this.outputFilename = ensureHtmlExtension(
2015
+ ortoniConfig.filename || "ortoni-report.html"
2016
+ );
2017
+ this.dbManager = new DatabaseManager();
2018
+ this.htmlGenerator = new HTMLGenerator(ortoniConfig, this.dbManager);
2019
+ this.fileManager = new FileManager(this.folderPath);
2020
+ this.serverManager = new ServerManager(ortoniConfig);
2021
+ this.testResultProcessor = new TestResultProcessor("");
2022
+ this.showConsoleLogs = ortoniConfig.stdIO !== false;
2023
+ }
2024
+ async onBegin(config, _suite) {
2025
+ this.skipTraceViewer = config.projects.every((project) => {
2026
+ const trace = project.use?.trace;
2027
+ return trace === void 0 || trace === "off";
2028
+ });
2029
+ this.reportsCount = config.reporter.length;
2030
+ this.results = [];
2031
+ this.testResultProcessor = new TestResultProcessor(config.rootDir);
2032
+ this.fileManager.ensureReportDirectory();
2033
+ await this.dbManager.initialize(
2034
+ import_path6.default.join(this.folderPath, "ortoni-data-history.sqlite")
2035
+ );
2036
+ this.config = config?.shard;
2037
+ }
2038
+ onStdOut(chunk, _test, _result) {
2039
+ if (this.reportsCount == 1 && this.showConsoleLogs) {
2040
+ console.log(chunk.toString().trim());
2041
+ }
2042
+ }
2043
+ onTestEnd(test, result) {
2044
+ try {
2045
+ const testResult = this.testResultProcessor.processTestResult(
2046
+ test,
2047
+ result,
2048
+ this.projectSet,
2049
+ this.ortoniConfig
2050
+ );
2051
+ this.results.push(testResult);
2052
+ } catch (error) {
2053
+ console.error("OrtoniReport: Error processing test end:", error);
2054
+ }
2055
+ }
2056
+ printsToStdio() {
2057
+ return true;
2058
+ }
2059
+ onError(error) {
2060
+ if (error.location === void 0) {
2061
+ this.shouldGenerateReport = false;
2062
+ }
2063
+ }
2064
+ async onEnd(result) {
2065
+ try {
2066
+ this.overAllStatus = result.status;
2067
+ if (this.shouldGenerateReport) {
2068
+ const filteredResults = this.results.filter(
2069
+ (r) => r.status !== "skipped"
2070
+ );
2071
+ const totalDuration = result.duration;
2072
+ if (this.config && this.config.total > 1) {
2073
+ const shard = this.config;
2074
+ const shardFile = `ortoni-shard-${shard.current}-of-${shard.total}.json`;
2075
+ const shardData = {
2076
+ status: result.status,
2077
+ duration: totalDuration,
2078
+ results: this.results,
2079
+ projectSet: Array.from(this.projectSet)
2080
+ };
2081
+ this.fileManager.writeRawFile(shardFile, shardData);
2082
+ console.log(`\u{1F4E6} OrtoniReport wrote shard file: ${shardFile}`);
2083
+ this.shouldGenerateReport = false;
2084
+ return;
2085
+ }
2086
+ const runId = await this.dbManager.saveTestRun();
2087
+ if (runId !== null) {
2088
+ await this.dbManager.saveTestResults(runId, this.results);
2089
+ const finalReportData = await this.htmlGenerator.generateFinalReport(
2090
+ filteredResults,
2091
+ totalDuration,
2092
+ this.results,
2093
+ this.projectSet
2094
+ );
2095
+ this.outputPath = this.fileManager.writeReportFile(
2096
+ this.outputFilename,
2097
+ finalReportData
2098
+ );
2099
+ } else {
2100
+ console.error("OrtoniReport: Error saving test run to database");
2101
+ }
2102
+ } else {
2103
+ console.error(
2104
+ "OrtoniReport: Report generation skipped due to error in Playwright worker!"
2105
+ );
2106
+ }
2107
+ } catch (error) {
2108
+ this.shouldGenerateReport = false;
2109
+ console.error("OrtoniReport: Error generating report:", error);
2110
+ }
2111
+ }
2112
+ async onExit() {
2113
+ try {
2114
+ await this.dbManager.close();
2115
+ if (this.shouldGenerateReport) {
2116
+ this.fileManager.copyTraceViewerAssets(this.skipTraceViewer);
2117
+ console.info(`Ortoni HTML report generated at ${this.outputPath}`);
2118
+ this.serverManager.startServer(
2119
+ this.folderPath,
2120
+ this.outputFilename,
2121
+ this.overAllStatus
2122
+ );
2123
+ await new Promise((_resolve) => {
2124
+ });
2125
+ }
2126
+ } catch (error) {
2127
+ console.error("OrtoniReport: Error in onExit:", error);
2128
+ }
2129
+ }
2130
+ };
2131
+ // Annotate the CommonJS export names for ESM import in node:
2132
+ 0 && (module.exports = {
2133
+ OrtoniReport
2134
+ });