Additional improvements to license notice formatting
This commit is contained in:
parent
fc7d3aa457
commit
b60091b6f8
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="menu-bar-input">
|
<div class="menu-bar-input">
|
||||||
<div class="entry-container">
|
<div class="entry-container">
|
||||||
<div @click="() => window.open('https://www.graphite.design', '_blank')" class="entry">
|
<div @click="visitWebsite('https://www.graphite.design')" class="entry">
|
||||||
<IconLabel :icon="'GraphiteLogo'" />
|
<IconLabel :icon="'GraphiteLogo'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -174,6 +174,10 @@ export default defineComponent({
|
||||||
if (menuEntry.ref) menuEntry.ref.setOpen();
|
if (menuEntry.ref) menuEntry.ref.setOpen();
|
||||||
else throw new Error("The menu bar floating menu has no associated ref");
|
else throw new Error("The menu bar floating menu has no associated ref");
|
||||||
},
|
},
|
||||||
|
visitWebsite(url: string) {
|
||||||
|
// This method is required because `window` isn't accessible from the Vue component HTML
|
||||||
|
window.open(url, "_blank");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ module.exports = {
|
||||||
|
|
||||||
function formatThirdPartyLicenses(jsLicenses) {
|
function formatThirdPartyLicenses(jsLicenses) {
|
||||||
// Remove the HTML character encoding caused by Handlebars
|
// Remove the HTML character encoding caused by Handlebars
|
||||||
const licenses = rustLicenses.map((rustLicense) => ({
|
let licenses = rustLicenses.map((rustLicense) => ({
|
||||||
licenseName: htmlDecode(rustLicense.licenseName),
|
licenseName: htmlDecode(rustLicense.licenseName),
|
||||||
licenseText: htmlDecode(rustLicense.licenseText),
|
licenseText: trimBlankLines(htmlDecode(rustLicense.licenseText)),
|
||||||
packages: rustLicense.packages.map((package) => ({
|
packages: rustLicense.packages.map((package) => ({
|
||||||
name: htmlDecode(package.name),
|
name: htmlDecode(package.name),
|
||||||
version: htmlDecode(package.version),
|
version: htmlDecode(package.version),
|
||||||
|
|
@ -90,14 +90,32 @@ function formatThirdPartyLicenses(jsLicenses) {
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// De-duplicate any licenses with the same text by merging their lists of packages
|
||||||
|
licenses.forEach((license, licenseIndex) => {
|
||||||
|
licenses.slice(0, licenseIndex).forEach((comparisonLicense) => {
|
||||||
|
if (license.licenseText === comparisonLicense.licenseText) {
|
||||||
|
license.packages.push(...comparisonLicense.packages);
|
||||||
|
comparisonLicense.packages = [];
|
||||||
|
// After emptying the packages, the redundant license with no packages will be removed in the next step's `filter()`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete the internal Graphite crates, which are not third-party and belong elsewhere
|
||||||
|
licenses = licenses.filter((license) => {
|
||||||
|
license.packages = license.packages.filter((package) => !(package.repository && package.repository.includes("github.com/GraphiteEditor/Graphite")));
|
||||||
|
return license.packages.length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
// Augment the imported Rust license list with the provided JS license list
|
// Augment the imported Rust license list with the provided JS license list
|
||||||
jsLicenses.dependencies.forEach((jsLicense) => {
|
jsLicenses.dependencies.forEach((jsLicense) => {
|
||||||
const { name, version, author, repository, licenseName, licenseText } = jsLicense;
|
const { name, version, author, repository, licenseName } = jsLicense;
|
||||||
|
const licenseText = trimBlankLines(jsLicense.licenseText);
|
||||||
|
|
||||||
// Remove the `git+` or `git://` prefix and `.git` suffix
|
// Remove the `git+` or `git://` prefix and `.git` suffix
|
||||||
const repo = repository ? repository.replace(/^.*(github.com\/.*?\/.*?)(?:.git)/, "https://$1") : repository;
|
const repo = repository ? repository.replace(/^.*(github.com\/.*?\/.*?)(?:.git)/, "https://$1") : repository;
|
||||||
|
|
||||||
const matchedLicense = licenses.find((license) => license.licenseName.trim() === licenseName.trim() && license.licenseText.trim() === licenseText.trim());
|
const matchedLicense = licenses.find((license) => trimBlankLines(license.licenseText) === licenseText);
|
||||||
|
|
||||||
const packages = { name, version, author, repository: repo };
|
const packages = { name, version, author, repository: repo };
|
||||||
if (matchedLicense) matchedLicense.packages.push(packages);
|
if (matchedLicense) matchedLicense.packages.push(packages);
|
||||||
|
|
@ -106,12 +124,13 @@ function formatThirdPartyLicenses(jsLicenses) {
|
||||||
|
|
||||||
// Sort the licenses, and the packages using each license, alphabetically
|
// Sort the licenses, and the packages using each license, alphabetically
|
||||||
licenses.sort((a, b) => a.licenseName.localeCompare(b.licenseName));
|
licenses.sort((a, b) => a.licenseName.localeCompare(b.licenseName));
|
||||||
|
licenses.sort((a, b) => a.licenseText.localeCompare(b.licenseText));
|
||||||
licenses.forEach((license) => {
|
licenses.forEach((license) => {
|
||||||
license.packages.sort((a, b) => a.name.localeCompare(b.name));
|
license.packages.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generate the formatted text file
|
// Generate the formatted text file
|
||||||
let formattedLicenseNotice = "THIRD-PARTY SOFTWARE LICENSE NOTICES\n\n";
|
let formattedLicenseNotice = "GRAPHITE THIRD-PARTY SOFTWARE LICENSE NOTICES\n\n";
|
||||||
if (debugMode) formattedLicenseNotice += "WARNING: Licenses for Rust packages are excluded in debug mode to improve performance — do not release without their inclusion!\n\n";
|
if (debugMode) formattedLicenseNotice += "WARNING: Licenses for Rust packages are excluded in debug mode to improve performance — do not release without their inclusion!\n\n";
|
||||||
|
|
||||||
licenses.forEach((license) => {
|
licenses.forEach((license) => {
|
||||||
|
|
@ -120,12 +139,15 @@ function formatThirdPartyLicenses(jsLicenses) {
|
||||||
const { name, version, author, repository } = package;
|
const { name, version, author, repository } = package;
|
||||||
packagesWithSameLicense += `${name} ${version}${author ? ` - ${author}` : ""}${repository ? ` - ${repository}` : ""}\n`;
|
packagesWithSameLicense += `${name} ${version}${author ? ` - ${author}` : ""}${repository ? ` - ${repository}` : ""}\n`;
|
||||||
});
|
});
|
||||||
|
packagesWithSameLicense = packagesWithSameLicense.trim();
|
||||||
|
const packagesLineLength = Math.max(...packagesWithSameLicense.split("\n").map((line) => line.length));
|
||||||
|
|
||||||
formattedLicenseNotice += `--------------------------------------------------------------------------------
|
formattedLicenseNotice += `--------------------------------------------------------------------------------
|
||||||
|
|
||||||
The following packages are licensed under the terms of the ${license.licenseName} license:
|
The following packages are licensed under the terms of the ${license.licenseName} license as printed beneath:
|
||||||
|
${"_".repeat(packagesLineLength)}
|
||||||
${packagesWithSameLicense}
|
${packagesWithSameLicense}
|
||||||
|
${"‾".repeat(packagesLineLength)}
|
||||||
${license.licenseText}
|
${license.licenseText}
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
@ -137,6 +159,9 @@ ${license.licenseText}
|
||||||
return formattedLicenseNotice;
|
return formattedLicenseNotice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function htmlDecode(input) {
|
||||||
|
if (!input) return input;
|
||||||
|
|
||||||
const htmlEntities = {
|
const htmlEntities = {
|
||||||
nbsp: " ",
|
nbsp: " ",
|
||||||
copy: "©",
|
copy: "©",
|
||||||
|
|
@ -149,10 +174,7 @@ const htmlEntities = {
|
||||||
quot: '"',
|
quot: '"',
|
||||||
};
|
};
|
||||||
|
|
||||||
function htmlDecode(str) {
|
return input.replace(/&([^;]+);/g, (entity, entityCode) => {
|
||||||
if (!str) return str;
|
|
||||||
|
|
||||||
return str.replace(/&([^;]+);/g, (entity, entityCode) => {
|
|
||||||
let match;
|
let match;
|
||||||
|
|
||||||
if (entityCode in htmlEntities) {
|
if (entityCode in htmlEntities) {
|
||||||
|
|
@ -170,3 +192,16 @@ function htmlDecode(str) {
|
||||||
return entity;
|
return entity;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function trimBlankLines(input) {
|
||||||
|
let result = input.replace(/\r/g, "");
|
||||||
|
|
||||||
|
while (result.charAt(0) === "\r" || result.charAt(0) === "\n") {
|
||||||
|
result = result.slice(1);
|
||||||
|
}
|
||||||
|
while (result.slice(-1) === "\r" || result.slice(-1) === "\n") {
|
||||||
|
result = result.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ name = "graphite-proc-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Graphite Authors <contact@graphite.design>"]
|
authors = ["Graphite Authors <contact@graphite.design>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
readme = "../README.md"
|
||||||
|
homepage = "https://www.graphite.design"
|
||||||
|
repository = "https://github.com/GraphiteEditor/Graphite"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue