fix(ci): resolve OOM issues when building docs locally with Docusaurus Faster + sync docs with latest build result (#38486)

Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Đỗ Trọng Hải
2026-04-27 15:45:53 +07:00
committed by GitHub
parent 7c24214857
commit 2b13e07521
58 changed files with 407 additions and 163 deletions

View File

@@ -185,6 +185,76 @@ const SKIP_STORIES = [
];
/**
* Collect the set of value names exported from a barrel file, following
* `export * from './X'` re-exports one level deep. Used to verify that a
* component the docs claim is importable is actually re-exported from the
* public package entry point.
*/
function collectBarrelExports(barrelPath, visited = new Set()) {
const exports = new Set();
if (!fs.existsSync(barrelPath) || visited.has(barrelPath)) return exports;
visited.add(barrelPath);
const content = fs.readFileSync(barrelPath, 'utf8');
for (const m of content.matchAll(/export\s+\{([\s\S]*?)\}(?:\s+from\s+['"][^'"]+['"])?/g)) {
for (const part of m[1].split(',')) {
const cleaned = part.trim().replace(/^type\s+/, '');
if (!cleaned) continue;
const asMatch = cleaned.match(/(?:^|\s)as\s+([A-Za-z_]\w*)\s*$/);
if (asMatch) {
exports.add(asMatch[1]);
} else {
const plain = cleaned.match(/^([A-Za-z_]\w*)\s*$/);
if (plain) exports.add(plain[1]);
}
}
}
for (const m of content.matchAll(
/export\s+(?:const|let|var|function|class)\s+([A-Za-z_]\w*)/g
)) {
exports.add(m[1]);
}
for (const m of content.matchAll(/export\s+\*\s+from\s+['"]([^'"]+)['"]/g)) {
const target = m[1];
if (!target.startsWith('.')) continue;
const baseDir = path.dirname(barrelPath);
const candidates = [
path.resolve(baseDir, `${target}.ts`),
path.resolve(baseDir, `${target}.tsx`),
path.resolve(baseDir, target, 'index.ts'),
path.resolve(baseDir, target, 'index.tsx'),
];
const resolved = candidates.find(p => fs.existsSync(p));
if (resolved) {
for (const name of collectBarrelExports(resolved, visited)) {
exports.add(name);
}
}
}
return exports;
}
const SOURCE_PUBLIC_EXPORTS = new Map();
function getPublicExports(sourceConfig) {
if (SOURCE_PUBLIC_EXPORTS.has(sourceConfig)) {
return SOURCE_PUBLIC_EXPORTS.get(sourceConfig);
}
const sourceDir = path.join(FRONTEND_DIR, sourceConfig.path);
const candidates = [
path.join(sourceDir, 'index.ts'),
path.join(sourceDir, 'index.tsx'),
];
const barrel = candidates.find(p => fs.existsSync(p));
const result = barrel ? collectBarrelExports(barrel) : null;
SOURCE_PUBLIC_EXPORTS.set(sourceConfig, result);
return result;
}
/**
* Recursively find all story files in a directory
*/
@@ -1048,6 +1118,28 @@ function generateMDX(component, storyContent) {
// Use resolved import path if available, otherwise fall back to source config
const componentImportPath = resolvedImportPath || sourceConfig.importPrefix;
// The displayed import in user docs should reflect the public package path,
// not the internal storybook alias.
const docImportPath = sourceConfig.importPrefix.startsWith('@superset/')
? sourceConfig.docImportPrefix
: componentImportPath;
// When the source uses the internal storybook alias, the public package
// re-exports components as named exports (e.g. `export { default as Foo }`),
// so users must use named imports even when the story uses a default import.
const useDefaultImport =
isDefaultExport && !sourceConfig.importPrefix.startsWith('@superset/');
// Only render the import snippet if the component is actually re-exported
// from the public package barrel; otherwise the snippet would mislead users
// copy-pasting it (e.g. TableCollection, which has a story but is not
// re-exported from `@superset-ui/core/components`).
const publicExports = sourceConfig.importPrefix.startsWith('@superset/')
? getPublicExports(sourceConfig)
: null;
const isPubliclyExported =
!publicExports || publicExports.has(componentName);
// Determine component description based on source
const defaultDesc = sourceConfig.category === 'ui'
? `The ${componentName} component from Superset's UI library.`
@@ -1134,13 +1226,13 @@ ${Object.keys(args).length > 0 ? `## Props
|------|------|---------|-------------|
${propsTable}` : ''}
## Import
${isPubliclyExported ? `## Import
\`\`\`tsx
${isDefaultExport ? `import ${componentName} from '${componentImportPath}';` : `import { ${componentName} } from '${componentImportPath}';`}
${useDefaultImport ? `import ${componentName} from '${docImportPath}';` : `import { ${componentName} } from '${docImportPath}';`}
\`\`\`
---
---` : '---'}
:::tip[Improve this page]
This documentation is auto-generated from the component's Storybook story.