ortoni-report 4.0.2-beta.1 → 4.0.2

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.
@@ -1,2134 +0,0 @@
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
- });