PageSourceSearch

https://www.parkersklep.com/modules/wb_glitchtip/views/js/front/wb_glitchtip.js

js parkersklep.com collected 2026-09-26 16:45:11 UTC 6,162 bytes, 197 lines download raw bytes

1/**
2 * wb_glitchtip - storefront errors, relayed through the shop.
3 *
4 * Reports go to the shop's own endpoint, never straight to GlitchTip: the DSN
5 * stays on the server, and the same scrubbing and limits apply as for PHP
6 * errors. Nothing here may change how the page behaves - every path is
7 * wrapped, the wrapped fetch/XHR return exactly what the originals return,
8 * and reports leave by sendBeacon, which neither blocks nor delays navigation.
9 *
10 * Never read: form values, element text, cookies, storage. Clicks are
11 * recorded as tag#id.class only.
12 *
13 * @author    WBShop <[email protected]>
14 * @copyright WBShop
15 * @license   Commercial license - all rights reserved
16 */
17(function () {
18  'use strict';
19
20  var cfg = window.wbGlitchtip;
21  if (!cfg || !cfg.endpoint || window.__wbGlitchtipLoaded) {
22    return;
23  }
24  window.__wbGlitchtipLoaded = true;
25
26  var MAX_EVENTS = 5;        // per page view
27  var MAX_CRUMBS = 20;
28  var IGNORED_STATUS = { 401: 1, 403: 1, 422: 1, 429: 1 };
29  var sent = 0;
30  var seen = {};
31  var crumbs = [];
32  var origFetch = window.fetch;
33
34  function now() {
35    return Date.now() / 1000;
36  }
37
38  function crumb(c) {
39    try {
40      c.timestamp = now();
41      crumbs.push(c);
42      if (crumbs.length > MAX_CRUMBS) {
43        crumbs.shift();
44      }
45    } catch (e) { /* never */ }
46  }
47
48  function send(kind, message, stack, extra) {
49    try {
50      if (sent >= MAX_EVENTS) {
51        return;
52      }
53      var key = kind + '|' + String(message).slice(0, 200);
54      if (seen[key]) {
55        return;
56      }
57      seen[key] = 1;
58      sent++;
59      var body = JSON.stringify({
60        kind: kind,
61        message: String(message || '').slice(0, 1000),
62        stack: String(stack || '').slice(0, 6000),
63        url: String(location.href).slice(0, 2000),
64        extra: extra || {},
65        breadcrumbs: crumbs.slice(-MAX_CRUMBS)
66      });
67      if (navigator.sendBeacon) {
68        navigator.sendBeacon(cfg.endpoint, new Blob([body], { type: 'text/plain' }));
69      } else if (origFetch) {
70        origFetch.call(window, cfg.endpoint, { method: 'POST', body: body, keepalive: true, credentials: 'omit' });
71      }
72    } catch (e) { /* never */ }
73  }
74
75  function parse(url) {
76    var a = document.createElement('a');
77    a.href = url;
78    return a;
79  }
80
81  /* Exactly this module's endpoints - a looser match ("module=wb_glitchtip")
82     also swallowed every module whose name merely starts the same way. */
83  var ownPath = parse(cfg.endpoint).pathname;
84  function isOwnReport(url) {
85    var u = String(url);
86    return parse(u).pathname === ownPath
87      || /[?&]module=wb_glitchtip(&|$)/.test(u)
88      || u.indexOf('/module/wb_glitchtip/') !== -1;
89  }
90
91  function http(method, url, status, ms) {
92    try {
93      if (isOwnReport(url)) {
94        return;
95      }
96      var a = parse(url);
97      var same = a.host === location.host;
98      var path = a.pathname || '/';
99      var level = status === 0 || status >= 500 ? 'error' : (status >= 400 ? 'warning' : 'info');
100      var data = { method: String(method || 'GET').toUpperCase(), status_code: status, duration_ms: ms };
101      if (same) {
102        data.path = path;
103      } else {
104        data.host = a.host;
105      }
106      crumb({ category: 'xhr', level: level, data: data });
107      if (same && status >= 400 && !IGNORED_STATUS[status]) {
108        send('http', String(method || 'GET').toUpperCase() + ' ' + path + ' -> ' + status, '', {
109          method: String(method || 'GET').toUpperCase(), path: path, status: status, ms: ms
110        });
111      }
112    } catch (e) { /* never */ }
113  }
114
115  window.addEventListener('error', function (ev) {
116    try {
117      /* Resource load errors (img, script tags) have no message: not JS errors. */
118      if (!ev || !ev.message) {
119        return;
120      }
121      send('error', ev.message, ev.error && ev.error.stack, {
122        filename: ev.filename, lineno: ev.lineno, colno: ev.colno
123      });
124    } catch (e) { /* never */ }
125  });
126
127  window.addEventListener('unhandledrejection', function (ev) {
128    try {
129      var r = ev && ev.reason;
130      var message = r && r.message ? (r.name ? r.name + ': ' : '') + r.message : 
130String(r);
131      send('rejection', message, r && r.stack);
132    } catch (e) { /* never */ }
133  });
134
135  if (origFetch) {
136    window.fetch = function (input, init) {
137      var t0 = Date.now();
138      var p = origFetch.apply(this, arguments);
139      try {
140        var method = (init && init.method) || (input && input.method) || 'GET';
141        var url = typeof input === 'string' ? input : (input && input.url) || String(input);
142        p.then(function (res) {
143          http(method, url, res.status, Date.now() - t0);
144        }, function () {
145          http(method, url, 0, Date.now() - t0);
146        });
147      } catch (e) { /* never */ }
148      return p;
149    };
150  }
151
152  if (window.XMLHttpRequest) {
153    var proto = XMLHttpRequest.prototype;
154    var open = proto.open;
155    var sendXhr = proto.send;
156    proto.open = function (method, url) {
157      try {
158        this.__wbgt = { m: method, u: url };
159      } catch (e) { /* never */ }
160      return open.apply(this, arguments);
161    };
162    proto.send = function () {
163      try {
164        var xhr = this;
165        var s = xhr.__wbgt;
166        if (s) {
167          s.t = Date.now();
168          xhr.addEventListener('loadend', function () {
169            http(s.m, s.u, xhr.status, Date.now() - s.t);
170          });
171        }
172      } catch (e) { /* never */ }
173      return sendXhr.apply(this, arguments);
174    };
175  }
176
177  document.addEventListener('click', function (ev) {
178    try {
179      var t = ev.target;
180      if (!t || !t.tagName) {
181        return;
182      }
183      var cls = typeof t.className === 'string' ? t.className.trim().split(/\s+/).slice(0, 2).join('.') : '';
184      crumb({
185        category: 'ui.click',
186        message: t.tagName.toLowerCase() + (t.id ? '#' + t.id : '') + (cls ? '.' + cls : '')
187      });
188    } catch (e) { /* never */ }
189  }, true);
190
191  crumb({ category: 'navigation', data: { path: location.pathname } });
192
193  /* For a quick check in the console: wbGlitchtip.status() */
194  cfg.status = function () {
195    return { sent: sent, breadcrumbs: crumbs.length, endpoint: cfg.endpoint };
196  };
197})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.