netstack.js 1.2.0 → 2.1.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 +12 -6
  2. package/netstack.js +195 -158
  3. package/package.json +8 -6
package/README.md CHANGED
@@ -4,10 +4,10 @@
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
- [![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)](#)
10
+ [![English](images/flags/US%20-%20United%20States.svg)](#) [![Danish](images/flags/DK%20-%20Denmark.svg)](#) [![German](images/flags/DE%20-%20Germany.svg)](#) [![Spanish](images/flags/ES%20-%20Spain.svg)](#) [![Russian](images/flags/RU%20-%20Russian%20Federation.svg)](#) [![Chinese](images/flags/CN%20-%20China.svg)](#)
11
11
 
12
12
  #### Demo
13
13
  [![netStack.js - demo](images/example.jpg)](https://elmah.io/tools/stack-trace-formatter/)
@@ -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.1.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,162 +42,218 @@
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' },
51
+ { name: 'spanish', at: 'en', in: 'en', line: 'línea' },
71
52
  { name: 'russian', at: 'в', in: 'в', line: 'строка' },
72
53
  { name: 'chinese', at: '在', in: '位置', line: '行号' }
73
54
  ];
74
55
 
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
- }
56
+ this.init();
57
+ }
58
+
59
+ function extend() {
60
+ for (var i = 1; i < arguments.length; i++) {
61
+ for (var key in arguments[i]) {
62
+ if (arguments[i].hasOwnProperty(key)) {
63
+ arguments[0][key] = arguments[i][key];
106
64
  }
107
65
  }
66
+ }
67
+ return arguments[0];
68
+ }
108
69
 
109
- if (lang === '') return;
70
+ netStack.prototype.search = function(nameKey, myArray) {
71
+ for (var i = 0; i < myArray.length; i++) {
72
+ if (myArray[i].name === nameKey) {
73
+ return myArray[i];
74
+ }
75
+ }
76
+ return null;
77
+ };
110
78
 
111
- var selectedLanguage = search(lang, languages);
79
+ netStack.prototype.replacer = function(args, at_language) {
80
+ if (args[0].substring(0).match(/(-{3}&gt;)/)) {
81
+ return '\r\n ' + args[0];
82
+ } else if (args[0].substring(0).match(/(-{3})/)) {
83
+ return '\r\n ' + args[0];
84
+ } else {
85
+ return '\r\n ' + at_language + ' ' + args[2] + '(' + args[3] + ')';
86
+ }
87
+ };
88
+
89
+ netStack.prototype.formatException = function(exceptionMessage, at_language) {
90
+ var result = exceptionMessage || '';
91
+ var searchReplaces = [
92
+ {
93
+ find: new RegExp('(-{3}&gt;\\s)(.*?)(?=\\s-{3}|(\\s)+' + at_language + ')', 'g'),
94
+ repl: null
95
+ },
96
+ {
97
+ find: /(-{3}\s)(.*?)(-{3})/gm,
98
+ repl: null
99
+ },
100
+ {
101
+ find: new RegExp('(\\s)' + at_language + ' ([^-:]*?)\\((.*?)\\)', 'g'),
102
+ repl: null
103
+ }
104
+ ];
105
+
106
+ var self = this;
107
+ searchReplaces.forEach(function(item) {
108
+ if (item.repl == null) {
109
+ result = result.replace(item.find, function() {
110
+ return self.replacer(arguments, at_language);
111
+ });
112
+ } else {
113
+ result = result.replace(item.find, item.repl);
114
+ }
115
+ });
116
+ return result;
117
+ };
112
118
 
113
- // Pritty print result if is set to true
114
- if (settings.prettyprint) {
115
- sanitizedStack = formatException(sanitizedStack, selectedLanguage['at']);
116
- lines = sanitizedStack.split('\n');
119
+ netStack.prototype.init = function() {
120
+ // Get the stacktrace, sanitize it, and split it into lines
121
+ var stacktrace = this.element.textContent,
122
+ sanitizedStack = stacktrace.replace(/</g, '&lt;').replace(/>/g, '&gt;'),
123
+ lines = sanitizedStack.split('\n'),
124
+ lang = '',
125
+ clone = '';
126
+
127
+ // look for the language
128
+ for (var i = 0; i < lines.length; ++i) {
129
+ if (lang === '') {
130
+ var regexes = {
131
+ english: /\s+at .*\)/,
132
+ danish: /\s+ved .*\)/,
133
+ german: /\s+bei .*\)/,
134
+ spanish: /\s+en .*\)/,
135
+ russian: /\s+в .*\)/,
136
+ chinese: /\s+在 .*\)/
137
+ };
138
+
139
+ for (var key in regexes) {
140
+ if (regexes[key].test(lines[i])) {
141
+ lang = key;
142
+ break;
143
+ }
144
+ }
117
145
  }
146
+ }
118
147
 
119
- for (var i = 0, j = lines.length; i < j; ++i) {
148
+ if (lang === '') return;
120
149
 
121
- var li = lines[i],
122
- hli = new RegExp('(\\S*)'+selectedLanguage['at']+' .*\\)');
150
+ var selectedLanguage = this.search(lang, this.languages);
151
+ this.language = selectedLanguage.name;
123
152
 
153
+ // Pritty print result if is set to true
154
+ if (this.settings.prettyprint) {
155
+ sanitizedStack = this.formatException(sanitizedStack, selectedLanguage.at);
156
+ lines = sanitizedStack.split('\n');
157
+ }
124
158
 
125
- if (hli.test(lines[i])) {
159
+ for (var i = 0; i < lines.length; ++i) {
160
+ var li = lines[i],
161
+ hli = new RegExp('(\\S*)' + selectedLanguage.at + ' .*\\)');
126
162
 
127
- // Frame
128
- var regFrame = new RegExp('(\\S*)'+selectedLanguage['at']+' .*?\\)'),
129
- partsFrame = String(regFrame.exec(lines[i]));
163
+ if (hli.test(lines[i])) {
164
+
165
+ // Frame
166
+ var regFrame = new RegExp('(\\S*)' + selectedLanguage.at + ' .*?\\)'),
167
+ partsFrame = String(regFrame.exec(lines[i]));
130
168
 
131
- if(partsFrame.substr(partsFrame.length - 1) == ',') {
132
- partsFrame = partsFrame.slice(0, -1);
133
- }
169
+ if (partsFrame.substring(partsFrame.length - 1) == ',') {
170
+ partsFrame = partsFrame.slice(0, -1);
171
+ }
134
172
 
135
- partsFrame = partsFrame.replace(selectedLanguage['at']+' ', '');
173
+ partsFrame = partsFrame.replace(selectedLanguage.at + ' ', '');
136
174
 
137
- // Frame -> ParameterList
138
- var regParamList = new RegExp('\\(.*\\)'),
139
- partsParamList = String(regParamList.exec(lines[i]));
175
+ // Frame -> ParameterList
176
+ var regParamList = /\(.*\)/,
177
+ partsParamList = String(regParamList.exec(lines[i]));
140
178
 
141
- // Frame -> Params
142
- var partsParams = partsParamList.replace('(', '').replace(')', ''),
143
- arrParams = partsParams.split(', '),
144
- stringParam = '';
179
+ // Frame -> Params
180
+ var partsParams = partsParamList.replace('(', '').replace(')', ''),
181
+ arrParams = partsParams.split(', '),
182
+ stringParam = '';
145
183
 
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];
184
+ for (var x = 0; x < arrParams.length; ++x) {
185
+ var param = arrParams[x].split(' '),
186
+ paramType = param[0],
187
+ paramName = param[1];
151
188
 
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
- }
189
+ if (param[0] !== "null" && param[0] !== '') {
190
+ var theParam = '<span class="' + this.settings.paramType + '">' + paramType + '</span>' + ' ' + '<span class="' + this.settings.paramName + '">' + paramName + '</span>';
191
+ stringParam += String(theParam) + ', ';
156
192
  }
193
+ }
157
194
 
158
- stringParam = stringParam.replace(/,\s*$/, "");
159
- stringParam = '<span class="' + settings.paramsList + '">' + '(' + stringParam + ')' + '</span>';
195
+ stringParam = stringParam.replace(/,\s*$/, "");
196
+ stringParam = '<span class="' + this.settings.paramsList + '">' + '(' + stringParam + ')' + '</span>';
160
197
 
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>';
198
+ // Frame -> Type & Method
199
+ var partsTypeMethod = partsFrame.replace(partsParamList, ''),
200
+ arrTypeMethod = partsTypeMethod.split('.'),
201
+ method = arrTypeMethod.pop(),
202
+ type = partsTypeMethod.replace('.' + method, ''),
203
+ stringTypeMethod = '<span class="' + this.settings.type + '">' + type + '</span>.' + '<span class="' + this.settings.method + '">' + method + '</span>';
167
204
 
168
- // Construct Frame
169
- var newPartsFrame = partsFrame.replace(partsParamList, stringParam).replace(partsTypeMethod, stringTypeMethod);
205
+ // Construct Frame
206
+ var newPartsFrame = partsFrame.replace(partsParamList, stringParam).replace(partsTypeMethod, stringTypeMethod);
170
207
 
171
- // Line
172
- var regLine = new RegExp('\\b:'+selectedLanguage['line']+'.*'),
173
- partsLine = String(regLine.exec(lines[i]));
174
- partsLine = partsLine.replace(':', '').trim();
208
+ // Line
209
+ var regLine = new RegExp('\\b:' + selectedLanguage.line + ' \\d+'),
210
+ partsLine = String(regLine.exec(lines[i]));
175
211
 
176
- var fileLi = li.replace(selectedLanguage['at'] + " " + partsFrame, '').trim();
212
+ partsLine = partsLine.replace(':', '').trim();
177
213
 
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));
214
+ var fileLi = li.replace(selectedLanguage.at + " " + partsFrame, '').trim();
181
215
 
182
- partsFile = partsFile.replace(selectedLanguage['in']+' ', '').replace(':' + partsLine, '');
216
+ // File => (!) text requires multiline to exec regex, otherwise it will return null.
217
+ var regFile = new RegExp(selectedLanguage.in + '\\s.*$', 'm'),
218
+ partsFile = String(regFile.exec(fileLi));
183
219
 
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>');
220
+ partsFile = partsFile.replace(selectedLanguage.in + ' ', '').replace(':' + partsLine, '').replace('&lt;---', '');
187
221
 
188
- li = li.replace(/&lt;/g, '<span>&lt;</span>').replace(/&gt;/g, '<span>&gt;</span>');
222
+ li = li.replace(partsFrame, '<span class="' + this.settings.frame + '">' + newPartsFrame + '</span>')
223
+ .replace(partsFile, '<span class="' + this.settings.file + '">' + partsFile + '</span>')
224
+ .replace(partsLine, '<span class="' + this.settings.line + '">' + partsLine + '</span>');
225
+
226
+ li = li.replace(/&lt;/g, '<span>&lt;</span>').replace(/&gt;/g, '<span>&gt;</span>');
227
+
228
+ if (lines.length - 1 == i) {
229
+ clone += li;
230
+ } else {
231
+ clone += li + '\n';
232
+ }
233
+ } else {
234
+ if ((lines[i].trim()).length) {
235
+ li = lines[i];
189
236
 
190
237
  if (lines.length - 1 == i) {
191
238
  clone += li;
192
239
  } else {
193
240
  clone += li + '\n';
194
241
  }
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
242
  }
206
243
  }
244
+ }
207
245
 
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);
246
+ this.element.innerHTML = clone;
247
+ };
217
248
 
218
- });
249
+ netStack.prototype.getJSON = function() {
250
+ return JSON.stringify(this.element.innerHTML);
251
+ };
219
252
 
253
+ netStack.prototype.getLanguage = function() {
254
+ return this.language;
220
255
  };
221
256
 
222
- }(jQuery));
257
+ return netStack;
258
+
259
+ }));
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.1.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
+ }