UNPKG

dumi

Version:

📖 Documentation Generator of React Component

374 lines (372 loc) • 12.7 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/features/compile/utoopackLoaders.ts var utoopackLoaders_exports = {}; __export(utoopackLoaders_exports, { LOADER_CTX_FILENAME: () => LOADER_CTX_FILENAME, UTOOPACK_DEMO_ASSETS_FILENAME: () => UTOOPACK_DEMO_ASSETS_FILENAME, UTOOPACK_LOADER_CTX_KEY: () => UTOOPACK_LOADER_CTX_KEY, buildLoaderContextContent: () => buildLoaderContextContent, getUtoopackRules: () => getUtoopackRules }); module.exports = __toCommonJS(utoopackLoaders_exports); var import_esbuild = __toESM(require("@umijs/bundler-utils/compiled/esbuild")); var import_utils = require("@umijs/utils"); var import_path = __toESM(require("path")); var import_utils2 = require("./utils"); var mdLoaderPath = require.resolve("../../loaders/markdown"); var utilsRegisterPath = require.resolve("@umijs/utils"); var esbuildImplementorPath = require.resolve("@umijs/bundler-utils/compiled/esbuild"); var UTOOPACK_LOADER_CTX_KEY = "__dumiLoaderContextPath"; var LOADER_CTX_FILENAME = "dumi-loader-ctx.cjs"; var UTOOPACK_DEMO_ASSETS_FILENAME = "dumi-utoopack-demo-assets.jsonl"; function toSerializable(value) { return JSON.parse(JSON.stringify(value)); } function findInRequireCache(target) { for (const [filename, mod] of Object.entries(require.cache)) { if (!(mod == null ? void 0 : mod.exports)) continue; const exp = mod.exports; if (exp === target) return { modulePath: filename, exportName: "module.exports" }; if ((exp == null ? void 0 : exp.default) === target) return { modulePath: filename, exportName: "default" }; for (const [k, v] of Object.entries(exp)) { if (v === target) return { modulePath: filename, exportName: k }; } } return null; } function normalizeFnSource(fn) { return Function.prototype.toString.call(fn).replace(/\s+/g, " "); } function isSameFunction(candidate, target) { return typeof candidate === "function" && candidate.name === target.name && normalizeFnSource(candidate) === normalizeFnSource(target); } function findInModuleExports(target, mod) { const exp = mod.exports; if (!exp) return null; if (isSameFunction(exp, target)) { return { modulePath: mod.filename, exportName: "module.exports" }; } if (isSameFunction(exp == null ? void 0 : exp.default, target)) { return { modulePath: mod.filename, exportName: "default" }; } for (const [k, v] of Object.entries(exp)) { if (isSameFunction(v, target)) { return { modulePath: mod.filename, exportName: k }; } } return null; } function findInSourceFiles(target, sourceFiles) { import_utils.register.register({ implementor: import_esbuild.default }); import_utils.register.clearFiles(); try { for (const file of sourceFiles) { try { require(file); const mod = require.cache[file]; if (!(mod == null ? void 0 : mod.exports)) continue; const found = findInModuleExports(target, mod); if (found) return found; } catch { } } return null; } finally { for (const file of import_utils.register.getFiles()) { delete require.cache[file]; } for (const file of sourceFiles) { delete require.cache[file]; } import_utils.register.restore(); } } function toRequireRef(found) { const modRef = `require(${JSON.stringify(found.modulePath)})`; return found.exportName === "module.exports" ? modRef : `(${modRef})[${JSON.stringify(found.exportName)}]`; } function toTechStackRefs(techStacks) { const refs = []; for (const ts of techStacks) { const ctor = ts.constructor; let ref; if (ctor !== Object) { const found = findInRequireCache(ctor); if (found) { ref = `new (${toRequireRef(found)})()`; } } else { const found = findInRequireCache(ts); if (found) { ref = toRequireRef(found); } } if (ref) { refs.push(ref); } else { const name = ts.constructor.name ? ` (${ts.constructor.name})` : ""; console.warn( `[dumi] Utoopack markdown loader cannot serialize tech stack "${ts.name}"${name}. Please export the tech stack class from a module.` ); } } return refs; } function toPluginTargetRef(target, sourceFiles) { if (typeof target === "string") return JSON.stringify(target); const found = findInRequireCache(target) ?? findInSourceFiles(target, sourceFiles); if (!found) { const name = target.name ? ` "${target.name}"` : ""; throw new Error( `Utoopack markdown loader requires extra unified plugin function${name} to be exported from a module.` ); } return toRequireRef(found); } function toPluginRefs(plugins = [], sourceFiles = []) { return `[${plugins.map((plugin) => { if (Array.isArray(plugin)) { const [target, options] = plugin; const optionsRef = typeof options === "undefined" ? "undefined" : JSON.stringify(options); return `[${toPluginTargetRef( target, sourceFiles )}, ${optionsRef}]`; } return toPluginTargetRef(plugin, sourceFiles); }).join(", ")}]`; } function buildLoaderContextContent(techStacks, builtins = {}, routes = {}, extraRemarkPlugins = [], extraRehypePlugins = [], sourceFiles = [], demoAssetsFile) { const refs = toTechStackRefs(techStacks); return `'use strict'; try { require(${JSON.stringify( utilsRegisterPath )}).register.register({ implementor: require(${JSON.stringify( esbuildImplementorPath )}) }); } catch (e) { console.warn('[dumi] failed to register TS require hook for utoopack loader context:', e); } exports.techStacks = [${refs.join(", ")}]; exports.builtins = ${JSON.stringify(builtins)}; exports.routes = ${JSON.stringify(routes)}; exports.demoAssetsFile = ${JSON.stringify(demoAssetsFile)}; exports.extraRemarkPlugins = ${toPluginRefs( extraRemarkPlugins, sourceFiles )}; exports.extraRehypePlugins = ${toPluginRefs( extraRehypePlugins, sourceFiles )}; `; } var getUtoopackRules = (api, config = api.config) => { const disableLiveDemo = (0, import_utils2.shouldDisabledLiveDemo)(api); const loaderContextPath = import_path.default.join( api.paths.absTmpPath, LOADER_CTX_FILENAME ); const cfgResolve = config.resolve ?? {}; const serializableBaseOpts = toSerializable({ cwd: api.cwd, alias: config.alias || {}, resolve: { atomDirs: cfgResolve.atomDirs ?? [{ type: "component", dir: "src" }], docDirs: cfgResolve.docDirs ?? ["docs"], codeBlockMode: cfgResolve.codeBlockMode ?? "active", forceKebabCaseRouting: cfgResolve.forceKebabCaseRouting ?? true, ...cfgResolve.entryFile ? { entryFile: cfgResolve.entryFile } : {} }, routes: {}, builtins: {}, locales: config.locales || [], pkg: api.pkg, disableLiveDemo, [UTOOPACK_LOADER_CTX_KEY]: loaderContextPath }); const externalDemoLoader = { loader: require.resolve("../../loaders/demo"), options: toSerializable({ cwd: api.cwd, [UTOOPACK_LOADER_CTX_KEY]: loaderContextPath }) }; return { // handle ?watch=parent virtual module: return empty content to establish file-watching dependency "**/*": [ { condition: { query: /^\?watch=parent$/ }, loaders: [require.resolve("../../loaders/null")], as: "*.js" }, // handle raw content for demo source display (?dumi-raw) { condition: { query: /^\?dumi-raw$/ }, loaders: [ require.resolve("../../loaders/post-raw"), require.resolve("raw-loader"), require.resolve("../../loaders/pre-raw") ], as: "*.js" }, // handle untouched raw content for user imports like `import source from './file?raw'` { condition: { query: /^\?raw$/ }, loaders: [require.resolve("raw-loader")], as: "*.js" }, // handle external demo component files (?techStack=xxx) // techStacks are NOT serializable; pass loaderContextPath and hydrate in the loader { condition: { all: [{ query: /^\?techStack=.*$/ }, { path: /\.tsx$/ }] }, loaders: [externalDemoLoader], as: "*.tsx" }, { condition: { all: [{ query: /^\?techStack=.*$/ }, { path: /\.ts$/ }] }, loaders: [externalDemoLoader], as: "*.ts" }, { condition: { all: [{ query: /^\?techStack=.*$/ }, { path: /\.jsx$/ }] }, loaders: [externalDemoLoader], as: "*.jsx" }, { condition: { all: [ { query: /^\?techStack=.*$/ }, { not: { path: /\.(tsx?|jsx)$/ } } ] }, loaders: [externalDemoLoader], as: "*.js" } ], // extract frontmatter/toc metadata from JS/TS page components (?type=frontmatter) // NOTE: // - Markdown ?type=frontmatter is already handled by the '*.md' rule below. // - After the md loader outputs JS, utoopack will expose that virtual module as // '*.md.js?type=frontmatter'. Without the extra path guard here, this JS rule // runs again and page-loader overwrites markdown frontmatter with filename-based // fallbacks like "Docs" / "C Md". // - Excluding '*.md.js' keeps the markdown frontmatter result intact while still // allowing real JS/TS page components to use page-loader. "*.{js,jsx,ts,tsx}": { condition: { all: [ { query: /^\?type=frontmatter$/ }, { not: { path: /\.md\.js$/ } } ] }, loaders: [require.resolve("../../loaders/page")], as: "*.js" }, // handle markdown files with different modes based on query type "*.md": [ { condition: { query: /^\?type=frontmatter$/ }, loaders: [ { loader: mdLoaderPath, options: { ...serializableBaseOpts, mode: "frontmatter" } } ], as: "*.js" }, // extract plain text for full-text search { condition: { query: /^\?type=text$/ }, loaders: [ { loader: mdLoaderPath, options: { ...serializableBaseOpts, mode: "text" } } ], as: "*.js" }, // extract demo index metadata from markdown { condition: { query: /^\?type=demo-index$/ }, loaders: [ { loader: mdLoaderPath, options: { ...serializableBaseOpts, mode: "demo-index" } } ], as: "*.js" }, // compile inline demo code blocks { condition: { query: /^\?type=demo$/ }, loaders: [ { loader: mdLoaderPath, options: { ...serializableBaseOpts, mode: "demo" } } ], as: "*.js" }, // default: transform markdown into a React page component { loaders: [ { loader: mdLoaderPath, options: serializableBaseOpts } ], as: "*.js" } ] }; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { LOADER_CTX_FILENAME, UTOOPACK_DEMO_ASSETS_FILENAME, UTOOPACK_LOADER_CTX_KEY, buildLoaderContextContent, getUtoopackRules });