Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions public/components/file-box/file-box.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
/**
* LICENSES
*/
.box-container-licenses {
display: flex;
flex-wrap: wrap;
}

.box-container-licenses>div {
flex-grow: 1;
flex-basis: 150px;
height: 26px;
display: flex;
align-items: center;
box-sizing: border-box;
font-weight: 500;
color: #D1C4E9;
font-family: system-ui;
}

/**
* WARNINGS
*/
Expand Down
17 changes: 15 additions & 2 deletions public/components/icon/icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ const kIcons = {
t27.648-43.008zM951.296 951.296v-658.432h-220.16v237.568q0 22.528-15.36 38.912
t-38.912 15.36h-237.568v366.592h512z"/>
</svg>
`,
"info-circled": html`
<svg viewBox="0 0 804 1024" aria-hidden="true">
<path fill="currentColor"
d="M0 512q0-97.28 37.888-186.368t102.4-152.576 152.576-102.4 187.392-37.888q97.28 0
186.368 37.888t152.576 102.4 102.4 152.576 37.888 186.368q0 97.28-37.888 186.368t-102.4
153.6-152.576 102.4-186.368 37.888-187.392-37.888-152.576-102.4-102.4-153.6-37.888
-186.368zM119.808 512q0 72.704 28.672 140.288t76.8 114.688 114.688 76.8 140.288 28.672
139.264-28.672 114.688-76.8 76.8-114.688 28.672-140.288-28.672-139.264-76.8-114.688
-114.688-76.8-139.264-28.672-140.288 28.672-114.688 76.8-76.8 114.688-28.672 139.264z
M407.552 337.92q0-28.672 20.48-46.080t52.224-17.408q32.768 0 52.224 17.408t19.456
46.080-19.456 47.104-52.224 17.408q-32.768 0-52.224-17.408t-20.48-47.104zM412.672
749.568v-306.176h135.168v306.176h-135.168z"/>
</svg>
`
};

Expand All @@ -65,8 +79,7 @@ export class Icon extends LitElement {
`;

static properties = {
name: { type: String },
size: { type: String }
name: { type: String }
};

render() {
Expand Down
8 changes: 7 additions & 1 deletion public/components/package/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ export class PackageInfo {
files.id = "pan-files";
files.classList.add("package-container", "hidden");
panFiles.parentElement.replaceChild(files, panFiles);

const panLicenses = packageHTMLElement.querySelector("#pan-licenses");
const licenses = document.createElement("package-licenses");
licenses.package = this;
licenses.id = "pan-licenses";
files.classList.add("package-container", "hidden");
panLicenses.parentElement.replaceChild(licenses, panLicenses);
}

/**
Expand Down Expand Up @@ -153,7 +160,6 @@ export class PackageInfo {
this.links = new PackageHeader(this).generate(clone);

new Pannels.Overview(this).generate(clone);
new Pannels.Licenses(this).generate(clone);
new Pannels.Warnings(this).generate(clone);
new Pannels.Scripts(this).generate(clone);
new Pannels.Vulnerabilities(this).generate(clone);
Expand Down
152 changes: 113 additions & 39 deletions public/components/package/pannels/licenses/licenses.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,124 @@
// Import Third-party Dependencies
import { LitElement, css, html } from "lit";
import { repeat } from "lit/directives/repeat.js";

// Import Internal Dependencies
import * as utils from "../../../../common/utils.js";
import { selectLicenses } from "./view-model.js";
import { currentLang } from "../../../../common/utils.js";
import "../../../file-box/file-box.js";
import "../../../icon/icon.js";

class Licenses extends LitElement {
static styles = css`
.box-container-licenses {
display: flex;
flex-wrap: wrap;
}

.box-container-licenses>div {
flex-grow: 1;
flex-basis: 150px;
height: 26px;
display: flex;
align-items: center;
box-sizing: border-box;
font-weight: 500;
color: #D1C4E9;
font-family: system-ui;
}

.help-dialog {
display: flex;
padding: 10px;
border-radius: 8px;
margin-bottom: 10px;
border: 2px dashed #57e1bf4a;
color: #9de157;
letter-spacing: 0.5px;
align-items: center;
}

.help-dialog> nsecure-icon {
margin-right: 11px;
font-size: 28px;
}

.help-dialog>p {
font-size: 14px;
font-style: italic;
}

.help-dialog>p b {
background: #9de157;
padding: 2px 5px;
color: #000;
border-radius: 4px;
font-style: normal;
font-weight: bold;
cursor: pointer;
}

export class Licenses {
constructor(pkg) {
this.package = pkg;
.help-dialog>p b:hover {
background: var(--secondary);
}

/**
* @param {!HTMLTemplateElement} clone
*/
generate(clone) {
clone.getElementById("pan-licenses")
.appendChild(this.renderLicenses());
.help-dialog>p a {
color: inherit;
cursor: pointer;
text-decoration: underline;
font-weight: bold;
}
`;

static properties = {
package: { type: Object }
};

renderLicenses() {
render() {
const { licenses } = this.package.dependencyVersion;
const fragment = document.createDocumentFragment();
const unpkgRoot = this.package.links.unpkg.href;
const processedLicenses = new Set();

for (const license of licenses) {
const [licenseName, licenseLink] = Object.entries(license.licenses)[0];
if (processedLicenses.has(licenseName)) {
continue;
}
processedLicenses.add(licenseName);

const spdx = Object.entries(license.spdx)
.map(([key, value]) => `${value ? "✔️" : "❌"} ${key}`);

const boxContainer = utils.createDOMElement("div", {
classList: ["box-container-licenses"],
childs: spdx.map((text) => utils.createDOMElement("div", { text }))
});

const box = document.createElement("file-box");
box.title = licenseName;
box.fileName = license.from;
box.titleHref = licenseLink;
box.fileHref = `${unpkgRoot}${license.from}`;
box.appendChild(boxContainer);
fragment.appendChild(box);
}

return fragment;
const { package_info } = window.i18n[currentLang()];

return html`
<div class="help-dialog">
<nsecure-icon name="info-circled"></nsecure-icon>
<p>
${package_info.helpers.spdx}
<a href="https://spdx.dev/about/" target="_blank"
rel="noopener noreferrer">${package_info.helpers.here}
</a>
</p>
</div>
${repeat(
selectLicenses(licenses, unpkgRoot),
(license) => license,
({
title,
spdx,
fileName,
fileHref,
titleHref
}) => html`
<file-box
.title=${title}
.file-name=${fileName}
.title-href=${titleHref}
.file-href=${fileHref}
>
<div class="box-container-licenses">
${repeat(
spdx,
(text) => text,
(text) => html`
<div>${text}</div>
`
)}
</div>
</file-box>
`
)}
`;
}
}

customElements.define("package-licenses", Licenses);
21 changes: 21 additions & 0 deletions public/components/package/pannels/licenses/view-model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export function selectLicenses(licenses, unpkgRoot) {
const processedLicenses = new Set();

return licenses.flatMap((license) => {
const [licenseName, licenseLink] = Object.entries(license.licenses)[0];
if (processedLicenses.has(licenseName)) {
return [];
}
processedLicenses.add(licenseName);

return [
{
title: licenseName,
spdx: Object.entries(license.spdx).map(([key, value]) => `${value ? "✔️" : "❌"} ${key}`),
fileName: license.from,
fileHref: `${unpkgRoot}${license.from}`,
titleHref: licenseLink
}
];
});
}
4 changes: 3 additions & 1 deletion public/components/package/pannels/warnings/warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ export class Warnings {
box.fileHref = `${unpkgRoot}${warning.file}`;
box.severity = warning.severity ?? "Information";
box.appendChild(boxContainer);
box.appendChild(boxPosition);
if (boxPosition) {
box.appendChild(boxPosition);
}
fragment.appendChild(box);
}

Expand Down
98 changes: 98 additions & 0 deletions test/ui/licenses.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Import Node.js Dependencies
import assert from "node:assert";
import { describe, it } from "node:test";

// Import Internal Dependencies
import { selectLicenses } from "../../public/components/package/pannels/licenses/view-model.js";

describe("select licenses", () => {
it("should have no licenses", () => {
const licenses = [];
assert.deepEqual(selectLicenses(licenses, "./"), []);
});

it("should select a licences with spdx ✔️", () => {
const licenses = [
{
licenses: {
"Apache-2.0": "https://spdx.org/licenses/Apache-2.0.html#licenseText"
},
spdx: {
osi: true,
fsf: true,
fsfAndOsi: true,
includesDeprecated: true
},
from: "package.json"
}
];
assert.deepEqual(selectLicenses(licenses, "./"), [{
title: "Apache-2.0",
spdx: ["✔️ osi", "✔️ fsf", "✔️ fsfAndOsi", "✔️ includesDeprecated"],
fileName: "package.json",
fileHref: "./package.json",
titleHref: "https://spdx.org/licenses/Apache-2.0.html#licenseText"
}]);
});

it("should select a licences with spdx ❌", () => {
const licenses = [
{
licenses: {
"Apache-3.0": "https://spdx.org/licenses/Apache-3.0.html#licenseText"
},
spdx: {
osi: false,
fsf: false,
fsfAndOsi: false,
includesDeprecated: false
},
from: "/package.json"
}
];
assert.deepEqual(selectLicenses(licenses, ".."), [{
title: "Apache-3.0",
spdx: ["❌ osi", "❌ fsf", "❌ fsfAndOsi", "❌ includesDeprecated"],
fileName: "/package.json",
fileHref: "../package.json",
titleHref: "https://spdx.org/licenses/Apache-3.0.html#licenseText"
}]);
});

it("should drop duplicates", () => {
const licenses = [
{
licenses: {
"Apache-3.0": "https://spdx.org/licenses/Apache-3.0.html#licenseText"
},
spdx: {
osi: false,
fsf: false,
fsfAndOsi: false,
includesDeprecated: false
},
from: "/package.json"
},
{
licenses: {
"Apache-3.0": "https://spdx.org/licenses/Apache-3.0.html#licenseText"
},
spdx: {
osi: false,
fsf: false,
fsfAndOsi: false,
includesDeprecated: false
},
from: "/package.json"
}
];

assert.deepEqual(selectLicenses(licenses, ".."), [{
title: "Apache-3.0",
spdx: ["❌ osi", "❌ fsf", "❌ fsfAndOsi", "❌ includesDeprecated"],
fileName: "/package.json",
fileHref: "../package.json",
titleHref: "https://spdx.org/licenses/Apache-3.0.html#licenseText"
}]);
});
});
Loading