UNPKG

@mui/internal-docs-infra

Version:

MUI Infra - internal documentation creation tools.

227 lines (223 loc) 10.9 kB
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); }