docs-v2/cypress/support/map-files-to-urls.js

140 lines
4.1 KiB
JavaScript

#!/usr/bin/env node
import process from 'process';
import fs from 'fs';
import { execSync } from 'child_process';
import matter from 'gray-matter';
// Get file paths from command line arguments
const filePaths = process.argv.slice(2).filter((arg) => !arg.startsWith('--'));
// Parse options
const debugMode = process.argv.includes('--debug'); // deprecated, no longer used
const jsonMode = process.argv.includes('--json');
// Separate shared content files and regular content files
const sharedContentFiles = filePaths.filter(
(file) =>
file.startsWith('content/shared/') &&
(file.endsWith('.md') || file.endsWith('.html'))
);
const regularContentFiles = filePaths.filter(
(file) =>
file.startsWith('content/') &&
!file.startsWith('content/shared/') &&
(file.endsWith('.md') || file.endsWith('.html'))
);
// Find pages that reference shared content files in their frontmatter
function findPagesReferencingSharedContent(sharedFilePath) {
try {
// Remove the leading "content/" to match how it would appear in frontmatter
const relativePath = sharedFilePath.replace(/^content\//, '');
// Use grep to find files that reference this shared content in frontmatter
// Look for source: <path> pattern in YAML frontmatter
const grepCmd = `grep -l "source: .*${relativePath}" --include="*.md" --include="*.html" -r content/`;
// Execute grep command and parse results
const result = execSync(grepCmd, { encoding: 'utf8' }).trim();
if (!result) {
return [];
}
return result.split('\n').filter(Boolean);
} catch (error) {
// grep returns non-zero exit code when no matches are found
if (error.status === 1) {
return [];
}
console.error(
`Error finding references to ${sharedFilePath}: ${error.message}`
);
return [];
}
}
/**
* Extract source from frontmatter or use the file path as source
* @param {string} filePath - Path to the file
* @returns {string} Source path
*/
function extractSourceFromFile(filePath) {
try {
if (fs.existsSync(filePath)) {
const fileContent = fs.readFileSync(filePath, 'utf8');
const { data } = matter(fileContent);
// If source is specified in frontmatter, return it
if (data.source) {
if (data.source.startsWith('/shared')) {
return 'content' + data.source;
}
return data.source;
}
}
// If no source in frontmatter or can't read file, use the file path itself
return filePath;
} catch (error) {
console.error(`Error extracting source from ${filePath}: ${error.message}`);
return filePath;
}
}
// Process shared content files to find pages that reference them
let pagesToTest = [...regularContentFiles];
if (sharedContentFiles.length > 0) {
console.log(
`Processing ${sharedContentFiles.length} shared content files...`
);
for (const sharedFile of sharedContentFiles) {
const referencingPages = findPagesReferencingSharedContent(sharedFile);
if (referencingPages.length > 0) {
console.log(
`Found ${referencingPages.length} pages referencing ${sharedFile}`
);
// Add referencing pages to the list of pages to test (avoid duplicates)
pagesToTest = [...new Set([...pagesToTest, ...referencingPages])];
} else {
console.log(`No pages found referencing ${sharedFile}`);
}
}
}
if (pagesToTest.length === 0) {
console.log('No content files to map.');
process.exit(0);
}
// Map file paths to URL paths and source information
function mapFilePathToUrlAndSource(filePath) {
// Map to URL
let url = filePath.replace(/^content/, '');
url = url.replace(/\/_index\.(html|md)$/, '/');
url = url.replace(/\.md$/, '/');
url = url.replace(/\.html$/, '/');
if (!url.startsWith('/')) {
url = '/' + url;
}
// Extract source
const source = extractSourceFromFile(filePath);
return { url, source };
}
const mappedFiles = pagesToTest.map(mapFilePathToUrlAndSource);
if (jsonMode) {
console.log(JSON.stringify(mappedFiles, null, 2));
} else {
// Print URL and source info in a format that's easy to parse
mappedFiles.forEach((item) => console.log(`${item.url}|${item.source}`));
}