Skip to content

Commit

Permalink
Improve third-party licenses generation.
Browse files Browse the repository at this point in the history
• Show module version next to its name.
• Generate links to the NPM based on module versions.
• Show module description on hover.
• Update `package.json` proxy to support `description` property.
• Move `sanitizeConfig` to `global.ts`.
• Import types with `import type` instead of `import` in `settings.ts`.
• Update some comments in code.
  • Loading branch information
SpacingBat3 committed May 29, 2022
1 parent 4249b9b commit 0b855dd
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 21 deletions.
4 changes: 4 additions & 0 deletions sources/assets/web/css/about.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ h1 ~ h2 {
}
#licenses h3 {
color: var(--color-link);
vertical-align: bottom;
}
#licenses h3 > small {
font-size: calc(var(--font-size-factor) * 0.8);
}
hr {
width: calc(100% - 4px);
Expand Down
18 changes: 15 additions & 3 deletions sources/code/common/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ export const discordFavicons = {
/**
* Allowed protocol list.
*
* For security reasons, `shell.openExternal()` should not be used for any type
* of the link, as this may allow potential attackers to compromise host or even
* execute arbitary commands.
* For security reasons, `shell.openExternal()` should not be used for every
* link protocol handling, as this may allow potential attackers to compromise
* host or even execute arbitary commands.
*
* This way, we can also force the usage of the secure links variants where
* applicable and block *insecure* and unencrypted protocols.
Expand Down Expand Up @@ -219,4 +219,16 @@ export type SessionLatest = Electron.Session & {
* range `>=14.1.0 && <15.0.0 || >=15.1.0`.
*/
setDevicePermissionHandler: (handler: (()=>boolean)|null)=>void;
}


/**
* A sanitizer configuration that allows only for tags that modifies the code
* formatting.
*/
export const sanitizeConfig = {
// Allow tags that modifies text style and/or has a semantic meaning.
ALLOWED_TAGS: ['b', 'i', 'u', 's', 'em', 'kbd', 'strong', 'code', 'small'],
// Block every attribute
ALLOWED_ATTR: []
}
10 changes: 6 additions & 4 deletions sources/code/common/modules/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ export type PersonLike = string | PersonObject
export interface PackageJsonProperties {
/** Node.js-friendly application name. */
name: string,
/** Application version. */
/** Node package description. */
description: string,
/** Node package version, must be parsable by `semver`. */
version: string,
/** Application author. */
/** Node package author. */
author?: PersonLike,
/** Application license. */
license: string,
Expand Down Expand Up @@ -143,8 +145,8 @@ export class PackageJSON<T extends Array<keyof PackageJsonProperties>> {
if (!this.isPerson((object as PackageJsonProperties).author))
return "Author field is of invalid type.";

// Check 4: 'name', 'license' and 'homepage' are strings.
for (const stringKey of ['name', 'license'])
// Check 4: 'name', 'description' and 'license' are strings.
for (const stringKey of ['name', 'description', 'license'])
if (typeof ((object as { [key: string]: string; })[stringKey]) !== 'string')
return "'"+stringKey+"' is not assignable to type 'string'.";

Expand Down
17 changes: 11 additions & 6 deletions sources/code/renderer/preload/about.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ipcRenderer as ipc } from "electron/renderer";
import { buildInfo, getAppIcon } from "../../common/global";
import { buildInfo, getAppIcon, sanitizeConfig } from "../../common/global";
import { getAppPath } from "../../common/modules/electron";
import { resolve } from "path";
import L10N from "../../common/modules/l10n";
import packageJson, { PackageJSON, Person } from "../../common/modules/package";
import { createHash } from "crypto";
import { sanitize } from "dompurify";

/**
* Fetches user avatar by making the requests to both GitHub and Gravatar
Expand Down Expand Up @@ -159,18 +160,22 @@ function generateLicenseContent(l10n:L10N["web"]["aboutWindow"], name:string) {
for (const packName in packageJson.data.dependencies) {
if(packName.startsWith('@spacingbat3/')) continue;
const {data} = new PackageJSON(
["author", "license"],
["author", "license", "version", "description"],
resolve(getAppPath(), "node_modules/"+packName+"/package.json")
)
const npmLink = document.createElement("a");
const title = document.createElement("h3");
const copy = document.createElement("p");
npmLink.href = "https://www.npmjs.com/package/"+packName;
npmLink.title = data.description.match(/^[^.]*\.?/)?.[0] ?? "";
npmLink.href = "https://www.npmjs.com/package/"+packName+"/v/"+data.version;
npmLink.relList.add("noreferrer");
npmLink.target = "_blank";
title.innerText = packName;
copy.innerText = "© " +
new Person(data.author ?? '"'+l10n.licenses.packageAuthors.replace("%s", packName)+'"').name + " " + l10n.licenses.licensedUnder.replace("%s",data.license)
title.innerHTML = sanitize(packName+" <small>v"+data.version+"</small>", sanitizeConfig);
copy.innerHTML = sanitize("© " +
new Person(data.author ?? '"'+l10n.licenses.packageAuthors
.replace("%s", packName)+'"').name + " " +
l10n.licenses.licensedUnder.replace("%s","<code>"+data.license+"</code>")
, sanitizeConfig)
npmLink.appendChild(title);
document.getElementById("licenses")?.appendChild(npmLink);
document.getElementById("licenses")?.appendChild(copy);
Expand Down
10 changes: 2 additions & 8 deletions sources/code/renderer/preload/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@
* @todo: Implement script inside WebCord
*/
import { ipcRenderer } from "electron/renderer";
import { HTMLChecklistForms, HTMLRadioCustom, HTMLRadioForms, HTMLRadioOption, HTMLSettingsGroup, wLog } from "../../common/global";
import type { HTMLChecklistForms, HTMLRadioCustom, HTMLRadioForms, HTMLRadioOption, HTMLSettingsGroup } from "../../common/global";
import { wLog, sanitizeConfig } from "../../common/global";
import { sanitize } from 'dompurify';

function isChecklistForms(arg: HTMLRadioForms|HTMLChecklistForms|HTMLRadioCustom):arg is HTMLChecklistForms {
return (arg as unknown as HTMLChecklistForms).id !== undefined
}

const sanitizeConfig = {
// Allow tags that modifies text style and/or has a semantic meaning.
ALLOWED_TAGS: ['b', 'i', 'u', 's', 'em', 'kbd', 'strong', 'code'],
// Block every attribute
ALLOWED_ATTR: []
}

function fetchFromWebsite(this: HTMLInputElement) {

const dotArray = this.name.split('.');
Expand Down

0 comments on commit 0b855dd

Please sign in to comment.