From e9da5cf179be2a588869a95b84dc6960d1c1fd39 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 5 Oct 2020 18:52:14 -0400 Subject: [PATCH] Support VarDumper JS --- resources/js/screens/dumps/index.vue | 38 ++- resources/js/screens/dumps/sfdump.js | 494 +++++++++++++++++++++++++++ 2 files changed, 530 insertions(+), 2 deletions(-) create mode 100644 resources/js/screens/dumps/sfdump.js diff --git a/resources/js/screens/dumps/index.vue b/resources/js/screens/dumps/index.vue index d0f243c5e..5f6e7f551 100644 --- a/resources/js/screens/dumps/index.vue +++ b/resources/js/screens/dumps/index.vue @@ -1,5 +1,6 @@ @@ -126,7 +160,7 @@ {{timeAgo(entry.created_at)}} -
+
diff --git a/resources/js/screens/dumps/sfdump.js b/resources/js/screens/dumps/sfdump.js new file mode 100644 index 000000000..fef1bc051 --- /dev/null +++ b/resources/js/screens/dumps/sfdump.js @@ -0,0 +1,494 @@ +export default function (doc) { + + var refStyle = doc.createElement('style'), + rxEsc = /([.*+?^${}()|\[\]\/\\])/g, + idRx = /\bsf-dump-\d+-ref[012]\w+\b/, + keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', + addEventListener = function (e, n, cb) { + e.addEventListener(n, cb, false); + }; + + (doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); + + if (!doc.addEventListener) { + addEventListener = function (element, eventName, callback) { + element.attachEvent('on' + eventName, function (e) { + e.preventDefault = function () {e.returnValue = false;}; + e.target = e.srcElement; + callback(e); + }); + }; + } + + function toggle(a, recursive) { + var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; + + if (/\bsf-dump-compact\b/.test(oldClass)) { + arrow = '▼'; + newClass = 'sf-dump-expanded'; + } else if (/\bsf-dump-expanded\b/.test(oldClass)) { + arrow = '▶'; + newClass = 'sf-dump-compact'; + } else { + return false; + } + + if (doc.createEvent && s.dispatchEvent) { + var event = doc.createEvent('Event'); + event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false); + + s.dispatchEvent(event); + } + + a.lastChild.innerHTML = arrow; + s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); + + if (recursive) { + try { + a = s.querySelectorAll('.'+oldClass); + for (s = 0; s < a.length; ++s) { + if (-1 == a[s].className.indexOf(newClass)) { + a[s].className = newClass; + a[s].previousSibling.lastChild.innerHTML = arrow; + } + } + } catch (e) { + } + } + + return true; + }; + + function collapse(a, recursive) { + var s = a.nextSibling || {}, oldClass = s.className; + + if (/\bsf-dump-expanded\b/.test(oldClass)) { + toggle(a, recursive); + + return true; + } + + return false; + }; + + function expand(a, recursive) { + var s = a.nextSibling || {}, oldClass = s.className; + + if (/\bsf-dump-compact\b/.test(oldClass)) { + toggle(a, recursive); + + return true; + } + + return false; + }; + + function collapseAll(root) { + var a = root.querySelector('a.sf-dump-toggle'); + if (a) { + collapse(a, true); + expand(a); + + return true; + } + + return false; + } + + function reveal(node) { + var previous, parents = []; + + while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) { + parents.push(previous); + } + + if (0 !== parents.length) { + parents.forEach(function (parent) { + expand(parent); + }); + + return true; + } + + return false; + } + + function highlight(root, activeNode, nodes) { + resetHighlightedNodes(root); + + Array.from(nodes||[]).forEach(function (node) { + if (!/\bsf-dump-highlight\b/.test(node.className)) { + node.className = node.className + ' sf-dump-highlight'; + } + }); + + if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { + activeNode.className = activeNode.className + ' sf-dump-highlight-active'; + } + } + + function resetHighlightedNodes(root) { + Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { + strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); + strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); + }); + } + + return function (root, x) { + root = doc.getElementById(root); + + var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'), + options = {maxDepth: 1, maxStringLength: 160, fileLinkFormat: false}, + elt = root.getElementsByTagName('A'), + len = elt.length, + i = 0, s, h, + t = []; + + while (i < len) t.push(elt[i++]); + + for (i in x) { + options[i] = x[i]; + } + + function a(e, f) { + addEventListener(root, e, function (e, n) { + if ('A' == e.target.tagName) { + f(e.target, e); + } else if ('A' == e.target.parentNode.tagName) { + f(e.target.parentNode, e); + } else { + n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target; + + if ((n = n.nextElementSibling) && 'A' == n.tagName) { + if (!/\bsf-dump-toggle\b/.test(n.className)) { + n = n.nextElementSibling || n; + } + + f(n, e, true); + } + } + }); + }; + function isCtrlKey(e) { + return e.ctrlKey || e.metaKey; + } + function xpathString(str) { + var parts = str.match(/[^'"]+|['"]/g).map(function (part) { + if ("'" == part) { + return '"\'"'; + } + if ('"' == part) { + return "'\"'"; + } + + return "'" + part + "'"; + }); + + return "concat(" + parts.join(",") + ", '')"; + } + function xpathHasClass(className) { + return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')"; + } + addEventListener(root, 'mouseover', function (e) { + if ('' != refStyle.innerHTML) { + refStyle.innerHTML = ''; + } + }); + a('mouseover', function (a, e, c) { + if (c) { + e.target.style.cursor = "pointer"; + } else if (a = idRx.exec(a.className)) { + try { + refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}'; + } catch (e) { + } + } + }); + a('click', function (a, e, c) { + if (/\bsf-dump-toggle\b/.test(a.className)) { + e.preventDefault(); + if (!toggle(a, isCtrlKey(e))) { + var r = doc.getElementById(a.getAttribute('href').substr(1)), + s = r.previousSibling, + f = r.parentNode, + t = a.parentNode; + t.replaceChild(r, a); + f.replaceChild(a, s); + t.insertBefore(s, r); + f = f.firstChild.nodeValue.match(indentRx); + t = t.firstChild.nodeValue.match(indentRx); + if (f && t && f[0] !== t[0]) { + r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); + } + if (/\bsf-dump-compact\b/.test(r.className)) { + toggle(s, isCtrlKey(e)); + } + } + + if (c) { + } else if (doc.getSelection) { + try { + doc.getSelection().removeAllRanges(); + } catch (e) { + doc.getSelection().empty(); + } + } else { + doc.selection.empty(); + } + } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { + e.preventDefault(); + e = a.parentNode.parentNode; + e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className); + } + }); + + elt = root.getElementsByTagName('SAMP'); + len = elt.length; + i = 0; + + while (i < len) t.push(elt[i++]); + len = t.length; + + for (i = 0; i < len; ++i) { + elt = t[i]; + if ('SAMP' == elt.tagName) { + a = elt.previousSibling || {}; + if ('A' != a.tagName) { + a = doc.createElement('A'); + a.className = 'sf-dump-ref'; + elt.parentNode.insertBefore(a, elt); + } else { + a.innerHTML += ' '; + } + a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children'; + a.innerHTML += ''; + a.className += ' sf-dump-toggle'; + + x = 1; + if ('sf-dump' != elt.parentNode.className) { + x += elt.parentNode.getAttribute('data-depth')/1; + } + elt.setAttribute('data-depth', x); + var className = elt.className; + elt.className = 'sf-dump-expanded'; + if (className ? 'sf-dump-expanded' !== className : (x > options.maxDepth)) { + toggle(a); + } + } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) { + a = a.substr(1); + elt.className += ' '+a; + + if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { + a = a != elt.nextSibling.id && doc.getElementById(a); + try { + s = a.nextSibling; + elt.appendChild(a); + s.parentNode.insertBefore(a, s); + if (/^[@#]/.test(elt.innerHTML)) { + elt.innerHTML += ' '; + } else { + elt.innerHTML = ''; + elt.className = 'sf-dump-ref'; + } + elt.className += ' sf-dump-toggle'; + } catch (e) { + if ('&' == elt.innerHTML.charAt(0)) { + elt.innerHTML = '…'; + elt.className = 'sf-dump-ref'; + } + } + } + } + } + + if (doc.evaluate && Array.from && root.children.length > 1) { + root.setAttribute('tabindex', 0); + + let SearchState = function () { + this.nodes = []; + this.idx = 0; + }; + SearchState.prototype = { + next: function () { + if (this.isEmpty()) { + return this.current(); + } + this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0; + + return this.current(); + }, + previous: function () { + if (this.isEmpty()) { + return this.current(); + } + this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1); + + return this.current(); + }, + isEmpty: function () { + return 0 === this.count(); + }, + current: function () { + if (this.isEmpty()) { + return null; + } + return this.nodes[this.idx]; + }, + reset: function () { + this.nodes = []; + this.idx = 0; + }, + count: function () { + return this.nodes.length; + }, + }; + + function showCurrent(state) + { + var currentNode = state.current(), currentRect, searchRect; + if (currentNode) { + reveal(currentNode); + highlight(root, currentNode, state.nodes); + if ('scrollIntoView' in currentNode) { + currentNode.scrollIntoView(true); + currentRect = currentNode.getBoundingClientRect(); + searchRect = search.getBoundingClientRect(); + if (currentRect.top < (searchRect.top + searchRect.height)) { + window.scrollBy(0, -(searchRect.top + searchRect.height + 5)); + } + } + } + counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count(); + } + + var search = doc.createElement('div'); + search.className = 'sf-dump-search-wrapper sf-dump-search-hidden'; + search.innerHTML = ` + + 0 of 0<\/span> +