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:
Denys Vuika
2026-07-30 13:22:47 +01:00
committed by GitHub
parent 4f32198afd
commit 0c099eafb0
11 changed files with 1217 additions and 1233 deletions
+34 -29
View File
@@ -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);
});
}