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