mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
chore(cli): replace ejs with native node template rendering (#12109)
* chore(cli): replace ejs with native node template rendering * chore(cli): add HTML escaping to audit, changelog, and licenses rendering functions * chore(cli): remove templates directory from dist script in package.json * chore(cli): remove node-fetch dependency from package.json
This commit is contained in:
@@ -17,14 +17,12 @@
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"develop": "tsc -p tsconfig.json --watch",
|
||||
"dist": "rm -rf ../../dist/libs/cli && npm run build && cp -R ./bin ../../dist/libs/cli && cp -R ./resources ../../dist/libs/cli && cp -R ./templates ../../dist/libs/cli && cp ./package.json ../../dist/libs/cli",
|
||||
"dist": "rm -rf ../../dist/libs/cli && npm run build && cp -R ./bin ../../dist/libs/cli && cp -R ./resources ../../dist/libs/cli && cp ./package.json ../../dist/libs/cli",
|
||||
"link": "npm run dist && cd ../../dist/libs/cli && npm link",
|
||||
"unlink": "cd ../../dist/libs/cli && npm unlink"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alfresco/js-api": ">=10.0.0",
|
||||
"ejs": "^3.1.10",
|
||||
"node-fetch": "^2.7.0",
|
||||
"spdx-license-list": "^5.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
@@ -32,7 +30,6 @@
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/ejs": "^3.1.2",
|
||||
"@types/node": "^20.1.7",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
|
||||
+47
-29
@@ -18,17 +18,56 @@
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import * as ejs from 'ejs';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { argv, exit } from 'node:process';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { escapeHtml } from './utils';
|
||||
|
||||
interface AuditCommandArgs {
|
||||
package?: string;
|
||||
outDir?: string;
|
||||
}
|
||||
|
||||
function renderAuditPage(jsonAudit: any, projName: string, projVersion: string): string {
|
||||
const rows: string[] = [];
|
||||
if (jsonAudit.auditReportVersion >= 2) {
|
||||
for (const key in jsonAudit.vulnerabilities) {
|
||||
const v = jsonAudit.vulnerabilities[key];
|
||||
rows.push(`|${escapeHtml(v.severity)} | ${escapeHtml(v.name)} | ${JSON.stringify(v.range)} |`);
|
||||
}
|
||||
} else {
|
||||
for (const key in jsonAudit.advisories) {
|
||||
const a = jsonAudit.advisories[key];
|
||||
rows.push(`|${escapeHtml(a.severity)} | ${escapeHtml(a.module_name)} | ${JSON.stringify(a.vulnerable_versions)} |`);
|
||||
}
|
||||
}
|
||||
|
||||
return `---
|
||||
Title: Audit info, ${escapeHtml(projName)} ${escapeHtml(projVersion)}
|
||||
---
|
||||
|
||||
# Audit information for ${escapeHtml(projName)} ${escapeHtml(projVersion)}
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: ${jsonAudit.metadata.vulnerabilities.critical}
|
||||
- High risk: ${jsonAudit.metadata.vulnerabilities.high}
|
||||
- Moderate risk: ${jsonAudit.metadata.vulnerabilities.moderate}
|
||||
- Low risk: ${jsonAudit.metadata.vulnerabilities.low}
|
||||
|
||||
Dependencies analyzed: ${jsonAudit.metadata.totalDependencies}
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
${rows.join('\n')}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audit report command
|
||||
*
|
||||
@@ -82,12 +121,6 @@ Options:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const templatePath = path.resolve(__dirname, '../templates/auditPage.ejs');
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
console.error(`Cannot find the report template: ${templatePath}`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Running audit on ${packagePath}`);
|
||||
@@ -133,29 +166,14 @@ Options:
|
||||
return;
|
||||
}
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
{
|
||||
jsonAudit,
|
||||
projVersion: packageJson.version,
|
||||
projName: packageJson.name
|
||||
},
|
||||
{},
|
||||
(err: any, mdText: string) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
} else {
|
||||
const outputPath = path.resolve(options.outDir || workingDir);
|
||||
const outputFile = path.join(outputPath, `audit-info-${packageJson.version}.md`);
|
||||
const mdText = renderAuditPage(jsonAudit, packageJson.name, packageJson.version);
|
||||
const outputPath = path.resolve(options.outDir || workingDir);
|
||||
const outputFile = path.join(outputPath, `audit-info-${packageJson.version}.md`);
|
||||
|
||||
fs.writeFileSync(outputFile, mdText);
|
||||
fs.writeFileSync(outputFile, mdText);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Report saved as ${outputFile}`);
|
||||
resolve(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Report saved as ${outputFile}`);
|
||||
resolve(0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import { spawnSync } from 'node:child_process';
|
||||
import * as path from 'path';
|
||||
import { logger } from './logger';
|
||||
import * as fs from 'fs';
|
||||
import * as ejs from 'ejs';
|
||||
import { escapeHtml } from './utils';
|
||||
|
||||
interface Commit {
|
||||
hash: string;
|
||||
@@ -167,6 +167,39 @@ function commitAuthorAllowed(commit: Commit, authorFilter: string): boolean {
|
||||
return !(filterRegex.test(commit.author) || filterRegex.test(commit.author_email));
|
||||
}
|
||||
|
||||
function renderChangelogMd(commits: Commit[], projName: string, projVersion: string, repoUrl: string): string {
|
||||
const lines = commits.map((c) => `- [${c.hash}](${repoUrl}/commit/${c.hash}) ${escapeHtml(c.subject)}`);
|
||||
return `---
|
||||
Title: Changelog for ${escapeHtml(projName)} v${escapeHtml(projVersion)}
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
${lines.join('\n')}
|
||||
`;
|
||||
}
|
||||
|
||||
function renderChangelogHtml(commits: Commit[], projName: string, projVersion: string, repoUrl: string): string {
|
||||
const items = commits
|
||||
.map((c) => ` <li>\n <a href="${repoUrl}/commit/${c.hash}">[${c.hash}]</a> ${escapeHtml(c.subject)}\n </li>`)
|
||||
.join('\n');
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Changelog for ${escapeHtml(projName)} v${escapeHtml(projVersion)}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Changelog</h1>
|
||||
<ul>
|
||||
${items}
|
||||
</ul>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changelog command
|
||||
*
|
||||
@@ -265,42 +298,23 @@ Options:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const templatePath = path.resolve(__dirname, `../templates/changelog-${format}.ejs`);
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
console.error(`Cannot find the report template: ${templatePath}`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath).toString());
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
{
|
||||
remote,
|
||||
repo_url,
|
||||
commits,
|
||||
projVersion: packageJson.version,
|
||||
projName: packageJson.name
|
||||
},
|
||||
{},
|
||||
(err: any, text: string) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
} else {
|
||||
if (output) {
|
||||
const outputDir = path.resolve(output);
|
||||
const outputFile = path.join(outputDir, `changelog-${packageJson.version}.${format}`);
|
||||
console.log('Writing changelog to', outputFile);
|
||||
const text =
|
||||
format === 'html'
|
||||
? renderChangelogHtml(commits, packageJson.name, packageJson.version, repo_url)
|
||||
: renderChangelogMd(commits, packageJson.name, packageJson.version, repo_url);
|
||||
|
||||
fs.writeFileSync(outputFile, text);
|
||||
} else {
|
||||
console.log(text);
|
||||
}
|
||||
resolve(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (output) {
|
||||
const outputDir = path.resolve(output);
|
||||
const outputFile = path.join(outputDir, `changelog-${packageJson.version}.${format}`);
|
||||
console.log('Writing changelog to', outputFile);
|
||||
|
||||
fs.writeFileSync(outputFile, text);
|
||||
} else {
|
||||
console.log(text);
|
||||
}
|
||||
resolve(0);
|
||||
});
|
||||
}
|
||||
|
||||
+34
-29
@@ -22,7 +22,7 @@ import { parseArgs } from 'node:util';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as licenseList from 'spdx-license-list';
|
||||
import * as ejs from 'ejs';
|
||||
import { escapeHtml } from './utils';
|
||||
|
||||
const { collectProductionLicenses } = require('../resources/license-collector.cjs');
|
||||
|
||||
@@ -112,6 +112,32 @@ function toLinkedLicenseExpression(rawExpression: string): string {
|
||||
});
|
||||
}
|
||||
|
||||
function renderLicensePage(filteredPackages: Record<string, PackageInfoWithMetadata>, projName: string, projVersion: string): string {
|
||||
const rows = Object.entries(filteredPackages).map(([packageName, pack]) => {
|
||||
const lastAtSignPos = packageName.lastIndexOf('@');
|
||||
const name = packageName.substring(0, lastAtSignPos);
|
||||
const version = packageName.substring(lastAtSignPos + 1);
|
||||
const licenses = escapeHtml(pack.licenseExp || 'N/A');
|
||||
const linkedName = pack.repository ? `[${escapeHtml(name)}](${pack.repository})` : escapeHtml(name);
|
||||
return `| ${linkedName} | ${escapeHtml(version)} | ${licenses} |`;
|
||||
});
|
||||
|
||||
return `---
|
||||
Title: License info, ${escapeHtml(projName)} ${escapeHtml(projVersion)}
|
||||
---
|
||||
|
||||
# License information for ${escapeHtml(projName)} ${escapeHtml(projVersion)}
|
||||
|
||||
This page lists all third party libraries the project depends on.
|
||||
|
||||
## Libraries
|
||||
|
||||
| Name | Version | License |
|
||||
| --- | --- | --- |
|
||||
${rows.join('\n')}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Licenses command
|
||||
*
|
||||
@@ -165,12 +191,6 @@ Options:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const templatePath = path.resolve(__dirname, '../templates/licensePage.ejs');
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
console.error(`Cannot find the report template: ${templatePath}`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(`Checking ${packagePath}`);
|
||||
@@ -198,28 +218,13 @@ Options:
|
||||
|
||||
const packageJson: PackageInfo = getPackageFile(packagePath);
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
{
|
||||
filteredPackages,
|
||||
projVersion: packageJson.version,
|
||||
projName: packageJson.name
|
||||
},
|
||||
{},
|
||||
(ejsError: unknown, mdText: string) => {
|
||||
if (ejsError) {
|
||||
console.error(ejsError);
|
||||
reject(ejsError);
|
||||
} else {
|
||||
const outputPath = path.resolve(options.outDir || workingDir);
|
||||
const outputFile = path.join(outputPath, `license-info-${packageJson.version}.md`);
|
||||
const mdText = renderLicensePage(filteredPackages, packageJson.name, packageJson.version);
|
||||
const outputPath = path.resolve(options.outDir || workingDir);
|
||||
const outputFile = path.join(outputPath, `license-info-${packageJson.version}.md`);
|
||||
|
||||
fs.writeFileSync(outputFile, mdText);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Report saved as ${outputFile}`);
|
||||
resolve(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
fs.writeFileSync(outputFile, mdText);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Report saved as ${outputFile}`);
|
||||
resolve(0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2026 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export function escapeHtml(text: string): string {
|
||||
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
Title: Audit info, <%= projName %> <%= projVersion %>
|
||||
---
|
||||
|
||||
# Audit information for <%= projName %> <%= projVersion %>
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: <%= jsonAudit.metadata.vulnerabilities.critical %>
|
||||
- High risk: <%= jsonAudit.metadata.vulnerabilities.high %>
|
||||
- Moderate risk: <%= jsonAudit.metadata.vulnerabilities.moderate %>
|
||||
- Low risk: <%= jsonAudit.metadata.vulnerabilities.low %>
|
||||
|
||||
Dependencies analyzed: <%= jsonAudit.metadata.totalDependencies %>
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
<% if(jsonAudit.auditReportVersion >= 2) {
|
||||
for(var currentVulnerabilities in jsonAudit.vulnerabilities) {
|
||||
severity = jsonAudit.vulnerabilities[currentVulnerabilities].severity;
|
||||
vulnerable_versions = JSON.stringify(jsonAudit.vulnerabilities[currentVulnerabilities].range);
|
||||
module = jsonAudit.vulnerabilities[currentVulnerabilities].name;
|
||||
-%>
|
||||
|<%= severity %> | <%= module %> | <%= vulnerable_versions %> |
|
||||
<% } %>
|
||||
<% } else {
|
||||
for(var currentAdvisories in jsonAudit.advisories) {
|
||||
severity = jsonAudit.advisories[currentAdvisories].severity;
|
||||
vulnerable_versions = JSON.stringify(jsonAudit.advisories[currentAdvisories].vulnerable_versions);
|
||||
module = jsonAudit.advisories[currentAdvisories].module_name;
|
||||
-%>
|
||||
|<%= severity %> | <%= module %> | <%= vulnerable_versions %> |
|
||||
<% } %>
|
||||
<% } %>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Changelog for <%= projName %> v<%= projVersion %></title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Changelog</h1>
|
||||
<ul>
|
||||
<% for(var idx in commits) {
|
||||
commit = commits[idx];
|
||||
-%>
|
||||
<li>
|
||||
<a href="<%= repo_url %>/commit/<%= commit.hash %>">[<%= commit.hash %>]</a> <%= commit.subject %>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
Title: Changelog for <%= projName %> v<%= projVersion %>
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
<% for(var idx in commits) {
|
||||
commit = commits[idx];
|
||||
-%>
|
||||
- [<%= commit.hash %>](<%= repo_url %>/commit/<%= commit.hash %>) <%= commit.subject %>
|
||||
<% } %>
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
Title: License info, <%= projName %> <%= projVersion %>
|
||||
---
|
||||
|
||||
# License information for <%= projName %> <%= projVersion %>
|
||||
|
||||
This page lists all third party libraries the project depends on.
|
||||
|
||||
## Libraries
|
||||
|
||||
| Name | Version | License |
|
||||
| --- | --- | --- |
|
||||
<% for (var packageName in filteredPackages) {
|
||||
var lastAtSignPos = packageName.lastIndexOf('@');
|
||||
|
||||
var name = packageName.substring(0, lastAtSignPos);
|
||||
var version = packageName.substring(lastAtSignPos + 1);
|
||||
var pack = filteredPackages[packageName];
|
||||
var licenses = pack['licenseExp'] || 'N/A';
|
||||
var repo = pack['repository'];
|
||||
var linkedName = name;
|
||||
|
||||
if (repo) {
|
||||
linkedName = `[${name}](${repo})`
|
||||
}
|
||||
-%>
|
||||
| <%= linkedName %> | <%= version %> | <%= licenses %> |
|
||||
<% } %>
|
||||
@@ -93,7 +93,6 @@
|
||||
"@schematics/angular": "20.3.32",
|
||||
"@storybook/addon-themes": "10.4.0",
|
||||
"@storybook/angular": "10.4.0",
|
||||
"@types/ejs": "3.1.5",
|
||||
"@types/jasmine": "4.0.3",
|
||||
"@types/jasminewd2": "2.0.13",
|
||||
"@types/minimatch": "5.1.2",
|
||||
@@ -105,7 +104,6 @@
|
||||
"@typescript-eslint/utils": "8.59.4",
|
||||
"ajv": "8.20.0",
|
||||
"dotenv": "16.4.7",
|
||||
"ejs": "3.1.10",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-ban": "2.0.0",
|
||||
|
||||
Generated
+1066
-1036
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user