@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
172 lines (156 loc) • 6.95 kB
JavaScript
// webpack does not like node: imports
// eslint-disable-next-line n/prefer-node-protocol
import path from 'path';
// eslint-disable-next-line n/prefer-node-protocol
import { fileURLToPath, pathToFileURL } from 'url';
import { createPerformanceLogger, logPerformance, nameMark, performanceMeasure } from "../loadPrecomputedCodeHighlighter/performanceLogger.mjs";
import { parseCreateFactoryCall } from "../parseCreateFactoryCall/parseCreateFactoryCall.mjs";
import { replacePrecomputeValue } from "../parseCreateFactoryCall/replacePrecomputeValue.mjs";
import { rewriteImportsToNull } from "../loaderUtils/rewriteImports.mjs";
import { createLoadServerPageIndex } from "../loadServerPageIndex/loadServerPageIndex.mjs";
import { createSitemapSchema } from "../loadServerSitemap/loadServerSitemap.mjs";
const functionName = 'Load Precomputed Sitemap';
export async function loadPrecomputedSitemap(source) {
const callback = this.async();
this.cacheable();
const options = this.getOptions();
const performanceNotableMs = options.performance?.notableMs ?? 100;
const performanceShowWrapperMeasures = options.performance?.showWrapperMeasures ?? false;
// const resourceName = extractNameAndSlugFromUrl(
// new URL('.', `file://${this.resourcePath}`).pathname,
// ).name;
const relativePath = path.relative(this.rootContext || process.cwd(), this.resourcePath);
let observer = undefined;
if (options.performance?.logging) {
observer = new PerformanceObserver(createPerformanceLogger(performanceNotableMs, performanceShowWrapperMeasures, relativePath));
observer.observe({
entryTypes: ['measure']
});
}
let currentMark = nameMark(functionName, 'Start Loading', [relativePath]);
performance.mark(currentMark);
try {
// Convert the filesystem path to a file:// URL for cross-platform compatibility
// pathToFileURL handles Windows drive letters correctly (e.g., C:\... → file:///C:/...)
const resourceFileUrl = pathToFileURL(this.resourcePath).toString();
// Parse the source to find a single createSitemap call
const sitemapCall = await parseCreateFactoryCall(source, resourceFileUrl);
currentMark = performanceMeasure(currentMark, {
mark: 'Parsed Factory',
measure: 'Factory Parsing'
}, [functionName, relativePath]);
// If no createSitemap call found, return the source unchanged
if (!sitemapCall) {
callback(null, source);
return;
}
// If skipPrecompute is true, return the source unchanged
if (sitemapCall.options.skipPrecompute) {
callback(null, source);
return;
}
// Extract the variants (imported markdown files)
const variants = sitemapCall.variants;
if (!variants || Object.keys(variants).length === 0) {
callback(null, source);
return;
}
currentMark = performanceMeasure(currentMark, {
mark: 'Extracted Variants',
measure: 'Variant Extraction'
}, [functionName, relativePath]);
// Read and parse each markdown file
const sitemapData = {};
// Create page index loader with root context
const rootContext = this.rootContext || process.cwd();
const loadPageIndex = createLoadServerPageIndex({
rootContext
});
// Process all markdown files in parallel using shared logic
const entries = Object.entries(variants);
const results = await Promise.all(entries.map(async ([key, importPath]) => {
// Convert file:// URLs to proper file system paths for webpack's dependency tracking
// Using fileURLToPath handles Windows drive letters correctly (e.g., file:///C:/... → C:\...)
const absolutePath = importPath.startsWith('file://') ? fileURLToPath(importPath) : importPath;
try {
const metadata = await loadPageIndex(importPath);
return {
key,
absolutePath,
metadata,
error: null
};
} catch (error) {
return {
key,
absolutePath,
metadata: null,
error: error instanceof Error ? error : new Error(String(error))
};
}
}));
currentMark = performanceMeasure(currentMark, {
mark: 'Processed All Files',
measure: 'Process Markdown Files'
}, [functionName, relativePath]);
// Collect results and dependencies
for (const result of results) {
if (result.error) {
// Log error but continue processing other files
console.error(`Failed to process ${result.key} at ${result.absolutePath}:`, result.error);
} else if (result.metadata) {
sitemapData[result.key] = result.metadata;
// Add to dependencies for webpack watching
this.addDependency(result.absolutePath);
}
}
// Create sitemap with Orama schema for search indexing
const precomputeData = {
schema: createSitemapSchema(),
data: sitemapData
};
// Replace the factory function call with the precomputed sitemap data
let modifiedSource = replacePrecomputeValue(source, precomputeData, sitemapCall);
performanceMeasure(currentMark, {
mark: 'replaced precompute',
measure: 'precompute replacement'
}, [functionName, relativePath]);
// Rewrite MDX imports to const declarations since we've precomputed the data
if (sitemapCall.importsAndComments) {
const {
relative
} = sitemapCall.importsAndComments;
// Build a set of MDX imports to rewrite
const importPathsToRewrite = new Set();
const importResult = {};
for (const [importPath, importData] of Object.entries(relative)) {
// Check if this is an MDX file
if (importPath.endsWith('.mdx')) {
// Add to the set of imports to rewrite
importPathsToRewrite.add(importPath);
importResult[importPath] = {
positions: importData.positions,
names: importData.names
};
}
}
// Rewrite the import statements to const declarations if there are any MDX imports
if (importPathsToRewrite.size > 0) {
modifiedSource = rewriteImportsToNull(modifiedSource, importPathsToRewrite, importResult);
currentMark = performanceMeasure(currentMark, {
mark: 'rewritten imports',
measure: 'import rewriting'
}, [functionName, relativePath]);
}
}
// log any pending performance entries before completing
observer?.takeRecords()?.forEach(entry => logPerformance(entry, performanceNotableMs, performanceShowWrapperMeasures, relativePath));
observer?.disconnect();
callback(null, modifiedSource);
} catch (error) {
// log any pending performance entries before completing
observer?.takeRecords()?.forEach(entry => logPerformance(entry, performanceNotableMs, performanceShowWrapperMeasures, relativePath));
observer?.disconnect();
callback(error instanceof Error ? error : new Error(String(error)));
}
}