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