UNPKG

@mui/internal-docs-infra

Version:

MUI Infra - internal documentation creation tools.

154 lines (148 loc) 5.44 kB
import { parseImportsAndComments } from "../loaderUtils/index.mjs"; import { processRelativeImports } from "../loaderUtils/processRelativeImports.mjs"; import { isJavaScriptModule } from "../loaderUtils/resolveModulePath.mjs"; /** * Imports record passed to {@link LoadIsomorphicCodeSourceOptions.resolveImports}. * * Mirrors the shape produced by `parseImportsAndComments` once names have been * flattened, so resolvers can look up each import by its source path. */ /** * Creates a `LoadSource` function that performs all the platform-independent * work shared between server-side and client-side source loaders: fetching * the file via the supplied `fetchSource`, parsing its imports and comments, * reshaping externals, and assembling `extraFiles` / `extraDependencies` for * recursive loading. * * Platform-specific concerns (`fs.readFile`, `fetch`, module resolution * against a real filesystem vs. a remote tree) are injected via the * `fetchSource` and `resolveImports` options. */ export function createLoadIsomorphicCodeSource(options) { const { fetchSource, resolveImports, includeDependencies = true, storeAt = 'flat', removeCommentsWithPrefix, notableCommentsPrefix } = options; return async function loadSource(url) { const source = await fetchSource(url); if (!includeDependencies) { return { source }; } // Static assets (JSON, images, etc.) have no imports to resolve. const isJavascriptModuleFile = isJavaScriptModule(url); const isCssFile = url.toLowerCase().endsWith('.css'); if (!isJavascriptModuleFile && !isCssFile) { return { source }; } const { relative: importResult, externals, comments, code: processedCode } = await parseImportsAndComments(source, url, { removeCommentsWithPrefix, notableCommentsPrefix }); // Use the comment-stripped source when `removeCommentsWithPrefix` rewrote // the file; fall back to the raw source otherwise. const finalSource = processedCode ?? source; // Reshape externals from the parser's per-import structure into the // framework's flat `Externals` record (drops position info that was only // needed for source rewriting). const transformedExternals = {}; for (const [modulePath, externalImport] of Object.entries(externals)) { transformedExternals[modulePath] = externalImport.names.map(importName => ({ name: importName.name, type: importName.type, isType: importName.isType })); } const externalsResult = Object.keys(transformedExternals).length > 0 ? transformedExternals : undefined; if (Object.keys(importResult).length === 0) { return { source: finalSource, externals: externalsResult, comments }; } // `processRelativeImports` expects names as plain strings (alias-aware). const importsCompatible = {}; for (const [importPath, { url: importUrl, names, positions }] of Object.entries(importResult)) { importsCompatible[importPath] = { url: importUrl, names: names.map(({ name, alias }) => alias || name), positions }; } let processedSource; let extraFiles; let extraDependencies; if (isCssFile) { // CSS imports are already absolute paths after `parseImportsAndComments`. const result = processRelativeImports(finalSource, importsCompatible, storeAt); processedSource = result.processedSource; extraFiles = result.extraFiles; extraDependencies = Object.values(importResult).map(({ url: importUrl }) => importUrl); } else { // JS/TS: optionally resolve each import to an absolute URL via the // platform-specific resolver. When no resolver is supplied, fall back to // the raw import URLs (suitable for callers that pre-resolve themselves // or don't need rewritten output). let resolvedPathsMap; if (resolveImports) { const relativeImportsCompatible = {}; for (const [importPath, { url: importUrl, names, includeTypeDefs, positions }] of Object.entries(importResult)) { relativeImportsCompatible[importPath] = { url: importUrl, names: names.map(({ name, alias }) => alias || name), positions, ...(includeTypeDefs && { includeTypeDefs }) }; } resolvedPathsMap = await resolveImports(relativeImportsCompatible); } const result = processRelativeImports(finalSource, importsCompatible, storeAt, true, resolvedPathsMap); processedSource = result.processedSource; extraFiles = result.extraFiles; extraDependencies = resolvedPathsMap ? Object.values(importResult).map(({ url: importUrl }) => resolvedPathsMap.get(importUrl)).filter(resolved => resolved !== undefined) : Object.values(importResult).map(({ url: importUrl }) => importUrl); } return { source: processedSource, extraFiles: Object.keys(extraFiles).length > 0 ? extraFiles : undefined, extraDependencies: extraDependencies.length > 0 ? extraDependencies : undefined, externals: externalsResult, comments }; }; }