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
35 changes: 33 additions & 2 deletions i18n/english.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
/* eslint-disable max-len */
import { taggedString as tS } from "@nodesecure/i18n";

const localI18n = {
const cli = {
startHttp: {
invalidScannerVersion: tS`the payload has been scanned with version '${0}' and do not satisfies the required CLI range '${1}'`,
regenerate: "please re-generate a new JSON payload using the CLI"
}
};

export default { localI18n };
const ui = {
popup: {
maintainer: {
intree: "packages in the dependency tree"
}
},
home: {
overview: {
title: "Overview"
},
watch: "Packages in the dependency tree requiring greater attention",
criticalWarnings: "Critical Warnings",
maintainers: "Maintainers"
},
settings: {
general: {
title: "General",
save: "save",
defaultPannel: "Default Package Menu",
warnings: "SAST Warnings to ignore",
flags: "Flags (emojis) to ignore"
},
shortcuts: {
title: "Shortcuts",
blockquote: "Click on hotkey to update",
goto: "Goto",
openCloseWiki: "Open/Close wiki"
}
}
};

export default { cli, ui };
35 changes: 33 additions & 2 deletions i18n/french.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
/* eslint-disable max-len */
import { taggedString as tS } from "@nodesecure/i18n";

const localI18n = {
const cli = {
startHttp: {
invalidScannerVersion: tS`le fichier d'analyse correspond à la version '${0}' du scanner et ne satisfait pas la range '${1}' attendu par la CLI`,
regenerate: "veuillez re-générer un nouveau fichier d'analyse JSON en utilisant votre CLI"
}
};

export default { localI18n };
const ui = {
popup: {
maintainer: {
intree: "packages dans l'abre de dépendances"
}
},
home: {
overview: {
title: "Vue d'ensemble"
},
watch: "Packages dans l'arbre de dépendance nécessitant une plus grande attention",
criticalWarnings: "Avertissements critiques",
maintainers: "Mainteneurs"
},
settings: {
general: {
title: "Général",
save: "sauvegarder",
defaultPannel: "Panneau par défaut",
warnings: "Avertissements à ignorer",
flags: "Drapeau (emojis) à ignorer"
},
shortcuts: {
title: "Raccourcis",
blockquote: "Cliquer sur le raccourci clavier pour mettre à jour",
goto: "Ouvrir",
openCloseWiki: "Ouverture/Fermeture du wiki"
}
}
};

export default { cli, ui };
21 changes: 19 additions & 2 deletions public/components/expandable/expandable.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
// Import Internal Dependencies
import { createDOMElement } from "../../common/utils";

// TODO: migrate this to ./i18n ?
const ki18nTranslaction = {
french: {
showMore: "voir plus",
showLess: "voir moins"
},
english: {
showMore: "show more",
showLess: "show less"
}
};

export function createExpandableSpan(
hideItemsLength,
onclick = () => void 0
) {
const detectedLang = document.getElementById("lang").dataset.lang;
const lang = detectedLang in ki18nTranslaction ? detectedLang : "english";

const span = createDOMElement("span", {
classList: ["expandable"],
attributes: { "data-value": "closed" },
childs: [
createDOMElement("i", { className: "icon-plus-squared-alt" }),
createDOMElement("p", { text: "show more" })
createDOMElement("p", { text: ki18nTranslaction[lang].showMore })
]
});
span.addEventListener("click", function itemListClickAction() {
Expand All @@ -20,7 +35,9 @@ export function createExpandableSpan(
innerI.classList.remove(isClosed ? "icon-plus-squared-alt" : "icon-minus-squared-alt");
innerI.classList.add(isClosed ? "icon-minus-squared-alt" : "icon-plus-squared-alt");
}
this.querySelector("p").textContent = isClosed ? "show less" : "show more";

this.querySelector("p").textContent = isClosed ?
ki18nTranslaction[lang].showLess : ki18nTranslaction[lang].showMore;
this.setAttribute("data-value", isClosed ? "opened" : "closed");

for (let id = 0; id < this.parentNode.childNodes.length; id++) {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ function assertScannerVersion(

if (!SemVer.satisfies(scannerVersion, kRequiredScannerRange)) {
const error = i18n.getTokenSync(
"localI18n.startHttp.invalidScannerVersion",
"cli.startHttp.invalidScannerVersion",
kleur.yellow(scannerVersion),
kleur.yellow(kRequiredScannerRange)
);
const regenerate = i18n.getTokenSync("localI18n.startHttp.regenerate");
const regenerate = i18n.getTokenSync("cli.startHttp.regenerate");

console.log(" > " + path.basename(dataFilePath));
console.log(" > " + kleur.red().bold(error));
Expand Down
4 changes: 3 additions & 1 deletion src/http-server/endpoints/root.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
const kProjectRootDir = join(__dirname, "..", "..", "..");

export async function buildHtml() {
await i18n.getLocalLang();
const i18nLangName = await i18n.getLocalLang();

const HTMLStr = await readFile(join(kProjectRootDir, "views", "index.html"), "utf-8");
const templateStr = zup(HTMLStr)({
lang: i18n.getTokenSync("lang"),
i18nLangName,
token: (tokenName) => i18n.getTokenSync(`ui.${tokenName}`)
});

Expand Down
10 changes: 7 additions & 3 deletions test/httpServer.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Import Node.js Dependencies
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { after, before, describe, test } from "node:test";
import { once } from "node:events";
import path from "node:path";
import os from "node:os";
import { after, before, describe, test } from "node:test";
import assert from "node:assert";
import { once } from "node:events";

// Import Third-party Dependencies
import { get, MockAgent, getGlobalDispatcher, setGlobalDispatcher } from "@myunisoft/httpie";
Expand Down Expand Up @@ -44,6 +44,9 @@ describe("httpServer", () => {
openLink: false
});
await once(httpServer.server, "listening");
await i18n.extendFromSystemPath(
path.join(__dirname, "..", "i18n")
);

enableDestroy(httpServer.server);
}, { timeout: 5000 });
Expand All @@ -55,14 +58,15 @@ describe("httpServer", () => {
});

test("'/' should return index.html content", async() => {
await i18n.getLocalLang();
const i18nLangName = await i18n.getLocalLang();
const result = await get(HTTP_URL);

assert.equal(result.statusCode, 200);
assert.equal(result.headers["content-type"], "text/html");

const templateStr = zup(INDEX_HTML)({
lang: i18n.getTokenSync("lang"),
i18nLangName,
token: (tokenName) => i18n.getTokenSync(`ui.${tokenName}`)
});
assert.equal(result.data, templateStr);
Expand Down
48 changes: 25 additions & 23 deletions views/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<script src="public/main.js" defer></script>
<title>NodeSecure</title>

<div id="lang" data-lang="[[=z.i18nLangName]]" style="display: none;"></div>

<main>
<nav>
<a class="nsecure-logo" href="https://github.com/NodeSecure" target="_blank" rel="noopener">
Expand Down Expand Up @@ -85,20 +87,20 @@
<div class="module">
<div class="title">
<i class="icon-eye"></i>
<p>Overview</p>
<p>[[=z.token('home.overview.title')]]</p>
</div>
<div class="content">
<div class="home--overview"></div>
</div>
<div class="content" id="homewatch">
<p>Packages in the dependency tree requiring greater attention</p>
<p>[[=z.token('home.watch')]]</p>
<div class="home--packages--overview"></div>
</div>
</div>
<div class="module" id="warnings-module">
<div class="title warning">
<i class="icon-warning"></i>
<p>Critical Warnings</p>
<p>[[=z.token('home.criticalWarnings')]]</p>
<span class="count">1</span>
</div>
<div class="content">
Expand All @@ -117,7 +119,7 @@
<div class="module">
<div class="title">
<i class="icon-users"></i>
<p>Authors</p>
<p>[[=z.token('home.maintainers')]]</p>
<span class="count" id="authors-count">0</span>
</div>
<div class="content">
Expand Down Expand Up @@ -150,21 +152,21 @@
</div>
</div>
<div id="settings--view" class="view hidden">
<h1><i class="icon-cog"></i>General</h1>
<h1><i class="icon-cog"></i>[[=z.token('settings.general.title')]]</h1>
<form>
<div class="line">
<label for="default_package_menu">Default Package Menu:</label>
<label for="default_package_menu">[[=z.token('settings.general.defaultPannel')]]:</label>
<select name="defaultPackageMenu" id="default_package_menu">
<option value="info">overview</option>
<option value="files">files</option>
<option value="dependencies">scripts & dependencies</option>
<option value="warnings">warnings</option>
<option value="vulnerabilities">vulnerabilities</option>
<option value="licenses" selected>licenses conformance</option>
<option value="info">[[=z.token('package_info.navigation.overview')]]</option>
<option value="files">[[=z.token('package_info.navigation.files')]]</option>
<option value="dependencies">[[=z.token('package_info.navigation.dependencies')]]</option>
<option value="warnings">[[=z.token('package_info.navigation.warnings')]]</option>
<option value="vulnerabilities">[[=z.token('package_info.navigation.vulnerabilities')]]</option>
<option value="licenses" selected>[[=z.token('package_info.navigation.licenses')]]</option>
</select>
</div>
<div class="line">
<p>SAST Warnings to ignore:</p>
<p>[[=z.token('settings.general.warnings')]]:</p>
<div>
<input type="checkbox" checked name="warnings" value="parsing-error" id="parsing-error">
<label for="parsing-error">parsing error</label>
Expand Down Expand Up @@ -219,7 +221,7 @@ <h1><i class="icon-cog"></i>General</h1>
</div>
</div>
<div class="line">
<p>Flags to ignore:</p>
<p>[[=z.token('settings.general.flags')]]:</p>
<div>
<input type="checkbox" name="flags" value="hasManyPublishers" id="hasManyPublishers">
<label for="hasManyPublishers">👥 hasManyPublishers</label>
Expand All @@ -246,26 +248,26 @@ <h1><i class="icon-cog"></i>General</h1>
</div>
</div>
</form>
<button class="save">save</button>
<button class="save">[[=z.token('settings.general.save')]]</button>
<div class="line">
<h2><i class="icon-keyboard"></i>Shortcuts</h2>
<h2><i class="icon-keyboard"></i>[[=z.token('settings.shortcuts.title')]]</h2>
<div class="shortcuts">
<div class="note">💡 Click on hotkey to update</div>
<div class="note">💡 [[=z.token('settings.shortcuts.blockquote')]]</div>
<div>
<input readonly id="home" class="hotkey">
<label for="home">Goto Home view</label>
<label for="home">[[=z.token('settings.shortcuts.goto')]] Home view</label>
</div>
<div>
<input readonly id="network" class="hotkey">
<label for="network">Goto Network view</label>
<label for="network">[[=z.token('settings.shortcuts.goto')]] Network view</label>
</div>
<div>
<input readonly id="settings" class="hotkey">
<label for="settings">Goto Settings view</label>
<label for="settings">[[=z.token('settings.shortcuts.goto')]] Settings view</label>
</div>
<div>
<input readonly id="wiki" class="hotkey">
<label for="wiki">Open/Close wiki</label>
<label for="wiki">[[=z.token('settings.shortcuts.openCloseWiki')]]</label>
</div>
</div>
</div>
Expand Down Expand Up @@ -313,7 +315,7 @@ <h2><i class="icon-keyboard"></i>Shortcuts</h2>
</div>
</div>
<div class="separator">
<p>packages in tree</p>
<p>[[=z.token('popup.maintainer.intree')]]</p>
</div>
<ul class="maintainers--packages"></ul>
</div>
Expand All @@ -333,7 +335,7 @@ <h2><i class="icon-keyboard"></i>Shortcuts</h2>
</div>

<div class="package-navigation">
<span class="container-title">overview</span>
<span class="container-title">[[=z.token('package_info.navigation.overview')]]</span>

<div class="active" data-menu="info" data-title="[[=z.token('package_info.navigation.overview')]]">
<i class="icon-cube"></i>
Expand Down