@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
227 lines (223 loc) • 10.9 kB
JavaScript
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import { loadVariant } from "../../CodeHighlighter/loadVariant.js";
import { createParseSource } from "../parseSource/index.js";
// TODO: re-enable following benchmarking
// import { TypescriptToJavascriptTransformer } from '../transformTypescriptToJavascript';
import { parseCreateFactoryCall } from "./parseCreateFactoryCall.js";
import { resolveVariantPathsWithFs } from "../loaderUtils/resolveModulePathWithFs.js";
import { replacePrecomputeValue } from "./replacePrecomputeValue.js";
import { createLoadServerSource } from "../loadServerSource/index.js";
import { createExternalsProvider } from "./generateExternalsProvider.js";
import { mergeExternals } from "../loaderUtils/mergeExternals.js";
import { emitExternalsProvider } from "./emitExternalsProvider.js";
import { getFileNameFromUrl } from "../loaderUtils/index.js";
/**
* Filters out type-only imports from externals since they don't exist at runtime
*/
function filterRuntimeExternals(externals) {
var runtimeExternals = {};
for (var _i = 0, _Object$entries = Object.entries(externals); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
modulePath = _Object$entries$_i[0],
imports = _Object$entries$_i[1];
// Filter out imports where isType is true
var runtimeImports = imports.filter(function (importItem) {
return !importItem.isType;
});
// Only include the module if it has runtime imports
if (runtimeImports.length > 0) {
runtimeExternals[modulePath] = runtimeImports;
}
}
return runtimeExternals;
}
/**
* Webpack loader that processes demo files and precomputes variant data.
*
* Finds createDemo calls, loads and processes all variants with syntax highlighting
* and TypeScript transformation, then injects the precomputed data back into the source.
*
* Supports single component syntax: createDemo(import.meta.url, Component)
* And object syntax: createDemo(import.meta.url, { Component1, Component2 })
*
* Automatically skips processing if skipPrecompute: true is set.
*/
export function loadPrecomputedCodeHighlighter(_x) {
return _loadPrecomputedCodeHighlighter.apply(this, arguments);
}
function _loadPrecomputedCodeHighlighter() {
_loadPrecomputedCodeHighlighter = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(source) {
var _this = this;
var callback, demoCall, variantData, allDependencies, resolvedVariantMap, loadSource, sourceTransformers, sourceParser, variantPromises, variantResults, allExternalsArray, _iterator, _step, result, allExternals, runtimeExternals, externalsProviderPath, externalsProviderInfo, modifiedSource;
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
callback = this.async();
this.cacheable();
_context2.prev = 2;
_context2.next = 5;
return parseCreateFactoryCall(source, this.resourcePath);
case 5:
demoCall = _context2.sent;
if (demoCall) {
_context2.next = 9;
break;
}
callback(null, source);
return _context2.abrupt("return");
case 9:
if (!demoCall.options.skipPrecompute) {
_context2.next = 12;
break;
}
callback(null, source);
return _context2.abrupt("return");
case 12:
// Load variant data for all variants
variantData = {};
allDependencies = []; // Resolve all variant entry point paths using resolveVariantPathsWithFs
_context2.next = 16;
return resolveVariantPathsWithFs(demoCall.variants);
case 16:
resolvedVariantMap = _context2.sent;
// Create loader functions
loadSource = createLoadServerSource({
includeDependencies: true,
storeAt: 'flat' // TODO: this should be configurable
}); // Setup source transformers for TypeScript to JavaScript conversion
// const sourceTransformers: SourceTransformers = [TypescriptToJavascriptTransformer];
// TODO: maybe we should have `loadPrecomputedCodeHighlighterWithJsToTs`
sourceTransformers = []; // Create sourceParser promise for syntax highlighting
sourceParser = createParseSource(); // Process variants in parallel
variantPromises = Array.from(resolvedVariantMap.entries()).map(/*#__PURE__*/function () {
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref) {
var _ref3, variantName, fileUrl, namedExport, variant, _getFileNameFromUrl, fileName, _yield$loadVariant, processedVariant, dependencies, externals;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_ref3 = _slicedToArray(_ref, 2), variantName = _ref3[0], fileUrl = _ref3[1];
namedExport = demoCall.namedExports[variantName];
variant = fileUrl;
if (!namedExport) {
_context.next = 8;
break;
}
_getFileNameFromUrl = getFileNameFromUrl(variant), fileName = _getFileNameFromUrl.fileName;
if (fileName) {
_context.next = 7;
break;
}
throw new Error("Cannot determine fileName from URL \"".concat(variant, "\" for variant \"").concat(variantName, "\". ") + "Please ensure the URL has a valid file extension.");
case 7:
variant = {
url: fileUrl,
fileName: fileName,
namedExport: namedExport
};
case 8:
_context.prev = 8;
_context.next = 11;
return loadVariant(fileUrl,
// URL for the variant entry point (already includes file://)
variantName, variant, sourceParser,
// For syntax highlighting
loadSource,
// For loading source files and dependencies
undefined, sourceTransformers,
// For TypeScript to JavaScript conversion
{
maxDepth: 5
});
case 11:
_yield$loadVariant = _context.sent;
processedVariant = _yield$loadVariant.code;
dependencies = _yield$loadVariant.dependencies;
externals = _yield$loadVariant.externals;
return _context.abrupt("return", {
variantName: variantName,
variantData: processedVariant,
// processedVariant is a complete VariantCode
dependencies: dependencies,
// All files that were loaded
externals: externals // Combined externals from all loaded files
});
case 18:
_context.prev = 18;
_context.t0 = _context["catch"](8);
throw new Error("Failed to load variant ".concat(variantName, " from ").concat(fileUrl, ": ").concat(_context.t0));
case 21:
case "end":
return _context.stop();
}
}, _callee, null, [[8, 18]]);
}));
return function (_x2) {
return _ref2.apply(this, arguments);
};
}());
_context2.next = 23;
return Promise.all(variantPromises);
case 23:
variantResults = _context2.sent;
// Process results and collect dependencies and externals
allExternalsArray = [];
_iterator = _createForOfIteratorHelper(variantResults);
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
result = _step.value;
if (result) {
variantData[result.variantName] = result.variantData;
result.dependencies.forEach(function (file) {
allDependencies.push(file);
});
// Collect externals for proper merging
allExternalsArray.push(result.externals);
}
}
// Properly merge externals from all variants
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
allExternals = mergeExternals(allExternalsArray); // Filter out type-only imports for the externals provider since they don't exist at runtime
runtimeExternals = filterRuntimeExternals(allExternals); // Create externals provider file if there are runtime external dependencies
// Only process externals for live demos
if (!demoCall.live) {
_context2.next = 35;
break;
}
externalsProviderInfo = createExternalsProvider(runtimeExternals, this.resourcePath);
if (!externalsProviderInfo) {
_context2.next = 35;
break;
}
_context2.next = 34;
return emitExternalsProvider(this, externalsProviderInfo);
case 34:
externalsProviderPath = _context2.sent;
case 35:
// Replace the factory function call with the actual precomputed data
modifiedSource = replacePrecomputeValue(source, variantData, demoCall, externalsProviderPath); // Add all dependencies to webpack's watch list
allDependencies.forEach(function (dep) {
// Strip 'file://' prefix if present before adding to webpack's dependency tracking
_this.addDependency(dep.startsWith('file://') ? dep.slice(7) : dep);
});
callback(null, modifiedSource);
_context2.next = 43;
break;
case 40:
_context2.prev = 40;
_context2.t0 = _context2["catch"](2);
callback(_context2.t0 instanceof Error ? _context2.t0 : new Error(String(_context2.t0)));
case 43:
case "end":
return _context2.stop();
}
}, _callee2, this, [[2, 40]]);
}));
return _loadPrecomputedCodeHighlighter.apply(this, arguments);
}