From 76b5048b1e7c013a10f86756d30479773668cf98 Mon Sep 17 00:00:00 2001 From: Oliver Burgmaier Date: Tue, 23 Apr 2024 07:35:51 +0000 Subject: [PATCH] Squashed rebase of changes from https://github.com/lapo-luchini/asn1js/pull/87 From 64546e452611da59a9d8c9d72ba7fb15e49d0415 Date: Sun, 28 Jan 2024 18:17:45 +0100 Subject: [PATCH 01/25] hex copy on click From 151289b9b0cac66c1ef8b24266c8b2677420e389 Date: Sun, 28 Jan 2024 22:08:09 +0100 Subject: [PATCH 02/25] Context menu and copyAsString added From 5efe7f7d69343dd1f981fc172a0c58f545e52ad9 Date: Mon, 29 Jan 2024 08:26:40 +0100 Subject: [PATCH 03/25] Context menu initially hidden From 36dd23909e43b0cbe468264bedfaa42282066ead Date: Mon, 29 Jan 2024 13:28:54 +0100 Subject: [PATCH 04/25] Fix: Copy the string to clipboard From 01b1525883c77616d77421d0f30c5423ded0fa82 Date: Mon, 29 Jan 2024 13:31:51 +0100 Subject: [PATCH 05/25] New: Copy as pretty From 4978b90571a755cabe729621b929bc77162c9a59 Date: Mon, 29 Jan 2024 13:33:13 +0100 Subject: [PATCH 06/25] New: Align context menu to left From c7cc3ba57541ad844954fb4844bb7b7e90801a91 Date: Mon, 29 Jan 2024 18:48:31 +0100 Subject: [PATCH 07/25] Negative list for set and sequence From c69ed8d1b900fc7b4a05df4f46ba8a47620d1263 Date: Mon, 29 Jan 2024 18:52:28 +0100 Subject: [PATCH 08/25] Fix: Show context menu at correct position From 0b9b3f308062f6ef697cc88c538663cf33b1a6f8 Date: Mon, 29 Jan 2024 19:22:45 +0100 Subject: [PATCH 09/25] Simple marker with toggle method From 8eb74573629043c0e3d2ce25d62097aef78be5a9 Date: Wed, 31 Jan 2024 19:50:58 +0100 Subject: [PATCH 10/25] Indention fixed From 80e7a8b94d492cf21f91d22c159d837769a54ecc Date: Sun, 31 Mar 2024 19:35:37 +0200 Subject: [PATCH 11/25] Menu added to tree view From 6dcb05766e312f546b0975d63fd0717115a33324 Date: Sun, 31 Mar 2024 22:09:03 +0200 Subject: [PATCH 12/25] Pretty text from innerText From 88d7afdefa5dd34592f31f6f5ea6d944cc02af96 Date: Wed, 10 Apr 2024 21:01:10 +0200 Subject: [PATCH 13/25] new: tree view From 59d44dca61ca52f3c29cdca89d282936520c4b42 Date: Fri, 19 Apr 2024 15:42:51 +0200 Subject: [PATCH 14/25] Only highlight the current selected node From 1dc1323628c7bd7c4e3afd49f4e9a9de306ddfd5 Date: Fri, 19 Apr 2024 15:48:44 +0200 Subject: [PATCH 15/25] smaller padding as of tree layout From 60383f905db9013ba2f206027b93474c7b93bed6 Date: Fri, 19 Apr 2024 16:17:50 +0200 Subject: [PATCH 16/25] Smaller borders and icon From a6cf850b9ca813e342814ccc4342855257c8e422 Date: Fri, 19 Apr 2024 16:31:23 +0200 Subject: [PATCH 17/25] do not show the menu in case of clicking the icon From 174df2c95a190ccc918d02bc39b9fa603b475870 Date: Fri, 19 Apr 2024 16:38:45 +0200 Subject: [PATCH 18/25] Installation of node to execute lint correctly From 48fbe0bd3f1e44597eebc068981f78ddb1a196e6 Date: Fri, 19 Apr 2024 16:38:54 +0200 Subject: [PATCH 19/25] Singlequotes From fbd2b26563fbe2b043b23f1e048f3aa23b8e7b71 Date: Sat, 20 Apr 2024 13:33:30 +0200 Subject: [PATCH 20/25] Only show context menu on highlighted element From ea3c28fdcc467f2f8c20dd97747e27f3add2605b Date: Sat, 20 Apr 2024 14:09:29 +0200 Subject: [PATCH 21/25] Less offensive tree icons From 1f9913ce2ec63232931a41be54b54f7ab7f71579 Date: Sat, 20 Apr 2024 14:28:33 +0200 Subject: [PATCH 22/25] Original layout recovered From 0d84f33fd88e2fe35c27a675e1d07fe1498bf541 Date: Sat, 20 Apr 2024 15:02:26 +0200 Subject: [PATCH 23/25] Layout issue fixed From ba21d40f4647dbfe13185e90fb64a42ccf8c415c Date: Mon, 22 Apr 2024 19:46:31 +0200 Subject: [PATCH 24/25] Fix: Zoom issues of the border line in treeview From d303e65a60e05c8d4040ef6c57803199b9253e08 Date: Tue, 23 Apr 2024 09:35:51 +0200 Subject: [PATCH 25/25] Indentation fixed --- context.js | 20 ++++++----- dom.js | 50 +++++++++++++++++++++----- index.css | 86 ++++++++++++++++++++++++++++++++++++++++----- index.js | 21 ++++++++++- tree-icon-dark.svg | 67 +++++++++++++++++++++++++++++++++++ tree-icon-light.svg | 64 +++++++++++++++++++++++++++++++++ 6 files changed, 281 insertions(+), 27 deletions(-) create mode 100644 tree-icon-dark.svg create mode 100644 tree-icon-light.svg diff --git a/context.js b/context.js index e2d4a5e..05d0b54 100644 --- a/context.js +++ b/context.js @@ -11,14 +11,18 @@ export function bindContextMenu(node) { const type = node.asn1.typeName(); const valueEnabled = type != 'SET' && type != 'SEQUENCE'; node.onclick = function (event) { - contextMenu.style.left = event.pageX + 'px'; - contextMenu.style.top = event.pageY + 'px'; - contextMenu.style.visibility = 'visible'; - contextMenu.node = this; - btnHideTree.innerText = (node.className == 'node') ? 'Hide subtree' : 'Show subtree'; - btnHideTree.style.display = node.className.startsWith('node') ? 'block' : 'none'; - btnCopyValue.style.display = valueEnabled ? 'block' : 'none'; - event.stopPropagation(); + // do not show the menu in case of clicking the icon + if (event.srcElement.nodeName === 'SPAN') { + contextMenu.style.left = event.pageX + 'px'; + contextMenu.style.top = event.pageY + 'px'; + contextMenu.style.visibility = 'visible'; + contextMenu.node = this; + btnHideTree.innerText = (node.className == 'node') ? 'Hide subtree' : 'Show subtree'; + btnHideTree.style.display = node.className.startsWith('node') ? 'block' : 'none'; + btnCopyValue.style.display = valueEnabled ? 'block' : 'none'; + event.preventDefault(); + event.stopPropagation(); + } }; } diff --git a/dom.js b/dom.js index 8ae7c1e..bd89805 100644 --- a/dom.js +++ b/dom.js @@ -53,13 +53,17 @@ const export class ASN1DOM extends ASN1 { + buf2hex(buffer) { + return [...new Uint8Array(buffer)].map((x) => x.toString(16).padStart(2, '0')).join(' '); + } + toDOM(spaces) { spaces = spaces || ''; let isOID = (typeof oids === 'object') && (this.tag.isUniversal() && (this.tag.tagNumber == 0x06) || (this.tag.tagNumber == 0x0D)); - let node = DOM.tag('div', 'node'); - node.asn1 = this; + let node; + node = document.createElement('li'); + node.asn1 = this; let head = DOM.tag('span', 'head'); - head.appendChild(DOM.tag('span', 'spaces', spaces)); const typeName = this.typeName().replace(/_/g, ' '); if (this.def) { if (this.def.id) { @@ -75,6 +79,8 @@ export class ASN1DOM extends ASN1 { head.appendChild(DOM.space()); } } + head.setAttribute('pos', this.posStart()); + head.setAttribute('end', this.posEnd()); head.appendChild(DOM.text(typeName)); let content; try { @@ -111,8 +117,28 @@ export class ASN1DOM extends ASN1 { content = content.replace(/'); } - node.appendChild(head); - this.node = node; + // add the li and details section for this node + let contentNode; + let childNode; + if (this.sub !== null) { + let details = document.createElement('details'); + details.setAttribute('open', ''); + node.appendChild(details); + let summary = document.createElement('summary'); + summary.setAttribute('class', 'node'); + details.appendChild(summary); + summary.appendChild(head); + // summary.setAttribute('class', 'node'); + contentNode = summary; + childNode = details; + } + else { + contentNode = node; + contentNode.setAttribute('class', 'node'); + contentNode.appendChild(head); + } + + this.node = contentNode; this.head = head; let value = DOM.tag('div', 'value'); let s = 'Offset: ' + this.stream.pos + '
'; @@ -135,14 +161,16 @@ export class ASN1DOM extends ASN1 { } } value.innerHTML = s; - node.appendChild(value); + contentNode.appendChild(value); let sub = DOM.tag('div', 'sub'); if (this.sub !== null) { + let ul = document.createElement('ul'); + childNode.appendChild(ul); + spaces += '\xA0 '; for (let i = 0, max = this.sub.length; i < max; ++i) - sub.appendChild(this.sub[i].toDOM(spaces)); + ul.appendChild(this.sub[i].toDOM(spaces)); } - node.appendChild(sub); bindContextMenu(node); return node; } @@ -169,13 +197,14 @@ export class ASN1DOM extends ASN1 { this.head.onmouseover = function () { this.hexNode.className = 'hexCurrent'; }; this.head.onmouseout = function () { this.hexNode.className = 'hex'; }; node.asn1 = this; - node.onmouseover = function () { + node.onmouseover = function (event) { let current = !root.selected; if (current) { root.selected = this.asn1; this.className = 'hexCurrent'; } this.asn1.fakeHover(current); + event.stopPropagation(); }; node.onmouseout = function () { let current = (root.selected == this.asn1); @@ -199,6 +228,9 @@ export class ASN1DOM extends ASN1 { node.appendChild(skip); } } + // set the current start and end position as an attribute at the node to know the selected area + node.setAttribute('pos', this.posStart()); + node.setAttribute('end', this.posEnd()); this.toHexDOM_sub(node, 'tag', this.stream, this.posStart(), this.posLen()); this.toHexDOM_sub(node, (this.length >= 0) ? 'dlen' : 'ulen', this.stream, this.posLen(), this.posContent()); if (this.sub === null) { diff --git a/index.css b/index.css index ad495a1..d418189 100644 --- a/index.css +++ b/index.css @@ -29,6 +29,7 @@ html[data-theme="light"] { --dump-hex-current-hex: #A0A0A0; --dump-hex-current-dlen: #004040; --hover-bg-color: #E0E0E0; + --zoom-fix: -1px; } html[data-theme="dark"] { --main-bg-color: #0d1116; @@ -126,7 +127,7 @@ header { #main-page { background-color: var(--main-bg-color); border: 0px; - padding: 15px; + padding: 5px; } #main-page > div { position: relative; @@ -158,13 +159,6 @@ header { /*display: block;*/ visibility: visible; } -.node { - position: relative; -} -.sub { - padding-left: 1.5em; - border-left: solid 1px var(--sub-border-color); -} .head { height: 1em; white-space: nowrap; @@ -197,7 +191,7 @@ header { position: absolute; z-index: 2; top: 1.2em; - left: 0; + left: 30px; background-color: #efefef; /*minimal support for IE11*/ background-color: var(--button-bg-color); border: solid 1px var(--button-border-color); @@ -267,3 +261,77 @@ header { #contextmenu > button:hover { background-color: var(--button-bghover-color); } +.treecollapse { + --spacing: 1.5rem; + --radius: 7px; + padding-inline-start: 0px; +} + +.treecollapse li{ + display: block; + position: relative; + padding-left: calc(2 * var(--spacing) - var(--radius) - 2px); +} + +.treecollapse ul{ + padding-left: 0; + margin-left: calc(var(--radius) - var(--spacing)); +} + +.treecollapse ul li{ + border-left: 1px solid #999; +} + +.treecollapse ul li:last-child{ + border-color: transparent; +} + +.treecollapse ul li::before{ + content: ''; + display: block; + position: absolute; + top: calc(var(--spacing) / -1.6); + left: var(--zoom-fix); + width: calc(var(--spacing) + 2px); + height: calc(var(--spacing) + 1px); + border: solid #999; + border-width: 0 0 1px 1px; +} + +.treecollapse summary{ + display : block; + cursor : pointer; +} + +.treecollapse summary::marker, +.treecollapse summary::-webkit-details-marker{ + display : none; +} + +.treecollapse summary:focus{ + outline : none; +} + +.treecollapse summary:focus-visible{ + outline : 1px dotted #000; +} + +.treecollapse summary::before{ + content: ''; + display: block; + position: absolute; + top: calc(var(--spacing) / 2 - var(--radius)); + left: calc(var(--spacing) - var(--radius) - 1px); + width: calc(2 * var(--radius)); + height: calc(2 * var(--radius)); +} + +.treecollapse summary::before{ + z-index: 1; + top: 1px; + background: url('tree-icon-light.svg'); +} + +.treecollapse details[open] > summary::before{ + background-position : calc(-2 * var(--radius)) 0; +} \ No newline at end of file diff --git a/index.js b/index.js index a0a2a4e..3e4385f 100644 --- a/index.js +++ b/index.js @@ -41,7 +41,10 @@ function checkbox(name) { function show(asn1) { tree.innerHTML = ''; dump.innerHTML = ''; - tree.appendChild(asn1.toDOM()); + let ul = document.createElement('ul'); + ul.setAttribute('class', 'treecollapse'); + tree.appendChild(ul); + ul.appendChild(asn1.toDOM()); if (wantHex.checked) dump.appendChild(asn1.toHexDOM(undefined, trimHex.checked)); } export function decode(der, offset) { @@ -211,3 +214,19 @@ selectTag.onchange = function (ev) { let tag = ev.target.selectedOptions[0].value; window.location.href = 'https://rawcdn.githack.com/lapo-luchini/asn1js/' + tag + '/index.html'; }; + +// zoom fix to have straight lines in treeview +if (window.devicePixelRatio >= 2 ) { + let treecollapse = document.querySelector(':root'); + treecollapse.style.setProperty('--zoom-fix', '-0.8px'); +} else if (window.devicePixelRatio >= 1.5 ) { + let treecollapse = document.querySelector(':root'); + treecollapse.style.setProperty('--zoom-fix', '-0.5px'); +} else if (window.devicePixelRatio <= 0.81 ) { + let treecollapse = document.querySelector(':root'); + treecollapse.style.setProperty('--zoom-fix', '-1.4px'); +} else if (window.devicePixelRatio <= 0.9 ) { + let treecollapse = document.querySelector(':root'); + treecollapse.style.setProperty('--zoom-fix', '-1.5px'); +} +console.log(window.devicePixelRatio); \ No newline at end of file diff --git a/tree-icon-dark.svg b/tree-icon-dark.svg new file mode 100644 index 0000000..93c7fb3 --- /dev/null +++ b/tree-icon-dark.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + diff --git a/tree-icon-light.svg b/tree-icon-light.svg new file mode 100644 index 0000000..fc1ddd6 --- /dev/null +++ b/tree-icon-light.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + -- 2.51.2