netstack.js 1.2.0 → 2.0.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.
Files changed (3) hide show
  1. package/README.md +11 -5
  2. package/netstack.js +193 -158
  3. package/package.json +8 -6
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  ![Tests](https://github.com/elmahio/netstack.js/actions/workflows/test.yml/badge.svg)
5
5
 
6
6
 
7
- A simple and easy jQuery plugin for highlighting .NET stack traces
7
+ A simple and easy JavaScript library for highlighting .NET stack traces
8
8
 
9
9
  #### Stacktrace - Language support
10
10
  [![English](images/flags/US%20-%20United%20States.svg)](#) [![Danish](images/flags/DK%20-%20Denmark.svg)](#) [![German](images/flags/DE%20-%20Germany.svg)](#) [![Russian](images/flags/RU%20-%20Russian%20Federation.svg)](#) [![Chinese](images/flags/CN%20-%20China.svg)](#)
@@ -15,13 +15,19 @@ A simple and easy jQuery plugin for highlighting .NET stack traces
15
15
  [Stack Trace Formatter - Online pretty print of .NET stack traces](https://elmah.io/tools/stack-trace-formatter/)
16
16
 
17
17
  #### Initialization
18
+ Using a string that represents a CSS selector:
18
19
  ```javascript
19
- $('.stacktrace').netStack();
20
+ const stack = new netStack('.stacktrace');
21
+ ```
22
+ Passing an HTMLElement object:
23
+ ```javascript
24
+ const stackElement = document.querySelector('.stacktrace');
25
+ const stack = new netStack(stackElement);
20
26
  ```
21
27
 
22
28
  #### Default values for classes
23
29
  ```javascript
24
- $('.stacktrace').netStack({
30
+ const stack = new netStack('.stacktrace', {
25
31
  frame: 'st-frame',
26
32
  type: 'st-type',
27
33
  method: 'st-method',
@@ -38,7 +44,7 @@ $('.stacktrace').netStack({
38
44
  Default: false.
39
45
  Pretty prints your stacktrace.
40
46
  ```javascript
41
- $('.stacktrace').netStack({
47
+ const stack = new netStack('.stacktrace', {
42
48
  prettyprint: true
43
49
  });
44
50
  ```
@@ -58,4 +64,4 @@ pre, code {background-color:#333; color: #ffffff;}
58
64
  ---
59
65
  ### Acknowledgments
60
66
 
61
- * [IgoR-NiK](https://github.com/IgoR-NiK)
67
+ * [IgoR-NiK](https://github.com/IgoR-NiK)
package/netstack.js CHANGED
@@ -1,57 +1,38 @@
1
1
  /*!
2
- * netStack v1.2.0
3
- * A simple and easy jQuery plugin for highlighting .NET stack traces
4
- * License : Apache 2
5
- * Author : https://elmah.io
2
+ * netStack v2.0.0
3
+ * A simple and easy JavaScript library for highlighting .NET stack traces
4
+ * License: Apache 2
5
+ * Author: https://elmah.io
6
6
  */
7
- (function($) {
8
- 'use strict';
9
7
 
10
- $.fn.netStack = function(options) {
11
-
12
- var self = this;
13
-
14
- function search(nameKey, myArray){
15
- for (var i=0; i < myArray.length; i++) {
16
- if (myArray[i].name === nameKey) {
17
- return myArray[i];
18
- }
19
- }
20
- }
21
-
22
- function replacer(args, at_language) {
23
- if(args[0].substr(0).match(/(-{3})/)) {
24
- return '\r\n\ ' + args[0];
8
+ (function(root, factory) {
9
+ if (typeof define === 'function' && define.amd) {
10
+ // AMD
11
+ define([], factory);
12
+ } else if (typeof module === 'object' && module.exports) {
13
+ // Node, CommonJS-like
14
+ module.exports = factory();
15
+ } else {
16
+ // Browser globals (root is window)
17
+ root.netStack = factory();
18
+ }
19
+ }(typeof self !== 'undefined' ? self : this, function() {
20
+
21
+ function netStack(element, options) {
22
+ if (typeof document !== 'undefined') {
23
+ if (typeof element === 'string') {
24
+ this.element = document.querySelector(element);
25
+ } else if (element instanceof HTMLElement) {
26
+ this.element = element;
25
27
  } else {
26
- return '\r\n\ ' + at_language + ' ' + args[2] + '(' + args[3] + ')';
28
+ throw new Error('The element parameter must be a selector string or an HTMLElement.');
27
29
  }
30
+ } else {
31
+ throw new Error('netStack requires a DOM environment');
28
32
  }
29
-
30
- function formatException(exceptionMessage, at_language){
31
- var result = exceptionMessage || '';
32
- var searchReplaces = [
33
- {
34
- find: /(-{3}\s)(.*?)(-{3})/gm,
35
- repl: null
36
- },
37
- {
38
- find: new RegExp('(\\s)'+at_language+' ([^-:]*?)\\((.*?)\\)', 'g'),
39
- repl: null
40
- }
41
- ]
42
- searchReplaces.forEach(function(item){
43
- if(item.repl == null) {
44
- result = result.replace(item.find, function(){ return replacer(arguments, at_language); });
45
- } else {
46
- result = result.replace(item.find, item.repl);
47
- }
48
- });
49
- return result;
50
- };
51
-
52
- var settings = $.extend({
53
-
54
- // Default values for classes
33
+
34
+ // Default values for classes
35
+ this.settings = extend({
55
36
  prettyprint: false,
56
37
  frame: 'st-frame',
57
38
  type: 'st-type',
@@ -61,10 +42,9 @@
61
42
  paramName: 'st-param-name',
62
43
  file: 'st-file',
63
44
  line: 'st-line'
64
-
65
45
  }, options);
66
46
 
67
- var languages = [
47
+ this.languages = [
68
48
  { name: 'english', at: 'at', in: 'in', line: 'line' },
69
49
  { name: 'danish', at: 'ved', in: 'i', line: 'linje' },
70
50
  { name: 'german', at: 'bei', in: 'in', line: 'Zeile' },
@@ -72,151 +52,206 @@
72
52
  { name: 'chinese', at: '在', in: '位置', line: '行号' }
73
53
  ];
74
54
 
75
- return this.each(function() {
76
-
77
- // Get the stacktrace, sanitize it, and split it into lines
78
-
79
- var stacktrace = $(this).text(),
80
- sanitizedStack = stacktrace.replace(/</g, '&lt;').replace(/>/g, '&gt;'),
81
- lines = sanitizedStack.split('\n'),
82
- lang = '',
83
- clone = '';
84
-
85
- // search for language
86
- for (var i = 0, j = lines.length; i < j; ++i) {
87
- if(lang === '') {
88
- var line = lines[i];
89
- var english = new RegExp('(\\s+)at .*\\)'),
90
- danish = new RegExp('(\\s+)ved .*\\)'),
91
- german = new RegExp('(\\s+)bei .*\\)'),
92
- russian = new RegExp('(\\s+)в .*\\)'),
93
- chinese = new RegExp('(\\s+)在 .*\\)');
94
-
95
- if(english.test(lines[i])) {
96
- lang = 'english';
97
- } else if (danish.test(lines[i])) {
98
- lang = 'danish';
99
- } else if (german.test(lines[i])) {
100
- lang = 'german';
101
- } else if (russian.test(lines[i])) {
102
- lang = 'russian';
103
- } else if (chinese.test(lines[i])) {
104
- lang = 'chinese';
105
- }
55
+ this.init();
56
+ }
57
+
58
+ function extend() {
59
+ for (var i = 1; i < arguments.length; i++) {
60
+ for (var key in arguments[i]) {
61
+ if (arguments[i].hasOwnProperty(key)) {
62
+ arguments[0][key] = arguments[i][key];
106
63
  }
107
64
  }
65
+ }
66
+ return arguments[0];
67
+ }
108
68
 
109
- if (lang === '') return;
69
+ netStack.prototype.search = function(nameKey, myArray) {
70
+ for (var i = 0; i < myArray.length; i++) {
71
+ if (myArray[i].name === nameKey) {
72
+ return myArray[i];
73
+ }
74
+ }
75
+ return null;
76
+ };
110
77
 
111
- var selectedLanguage = search(lang, languages);
78
+ netStack.prototype.replacer = function(args, at_language) {
79
+ if (args[0].substring(0).match(/(-{3}&gt;)/)) {
80
+ return '\r\n ' + args[0];
81
+ } else if (args[0].substring(0).match(/(-{3})/)) {
82
+ return '\r\n ' + args[0];
83
+ } else {
84
+ return '\r\n ' + at_language + ' ' + args[2] + '(' + args[3] + ')';
85
+ }
86
+ };
87
+
88
+ netStack.prototype.formatException = function(exceptionMessage, at_language) {
89
+ var result = exceptionMessage || '';
90
+ var searchReplaces = [
91
+ {
92
+ find: new RegExp('(-{3}&gt;\\s)(.*?)(?=\\s-{3}|(\\s)+' + at_language + ')', 'g'),
93
+ repl: null
94
+ },
95
+ {
96
+ find: /(-{3}\s)(.*?)(-{3})/gm,
97
+ repl: null
98
+ },
99
+ {
100
+ find: new RegExp('(\\s)' + at_language + ' ([^-:]*?)\\((.*?)\\)', 'g'),
101
+ repl: null
102
+ }
103
+ ];
104
+
105
+ var self = this;
106
+ searchReplaces.forEach(function(item) {
107
+ if (item.repl == null) {
108
+ result = result.replace(item.find, function() {
109
+ return self.replacer(arguments, at_language);
110
+ });
111
+ } else {
112
+ result = result.replace(item.find, item.repl);
113
+ }
114
+ });
115
+ return result;
116
+ };
112
117
 
113
- // Pritty print result if is set to true
114
- if (settings.prettyprint) {
115
- sanitizedStack = formatException(sanitizedStack, selectedLanguage['at']);
116
- lines = sanitizedStack.split('\n');
118
+ netStack.prototype.init = function() {
119
+ // Get the stacktrace, sanitize it, and split it into lines
120
+ var stacktrace = this.element.textContent,
121
+ sanitizedStack = stacktrace.replace(/</g, '&lt;').replace(/>/g, '&gt;'),
122
+ lines = sanitizedStack.split('\n'),
123
+ lang = '',
124
+ clone = '';
125
+
126
+ // look for the language
127
+ for (var i = 0; i < lines.length; ++i) {
128
+ if (lang === '') {
129
+ var regexes = {
130
+ english: /\s+at .*\)/,
131
+ danish: /\s+ved .*\)/,
132
+ german: /\s+bei .*\)/,
133
+ russian: /\s+в .*\)/,
134
+ chinese: /\s+在 .*\)/
135
+ };
136
+
137
+ for (var key in regexes) {
138
+ if (regexes[key].test(lines[i])) {
139
+ lang = key;
140
+ break;
141
+ }
142
+ }
117
143
  }
144
+ }
118
145
 
119
- for (var i = 0, j = lines.length; i < j; ++i) {
146
+ if (lang === '') return;
120
147
 
121
- var li = lines[i],
122
- hli = new RegExp('(\\S*)'+selectedLanguage['at']+' .*\\)');
148
+ var selectedLanguage = this.search(lang, this.languages);
149
+ this.language = selectedLanguage.name;
123
150
 
151
+ // Pritty print result if is set to true
152
+ if (this.settings.prettyprint) {
153
+ sanitizedStack = this.formatException(sanitizedStack, selectedLanguage.at);
154
+ lines = sanitizedStack.split('\n');
155
+ }
124
156
 
125
- if (hli.test(lines[i])) {
157
+ for (var i = 0; i < lines.length; ++i) {
158
+ var li = lines[i],
159
+ hli = new RegExp('(\\S*)' + selectedLanguage.at + ' .*\\)');
126
160
 
127
- // Frame
128
- var regFrame = new RegExp('(\\S*)'+selectedLanguage['at']+' .*?\\)'),
129
- partsFrame = String(regFrame.exec(lines[i]));
161
+ if (hli.test(lines[i])) {
162
+
163
+ // Frame
164
+ var regFrame = new RegExp('(\\S*)' + selectedLanguage.at + ' .*?\\)'),
165
+ partsFrame = String(regFrame.exec(lines[i]));
130
166
 
131
- if(partsFrame.substr(partsFrame.length - 1) == ',') {
132
- partsFrame = partsFrame.slice(0, -1);
133
- }
167
+ if (partsFrame.substring(partsFrame.length - 1) == ',') {
168
+ partsFrame = partsFrame.slice(0, -1);
169
+ }
134
170
 
135
- partsFrame = partsFrame.replace(selectedLanguage['at']+' ', '');
171
+ partsFrame = partsFrame.replace(selectedLanguage.at + ' ', '');
136
172
 
137
- // Frame -> ParameterList
138
- var regParamList = new RegExp('\\(.*\\)'),
139
- partsParamList = String(regParamList.exec(lines[i]));
173
+ // Frame -> ParameterList
174
+ var regParamList = /\(.*\)/,
175
+ partsParamList = String(regParamList.exec(lines[i]));
140
176
 
141
- // Frame -> Params
142
- var partsParams = partsParamList.replace('(', '').replace(')', ''),
143
- arrParams = partsParams.split(', '),
144
- stringParam = '';
177
+ // Frame -> Params
178
+ var partsParams = partsParamList.replace('(', '').replace(')', ''),
179
+ arrParams = partsParams.split(', '),
180
+ stringParam = '';
145
181
 
146
- for (var x = 0, y = arrParams.length; x < y; ++x) {
147
- var theParam = '',
148
- param = arrParams[x].split(' '),
149
- paramType = param[0],
150
- paramName = param[1];
182
+ for (var x = 0; x < arrParams.length; ++x) {
183
+ var param = arrParams[x].split(' '),
184
+ paramType = param[0],
185
+ paramName = param[1];
151
186
 
152
- if (param[0] !== "null" && param[0] !== '') {
153
- theParam = '<span class="' + settings.paramType + '">' + paramType + '</span>' + ' ' + '<span class="' + settings.paramName + '">' + paramName + '</span>';
154
- stringParam += String(theParam) + ', ';
155
- }
187
+ if (param[0] !== "null" && param[0] !== '') {
188
+ var theParam = '<span class="' + this.settings.paramType + '">' + paramType + '</span>' + ' ' + '<span class="' + this.settings.paramName + '">' + paramName + '</span>';
189
+ stringParam += String(theParam) + ', ';
156
190
  }
191
+ }
157
192
 
158
- stringParam = stringParam.replace(/,\s*$/, "");
159
- stringParam = '<span class="' + settings.paramsList + '">' + '(' + stringParam + ')' + '</span>';
193
+ stringParam = stringParam.replace(/,\s*$/, "");
194
+ stringParam = '<span class="' + this.settings.paramsList + '">' + '(' + stringParam + ')' + '</span>';
160
195
 
161
- // Frame -> Type & Method
162
- var partsTypeMethod = partsFrame.replace(partsParamList, ''),
163
- arrTypeMethod = partsTypeMethod.split('.'),
164
- method = arrTypeMethod.pop(),
165
- type = partsTypeMethod.replace('.' + method, ''),
166
- stringTypeMethod = '<span class="' + settings.type + '">' + type + '</span>.' + '<span class="' + settings.method + '">' + method + '</span>';
196
+ // Frame -> Type & Method
197
+ var partsTypeMethod = partsFrame.replace(partsParamList, ''),
198
+ arrTypeMethod = partsTypeMethod.split('.'),
199
+ method = arrTypeMethod.pop(),
200
+ type = partsTypeMethod.replace('.' + method, ''),
201
+ stringTypeMethod = '<span class="' + this.settings.type + '">' + type + '</span>.' + '<span class="' + this.settings.method + '">' + method + '</span>';
167
202
 
168
- // Construct Frame
169
- var newPartsFrame = partsFrame.replace(partsParamList, stringParam).replace(partsTypeMethod, stringTypeMethod);
203
+ // Construct Frame
204
+ var newPartsFrame = partsFrame.replace(partsParamList, stringParam).replace(partsTypeMethod, stringTypeMethod);
170
205
 
171
- // Line
172
- var regLine = new RegExp('\\b:'+selectedLanguage['line']+'.*'),
173
- partsLine = String(regLine.exec(lines[i]));
174
- partsLine = partsLine.replace(':', '').trim();
206
+ // Line
207
+ var regLine = new RegExp('\\b:' + selectedLanguage.line + ' \\d+'),
208
+ partsLine = String(regLine.exec(lines[i]));
175
209
 
176
- var fileLi = li.replace(selectedLanguage['at'] + " " + partsFrame, '').trim();
210
+ partsLine = partsLine.replace(':', '').trim();
177
211
 
178
- // File => (!) text requires multiline to exec regex, otherwise it will return null.
179
- var regFile = new RegExp(selectedLanguage['in']+'\\s.*$', 'm'),
180
- partsFile = String(regFile.exec(fileLi));
212
+ var fileLi = li.replace(selectedLanguage.at + " " + partsFrame, '').trim();
181
213
 
182
- partsFile = partsFile.replace(selectedLanguage['in']+' ', '').replace(':' + partsLine, '');
214
+ // File => (!) text requires multiline to exec regex, otherwise it will return null.
215
+ var regFile = new RegExp(selectedLanguage.in + '\\s.*$', 'm'),
216
+ partsFile = String(regFile.exec(fileLi));
183
217
 
184
- li = li.replace(partsFrame, '<span class="' + settings.frame + '">' + newPartsFrame + '</span>')
185
- .replace(partsFile, '<span class="' + settings.file + '">' + partsFile + '</span>')
186
- .replace(partsLine, '<span class="' + settings.line + '">' + partsLine + '</span>');
218
+ partsFile = partsFile.replace(selectedLanguage.in + ' ', '').replace(':' + partsLine, '').replace('&lt;---', '');
187
219
 
188
- li = li.replace(/&lt;/g, '<span>&lt;</span>').replace(/&gt;/g, '<span>&gt;</span>');
220
+ li = li.replace(partsFrame, '<span class="' + this.settings.frame + '">' + newPartsFrame + '</span>')
221
+ .replace(partsFile, '<span class="' + this.settings.file + '">' + partsFile + '</span>')
222
+ .replace(partsLine, '<span class="' + this.settings.line + '">' + partsLine + '</span>');
223
+
224
+ li = li.replace(/&lt;/g, '<span>&lt;</span>').replace(/&gt;/g, '<span>&gt;</span>');
225
+
226
+ if (lines.length - 1 == i) {
227
+ clone += li;
228
+ } else {
229
+ clone += li + '\n';
230
+ }
231
+ } else {
232
+ if ((lines[i].trim()).length) {
233
+ li = lines[i];
189
234
 
190
235
  if (lines.length - 1 == i) {
191
236
  clone += li;
192
237
  } else {
193
238
  clone += li + '\n';
194
239
  }
195
- } else {
196
- if((lines[i].trim()).length) {
197
- li = lines[i];
198
-
199
- if (lines.length - 1 == i) {
200
- clone += li;
201
- } else {
202
- clone += li + '\n';
203
- }
204
- }
205
240
  }
206
241
  }
242
+ }
207
243
 
208
- self.getJSON = function () {
209
- return JSON.stringify(clone);
210
- }
211
-
212
- self.getLanguage = function () {
213
- return selectedLanguage ? selectedLanguage.name : null;
214
- }
215
-
216
- return $(this).html(clone);
244
+ this.element.innerHTML = clone;
245
+ };
217
246
 
218
- });
247
+ netStack.prototype.getJSON = function() {
248
+ return JSON.stringify(this.element.innerHTML);
249
+ };
219
250
 
251
+ netStack.prototype.getLanguage = function() {
252
+ return this.language;
220
253
  };
221
254
 
222
- }(jQuery));
255
+ return netStack;
256
+
257
+ }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "netstack.js",
3
- "version": "1.2.0",
4
- "description": "A simple and easy jQuery plugin for highlighting .NET stack traces",
3
+ "version": "2.0.0",
4
+ "description": "A simple and easy JavaScript library for highlighting .NET stack traces",
5
5
  "main": "netstack.js",
6
6
  "scripts": {
7
7
  "test": "mocha"
@@ -20,15 +20,17 @@
20
20
  ".NET",
21
21
  "stacktrace",
22
22
  "formatter",
23
- "jQuery",
24
- "plugin",
23
+ "JavaScript",
24
+ "library",
25
25
  "elmah.io"
26
26
  ],
27
27
  "devDependencies": {
28
28
  "assert": "^2.0.0",
29
29
  "chai": "^4.3.4",
30
- "jquery": "^3.6.0",
31
30
  "jsdom": "^17.0.0",
32
31
  "mocha": "^9.1.2"
32
+ },
33
+ "dependencies": {
34
+ "gulp": "^5.0.0"
33
35
  }
34
- }
36
+ }