Skip to content

Commit a90f620

Browse files
committed
Initial web page files
1 parent c81be2b commit a90f620

6 files changed

Lines changed: 239 additions & 0 deletions

File tree

src/app.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// npm Security Aggregator ~~ MIT License
2+
3+
const app = {
4+
5+
reportInfo: [
6+
{ name: 'Snyk', url: 'https://security.snyk.io/package/npm/[PKG-NAME]' },
7+
{ name: 'Socket', url: 'https://socket.dev/npm/package/[PKG-NAME]' },
8+
{ name: 'NPMScan', url: 'https://npmscan.com/package/[PKG-NAME]' },
9+
],
10+
11+
elem: null,
12+
13+
createElemMap() {
14+
const component = globalThis.document.querySelector('main');
15+
app.elem = {
16+
nameInput: component.querySelector('input[type=text]'),
17+
errorMessage: component.querySelector('span.error-message'),
18+
lookUpButton: component.querySelector('p >button'),
19+
registryFigure: component.querySelector('figure'),
20+
registryTitle: component.querySelector('figure >figcaption'),
21+
registryData: component.querySelector('figure >pre'),
22+
reportButtons: component.querySelector('nav:has(>button)'),
23+
};
24+
},
25+
26+
fetchPkg(name) {
27+
const pkgName = libX.str.toKebab(name);
28+
const registryUrl = `https://registry.npmjs.org/${pkgName}/latest`;
29+
app.elem.nameInput.value = pkgName;
30+
const updateReportButton = (info, i) => {
31+
const reportButton = app.elem.reportButtons.children[i];
32+
const reportUrl = info.url.replace('[PKG-NAME]', pkgName);
33+
reportButton.disabled = false;
34+
reportButton.dataset.href = reportUrl;
35+
reportButton.title = reportUrl;
36+
};
37+
const showPkg = (data) => {
38+
app.elem.registryTitle.textContent = pkgName;
39+
app.elem.registryTitle.title = registryUrl;
40+
app.elem.registryData.innerHTML = prettyPrintJson.toHtml(data);
41+
dna.ui.slideFadeIn(app.elem.registryFigure);
42+
app.reportInfo.forEach(updateReportButton);
43+
};
44+
const handlePkgData = (data) => {
45+
globalThis.console.info(data);
46+
const invalidPkg = data.status === 404;
47+
const success = !data.error && data.name === pkgName;
48+
const errorMessage = invalidPkg ? 'Package not found!' : 'Error encountered!';
49+
if (success)
50+
showPkg(data);
51+
else if (app.elem.nameInput.value)
52+
dna.ui.pulse(app.elem.errorMessage, { text: errorMessage });
53+
};
54+
fetchJson.enableLogger();
55+
if (pkgName)
56+
fetchJson.get(registryUrl).then(handlePkgData);
57+
},
58+
59+
enableLookUp() {
60+
app.elem.lookUpButton.disabled = !app.elem.nameInput.value;
61+
},
62+
63+
lookUpPkg() {
64+
app.elem.lookUpButton.disabled = true;
65+
app.fetchPkg(app.elem.nameInput.value);
66+
},
67+
68+
setup() {
69+
app.createElemMap();
70+
const paramValue = new URLSearchParams(globalThis.location.search).get('package');
71+
const folderName = libX.url.getFolderName(globalThis.document.referrer);
72+
const addIcon = (info) => info.icon = `assets/icon-${info.name.toLowerCase()}.png`;
73+
dna.clone('report-button', app.reportInfo, { transform: addIcon });
74+
app.fetchPkg(paramValue ?? folderName);
75+
},
76+
};
77+
78+
app.setup();

src/assets/icon-npmscan.png

52.2 KB
Loading

src/assets/icon-snyk.png

3.44 KB
Loading

src/assets/icon-socket.png

4.18 KB
Loading

src/index.html

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<!doctype html>
2+
<html lang=en>
3+
<!-- - - - - - - - - - - - - - - - - - - - - -->
4+
<!-- npm Security Aggregator ~~ MIT License -->
5+
<!-- - - - - - - - - - - - - - - - - - - - - -->
6+
<head>
7+
<meta charset=utf-8>
8+
<meta name=viewport content="width=device-width, initial-scale=1, maximum-scale=1">
9+
<meta name=robots content="index, follow">
10+
<meta name=description content="npm Security Aggregator -- View audit reports for a published npm package">
11+
<meta name=apple-mobile-web-app-title content="Security">
12+
<meta property=og:title content="npm Security Aggregator">
13+
<meta property=og:description content="View audit reports for a published npm package">
14+
<meta property=og:type content="website">
15+
<meta property=og:image content="https://centerkey.com/graphics/center-key-logo-card.png">
16+
<meta property=og:image:alt content="Logo">
17+
<title>npm Security Aggregator &bull; View audit reports for a published npm package</title>
18+
<link rel=icon href=https://centerkey.com/graphics/bookmark-icon.png>
19+
<link rel=preconnect href=https://fonts.googleapis.com>
20+
<link rel=preconnect href=https://fonts.gstatic.com crossorigin>
21+
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@{{package.dependencies.-fortawesome-fontawesome-free|version}}/css/all.min.css>
22+
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/dna-dom@{{package.dependencies.dna-dom|version}}/dist/dna-dom.min.css>
23+
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/web-ignition@{{package.dependencies.web-ignition|version}}/dist/reset.min.css>
24+
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/pretty-print-json@{{package.dependencies.pretty-print-json|version}}/dist/css/pretty-print-json.prefers.min.css>
25+
<link rel=stylesheet href={{webRoot}}/style.min.css>
26+
<script defer src=https://cdn.jsdelivr.net/npm/dna-dom@{{package.dependencies.dna-dom|version}}/dist/dna-dom.min.js></script>
27+
<script defer src=https://cdn.jsdelivr.net/npm/web-ignition@{{package.dependencies.web-ignition|version}}/dist/lib-x.min.js></script>
28+
<script defer src=https://cdn.jsdelivr.net/npm/pretty-print-json@{{package.dependencies.pretty-print-json|version}}/dist/pretty-print-json.min.js></script>
29+
<script defer src=https://cdn.jsdelivr.net/npm/fetch-json@{{package.dependencies.fetch-json|version}}/dist/fetch-json.min.js></script>
30+
<script defer src={{webRoot}}/app.min.js></script>
31+
</head>
32+
<body>
33+
34+
<header>
35+
<figure>🛡️</figure>
36+
<h1>npm Security Aggregator</h1>
37+
<h2>View audit reports for a published npm package</h2>
38+
<a id=fork-me href=https://github.com/center-key/npm-security-aggregator>Fork me on GitHub</a>
39+
</header>
40+
41+
<main>
42+
<section>
43+
<h2>Input</h2>
44+
<label>
45+
<span>npm Package:</span>
46+
<input type=text data-on-key-up=app.enableLookUp data-on-enter-key=app.lookUpPkg
47+
placeholder="Enter npm package name" spellcheck=false autofocus>
48+
</label>
49+
<span class=error-message>&nbsp;</span>
50+
<p>
51+
<button data-on-click=app.lookUpPkg disabled>Look Up Package</button>
52+
</p>
53+
</section>
54+
<section>
55+
<h2>Output</h2>
56+
<figure>
57+
<figcaption>&nbsp;</figcaption>
58+
<pre class=json-container></pre>
59+
</figure>
60+
<h3>View Reports</h3>
61+
<nav class=external-site>
62+
<button id=report-button class=dna-template disabled>
63+
<img src=# data-attr-src=~~icon~~ alt=~~name~~><span>~~name~~</span>
64+
</button>
65+
</nav>
66+
</section>
67+
</main>
68+
69+
<footer>
70+
<div>
71+
<p><b>npm-security-aggregator</b><br>MIT License</p>
72+
<p><a href=https://github.com/center-key/npm-security-aggregator><i data-brand=github-alt></i></a></p>
73+
<p><a href=https://centerkey.com><img src=https://centerkey.com/graphics/center-key-icon.svg alt=logo></a></p>
74+
</div>
75+
</footer>
76+
77+
</body>
78+
</html>

src/style.less

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// npm Security Aggregator ~~ MIT License
2+
3+
body {
4+
max-width: 1200px;
5+
color: gainsboro;
6+
background-color: maroon;
7+
}
8+
9+
body >header {
10+
margin-bottom: 40px;
11+
>figure {
12+
font-size: 3.5em;
13+
}
14+
>h1 {
15+
margin-bottom: 10px;
16+
}
17+
}
18+
19+
main {
20+
margin-bottom: 40px;
21+
>section {
22+
display: flex;
23+
flex-direction: column;
24+
justify-content: center;
25+
align-items: center;
26+
>h2 {
27+
display: none;
28+
}
29+
>label {
30+
margin-bottom: 3px;
31+
>span {
32+
font-weight: bold;
33+
text-align: center;
34+
margin-bottom: 3px;
35+
}
36+
}
37+
>p {
38+
text-align: center;
39+
}
40+
>span.error-message {
41+
color: gold;
42+
font-weight: bold;
43+
margin-bottom: 5px;
44+
}
45+
>figure {
46+
display: none;
47+
width: 100%;
48+
margin-bottom: 20px;
49+
>figcaption {
50+
font-family: monospace;
51+
font-size: 1.6em;
52+
}
53+
>pre {
54+
max-width: 700px;
55+
max-height: 250px;
56+
text-align: left;
57+
border: 5px solid silver;
58+
border-radius: 3px;
59+
padding: 10px 20px;
60+
margin: 0px auto;
61+
overflow: scroll;
62+
}
63+
}
64+
>nav {
65+
text-align: center;
66+
>button {
67+
font-size: 1.2rem;
68+
margin: 0px 10px 10px 10px;
69+
>img {
70+
height: 1.8em;
71+
vertical-align: middle;
72+
margin: 0px 0.5em 2px 0px;
73+
}
74+
}
75+
}
76+
}
77+
}
78+
79+
body >footer {
80+
b {
81+
font-size: 1.1rem;
82+
}
83+
}

0 commit comments

Comments
 (0)