Skip to content

Commit 8af3a98

Browse files
authored
feat: add a preview of the incriminated code during mouse over (#52)
* feat: add a preview of the incriminated code during mouse over * feat: add cache & update css * feat: add overflow to the tooltip * fix: base the code line instead of all code * fix: clean code * feat: try a new tooltip position * feat: add a single tooltip, and trigger it with an onClick * feat: add an inspect cell
1 parent dadd313 commit 8af3a98

File tree

6 files changed

+89
-7
lines changed

6 files changed

+89
-7
lines changed

i18n/english.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ module.exports = {
9595
type: "type",
9696
file: "file",
9797
errorMsg: "incrimined value",
98-
position: "position"
98+
position: "position",
99+
inspect: "inspect"
99100
}
100101
},
101102
searchbar_placeholder: "Search",

i18n/french.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ module.exports = {
9595
type: "type",
9696
file: "fichier",
9797
errorMsg: "valeur incriminée",
98-
position: "position"
98+
position: "position",
99+
inspect: "inspecter"
99100
}
100101
},
101102
searchbar_placeholder: "Recherche",

public/css/popup.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,29 @@
5959
overflow-y: auto;
6060
}
6161

62+
.modal .tooltip {
63+
visibility: hidden;
64+
position: absolute;
65+
z-index: 1;
66+
min-width: 120px;
67+
max-width: 600px;
68+
max-height: 300px;
69+
overflow-y: auto;
70+
top: 50%;
71+
left: 50%;
72+
transform: translate(-50%);
73+
background: #212121;
74+
border: 1px solid #424242;
75+
color: #E1F5FE;
76+
padding: 10px;
77+
border-radius: 4px;
78+
text-align: left;
79+
font-size: 14px;
80+
font-family: "mononoki";
81+
letter-spacing: 0.5px;
82+
word-wrap: break-word;
83+
}
84+
6285
.flags-legend-tags > .platine-button-skin {
6386
height: 30px;
6487
justify-content: start;

public/css/reset.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,6 @@ table {
138138
font-weight: bold;
139139
font-family: "Roboto";
140140
}
141+
table tr td.inspect {
142+
cursor: pointer;
143+
}

public/js/popup.js

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as utils from "./utils.js";
22
import List from "list.js";
33

4+
const loadingMessage = "Loading ...";
5+
46
function licenseModal(clone, options) {
57
const { licenses, selectedNode } = options;
68
if (licenses === "unkown license") {
@@ -26,22 +28,64 @@ function locationToString(location) {
2628
return `[${start}] - [${end}]`;
2729
}
2830

31+
function getLineFromFile(code, location) {
32+
const [[startLine]] = location;
33+
const lines = code.split('\n');
34+
35+
return lines[startLine - 1];
36+
}
37+
38+
async function fetchCodeLine(event, url, location, cache, lineId) {
39+
const target = document.getElementById('tooltip');
40+
target.style.visibility = 'visible';
41+
42+
if (cache.has(lineId)) {
43+
target.innerText = cache.get(lineId);
44+
event.stopPropagation();
45+
return;
46+
}
47+
48+
target.innerText = loadingMessage;
49+
const code = await fetch(url).then((response) => response.text());
50+
51+
target.innerText = code.length ? getLineFromFile(code, location): "Line not found ...";
52+
cache.set(lineId, target.innerText);
53+
event.stopPropagation();
54+
}
55+
56+
function handleOutsideTooltipClick({ target }) {
57+
const tooltip = document.getElementById('tooltip');
58+
59+
if (!tooltip) {
60+
return;
61+
}
62+
63+
if ((tooltip.innerHTML && tooltip.innerHTML !== loadingMessage) && !tooltip.contains(target) && tooltip.style.visibility === "visible") {
64+
tooltip.style.visibility = "hidden";
65+
tooltip.innerHTML = "";
66+
}
67+
}
68+
2969
function warningModal(clone, options) {
3070
const { name, version, npmHomePageURL, homepage, warnings } = options;
71+
const cache = new Map();
3172

3273
const openLink = (link) => {
3374
return () => window.open(link).focus();
3475
}
3576
const unpkgRootURL = `https://unpkg.com/${name}@${version}/`;
36-
const homePageBtn = clone.getElementById("warning-link-homepage")
77+
const homePageBtn = clone.getElementById("warning-link-homepage");
3778
homePageBtn.addEventListener("click", openLink(homepage));
3879
homePageBtn.querySelector("span").textContent = homepage;
3980
clone.getElementById("warning-link-npm").addEventListener("click", openLink(npmHomePageURL));
4081
clone.getElementById("warning-link-unpkg").addEventListener("click", openLink(unpkgRootURL));
82+
document.addEventListener("click", handleOutsideTooltipClick);
4183

4284
const tbody = clone.querySelector("#warnings-table tbody");
4385
for (const { kind, file, value = null, location } of warnings) {
4486
const line = tbody.insertRow(0);
87+
const lineId = Math.random().toString(36).slice(2);
88+
const unpkgFile = `${unpkgRootURL}${file}`;
4589

4690
const kindCell = line.insertCell(0)
4791
kindCell.classList.add("type");
@@ -58,21 +102,29 @@ function warningModal(clone, options) {
58102
const errorCell = line.insertCell(2);
59103
errorCell.classList.add("highlight");
60104
errorCell.classList.add("msg");
61-
const positionCell = line.insertCell(3);
62-
positionCell.classList.add("position");
63105
if (value !== null) {
64106
errorCell.classList.add("clickable");
65107
errorCell.appendChild(document.createTextNode(value));
66108
errorCell.addEventListener("click", () => utils.copyToClipboard(value));
67109
}
68110

111+
const positionCell = line.insertCell(3);
112+
positionCell.classList.add("position");
69113
if (kind === "encoded-literal") {
70114
const text = location.map((loc) => locationToString(loc)).join(" // ");
71115
positionCell.appendChild(document.createTextNode(text));
72116
}
73117
else {
74118
positionCell.appendChild(document.createTextNode(locationToString(location)));
75119
}
120+
121+
const inspectCell = line.insertCell(4);
122+
inspectCell.innerHTML = "🔬";
123+
inspectCell.classList.add("inspect");
124+
if (!file.includes(".min") && kind !== "short-identifiers" && kind !== "obfuscated-code") {
125+
const currLocation = kind === "encoded-literal" ? location[0] : location;
126+
inspectCell.addEventListener("click", (event) => fetchCodeLine(event, unpkgFile, currLocation, cache, lineId));
127+
}
76128
}
77129

78130
setTimeout(() => {
@@ -81,9 +133,9 @@ function warningModal(clone, options) {
81133
}
82134

83135
export function openLicenseModal(options = {}) {
84-
return () => window.toggleModal("popup-license", (clone) => licenseModal(clone, options))
136+
return () => window.toggleModal("popup-license", (clone) => licenseModal(clone, options));
85137
}
86138

87139
export function openWarningsModal(options = {}) {
88-
return () => window.toggleModal("popup-warning", (clone) => warningModal(clone, options))
140+
return () => window.toggleModal("popup-warning", (clone) => warningModal(clone, options));
89141
}

views/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
</section>
8484

8585
<div class="modal">
86+
<div class="tooltip" id="tooltip"></div>
8687
<div class="modal-content dark-box-skin">
8788
<span class="close-button">&times;</span>
8889
<div class="infobox"></div>
@@ -230,6 +231,7 @@ <h1>[[=z.token('popups.warnings.title')]]</h1>
230231
<th class="sort" data-sort="file">[[=z.token('popups.warnings.file')]]</th>
231232
<th class="sort" data-sort="msg">[[=z.token('popups.warnings.errorMsg')]]</th>
232233
<th class="sort" data-sort="position">[[=z.token('popups.warnings.position')]]</th>
234+
<th class="sort" data-sort="position">[[=z.token('popups.warnings.inspect')]]</th>
233235
</tr>
234236
</thead>
235237
<tbody class="list"></tbody>

0 commit comments

Comments
 (0)