📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -1,11 +1,30 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import sanitizeFilename from 'sanitize-filename';
|
||||
import { getSeoLandingPaths } from './generate-sitemap.js';
|
||||
|
||||
const APP_ROOT_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const REPO_ROOT_DIR = path.resolve(APP_ROOT_DIR, '..', '..');
|
||||
|
||||
function safeUserPath(pathValue, baseDir = process.cwd()) {
|
||||
const basePath = path.resolve(baseDir);
|
||||
const resolvedPath = path.resolve(basePath, String(pathValue ?? ''));
|
||||
const relativePath = path.relative(basePath, resolvedPath);
|
||||
if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
|
||||
throw new Error(`Path escapes allowed directory: ${pathValue}`);
|
||||
}
|
||||
const sanitizedSegments = [];
|
||||
for (const segment of relativePath.split(path.sep).filter(Boolean)) {
|
||||
const sanitizedSegment = sanitizeFilename(segment);
|
||||
if (sanitizedSegment !== segment || !sanitizedSegment) {
|
||||
throw new Error(`Unsafe path segment: ${segment}`);
|
||||
}
|
||||
sanitizedSegments.push(sanitizedSegment);
|
||||
}
|
||||
return path.resolve(basePath, ...sanitizedSegments);
|
||||
}
|
||||
|
||||
export function extractSitemapLocations(xmlText) {
|
||||
const raw = String(xmlText ?? '');
|
||||
const matches = raw.matchAll(/<loc>(.*?)<\/loc>/g);
|
||||
@@ -46,62 +65,63 @@ function parseCliArgs(argv) {
|
||||
if (arg === '--artifacts-dir') {
|
||||
const value = argv[i + 1];
|
||||
if (value) {
|
||||
args.sitemapPath = path.join(value, 'sitemap.xml');
|
||||
args.robotsPath = path.join(value, 'robots.txt');
|
||||
args.llmsPath = path.join(value, 'llms.txt');
|
||||
args.manifestPath = path.join(value, 'site.webmanifest');
|
||||
args.indexPath = path.join(value, 'index.html');
|
||||
args.socialImagePath = path.join(value, 'social-card.svg');
|
||||
args.distDir = value;
|
||||
const artifactsDir = safeUserPath(value);
|
||||
args.sitemapPath = path.join(artifactsDir, 'sitemap.xml');
|
||||
args.robotsPath = path.join(artifactsDir, 'robots.txt');
|
||||
args.llmsPath = path.join(artifactsDir, 'llms.txt');
|
||||
args.manifestPath = path.join(artifactsDir, 'site.webmanifest');
|
||||
args.indexPath = path.join(artifactsDir, 'index.html');
|
||||
args.socialImagePath = path.join(artifactsDir, 'social-card.svg');
|
||||
args.distDir = artifactsDir;
|
||||
i += 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--dist-dir' && argv[i + 1]) {
|
||||
args.distDir = argv[i + 1];
|
||||
args.distDir = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--sitemap' && argv[i + 1]) {
|
||||
args.sitemapPath = argv[i + 1];
|
||||
args.sitemapPath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--robots' && argv[i + 1]) {
|
||||
args.robotsPath = argv[i + 1];
|
||||
args.robotsPath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--llms' && argv[i + 1]) {
|
||||
args.llmsPath = argv[i + 1];
|
||||
args.llmsPath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--manifest' && argv[i + 1]) {
|
||||
args.manifestPath = argv[i + 1];
|
||||
args.manifestPath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--index' && argv[i + 1]) {
|
||||
args.indexPath = argv[i + 1];
|
||||
args.indexPath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--source-index' && argv[i + 1]) {
|
||||
args.sourceIndexPath = argv[i + 1];
|
||||
args.sourceIndexPath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--social-image' && argv[i + 1]) {
|
||||
args.socialImagePath = argv[i + 1];
|
||||
args.socialImagePath = safeUserPath(argv[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -121,7 +141,7 @@ function parseCliArgs(argv) {
|
||||
}
|
||||
|
||||
function getPackageReleaseLabel() {
|
||||
const raw = readFile(path.join(REPO_ROOT_DIR, 'package.json'));
|
||||
const raw = readFile(path.join(REPO_ROOT_DIR, 'package.json'), REPO_ROOT_DIR);
|
||||
const pkg = JSON.parse(raw);
|
||||
assert(typeof pkg.version === 'string' && pkg.version.trim(), 'Root package.json must define version.');
|
||||
return `V${pkg.version.trim()}`;
|
||||
@@ -326,7 +346,7 @@ export function assertIndexSocialMeta(htmlText) {
|
||||
|
||||
function readSkillCountLabel(distDir) {
|
||||
try {
|
||||
const skills = JSON.parse(readFile(path.join(distDir, 'skills.json')));
|
||||
const skills = JSON.parse(readFile(path.join(distDir, 'skills.json'), distDir));
|
||||
if (Array.isArray(skills) && skills.length > 0) {
|
||||
return `${skills.length.toLocaleString('en-US')}+`;
|
||||
}
|
||||
@@ -453,36 +473,36 @@ function routePathToDistFile(routePath, normalizedRootPath) {
|
||||
export function assertPrerenderedSkillRoutes(skillUrls, distDir = 'dist', normalizedRootPath = '') {
|
||||
for (const skillUrl of skillUrls) {
|
||||
const parsed = new URL(skillUrl);
|
||||
const filePath = path.join(distDir, routePathToDistFile(parsed.pathname, normalizedRootPath));
|
||||
const filePath = safeUserPath(routePathToDistFile(parsed.pathname, normalizedRootPath), distDir);
|
||||
assert(
|
||||
fs.existsSync(filePath),
|
||||
`Missing prerendered page for skill route: ${parsed.pathname}. Expected ${filePath}.`,
|
||||
);
|
||||
assertStaticRelatedTopicLinks(readFile(filePath), 'Skill');
|
||||
assertStaticRelatedTopicLinks(readFile(filePath, distDir), 'Skill');
|
||||
}
|
||||
}
|
||||
|
||||
export function assertPrerenderedPluginRoutes(pluginUrls, distDir = 'dist', normalizedRootPath = '') {
|
||||
for (const pluginUrl of pluginUrls) {
|
||||
const parsed = new URL(pluginUrl);
|
||||
const filePath = path.join(distDir, routePathToDistFile(parsed.pathname, normalizedRootPath));
|
||||
const filePath = safeUserPath(routePathToDistFile(parsed.pathname, normalizedRootPath), distDir);
|
||||
assert(
|
||||
fs.existsSync(filePath),
|
||||
`Missing prerendered page for plugin route: ${parsed.pathname}. Expected ${filePath}.`,
|
||||
);
|
||||
assertPluginsDiscoveryMeta(readFile(filePath));
|
||||
assertPluginsDiscoveryMeta(readFile(filePath, distDir));
|
||||
}
|
||||
}
|
||||
|
||||
export function assertPrerenderedTopicRoutes(topicUrls, distDir = 'dist', normalizedRootPath = '') {
|
||||
for (const topicUrl of topicUrls) {
|
||||
const parsed = new URL(topicUrl);
|
||||
const filePath = path.join(distDir, routePathToDistFile(parsed.pathname, normalizedRootPath));
|
||||
const filePath = safeUserPath(routePathToDistFile(parsed.pathname, normalizedRootPath), distDir);
|
||||
assert(
|
||||
fs.existsSync(filePath),
|
||||
`Missing prerendered page for topic route: ${parsed.pathname}. Expected ${filePath}.`,
|
||||
);
|
||||
const html = readFile(filePath);
|
||||
const html = readFile(filePath, distDir);
|
||||
assertTopicDiscoveryMeta(html);
|
||||
assertStaticRelatedTopicLinks(html, 'Topic');
|
||||
}
|
||||
@@ -534,8 +554,8 @@ export function assertManifest(manifestText) {
|
||||
assert(manifest.icons.length > 0, 'Manifest icons array must not be empty.');
|
||||
}
|
||||
|
||||
function readFile(filePath) {
|
||||
return fs.readFileSync(filePath, 'utf-8');
|
||||
function readFile(filePath, baseDir = process.cwd()) {
|
||||
return fs.readFileSync(safeUserPath(filePath, baseDir), 'utf-8');
|
||||
}
|
||||
|
||||
export function runVerification({
|
||||
@@ -550,6 +570,15 @@ export function runVerification({
|
||||
minSkillUrls,
|
||||
requireHostedUrl = false,
|
||||
}) {
|
||||
sitemapPath = safeUserPath(sitemapPath);
|
||||
robotsPath = safeUserPath(robotsPath);
|
||||
llmsPath = safeUserPath(llmsPath);
|
||||
manifestPath = safeUserPath(manifestPath);
|
||||
indexPath = safeUserPath(indexPath);
|
||||
sourceIndexPath = safeUserPath(sourceIndexPath);
|
||||
socialImagePath = safeUserPath(socialImagePath);
|
||||
distDir = safeUserPath(distDir);
|
||||
|
||||
const expectedReleaseLabel = getPackageReleaseLabel();
|
||||
const sitemapText = readFile(sitemapPath);
|
||||
const sitemapReport = analyzeSitemap(sitemapText, { minSkillUrls, requireHostedUrl });
|
||||
|
||||
Reference in New Issue
Block a user