@eggjs/onerror 4.0.2-beta.1 → 4.0.2-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,7 +26,7 @@ Default error handling plugin for egg.
26
26
  - `html: Function` - customize html error handler.
27
27
  - `text: Function` - customize text error handler.
28
28
  - `json: Function` - customize json error handler.
29
- - `jsonp: Function` - customize jsonp error handler.
29
+ - `js: Function` - customize JSONP error handler.
30
30
 
31
31
  ```ts
32
32
  // config/config.default.ts
package/dist/app.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { OnerrorError } from "koa-onerror";
1
+ import { OnerrorError } from "./lib/onerror.js";
2
2
  import { Application, ILifecycleBoot } from "egg";
3
3
 
4
4
  //#region src/app.d.ts
package/dist/app.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { accepts, detectErrorMessage, detectStatus, isProd } from "./lib/utils.js";
2
2
  import { ErrorView } from "./lib/error_view.js";
3
+ import { onerror } from "./lib/onerror.js";
3
4
  import fs from "node:fs";
4
5
  import http from "node:http";
5
- import { onerror } from "koa-onerror";
6
6
 
7
7
  //#region src/app.ts
8
8
  var Boot = class {
@@ -12,7 +12,7 @@ var Boot = class {
12
12
  }
13
13
  async didLoad() {
14
14
  const config = this.app.config.onerror;
15
- const viewTemplate = fs.readFileSync(config.templatePath, "utf8");
15
+ const viewTemplate = config.templatePath ? fs.readFileSync(config.templatePath, "utf8") : (await import("./lib/onerror_page.js")).ONERROR_PAGE_TEMPLATE;
16
16
  const app = this.app;
17
17
  app.on("error", (err, ctx) => {
18
18
  if (!ctx) ctx = app.currentContext || app.createAnonymousContext();
@@ -1,4 +1,4 @@
1
- import { OnerrorError, OnerrorOptions } from "koa-onerror";
1
+ import { OnerrorError, OnerrorOptions } from "../lib/onerror.js";
2
2
  import { Context } from "egg";
3
3
 
4
4
  //#region src/config/config.default.d.ts
@@ -19,7 +19,9 @@ interface OnerrorConfig extends OnerrorOptions {
19
19
  */
20
20
  appErrorFilter?: (err: OnerrorError, ctx: Context) => boolean;
21
21
  /**
22
- * default template path
22
+ * Custom template path. If empty, uses the built-in error page template.
23
+ *
24
+ * Default: `''`
23
25
  */
24
26
  templatePath: string;
25
27
  }
@@ -1,10 +1,8 @@
1
- import path from "node:path";
2
-
3
1
  //#region src/config/config.default.ts
4
2
  var config_default_default = { onerror: {
5
3
  errorPageUrl: "",
6
4
  appErrorFilter: void 0,
7
- templatePath: path.join(import.meta.dirname, "../lib/onerror_page.mustache.html")
5
+ templatePath: ""
8
6
  } };
9
7
 
10
8
  //#endregion
@@ -1,4 +1,4 @@
1
- import { OnerrorError } from "koa-onerror";
1
+ import { OnerrorError } from "./onerror.js";
2
2
  import { StackFrame } from "stack-trace";
3
3
  import { Context } from "egg";
4
4
 
@@ -143,6 +143,10 @@ declare class ErrorView {
143
143
  baseDir: string;
144
144
  config: string;
145
145
  };
146
+ serializeConfig(): unknown;
147
+ getConfigIgnoreList(): (string | RegExp)[];
148
+ redactConfig(value: unknown, ignoreList: (string | RegExp)[], ancestors?: WeakSet<object>): unknown;
149
+ shouldRedactConfigKey(key: string, ignoreList: (string | RegExp)[]): boolean;
146
150
  }
147
151
  //#endregion
148
152
  export { ErrorView, Frame, FrameSource };
@@ -8,6 +8,18 @@ import stackTrace from "stack-trace";
8
8
 
9
9
  //#region src/lib/error_view.ts
10
10
  const startingSlashRegex = /\\|\//;
11
+ const defaultConfigIgnoreList = [
12
+ "pass",
13
+ "pwd",
14
+ "passd",
15
+ "passwd",
16
+ "password",
17
+ "keys",
18
+ "masterKey",
19
+ "accessKey",
20
+ /secret/i
21
+ ];
22
+ const redactedValue = "<Redacted>";
11
23
  var ErrorView = class {
12
24
  ctx;
13
25
  error;
@@ -211,13 +223,41 @@ var ErrorView = class {
211
223
  * serialize app info object
212
224
  */
213
225
  serializeAppInfo() {
214
- let config = this.app.config;
215
- if ("dumpConfigToObject" in this.app && typeof this.app.dumpConfigToObject === "function") config = this.app.dumpConfigToObject().config.config;
226
+ const config = this.serializeConfig();
216
227
  return {
217
228
  baseDir: this.app.config.baseDir,
218
229
  config: util.inspect(config)
219
230
  };
220
231
  }
232
+ serializeConfig() {
233
+ if ("dumpConfigToObject" in this.app && typeof this.app.dumpConfigToObject === "function") return this.app.dumpConfigToObject().config.config;
234
+ return this.redactConfig(this.app.config, this.getConfigIgnoreList());
235
+ }
236
+ getConfigIgnoreList() {
237
+ try {
238
+ return Array.from(this.app.config.dump.ignore);
239
+ } catch {
240
+ return defaultConfigIgnoreList;
241
+ }
242
+ }
243
+ redactConfig(value, ignoreList, ancestors = /* @__PURE__ */ new WeakSet()) {
244
+ if (!value || typeof value !== "object") return value;
245
+ if (value instanceof Date || value instanceof RegExp || value instanceof URL) return value.toString();
246
+ if (Buffer.isBuffer(value)) return value;
247
+ if (ancestors.has(value)) return "[Circular]";
248
+ ancestors.add(value);
249
+ try {
250
+ if (Array.isArray(value)) return value.map((item) => this.redactConfig(item, ignoreList, ancestors));
251
+ const result = {};
252
+ for (const key of Object.keys(value)) result[key] = this.shouldRedactConfigKey(key, ignoreList) ? redactedValue : this.redactConfig(value[key], ignoreList, ancestors);
253
+ return result;
254
+ } finally {
255
+ ancestors.delete(value);
256
+ }
257
+ }
258
+ shouldRedactConfigKey(key, ignoreList) {
259
+ return ignoreList.some((item) => typeof item === "string" ? item === key : item.test(key));
260
+ }
221
261
  };
222
262
 
223
263
  //#endregion
@@ -0,0 +1,20 @@
1
+ //#region src/lib/onerror.d.ts
2
+ type OnerrorError = Error & {
3
+ status: number;
4
+ code?: string;
5
+ headers?: Record<string, string>;
6
+ expose?: boolean;
7
+ };
8
+ type OnerrorHandler = (err: OnerrorError, ctx: any) => void;
9
+ interface OnerrorOptions {
10
+ text?: OnerrorHandler;
11
+ json?: OnerrorHandler;
12
+ html?: OnerrorHandler;
13
+ all?: OnerrorHandler;
14
+ js?: OnerrorHandler;
15
+ redirect?: string | null;
16
+ accepts?: (...args: string[]) => string;
17
+ }
18
+ declare function onerror(app: any, options?: OnerrorOptions): any;
19
+ //#endregion
20
+ export { OnerrorError, OnerrorHandler, OnerrorOptions, onerror };
@@ -0,0 +1,109 @@
1
+ import http from "node:http";
2
+ import { debuglog, inspect } from "node:util";
3
+
4
+ //#region src/lib/onerror.ts
5
+ const debug = debuglog("egg-onerror");
6
+ const defaultOptions = {
7
+ text,
8
+ json,
9
+ html
10
+ };
11
+ function onerror(app, options) {
12
+ options = {
13
+ ...defaultOptions,
14
+ ...options
15
+ };
16
+ app.context.onerror = function(err) {
17
+ debug("onerror: %s", err);
18
+ if (err == null) return;
19
+ if (typeof this.req?.resume === "function") {
20
+ this.req.resume();
21
+ debug("resume the req stream");
22
+ }
23
+ if (!(err instanceof Error)) {
24
+ debug("err is not an instance of Error");
25
+ let errMsg = err;
26
+ if (typeof err === "object") try {
27
+ errMsg = JSON.stringify(err);
28
+ } catch (e) {
29
+ debug("stringify error: %s", e);
30
+ errMsg = inspect(err);
31
+ }
32
+ const newError = /* @__PURE__ */ new Error("non-error thrown: " + errMsg);
33
+ if (err) {
34
+ if (err.name) newError.name = err.name;
35
+ if (err.message) newError.message = err.message;
36
+ if (err.stack) newError.stack = err.stack;
37
+ if (err.status) Reflect.set(newError, "status", err.status);
38
+ if (err.headers) Reflect.set(newError, "headers", err.headers);
39
+ }
40
+ err = newError;
41
+ debug("wrap err: %s", err);
42
+ }
43
+ const headerSent = this.headerSent || !this.writable;
44
+ if (headerSent) {
45
+ debug("headerSent is true");
46
+ err.headerSent = true;
47
+ }
48
+ this.app.emit("error", err, this);
49
+ if (headerSent) return;
50
+ if (err.code === "ENOENT") err.status = 404;
51
+ if (typeof err.status !== "number" || !http.STATUS_CODES[err.status]) err.status = 500;
52
+ this.status = err.status;
53
+ clearResponseHeaders(this);
54
+ if (err.headers) this.set(err.headers);
55
+ let type;
56
+ if (options.accepts) type = options.accepts.call(this, "html", "text", "json", "js");
57
+ else type = this.accepts("html", "text", "json", "js");
58
+ debug("accepts type: %s", type);
59
+ type = type || "text";
60
+ if (options.all) options.all.call(this, err, this);
61
+ else if (options.redirect && type !== "json") this.redirect(options.redirect);
62
+ else {
63
+ getHandler(options, type)?.call(this, err, this);
64
+ this.type = type;
65
+ }
66
+ if (type === "json" && typeof this.body !== "string") this.body = JSON.stringify(this.body);
67
+ debug("end the response, body: %s", this.body);
68
+ this.res.end(this.body);
69
+ };
70
+ return app;
71
+ }
72
+ function getHandler(options, type) {
73
+ if (type === "html" || type === "text" || type === "json" || type === "js") return options[type];
74
+ }
75
+ function isDev() {
76
+ return !process.env.NODE_ENV || process.env.NODE_ENV === "development";
77
+ }
78
+ function text(err, ctx) {
79
+ ctx.body = (isDev() || err.expose) && err.message ? err.message : http.STATUS_CODES[ctx.status];
80
+ }
81
+ function json(err, ctx) {
82
+ ctx.body = { error: (isDev() || err.expose) && err.message ? err.message : http.STATUS_CODES[ctx.status] };
83
+ }
84
+ function html(err, ctx) {
85
+ const message = (isDev() || err.expose) && err.message ? err.message : http.STATUS_CODES[ctx.status];
86
+ ctx.body = `<h2>${escapeHtml(String(err.status))} ${escapeHtml(String(message))}</h2>`;
87
+ ctx.type = "html";
88
+ }
89
+ function escapeHtml(value) {
90
+ return value.replace(/[&<>"']/g, (char) => {
91
+ switch (char) {
92
+ case "&": return "&amp;";
93
+ case "<": return "&lt;";
94
+ case ">": return "&gt;";
95
+ case "\"": return "&quot;";
96
+ default: return "&#39;";
97
+ }
98
+ });
99
+ }
100
+ function clearResponseHeaders(ctx) {
101
+ const headers = ctx.response?.header ?? ctx.response?.headers ?? ctx.res.getHeaders?.() ?? {};
102
+ for (const name of Object.keys(headers)) {
103
+ if (name.toLowerCase() === "set-cookie") continue;
104
+ ctx.res.removeHeader(name);
105
+ }
106
+ }
107
+
108
+ //#endregion
109
+ export { onerror };
@@ -0,0 +1,5 @@
1
+ //#region src/lib/onerror_page.d.ts
2
+ /** Built-in error page template. */
3
+ declare const ONERROR_PAGE_TEMPLATE = "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title></title>\n <style>\n /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript&plugins=line-highlight+line-numbers+toolbar+show-language */\n /**\n * prism.js default theme for JavaScript, CSS and HTML\n * Based on dabblet (http://dabblet.com)\n * @author Lea Verou\n */\n code[class*='language-'],\n pre[class*='language-'] {\n color: black;\n background: none;\n text-shadow: 0 1px white;\n font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n text-align: left;\n white-space: pre;\n word-spacing: normal;\n word-break: normal;\n word-wrap: normal;\n line-height: 1.5;\n -moz-tab-size: 4;\n -o-tab-size: 4;\n tab-size: 4;\n -webkit-hyphens: none;\n -moz-hyphens: none;\n -ms-hyphens: none;\n hyphens: none;\n }\n pre[class*='language-']::-moz-selection,\n pre[class*='language-'] ::-moz-selection,\n code[class*='language-']::-moz-selection,\n code[class*='language-'] ::-moz-selection {\n text-shadow: none;\n background: #98d8b7;\n }\n pre[class*='language-']::selection,\n pre[class*='language-'] ::selection,\n code[class*='language-']::selection,\n code[class*='language-'] ::selection {\n text-shadow: none;\n background: #98d8b7;\n }\n @media print {\n code[class*='language-'],\n pre[class*='language-'] {\n text-shadow: none;\n }\n }\n /* Code blocks */\n pre[class*='language-'] {\n padding: 1em;\n margin: 0.5em 0;\n overflow: auto;\n }\n :not(pre) > code[class*='language-'],\n pre[class*='language-'] {\n background: #f5f2f0;\n }\n /* Inline code */\n :not(pre) > code[class*='language-'] {\n padding: 0.1em;\n border-radius: 0.3em;\n white-space: normal;\n }\n .token.comment,\n .token.prolog,\n .token.doctype,\n .token.cdata {\n color: slategray;\n }\n .token.punctuation {\n color: #999;\n }\n .namespace {\n opacity: 0.7;\n }\n .token.property,\n .token.tag,\n .token.boolean,\n .token.number,\n .token.constant,\n .token.symbol,\n .token.deleted {\n color: #905;\n }\n .token.selector,\n .token.attr-name,\n .token.string,\n .token.char,\n .token.builtin,\n .token.inserted {\n color: #690;\n }\n .token.operator,\n .token.entity,\n .token.url,\n .language-css .token.string,\n .style .token.string {\n color: #a67f59;\n background: hsla(0, 0%, 100%, 0.5);\n }\n .token.atrule,\n .token.attr-value,\n .token.keyword {\n color: #07a;\n }\n .token.function {\n color: #dd4a68;\n }\n .token.regex,\n .token.important,\n .token.variable {\n color: #e90;\n }\n .token.important,\n .token.bold {\n font-weight: bold;\n }\n .token.italic {\n font-style: italic;\n }\n .token.entity {\n cursor: help;\n }\n pre[data-line] {\n position: relative;\n padding: 1em 0 1em 3em;\n }\n .line-highlight {\n position: absolute;\n left: 0;\n right: 0;\n padding: inherit 0;\n margin-top: 1em; /* Same as .prism’s padding-top */\n background: hsla(24, 20%, 50%, 0.08);\n background: linear-gradient(to right, hsla(24, 20%, 50%, 0.1) 70%, hsla(24, 20%, 50%, 0));\n pointer-events: none;\n line-height: inherit;\n white-space: pre;\n }\n .line-highlight:before,\n .line-highlight[data-end]:after {\n content: attr(data-start);\n position: absolute;\n top: 0.4em;\n left: 0.6em;\n min-width: 1em;\n padding: 0 0.5em;\n background-color: hsla(24, 20%, 50%, 0.4);\n color: hsl(24, 20%, 95%);\n font: bold 65%/1.5 sans-serif;\n text-align: center;\n vertical-align: 0.3em;\n border-radius: 999px;\n text-shadow: none;\n box-shadow: 0 1px white;\n }\n .line-highlight[data-end]:after {\n content: attr(data-end);\n top: auto;\n bottom: 0.4em;\n }\n pre.line-numbers {\n position: relative;\n padding-left: 3.8em;\n counter-reset: linenumber;\n }\n pre.line-numbers > code {\n position: relative;\n }\n .line-numbers .line-numbers-rows {\n position: absolute;\n pointer-events: none;\n top: 0;\n font-size: 100%;\n left: -3.8em;\n width: 3em; /* works for line-numbers below 1000 lines */\n letter-spacing: -1px;\n border-right: 1px solid #999;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n }\n .line-numbers-rows > span {\n pointer-events: none;\n display: block;\n counter-increment: linenumber;\n }\n .line-numbers-rows > span:before {\n content: counter(linenumber);\n color: #999;\n display: block;\n padding-right: 0.8em;\n text-align: right;\n }\n pre.code-toolbar {\n position: relative;\n }\n pre.code-toolbar > .toolbar {\n position: absolute;\n top: 0.3em;\n right: 0.2em;\n transition: opacity 0.3s ease-in-out;\n opacity: 0;\n }\n pre.code-toolbar:hover > .toolbar {\n opacity: 1;\n }\n pre.code-toolbar > .toolbar .toolbar-item {\n display: inline-block;\n }\n pre.code-toolbar > .toolbar a {\n cursor: pointer;\n }\n pre.code-toolbar > .toolbar button {\n background: none;\n border: 0;\n color: inherit;\n font: inherit;\n line-height: normal;\n overflow: visible;\n padding: 0;\n -webkit-user-select: none; /* for button */\n -moz-user-select: none;\n -ms-user-select: none;\n }\n pre.code-toolbar > .toolbar a,\n pre.code-toolbar > .toolbar button,\n pre.code-toolbar > .toolbar span {\n color: #bbb;\n font-size: 0.8em;\n padding: 0 0.5em;\n background: #f5f2f0;\n background: rgba(224, 224, 224, 0.2);\n box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2);\n border-radius: 0.5em;\n }\n pre.code-toolbar > .toolbar a:hover,\n pre.code-toolbar > .toolbar a:focus,\n pre.code-toolbar > .toolbar button:hover,\n pre.code-toolbar > .toolbar button:focus,\n pre.code-toolbar > .toolbar span:hover,\n pre.code-toolbar > .toolbar span:focus {\n color: inherit;\n text-decoration: none;\n }\n </style>\n\n <style>\n @keyframes hover-color {\n from {\n border-color: #c0c0c0;\n }\n to {\n border-color: #53b783;\n }\n }\n .magic-radio,\n .magic-checkbox {\n position: absolute;\n display: none;\n }\n .magic-radio[disabled],\n .magic-checkbox[disabled] {\n cursor: not-allowed;\n }\n .magic-radio + label,\n .magic-checkbox + label {\n position: relative;\n display: block;\n padding-left: 30px;\n cursor: pointer;\n vertical-align: middle;\n }\n .magic-radio + label:hover:before,\n .magic-checkbox + label:hover:before {\n animation-duration: 0.4s;\n animation-fill-mode: both;\n animation-name: hover-color;\n }\n .magic-radio + label:before,\n .magic-checkbox + label:before {\n position: absolute;\n top: 0;\n left: 0;\n display: inline-block;\n width: 20px;\n height: 20px;\n content: '';\n border: 1px solid #c0c0c0;\n }\n .magic-radio + label:after,\n .magic-checkbox + label:after {\n position: absolute;\n display: none;\n content: '';\n }\n .magic-radio[disabled] + label,\n .magic-checkbox[disabled] + label {\n cursor: not-allowed;\n color: #e4e4e4;\n }\n .magic-radio[disabled] + label:hover,\n .magic-radio[disabled] + label:before,\n .magic-radio[disabled] + label:after,\n .magic-checkbox[disabled] + label:hover,\n .magic-checkbox[disabled] + label:before,\n .magic-checkbox[disabled] + label:after {\n cursor: not-allowed;\n }\n .magic-radio[disabled] + label:hover:before,\n .magic-checkbox[disabled] + label:hover:before {\n border: 1px solid #e4e4e4;\n animation-name: none;\n }\n .magic-radio[disabled] + label:before,\n .magic-checkbox[disabled] + label:before {\n border-color: #e4e4e4;\n }\n .magic-radio:checked + label:before,\n .magic-checkbox:checked + label:before {\n animation-name: none;\n }\n .magic-radio:checked + label:after,\n .magic-checkbox:checked + label:after {\n display: block;\n }\n .magic-radio + label:before {\n border-radius: 50%;\n }\n .magic-radio + label:after {\n top: 6px;\n left: 6px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #53b783;\n }\n .magic-radio:checked + label:before {\n border: 1px solid #53b783;\n }\n .magic-radio:checked[disabled] + label:before {\n border: 1px solid #c9e2f9;\n }\n .magic-radio:checked[disabled] + label:after {\n background: #c9e2f9;\n }\n .magic-checkbox + label:before {\n border-radius: 3px;\n }\n .magic-checkbox + label:after {\n top: 2px;\n left: 7px;\n box-sizing: border-box;\n width: 6px;\n height: 12px;\n transform: rotate(45deg);\n border-width: 2px;\n border-style: solid;\n border-color: #fff;\n border-top: 0;\n border-left: 0;\n }\n .magic-checkbox:checked + label:before {\n border: #53b783;\n background: #53b783;\n }\n .magic-checkbox:checked[disabled] + label:before {\n border: #c9e2f9;\n background: #c9e2f9;\n }\n </style>\n\n <style>\n html,\n body {\n height: 100%;\n width: 100%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n body {\n font-family:\n Helvetica Neue For Number,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n PingFang SC,\n Hiragino Sans GB,\n Microsoft YaHei,\n Helvetica Neue,\n Helvetica,\n Arial,\n sans-serif;\n font-size: 14px;\n line-height: 24px;\n color: #444;\n }\n * {\n padding: 0;\n margin: 0;\n }\n ::selection {\n text-shadow: none;\n color: #fff;\n background: #98d8b7;\n }\n ::-moz-selection {\n text-shadow: none;\n color: #fff;\n background: #98d8b7;\n }\n .error-page {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n .error-logo {\n position: absolute;\n top: -15px;\n right: 0px;\n }\n .error-stack {\n background: #f1f1f1;\n padding: 140px 80px 40px;\n box-sizing: border-box;\n border-bottom: 1px solid #e2e2e2;\n }\n .error-status {\n color: #afafaf;\n font-size: 150px;\n position: absolute;\n opacity: 0.2;\n left: 76px;\n top: 80px;\n font-weight: 600;\n margin-bottom: 10px;\n }\n .error-name {\n color: #db5461;\n font-size: 18px;\n font-family: menlo, 'sans-serif';\n font-weight: 300;\n margin-bottom: 15px;\n }\n .error-title {\n border-bottom: 1px solid #e0e0e0;\n padding-bottom: 26px;\n margin-bottom: 20px;\n margin-top: 48px;\n }\n .error-title .box {\n color: #db5461;\n font-weight: 700;\n font-size: 20px;\n margin-left: 5px;\n }\n .error-title .context {\n color: #db5461;\n font-weight: 400;\n margin-left: 5px;\n margin-top: 48px;\n line-height: 1.5;\n }\n .error-frames {\n display: flex;\n flex-direction: row-reverse;\n margin-top: 40px;\n }\n .frame-preview {\n background: #fff;\n width: 50%;\n box-shadow: 0px 0px 9px #d3d3d3;\n height: 100%;\n box-sizing: border-box;\n overflow: auto;\n }\n .frame-stack {\n margin-right: 40px;\n flex: 1;\n padding: 10px 0;\n box-sizing: border-box;\n }\n .frames-list {\n overflow: auto;\n max-height: 334px;\n }\n .frames-filter-selector {\n margin-bottom: 30px;\n margin-left: 8px;\n }\n .request-details {\n padding: 50px 80px;\n }\n .request-title {\n text-transform: uppercase;\n font-size: 18px;\n letter-spacing: 1px;\n padding: 0 5px 5px 5px;\n margin-bottom: 15px;\n color: #53b783;\n }\n .request-details .table {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 80px;\n }\n .request-details .tr {\n display: flex;\n flex-direction: row;\n }\n .request-details .tr:nth-of-type(even) {\n background: #fbfbfb;\n }\n .request-details .table .td {\n padding: 6px 5px;\n font-size: 14px;\n letter-spacing: 0.4px;\n color: #455275;\n border-bottom: 1px solid #e8e8e8;\n word-break: break-word;\n }\n .request-details .table .td.title {\n flex: 1;\n color: #565655;\n font-size: 14px;\n font-weight: 600;\n }\n .request-details .table .td.content {\n width: 70%;\n }\n .request-details .table .td.content.code {\n background: #fff;\n width: 70%;\n box-shadow: 0px 0px 9px #d3d3d3;\n height: 100%;\n box-sizing: border-box;\n overflow: auto;\n }\n code[class*='language-'],\n pre[class*='language-'] {\n background: transparent;\n font-size: 13px;\n line-height: 1.8;\n }\n .line-numbers .line-numbers-rows {\n border: none;\n }\n .frame-row {\n display: flex;\n justify-content: space-between;\n padding: 6px 10px 6px 34px;\n position: relative;\n cursor: pointer;\n transition: background 300ms ease;\n }\n .frame-row.native-frame {\n display: none;\n opacity: 0.4;\n }\n .frame-row.native-frame.force-show {\n display: flex;\n }\n .frame-row:after {\n content: '';\n background: #db5461;\n position: absolute;\n top: 50%;\n left: 10px;\n transform: translateY(-50%);\n height: 10px;\n width: 10px;\n border-radius: 24px;\n }\n .frame-row:hover,\n .frame-row.active {\n background: #fff;\n }\n .frame-row.active {\n opacity: 1;\n }\n .frame-row-filepath {\n color: #455275;\n font-weight: 600;\n margin-right: 15px;\n }\n .frame-context {\n display: none;\n }\n .frame-row-code {\n color: #999;\n }\n #frame-file {\n color: #455275;\n font-weight: 600;\n border-bottom: 1px solid #e8e8e8;\n padding: 10px 22px;\n }\n #frame-method {\n color: #999;\n font-weight: 400;\n border-top: 1px solid #e8e8e8;\n padding: 10px 22px;\n }\n .is-hidden {\n display: none;\n }\n </style>\n </head>\n <body>\n <section class=\"error-page\">\n <section class=\"error-stack\">\n <h3 class=\"error-status\">{{ status }}</h3>\n <div class=\"error-title\">\n <h1 class=\"box\">{{ name }} in {{ request.url }}</h1>\n <div class=\"context\">{{ message }}</div>\n </div>\n\n <img class=\"error-logo\" src=\"https://zos.alipayobjects.com/rmsportal/JFKAMfmPehWfhBPdCjrw.svg\" />\n\n <div class=\"error-frames\">\n <div class=\"frame-preview is-hidden\">\n <div id=\"frame-file\"></div>\n <div id=\"frame-code\">\n <pre class=\"line-numbers\"><code id=\"code-drop\"></code></pre>\n </div>\n <div id=\"frame-method\"></div>\n </div>\n\n <div class=\"frame-stack\">\n <div class=\"frames-filter-selector\">\n <input type=\"checkbox\" class=\"magic-checkbox\" name=\"frames-filter\" id=\"frames-filter\" />\n <label for=\"frames-filter\">Show all frames</label>\n </div>\n\n <div class=\"frames-list\">\n {{#frames}} {{index}}\n <div class=\"frame-row {{classes}}\">\n <div class=\"frame-row-filepath\">{{ file }}:{{ line }}:{{ column }}</div>\n <div class=\"frame-row-code\">{{ method }}</div>\n <div\n class=\"frame-context\"\n data-start=\"{{context.start}}\"\n data-line=\"{{line}}\"\n data-file=\"{{file}}\"\n data-method=\"{{method}}\"\n data-extname=\"{{extname}}\"\n data-line-column=\"{{line}}:{{column}}\"\n >\n {{ context.pre }} {{ context.line }} {{ context.post }}\n </div>\n </div>\n {{/frames}}\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"request-details\">\n <h2 class=\"request-title\">Request Details</h2>\n <div class=\"table\">\n <div class=\"tr\">\n <div class=\"td title\">URI</div>\n <div class=\"td content\">{{ request.url }}</div>\n </div>\n\n <div class=\"tr\">\n <div class=\"td title\">Request Method</div>\n <div class=\"td content\">{{ request.method }}</div>\n </div>\n\n <div class=\"tr\">\n <div class=\"td title\">HTTP Version</div>\n <div class=\"td content\">{{ request.httpVersion }}</div>\n </div>\n\n <div class=\"tr\">\n <div class=\"td title\">Connection</div>\n <div class=\"td content\">{{ request.connection }}</div>\n </div>\n </div>\n\n <h2 class=\"request-title\">Headers</h2>\n <div class=\"table\">\n {{#request.headers}}\n <div class=\"tr\">\n <div class=\"td title\">{{ key }}</div>\n <div class=\"td content\">{{ value }}</div>\n </div>\n {{/request.headers}}\n </div>\n\n <h2 class=\"request-title\">Cookies</h2>\n <div class=\"table\">\n {{#request.cookies}}\n <div class=\"tr\">\n <div class=\"td title\">{{ key }}</div>\n <div class=\"td content\">{{ value }}</div>\n </div>\n {{/request.cookies}}\n </div>\n <h2 class=\"request-title\">AppInfo</h2>\n <div class=\"table\">\n <div class=\"tr\">\n <div class=\"td title\">baseDir</div>\n <div class=\"td content\">{{ appInfo.baseDir }}</div>\n </div>\n <div class=\"tr\">\n <div class=\"td title\">config</div>\n <div class=\"td content code\">\n <pre class=\"line-numbers\"><code class=\"language-json\">{{ appInfo.config }}</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <script type=\"text/javascript\">\n var _self =\n 'undefined' != typeof window\n ? window\n : 'undefined' != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope\n ? self\n : {},\n Prism = (function () {\n var e = /\\blang(?:uage)?-(\\w+)\\b/i,\n t = 0,\n n = (_self.Prism = {\n util: {\n encode: function (e) {\n return e instanceof a\n ? new a(e.type, n.util.encode(e.content), e.alias)\n : 'Array' === n.util.type(e)\n ? e.map(n.util.encode)\n : e\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/\\u00a0/g, ' ');\n },\n type: function (e) {\n return Object.prototype.toString.call(e).match(/\\[object (\\w+)\\]/)[1];\n },\n objId: function (e) {\n return (e.__id || Object.defineProperty(e, '__id', { value: ++t }), e.__id);\n },\n clone: function (e) {\n var t = n.util.type(e);\n switch (t) {\n case 'Object':\n var a = {};\n for (var r in e) e.hasOwnProperty(r) && (a[r] = n.util.clone(e[r]));\n return a;\n case 'Array':\n return (\n e.map &&\n e.map(function (e) {\n return n.util.clone(e);\n })\n );\n }\n return e;\n },\n },\n languages: {\n extend: function (e, t) {\n var a = n.util.clone(n.languages[e]);\n for (var r in t) a[r] = t[r];\n return a;\n },\n insertBefore: function (e, t, a, r) {\n r = r || n.languages;\n var i = r[e];\n if (2 == arguments.length) {\n a = arguments[1];\n for (var l in a) a.hasOwnProperty(l) && (i[l] = a[l]);\n return i;\n }\n var o = {};\n for (var s in i)\n if (i.hasOwnProperty(s)) {\n if (s == t) for (var l in a) a.hasOwnProperty(l) && (o[l] = a[l]);\n o[s] = i[s];\n }\n return (\n n.languages.DFS(n.languages, function (t, n) {\n n === r[e] && t != e && (this[t] = o);\n }),\n (r[e] = o)\n );\n },\n DFS: function (e, t, a, r) {\n r = r || {};\n for (var i in e)\n e.hasOwnProperty(i) &&\n (t.call(e, i, e[i], a || i),\n 'Object' !== n.util.type(e[i]) || r[n.util.objId(e[i])]\n ? 'Array' !== n.util.type(e[i]) ||\n r[n.util.objId(e[i])] ||\n ((r[n.util.objId(e[i])] = !0), n.languages.DFS(e[i], t, i, r))\n : ((r[n.util.objId(e[i])] = !0), n.languages.DFS(e[i], t, null, r)));\n },\n },\n plugins: {},\n highlightAll: function (e, t) {\n var a = {\n callback: t,\n selector:\n 'code[class*=\"language-\"], [class*=\"language-\"] code, code[class*=\"lang-\"], [class*=\"lang-\"] code',\n };\n n.hooks.run('before-highlightall', a);\n for (var r, i = a.elements || document.querySelectorAll(a.selector), l = 0; (r = i[l++]); )\n n.highlightElement(r, e === !0, a.callback);\n },\n highlightElement: function (t, a, r) {\n for (var i, l, o = t; o && !e.test(o.className); ) o = o.parentNode;\n (o && ((i = (o.className.match(e) || [, ''])[1].toLowerCase()), (l = n.languages[i])),\n (t.className = t.className.replace(e, '').replace(/\\s+/g, ' ') + ' language-' + i),\n (o = t.parentNode),\n /pre/i.test(o.nodeName) &&\n (o.className = o.className.replace(e, '').replace(/\\s+/g, ' ') + ' language-' + i));\n var s = t.textContent,\n u = { element: t, language: i, grammar: l, code: s };\n if ((n.hooks.run('before-sanity-check', u), !u.code || !u.grammar))\n return (u.code && (u.element.textContent = u.code), n.hooks.run('complete', u), void 0);\n if ((n.hooks.run('before-highlight', u), a && _self.Worker)) {\n var g = new Worker(n.filename);\n ((g.onmessage = function (e) {\n ((u.highlightedCode = e.data),\n n.hooks.run('before-insert', u),\n (u.element.innerHTML = u.highlightedCode),\n r && r.call(u.element),\n n.hooks.run('after-highlight', u),\n n.hooks.run('complete', u));\n }),\n g.postMessage(JSON.stringify({ language: u.language, code: u.code, immediateClose: !0 })));\n } else\n ((u.highlightedCode = n.highlight(u.code, u.grammar, u.language)),\n n.hooks.run('before-insert', u),\n (u.element.innerHTML = u.highlightedCode),\n r && r.call(t),\n n.hooks.run('after-highlight', u),\n n.hooks.run('complete', u));\n },\n highlight: function (e, t, r) {\n var i = n.tokenize(e, t);\n return a.stringify(n.util.encode(i), r);\n },\n tokenize: function (e, t) {\n var a = n.Token,\n r = [e],\n i = t.rest;\n if (i) {\n for (var l in i) t[l] = i[l];\n delete t.rest;\n }\n e: for (var l in t)\n if (t.hasOwnProperty(l) && t[l]) {\n var o = t[l];\n o = 'Array' === n.util.type(o) ? o : [o];\n for (var s = 0; s < o.length; ++s) {\n var u = o[s],\n g = u.inside,\n c = !!u.lookbehind,\n h = !!u.greedy,\n f = 0,\n d = u.alias;\n if (h && !u.pattern.global) {\n var p = u.pattern.toString().match(/[imuy]*$/)[0];\n u.pattern = RegExp(u.pattern.source, p + 'g');\n }\n u = u.pattern || u;\n for (var m = 0, y = 0; m < r.length; y += r[m].length, ++m) {\n var v = r[m];\n if (r.length > e.length) break e;\n if (!(v instanceof a)) {\n u.lastIndex = 0;\n var b = u.exec(v),\n k = 1;\n if (!b && h && m != r.length - 1) {\n if (((u.lastIndex = y), (b = u.exec(e)), !b)) break;\n for (\n var w = b.index + (c ? b[1].length : 0),\n _ = b.index + b[0].length,\n A = m,\n P = y,\n j = r.length;\n j > A && _ > P;\n ++A\n )\n ((P += r[A].length), w >= P && (++m, (y = P)));\n if (r[m] instanceof a || r[A - 1].greedy) continue;\n ((k = A - m), (v = e.slice(y, P)), (b.index -= y));\n }\n if (b) {\n c && (f = b[1].length);\n var w = b.index + f,\n b = b[0].slice(f),\n _ = w + b.length,\n x = v.slice(0, w),\n O = v.slice(_),\n S = [m, k];\n x && S.push(x);\n var N = new a(l, g ? n.tokenize(b, g) : b, d, b, h);\n (S.push(N), O && S.push(O), Array.prototype.splice.apply(r, S));\n }\n }\n }\n }\n }\n return r;\n },\n hooks: {\n all: {},\n add: function (e, t) {\n var a = n.hooks.all;\n ((a[e] = a[e] || []), a[e].push(t));\n },\n run: function (e, t) {\n var a = n.hooks.all[e];\n if (a && a.length) for (var r, i = 0; (r = a[i++]); ) r(t);\n },\n },\n }),\n a = (n.Token = function (e, t, n, a, r) {\n ((this.type = e),\n (this.content = t),\n (this.alias = n),\n (this.length = 0 | (a || '').length),\n (this.greedy = !!r));\n });\n if (\n ((a.stringify = function (e, t, r) {\n if ('string' == typeof e) return e;\n if ('Array' === n.util.type(e))\n return e\n .map(function (n) {\n return a.stringify(n, t, e);\n })\n .join('');\n var i = {\n type: e.type,\n content: a.stringify(e.content, t, r),\n tag: 'span',\n classes: ['token', e.type],\n attributes: {},\n language: t,\n parent: r,\n };\n if (('comment' == i.type && (i.attributes.spellcheck = 'true'), e.alias)) {\n var l = 'Array' === n.util.type(e.alias) ? e.alias : [e.alias];\n Array.prototype.push.apply(i.classes, l);\n }\n n.hooks.run('wrap', i);\n var o = Object.keys(i.attributes)\n .map(function (e) {\n return e + '=\"' + (i.attributes[e] || '').replace(/\"/g, '&quot;') + '\"';\n })\n .join(' ');\n return (\n '<' +\n i.tag +\n ' class=\"' +\n i.classes.join(' ') +\n '\"' +\n (o ? ' ' + o : '') +\n '>' +\n i.content +\n '</' +\n i.tag +\n '>'\n );\n }),\n !_self.document)\n )\n return _self.addEventListener\n ? (_self.addEventListener(\n 'message',\n function (e) {\n var t = JSON.parse(e.data),\n a = t.language,\n r = t.code,\n i = t.immediateClose;\n (_self.postMessage(n.highlight(r, n.languages[a], a)), i && _self.close());\n },\n !1\n ),\n _self.Prism)\n : _self.Prism;\n var r = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();\n return (\n r &&\n ((n.filename = r.src),\n document.addEventListener &&\n !r.hasAttribute('data-manual') &&\n ('loading' !== document.readyState\n ? window.requestAnimationFrame\n ? window.requestAnimationFrame(n.highlightAll)\n : window.setTimeout(n.highlightAll, 16)\n : document.addEventListener('DOMContentLoaded', n.highlightAll))),\n _self.Prism\n );\n })();\n ('undefined' != typeof module && module.exports && (module.exports = Prism),\n 'undefined' != typeof global && (global.Prism = Prism));\n ((Prism.languages.markup = {\n comment: /<!--[\\w\\W]*?-->/,\n prolog: /<\\?[\\w\\W]+?\\?>/,\n doctype: /<!DOCTYPE[\\w\\W]+?>/i,\n cdata: /<!\\[CDATA\\[[\\w\\W]*?]]>/i,\n tag: {\n pattern:\n /<\\/?(?!\\d)[^\\s>\\/=$<]+(?:\\s+[^\\s>\\/=]+(?:=(?:(\"|')(?:\\\\\\1|\\\\?(?!\\1)[\\w\\W])*\\1|[^\\s'\">=]+))?)*\\s*\\/?>/i,\n inside: {\n tag: { pattern: /^<\\/?[^\\s>\\/]+/i, inside: { punctuation: /^<\\/?/, namespace: /^[^\\s>\\/:]+:/ } },\n 'attr-value': { pattern: /=(?:('|\")[\\w\\W]*?(\\1)|[^\\s>]+)/i, inside: { punctuation: /[=>\"']/ } },\n punctuation: /\\/?>/,\n 'attr-name': { pattern: /[^\\s>\\/]+/, inside: { namespace: /^[^\\s>\\/:]+:/ } },\n },\n },\n entity: /&#?[\\da-z]{1,8};/i,\n }),\n Prism.hooks.add('wrap', function (a) {\n 'entity' === a.type && (a.attributes.title = a.content.replace(/&amp;/, '&'));\n }),\n (Prism.languages.xml = Prism.languages.markup),\n (Prism.languages.html = Prism.languages.markup),\n (Prism.languages.mathml = Prism.languages.markup),\n (Prism.languages.svg = Prism.languages.markup));\n ((Prism.languages.css = {\n comment: /\\/\\*[\\w\\W]*?\\*\\//,\n atrule: { pattern: /@[\\w-]+?.*?(;|(?=\\s*\\{))/i, inside: { rule: /@[\\w-]+/ } },\n url: /url\\((?:([\"'])(\\\\(?:\\r\\n|[\\w\\W])|(?!\\1)[^\\\\\\r\\n])*\\1|.*?)\\)/i,\n selector: /[^\\{\\}\\s][^\\{\\};]*?(?=\\s*\\{)/,\n string: { pattern: /(\"|')(\\\\(?:\\r\\n|[\\w\\W])|(?!\\1)[^\\\\\\r\\n])*\\1/, greedy: !0 },\n property: /(\\b|\\B)[\\w-]+(?=\\s*:)/i,\n important: /\\B!important\\b/i,\n function: /[-a-z0-9]+(?=\\()/i,\n punctuation: /[(){};:]/,\n }),\n (Prism.languages.css.atrule.inside.rest = Prism.util.clone(Prism.languages.css)),\n Prism.languages.markup &&\n (Prism.languages.insertBefore('markup', 'tag', {\n style: {\n pattern: /(<style[\\w\\W]*?>)[\\w\\W]*?(?=<\\/style>)/i,\n lookbehind: !0,\n inside: Prism.languages.css,\n alias: 'language-css',\n },\n }),\n Prism.languages.insertBefore(\n 'inside',\n 'attr-value',\n {\n 'style-attr': {\n pattern: /\\s*style=(\"|').*?\\1/i,\n inside: {\n 'attr-name': { pattern: /^\\s*style/i, inside: Prism.languages.markup.tag.inside },\n punctuation: /^\\s*=\\s*['\"]|['\"]\\s*$/,\n 'attr-value': { pattern: /.+/i, inside: Prism.languages.css },\n },\n alias: 'language-css',\n },\n },\n Prism.languages.markup.tag\n )));\n Prism.languages.clike = {\n comment: [\n { pattern: /(^|[^\\\\])\\/\\*[\\w\\W]*?\\*\\//, lookbehind: !0 },\n { pattern: /(^|[^\\\\:])\\/\\/.*/, lookbehind: !0 },\n ],\n string: { pattern: /([\"'])(\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/, greedy: !0 },\n 'class-name': {\n pattern:\n /((?:\\b(?:class|interface|extends|implements|trait|instanceof|new)\\s+)|(?:catch\\s+\\())[a-z0-9_\\.\\\\]+/i,\n lookbehind: !0,\n inside: { punctuation: /(\\.|\\\\)/ },\n },\n keyword:\n /\\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\\b/,\n boolean: /\\b(true|false)\\b/,\n function: /[a-z0-9_]+(?=\\()/i,\n number: /\\b-?(?:0x[\\da-f]+|\\d*\\.?\\d+(?:e[+-]?\\d+)?)\\b/i,\n operator: /--?|\\+\\+?|!=?=?|<=?|>=?|==?=?|&&?|\\|\\|?|\\?|\\*|\\/|~|\\^|%/,\n punctuation: /[{}[\\];(),.:]/,\n };\n ((Prism.languages.javascript = Prism.languages.extend('clike', {\n keyword:\n /\\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\\b/,\n number: /\\b-?(0x[\\dA-Fa-f]+|0b[01]+|0o[0-7]+|\\d*\\.?\\d+([Ee][+-]?\\d+)?|NaN|Infinity)\\b/,\n function: /[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*(?=\\()/i,\n operator: /--?|\\+\\+?|!=?=?|<=?|>=?|==?=?|&&?|\\|\\|?|\\?|\\*\\*?|\\/|~|\\^|%|\\.{3}/,\n })),\n Prism.languages.insertBefore('javascript', 'keyword', {\n regex: {\n pattern: /(^|[^\\/])\\/(?!\\/)(\\[.+?]|\\\\.|[^\\/\\\\\\r\\n])+\\/[gimyu]{0,5}(?=\\s*($|[\\r\\n,.;})]))/,\n lookbehind: !0,\n greedy: !0,\n },\n }),\n Prism.languages.insertBefore('javascript', 'string', {\n 'template-string': {\n pattern: /`(?:\\\\\\\\|\\\\?[^\\\\])*?`/,\n greedy: !0,\n inside: {\n interpolation: {\n pattern: /\\$\\{[^}]+\\}/,\n inside: {\n 'interpolation-punctuation': { pattern: /^\\$\\{|\\}$/, alias: 'punctuation' },\n rest: Prism.languages.javascript,\n },\n },\n string: /[\\s\\S]+/,\n },\n },\n }),\n Prism.languages.markup &&\n Prism.languages.insertBefore('markup', 'tag', {\n script: {\n pattern: /(<script[\\w\\W]*?>)[\\w\\W]*?(?=<\\/script>)/i,\n lookbehind: !0,\n inside: Prism.languages.javascript,\n alias: 'language-javascript',\n },\n }),\n (Prism.languages.js = Prism.languages.javascript));\n ((Prism.languages.json = {\n property: /\"(?:\\\\.|[^\\\\\"])*\"(?=\\s*:)/gi,\n string: /\"(?!:)(?:\\\\.|[^\\\\\"])*\"(?!:)/g,\n number: /\\b-?(0x[\\dA-Fa-f]+|\\d*\\.?\\d+([Ee][+-]?\\d+)?)\\b/g,\n punctuation: /[{}[\\]);,]/g,\n operator: /:/g,\n boolean: /\\b(true|false)\\b/gi,\n null: /\\bnull\\b/gi,\n }),\n (Prism.languages.jsonp = Prism.languages.json));\n ((Prism.languages.typescript = Prism.languages.extend('javascript', {\n keyword:\n /\\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|enum|symbol|namespace|abstract|require|type)\\b/,\n })),\n (Prism.languages.ts = Prism.languages.typescript));\n !(function () {\n function e(e, t) {\n return Array.prototype.slice.call((t || document).querySelectorAll(e));\n }\n function t(e, t) {\n return ((t = ' ' + t + ' '), (' ' + e.className + ' ').replace(/[\\n\\t]/g, ' ').indexOf(t) > -1);\n }\n function n(e, n, i) {\n for (\n var o,\n a = n.replace(/\\s+/g, '').split(','),\n l = +e.getAttribute('data-line-offset') || 0,\n d = r() ? parseInt : parseFloat,\n c = d(getComputedStyle(e).lineHeight),\n s = 0;\n (o = a[s++]);\n\n ) {\n o = o.split('-');\n var u = +o[0],\n m = +o[1] || u,\n h = document.createElement('div');\n ((h.textContent = Array(m - u + 2).join('\\n')),\n h.setAttribute('aria-hidden', 'true'),\n (h.className = (i || '') + ' line-highlight'),\n t(e, 'line-numbers') || (h.setAttribute('data-start', u), m > u && h.setAttribute('data-end', m)),\n (h.style.top = (u - l - 1) * c + 'px'),\n t(e, 'line-numbers') ? e.appendChild(h) : (e.querySelector('code') || e).appendChild(h));\n }\n }\n function i() {\n var t = location.hash.slice(1);\n e('.temporary.line-highlight').forEach(function (e) {\n e.parentNode.removeChild(e);\n });\n var i = (t.match(/\\.([\\d,-]+)$/) || [, ''])[1];\n if (i && !document.getElementById(t)) {\n var r = t.slice(0, t.lastIndexOf('.')),\n o = document.getElementById(r);\n o &&\n (o.hasAttribute('data-line') || o.setAttribute('data-line', ''),\n n(o, i, 'temporary '),\n document.querySelector('.temporary.line-highlight').scrollIntoView());\n }\n }\n if ('undefined' != typeof self && self.Prism && self.document && document.querySelector) {\n var r = (function () {\n var e;\n return function () {\n if ('undefined' == typeof e) {\n var t = document.createElement('div');\n ((t.style.fontSize = '13px'),\n (t.style.lineHeight = '1.5'),\n (t.style.padding = 0),\n (t.style.border = 0),\n (t.innerHTML = '&nbsp;<br />&nbsp;'),\n document.body.appendChild(t),\n (e = 38 === t.offsetHeight),\n document.body.removeChild(t));\n }\n return e;\n };\n })(),\n o = 0;\n (Prism.hooks.add('complete', function (t) {\n var r = t.element.parentNode,\n a = r && r.getAttribute('data-line');\n r &&\n a &&\n /pre/i.test(r.nodeName) &&\n (clearTimeout(o),\n e('.line-highlight', r).forEach(function (e) {\n e.parentNode.removeChild(e);\n }),\n n(r, a),\n (o = setTimeout(i, 1)));\n }),\n window.addEventListener && window.addEventListener('hashchange', i));\n }\n })();\n !(function () {\n 'undefined' != typeof self &&\n self.Prism &&\n self.document &&\n Prism.hooks.add('complete', function (e) {\n if (e.code) {\n var t = e.element.parentNode,\n s = /\\s*\\bline-numbers\\b\\s*/;\n if (\n t &&\n /pre/i.test(t.nodeName) &&\n (s.test(t.className) || s.test(e.element.className)) &&\n !e.element.querySelector('.line-numbers-rows')\n ) {\n (s.test(e.element.className) && (e.element.className = e.element.className.replace(s, '')),\n s.test(t.className) || (t.className += ' line-numbers'));\n var n,\n a = e.code.match(/\\n(?!$)/g),\n l = a ? a.length + 1 : 1,\n r = new Array(l + 1);\n ((r = r.join('<span></span>')),\n (n = document.createElement('span')),\n n.setAttribute('aria-hidden', 'true'),\n (n.className = 'line-numbers-rows'),\n (n.innerHTML = r),\n t.hasAttribute('data-start') &&\n (t.style.counterReset = 'linenumber ' + (parseInt(t.getAttribute('data-start'), 10) - 1)),\n e.element.appendChild(n));\n }\n }\n });\n })();\n <\/script>\n <script>\n (function () {\n const $ = function (value) {\n return document.querySelector(value);\n };\n const $$ = function (value) {\n return document.querySelectorAll(value);\n };\n var nativeFramesLength = $$('.frame-row.native-frame').length;\n var allFramesLength = $$('.frame-row').length;\n function filterFrames() {\n $('.frame-preview').classList.remove('is-hidden');\n var isSelected = $('#frames-filter').checked;\n if (isSelected) {\n $$('.frame-row.native-frame').forEach(function (node) {\n node.classList.add('force-show');\n });\n } else {\n $$('.frame-row.native-frame').forEach(function (node) {\n node.classList.remove('force-show');\n });\n var activeFrame = $('.frame-row.active');\n if (activeFrame && activeFrame.classList.contains('native-frame')) {\n activeFrame.classList.remove('active');\n var firstFrame = $$('.frame-row')[0];\n if (!firstFrame) {\n return;\n }\n firstFrame.classList.add('active');\n showFrameContext(firstFrame);\n }\n }\n }\n function displayFirstView() {\n if (nativeFramesLength !== allFramesLength) {\n $('.frame-preview').classList.remove('is-hidden');\n }\n }\n function showFrameContext(frame) {\n if (!frame) {\n return;\n }\n const $frameContext = frame.querySelector('.frame-context');\n if (!$frameContext) {\n return;\n }\n var $context = $frameContext.innerHTML;\n $context = $context.trim().length === 0 ? 'Missing stack frames' : $context;\n var $line = $frameContext.getAttribute('data-line');\n var $start = $frameContext.getAttribute('data-start');\n var $file = $frameContext.getAttribute('data-file');\n var $method = $frameContext.getAttribute('data-method');\n var $lineColumn = $frameContext.getAttribute('data-line-column');\n var $language = $frameContext.getAttribute('data-extname') || 'js';\n $('#code-drop').parentNode.setAttribute('data-line', $line);\n $('#code-drop').parentNode.setAttribute('data-start', $start);\n $('#code-drop').parentNode.setAttribute('data-language', $language);\n $('#code-drop').parentNode.setAttribute('data-line-offset', Number($start) - 1);\n $('#code-drop').setAttribute('class', 'language-' + $language);\n $('#code-drop').innerHTML = $context;\n $('#frame-file').innerHTML = $file || '';\n $('#frame-method').innerHTML = [$method, $lineColumn].filter(Boolean).join(' ');\n\n Prism.highlightAll();\n }\n $$('.frame-row').forEach(function (node) {\n node.onclick = function (e) {\n $$('.frame-row').forEach(function (_node) {\n _node.classList.remove('active');\n });\n e.currentTarget.classList.add('active');\n showFrameContext(e.currentTarget);\n };\n });\n $('#frames-filter').onclick = function () {\n filterFrames();\n };\n displayFirstView();\n showFrameContext($('.frame-row.active') || $('.frame-row'));\n })();\n <\/script>\n </section>\n </body>\n</html>\n";
4
+ //#endregion
5
+ export { ONERROR_PAGE_TEMPLATE };
@@ -1,4 +1,6 @@
1
- <!doctype html>
1
+ //#region src/lib/onerror_page.ts
2
+ /** Built-in error page template. */
3
+ const ONERROR_PAGE_TEMPLATE = `<!doctype html>
2
4
  <html lang="en">
3
5
  <head>
4
6
  <meta charset="UTF-8" />
@@ -729,7 +731,7 @@
729
731
  ? self
730
732
  : {},
731
733
  Prism = (function () {
732
- var e = /\blang(?:uage)?-(\w+)\b/i,
734
+ var e = /\\blang(?:uage)?-(\\w+)\\b/i,
733
735
  t = 0,
734
736
  n = (_self.Prism = {
735
737
  util: {
@@ -741,10 +743,10 @@
741
743
  : e
742
744
  .replace(/&/g, '&amp;')
743
745
  .replace(/</g, '&lt;')
744
- .replace(/\u00a0/g, ' ');
746
+ .replace(/\\u00a0/g, ' ');
745
747
  },
746
748
  type: function (e) {
747
- return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1];
749
+ return Object.prototype.toString.call(e).match(/\\[object (\\w+)\\]/)[1];
748
750
  },
749
751
  objId: function (e) {
750
752
  return (e.__id || Object.defineProperty(e, '__id', { value: ++t }), e.__id);
@@ -820,10 +822,10 @@
820
822
  highlightElement: function (t, a, r) {
821
823
  for (var i, l, o = t; o && !e.test(o.className); ) o = o.parentNode;
822
824
  (o && ((i = (o.className.match(e) || [, ''])[1].toLowerCase()), (l = n.languages[i])),
823
- (t.className = t.className.replace(e, '').replace(/\s+/g, ' ') + ' language-' + i),
825
+ (t.className = t.className.replace(e, '').replace(/\\s+/g, ' ') + ' language-' + i),
824
826
  (o = t.parentNode),
825
827
  /pre/i.test(o.nodeName) &&
826
- (o.className = o.className.replace(e, '').replace(/\s+/g, ' ') + ' language-' + i));
828
+ (o.className = o.className.replace(e, '').replace(/\\s+/g, ' ') + ' language-' + i));
827
829
  var s = t.textContent,
828
830
  u = { element: t, language: i, grammar: l, code: s };
829
831
  if ((n.hooks.run('before-sanity-check', u), !u.code || !u.grammar))
@@ -1009,21 +1011,21 @@
1009
1011
  ('undefined' != typeof module && module.exports && (module.exports = Prism),
1010
1012
  'undefined' != typeof global && (global.Prism = Prism));
1011
1013
  ((Prism.languages.markup = {
1012
- comment: /<!--[\w\W]*?-->/,
1013
- prolog: /<\?[\w\W]+?\?>/,
1014
- doctype: /<!DOCTYPE[\w\W]+?>/i,
1015
- cdata: /<!\[CDATA\[[\w\W]*?]]>/i,
1014
+ comment: /<!--[\\w\\W]*?-->/,
1015
+ prolog: /<\\?[\\w\\W]+?\\?>/,
1016
+ doctype: /<!DOCTYPE[\\w\\W]+?>/i,
1017
+ cdata: /<!\\[CDATA\\[[\\w\\W]*?]]>/i,
1016
1018
  tag: {
1017
1019
  pattern:
1018
- /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,
1020
+ /<\\/?(?!\\d)[^\\s>\\/=$<]+(?:\\s+[^\\s>\\/=]+(?:=(?:("|')(?:\\\\\\1|\\\\?(?!\\1)[\\w\\W])*\\1|[^\\s'">=]+))?)*\\s*\\/?>/i,
1019
1021
  inside: {
1020
- tag: { pattern: /^<\/?[^\s>\/]+/i, inside: { punctuation: /^<\/?/, namespace: /^[^\s>\/:]+:/ } },
1021
- 'attr-value': { pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i, inside: { punctuation: /[=>"']/ } },
1022
- punctuation: /\/?>/,
1023
- 'attr-name': { pattern: /[^\s>\/]+/, inside: { namespace: /^[^\s>\/:]+:/ } },
1022
+ tag: { pattern: /^<\\/?[^\\s>\\/]+/i, inside: { punctuation: /^<\\/?/, namespace: /^[^\\s>\\/:]+:/ } },
1023
+ 'attr-value': { pattern: /=(?:('|")[\\w\\W]*?(\\1)|[^\\s>]+)/i, inside: { punctuation: /[=>"']/ } },
1024
+ punctuation: /\\/?>/,
1025
+ 'attr-name': { pattern: /[^\\s>\\/]+/, inside: { namespace: /^[^\\s>\\/:]+:/ } },
1024
1026
  },
1025
1027
  },
1026
- entity: /&#?[\da-z]{1,8};/i,
1028
+ entity: /&#?[\\da-z]{1,8};/i,
1027
1029
  }),
1028
1030
  Prism.hooks.add('wrap', function (a) {
1029
1031
  'entity' === a.type && (a.attributes.title = a.content.replace(/&amp;/, '&'));
@@ -1033,21 +1035,21 @@
1033
1035
  (Prism.languages.mathml = Prism.languages.markup),
1034
1036
  (Prism.languages.svg = Prism.languages.markup));
1035
1037
  ((Prism.languages.css = {
1036
- comment: /\/\*[\w\W]*?\*\//,
1037
- atrule: { pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i, inside: { rule: /@[\w-]+/ } },
1038
- url: /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
1039
- selector: /[^\{\}\s][^\{\};]*?(?=\s*\{)/,
1040
- string: { pattern: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/, greedy: !0 },
1041
- property: /(\b|\B)[\w-]+(?=\s*:)/i,
1042
- important: /\B!important\b/i,
1043
- function: /[-a-z0-9]+(?=\()/i,
1038
+ comment: /\\/\\*[\\w\\W]*?\\*\\//,
1039
+ atrule: { pattern: /@[\\w-]+?.*?(;|(?=\\s*\\{))/i, inside: { rule: /@[\\w-]+/ } },
1040
+ url: /url\\((?:(["'])(\\\\(?:\\r\\n|[\\w\\W])|(?!\\1)[^\\\\\\r\\n])*\\1|.*?)\\)/i,
1041
+ selector: /[^\\{\\}\\s][^\\{\\};]*?(?=\\s*\\{)/,
1042
+ string: { pattern: /("|')(\\\\(?:\\r\\n|[\\w\\W])|(?!\\1)[^\\\\\\r\\n])*\\1/, greedy: !0 },
1043
+ property: /(\\b|\\B)[\\w-]+(?=\\s*:)/i,
1044
+ important: /\\B!important\\b/i,
1045
+ function: /[-a-z0-9]+(?=\\()/i,
1044
1046
  punctuation: /[(){};:]/,
1045
1047
  }),
1046
1048
  (Prism.languages.css.atrule.inside.rest = Prism.util.clone(Prism.languages.css)),
1047
1049
  Prism.languages.markup &&
1048
1050
  (Prism.languages.insertBefore('markup', 'tag', {
1049
1051
  style: {
1050
- pattern: /(<style[\w\W]*?>)[\w\W]*?(?=<\/style>)/i,
1052
+ pattern: /(<style[\\w\\W]*?>)[\\w\\W]*?(?=<\\/style>)/i,
1051
1053
  lookbehind: !0,
1052
1054
  inside: Prism.languages.css,
1053
1055
  alias: 'language-css',
@@ -1058,10 +1060,10 @@
1058
1060
  'attr-value',
1059
1061
  {
1060
1062
  'style-attr': {
1061
- pattern: /\s*style=("|').*?\1/i,
1063
+ pattern: /\\s*style=("|').*?\\1/i,
1062
1064
  inside: {
1063
- 'attr-name': { pattern: /^\s*style/i, inside: Prism.languages.markup.tag.inside },
1064
- punctuation: /^\s*=\s*['"]|['"]\s*$/,
1065
+ 'attr-name': { pattern: /^\\s*style/i, inside: Prism.languages.markup.tag.inside },
1066
+ punctuation: /^\\s*=\\s*['"]|['"]\\s*$/,
1065
1067
  'attr-value': { pattern: /.+/i, inside: Prism.languages.css },
1066
1068
  },
1067
1069
  alias: 'language-css',
@@ -1071,58 +1073,58 @@
1071
1073
  )));
1072
1074
  Prism.languages.clike = {
1073
1075
  comment: [
1074
- { pattern: /(^|[^\\])\/\*[\w\W]*?\*\//, lookbehind: !0 },
1075
- { pattern: /(^|[^\\:])\/\/.*/, lookbehind: !0 },
1076
+ { pattern: /(^|[^\\\\])\\/\\*[\\w\\W]*?\\*\\//, lookbehind: !0 },
1077
+ { pattern: /(^|[^\\\\:])\\/\\/.*/, lookbehind: !0 },
1076
1078
  ],
1077
- string: { pattern: /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: !0 },
1079
+ string: { pattern: /(["'])(\\\\(?:\\r\\n|[\\s\\S])|(?!\\1)[^\\\\\\r\\n])*\\1/, greedy: !0 },
1078
1080
  'class-name': {
1079
1081
  pattern:
1080
- /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,
1082
+ /((?:\\b(?:class|interface|extends|implements|trait|instanceof|new)\\s+)|(?:catch\\s+\\())[a-z0-9_\\.\\\\]+/i,
1081
1083
  lookbehind: !0,
1082
- inside: { punctuation: /(\.|\\)/ },
1084
+ inside: { punctuation: /(\\.|\\\\)/ },
1083
1085
  },
1084
1086
  keyword:
1085
- /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
1086
- boolean: /\b(true|false)\b/,
1087
- function: /[a-z0-9_]+(?=\()/i,
1088
- number: /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,
1089
- operator: /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
1090
- punctuation: /[{}[\];(),.:]/,
1087
+ /\\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\\b/,
1088
+ boolean: /\\b(true|false)\\b/,
1089
+ function: /[a-z0-9_]+(?=\\()/i,
1090
+ number: /\\b-?(?:0x[\\da-f]+|\\d*\\.?\\d+(?:e[+-]?\\d+)?)\\b/i,
1091
+ operator: /--?|\\+\\+?|!=?=?|<=?|>=?|==?=?|&&?|\\|\\|?|\\?|\\*|\\/|~|\\^|%/,
1092
+ punctuation: /[{}[\\];(),.:]/,
1091
1093
  };
1092
1094
  ((Prism.languages.javascript = Prism.languages.extend('clike', {
1093
1095
  keyword:
1094
- /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
1095
- number: /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,
1096
- function: /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,
1097
- operator: /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/,
1096
+ /\\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\\b/,
1097
+ number: /\\b-?(0x[\\dA-Fa-f]+|0b[01]+|0o[0-7]+|\\d*\\.?\\d+([Ee][+-]?\\d+)?|NaN|Infinity)\\b/,
1098
+ function: /[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*(?=\\()/i,
1099
+ operator: /--?|\\+\\+?|!=?=?|<=?|>=?|==?=?|&&?|\\|\\|?|\\?|\\*\\*?|\\/|~|\\^|%|\\.{3}/,
1098
1100
  })),
1099
1101
  Prism.languages.insertBefore('javascript', 'keyword', {
1100
1102
  regex: {
1101
- pattern: /(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,
1103
+ pattern: /(^|[^\\/])\\/(?!\\/)(\\[.+?]|\\\\.|[^\\/\\\\\\r\\n])+\\/[gimyu]{0,5}(?=\\s*($|[\\r\\n,.;})]))/,
1102
1104
  lookbehind: !0,
1103
1105
  greedy: !0,
1104
1106
  },
1105
1107
  }),
1106
1108
  Prism.languages.insertBefore('javascript', 'string', {
1107
1109
  'template-string': {
1108
- pattern: /`(?:\\\\|\\?[^\\])*?`/,
1110
+ pattern: /\`(?:\\\\\\\\|\\\\?[^\\\\])*?\`/,
1109
1111
  greedy: !0,
1110
1112
  inside: {
1111
1113
  interpolation: {
1112
- pattern: /\$\{[^}]+\}/,
1114
+ pattern: /\\$\\{[^}]+\\}/,
1113
1115
  inside: {
1114
- 'interpolation-punctuation': { pattern: /^\$\{|\}$/, alias: 'punctuation' },
1116
+ 'interpolation-punctuation': { pattern: /^\\$\\{|\\}$/, alias: 'punctuation' },
1115
1117
  rest: Prism.languages.javascript,
1116
1118
  },
1117
1119
  },
1118
- string: /[\s\S]+/,
1120
+ string: /[\\s\\S]+/,
1119
1121
  },
1120
1122
  },
1121
1123
  }),
1122
1124
  Prism.languages.markup &&
1123
1125
  Prism.languages.insertBefore('markup', 'tag', {
1124
1126
  script: {
1125
- pattern: /(<script[\w\W]*?>)[\w\W]*?(?=<\/script>)/i,
1127
+ pattern: /(<script[\\w\\W]*?>)[\\w\\W]*?(?=<\\/script>)/i,
1126
1128
  lookbehind: !0,
1127
1129
  inside: Prism.languages.javascript,
1128
1130
  alias: 'language-javascript',
@@ -1130,18 +1132,18 @@
1130
1132
  }),
1131
1133
  (Prism.languages.js = Prism.languages.javascript));
1132
1134
  ((Prism.languages.json = {
1133
- property: /"(?:\\.|[^\\"])*"(?=\s*:)/gi,
1134
- string: /"(?!:)(?:\\.|[^\\"])*"(?!:)/g,
1135
- number: /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/g,
1136
- punctuation: /[{}[\]);,]/g,
1135
+ property: /"(?:\\\\.|[^\\\\"])*"(?=\\s*:)/gi,
1136
+ string: /"(?!:)(?:\\\\.|[^\\\\"])*"(?!:)/g,
1137
+ number: /\\b-?(0x[\\dA-Fa-f]+|\\d*\\.?\\d+([Ee][+-]?\\d+)?)\\b/g,
1138
+ punctuation: /[{}[\\]);,]/g,
1137
1139
  operator: /:/g,
1138
- boolean: /\b(true|false)\b/gi,
1139
- null: /\bnull\b/gi,
1140
+ boolean: /\\b(true|false)\\b/gi,
1141
+ null: /\\bnull\\b/gi,
1140
1142
  }),
1141
1143
  (Prism.languages.jsonp = Prism.languages.json));
1142
1144
  ((Prism.languages.typescript = Prism.languages.extend('javascript', {
1143
1145
  keyword:
1144
- /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|enum|symbol|namespace|abstract|require|type)\b/,
1146
+ /\\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|enum|symbol|namespace|abstract|require|type)\\b/,
1145
1147
  })),
1146
1148
  (Prism.languages.ts = Prism.languages.typescript));
1147
1149
  !(function () {
@@ -1149,12 +1151,12 @@
1149
1151
  return Array.prototype.slice.call((t || document).querySelectorAll(e));
1150
1152
  }
1151
1153
  function t(e, t) {
1152
- return ((t = ' ' + t + ' '), (' ' + e.className + ' ').replace(/[\n\t]/g, ' ').indexOf(t) > -1);
1154
+ return ((t = ' ' + t + ' '), (' ' + e.className + ' ').replace(/[\\n\\t]/g, ' ').indexOf(t) > -1);
1153
1155
  }
1154
1156
  function n(e, n, i) {
1155
1157
  for (
1156
1158
  var o,
1157
- a = n.replace(/\s+/g, '').split(','),
1159
+ a = n.replace(/\\s+/g, '').split(','),
1158
1160
  l = +e.getAttribute('data-line-offset') || 0,
1159
1161
  d = r() ? parseInt : parseFloat,
1160
1162
  c = d(getComputedStyle(e).lineHeight),
@@ -1166,7 +1168,7 @@
1166
1168
  var u = +o[0],
1167
1169
  m = +o[1] || u,
1168
1170
  h = document.createElement('div');
1169
- ((h.textContent = Array(m - u + 2).join(' \n')),
1171
+ ((h.textContent = Array(m - u + 2).join('\\n')),
1170
1172
  h.setAttribute('aria-hidden', 'true'),
1171
1173
  (h.className = (i || '') + ' line-highlight'),
1172
1174
  t(e, 'line-numbers') || (h.setAttribute('data-start', u), m > u && h.setAttribute('data-end', m)),
@@ -1179,7 +1181,7 @@
1179
1181
  e('.temporary.line-highlight').forEach(function (e) {
1180
1182
  e.parentNode.removeChild(e);
1181
1183
  });
1182
- var i = (t.match(/\.([\d,-]+)$/) || [, ''])[1];
1184
+ var i = (t.match(/\\.([\\d,-]+)$/) || [, ''])[1];
1183
1185
  if (i && !document.getElementById(t)) {
1184
1186
  var r = t.slice(0, t.lastIndexOf('.')),
1185
1187
  o = document.getElementById(r);
@@ -1231,7 +1233,7 @@
1231
1233
  Prism.hooks.add('complete', function (e) {
1232
1234
  if (e.code) {
1233
1235
  var t = e.element.parentNode,
1234
- s = /\s*\bline-numbers\b\s*/;
1236
+ s = /\\s*\\bline-numbers\\b\\s*/;
1235
1237
  if (
1236
1238
  t &&
1237
1239
  /pre/i.test(t.nodeName) &&
@@ -1241,7 +1243,7 @@
1241
1243
  (s.test(e.element.className) && (e.element.className = e.element.className.replace(s, '')),
1242
1244
  s.test(t.className) || (t.className += ' line-numbers'));
1243
1245
  var n,
1244
- a = e.code.match(/\n(?!$)/g),
1246
+ a = e.code.match(/\\n(?!$)/g),
1245
1247
  l = a ? a.length + 1 : 1,
1246
1248
  r = new Array(l + 1);
1247
1249
  ((r = r.join('<span></span>')),
@@ -1256,7 +1258,7 @@
1256
1258
  }
1257
1259
  });
1258
1260
  })();
1259
- </script>
1261
+ <\/script>
1260
1262
  <script>
1261
1263
  (function () {
1262
1264
  const $ = function (value) {
@@ -1279,9 +1281,12 @@
1279
1281
  node.classList.remove('force-show');
1280
1282
  });
1281
1283
  var activeFrame = $('.frame-row.active');
1282
- if (activeFrame.classList.contains('native-frame')) {
1284
+ if (activeFrame && activeFrame.classList.contains('native-frame')) {
1283
1285
  activeFrame.classList.remove('active');
1284
1286
  var firstFrame = $$('.frame-row')[0];
1287
+ if (!firstFrame) {
1288
+ return;
1289
+ }
1285
1290
  firstFrame.classList.add('active');
1286
1291
  showFrameContext(firstFrame);
1287
1292
  }
@@ -1293,7 +1298,13 @@
1293
1298
  }
1294
1299
  }
1295
1300
  function showFrameContext(frame) {
1296
- $frameContext = frame.querySelector('.frame-context');
1301
+ if (!frame) {
1302
+ return;
1303
+ }
1304
+ const $frameContext = frame.querySelector('.frame-context');
1305
+ if (!$frameContext) {
1306
+ return;
1307
+ }
1297
1308
  var $context = $frameContext.innerHTML;
1298
1309
  $context = $context.trim().length === 0 ? 'Missing stack frames' : $context;
1299
1310
  var $line = $frameContext.getAttribute('data-line');
@@ -1308,8 +1319,8 @@
1308
1319
  $('#code-drop').parentNode.setAttribute('data-line-offset', Number($start) - 1);
1309
1320
  $('#code-drop').setAttribute('class', 'language-' + $language);
1310
1321
  $('#code-drop').innerHTML = $context;
1311
- $('#frame-file').innerHTML = $file;
1312
- $('#frame-method').innerHTML = $method + '' + $lineColumn;
1322
+ $('#frame-file').innerHTML = $file || '';
1323
+ $('#frame-method').innerHTML = [$method, $lineColumn].filter(Boolean).join(' ');
1313
1324
 
1314
1325
  Prism.highlightAll();
1315
1326
  }
@@ -1326,9 +1337,13 @@
1326
1337
  filterFrames();
1327
1338
  };
1328
1339
  displayFirstView();
1329
- showFrameContext($('.frame-row.active'));
1340
+ showFrameContext($('.frame-row.active') || $('.frame-row'));
1330
1341
  })();
1331
- </script>
1342
+ <\/script>
1332
1343
  </section>
1333
1344
  </body>
1334
1345
  </html>
1346
+ `;
1347
+
1348
+ //#endregion
1349
+ export { ONERROR_PAGE_TEMPLATE };
@@ -1,4 +1,4 @@
1
- import { OnerrorError } from "koa-onerror";
1
+ import { OnerrorError } from "./onerror.js";
2
2
  import { Application, Context } from "egg";
3
3
 
4
4
  //#region src/lib/utils.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eggjs/onerror",
3
- "version": "4.0.2-beta.1",
3
+ "version": "4.0.2-beta.10",
4
4
  "description": "error handler for egg",
5
5
  "keywords": [
6
6
  "egg",
@@ -28,6 +28,8 @@
28
28
  "./app": "./dist/app.js",
29
29
  "./config/config.default": "./dist/config/config.default.js",
30
30
  "./lib/error_view": "./dist/lib/error_view.js",
31
+ "./lib/onerror": "./dist/lib/onerror.js",
32
+ "./lib/onerror_page": "./dist/lib/onerror_page.js",
31
33
  "./lib/utils": "./dist/lib/utils.js",
32
34
  "./types": "./dist/types.js",
33
35
  "./package.json": "./package.json"
@@ -37,7 +39,6 @@
37
39
  },
38
40
  "dependencies": {
39
41
  "cookie": "^1.0.2",
40
- "koa-onerror": "^5.0.1",
41
42
  "mustache": "^4.2.0",
42
43
  "stack-trace": "^0.0.10"
43
44
  },
@@ -45,11 +46,11 @@
45
46
  "@types/mustache": "^4.2.5",
46
47
  "@types/stack-trace": "^0.0.33",
47
48
  "typescript": "^5.9.3",
48
- "@eggjs/mock": "7.0.2-beta.1",
49
- "egg": "4.1.2-beta.1"
49
+ "@eggjs/mock": "7.0.2-beta.10",
50
+ "egg": "4.1.2-beta.10"
50
51
  },
51
52
  "peerDependencies": {
52
- "egg": "4.1.2-beta.1"
53
+ "egg": "4.1.2-beta.10"
53
54
  },
54
55
  "engines": {
55
56
  "node": ">=22.18.0"