Skip to content

Commit aaf86a2

Browse files
committed
add script for reordering storybook stories
1 parent 6e2d5f9 commit aaf86a2

File tree

7 files changed

+156
-4
lines changed

7 files changed

+156
-4
lines changed

.github/workflows/docs-stable.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,24 @@ jobs:
4040
env:
4141
NODE_OPTIONS: '--max-old-space-size=4096'
4242

43+
- name: Build Storybook (reordered)
44+
run: |
45+
yarn build:storybook-reorder
46+
env:
47+
NODE_OPTIONS: '--max-old-space-size=4096'
48+
4349
- name: Deploy Docs
4450
uses: JamesIves/github-pages-deploy-action@6c2d9db40f9296374acc17b90404b6e8864128c8 # v4.7.3
4551
with:
4652
branch: gh-pages # The branch the action should deploy to.
4753
folder: .out # The folder the action should deploy.
4854
target-folder: v${{ env.MAJOR_VERSION }}
4955
clean: true
56+
57+
- name: Deploy Docs (reordered)
58+
uses: JamesIves/github-pages-deploy-action@6c2d9db40f9296374acc17b90404b6e8864128c8 # v4.7.3
59+
with:
60+
branch: gh-pages
61+
folder: .out-reorder
62+
target-folder: reordered
63+
clean: true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ yarn-error.log
77
@types
88
.cache
99
.out
10+
.out-reorder
1011
lerna-debug.log
1112
/temp
1213
*.tsbuildinfo

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ yarn.lock
66
dist
77
temp
88
.out
9+
.out-reorderd
910

1011
.nx

.storybook/main.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { mergeConfig } from 'vite';
66
import { isChromatic } from './utils.ts';
77

88
const isDevMode = process.env.NODE_ENV === 'development';
9+
const useReorder = process.env.STORYBOOK_REORDER === 'true';
910

1011
const storyList: StoriesEntry[] = isChromatic
1112
? ['../packages/main/src/components/**/*.stories.@(tsx|jsx)']
@@ -19,12 +20,12 @@ const storyList: StoriesEntry[] = isChromatic
1920
{
2021
directory: '../packages/charts/src/components',
2122
files: '**/*.@(mdx|stories.@(mdx|tsx))',
22-
titlePrefix: 'Charts',
23+
titlePrefix: useReorder ? 'ui5-webcomponents-react-charts' : 'Charts',
2324
},
2425
{
2526
directory: '../packages/base',
2627
files: '*.@(tsx|jsx)',
27-
titlePrefix: 'Base',
28+
titlePrefix: useReorder ? 'ui5-webcomponents-react-base ' : 'Base',
2829
},
2930
{
3031
directory: '../packages/cypress-commands',
@@ -36,12 +37,12 @@ const storyList: StoriesEntry[] = isChromatic
3637
{
3738
directory: '../packages/ai',
3839
files: '**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))',
39-
titlePrefix: 'AI',
40+
titlePrefix: useReorder ? 'ui5-webcomponents-ai-react / ui5-webcomponents-ai' : 'AI',
4041
},
4142
{
4243
directory: '../packages/compat',
4344
files: '**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))',
44-
titlePrefix: 'Legacy Components',
45+
titlePrefix: useReorder ? 'ui5-webcomponents-react-compat' : 'Legacy Components',
4546
},
4647
{
4748
directory: '../patterns',
@@ -64,6 +65,7 @@ const addons = [
6465
},
6566
},
6667
];
68+
6769
if (isDevMode) {
6870
addons.push('@storybook/addon-a11y');
6971
}

.storybook/preview.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ const preview: Preview = {
156156
'AI',
157157
['Docs'],
158158
'Legacy Components',
159+
// only relevant for reordered sb
160+
'ui5-webcomponents-react',
161+
['ui5-webcomponents', 'ui5-webcomponents-fiori'],
159162
],
160163
},
161164
},

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"setup": "lerna run build:i18n && lerna run build:css && lerna run build:css-bundle && lerna run build:version-info && rimraf node_modules/@types/mocha",
1313
"build": "yarn setup && tsc --build tsconfig.build.json && lerna run build:client && lerna run build:wrapper",
1414
"build:storybook": "yarn build && yarn create-cypress-commands-docs && storybook build -o .out",
15+
"build:storybook:reorder": "yarn build && yarn create-cypress-commands-docs && STORYBOOK_REORDER='true' node scripts/reorder-stories.js",
1516
"build:storybook-sitemap": "node ./scripts/create-storybook-sitemap.js --directory .out",
1617
"test:prepare": "rimraf temp && lerna run build",
1718
"test:open": "CYPRESS_COVERAGE=false cypress open --component --browser chrome",

scripts/reorder-stories.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/* eslint-disable @typescript-eslint/no-unsafe-return */
2+
3+
import { execSync } from 'child_process';
4+
import fs from 'fs';
5+
import path from 'path';
6+
7+
const ROOT_DIR = process.cwd();
8+
const STORIES_GLOB_EXT = '.stories.tsx';
9+
const OUTPUT_DIR = process.env.STORYBOOK_OUTPUT_DIR || '.out-reorder';
10+
11+
// Fixed replacements
12+
const MDX_META_REPLACEMENTS = {
13+
'docs/ReadMeAI.mdx': 'ui5-webcomponents-ai-react',
14+
'docs/ReadMeCharts.mdx': 'ui5-webcomponents-react-charts',
15+
'docs/ReadMeCompat.mdx': 'ui5-webcomponents-react-compat',
16+
'packages/main/src/components/AnalyticalTable/PluginAnnounceEmptyCells.mdx': 'ui5-webcomponents-react',
17+
'packages/main/src/components/AnalyticalTable/PluginDisableRowSelection.mdx': 'ui5-webcomponents-react',
18+
'packages/main/src/components/AnalyticalTable/PluginIndeterminateRowSelection.mdx': 'ui5-webcomponents-react',
19+
'packages/main/src/components/AnalyticalTable/PluginManualRowSelect.mdx': 'ui5-webcomponents-react',
20+
'packages/main/src/components/AnalyticalTable/PluginOnColumnResize.mdx': 'ui5-webcomponents-react',
21+
'packages/main/src/components/AnalyticalTable/PluginOrderedMultiSort.mdx': 'ui5-webcomponents-react',
22+
'packages/main/src/components/AnalyticalTable/Recipes.mdx': 'ui5-webcomponents-react',
23+
};
24+
25+
function getStoryFiles(dir) {
26+
if (!fs.existsSync(dir)) return [];
27+
let files = [];
28+
for (const file of fs.readdirSync(dir)) {
29+
const fullPath = path.join(dir, file);
30+
const stat = fs.statSync(fullPath);
31+
if (stat.isDirectory()) {
32+
files = files.concat(getStoryFiles(fullPath));
33+
} else if (file.endsWith(STORIES_GLOB_EXT)) {
34+
files.push(fullPath);
35+
}
36+
}
37+
return files;
38+
}
39+
40+
// Extract package name from tags (e.g.: ['package:@ui5/webcomponents'])
41+
function getPackageName(content) {
42+
const match = content.match(/['"`]package:([^'"`]+)['"`]/);
43+
return match ? match[1] : null;
44+
}
45+
46+
function resolveFirstSegment(packageName, titleParts) {
47+
const clean = packageName.replace(/^@ui5\//, 'ui5-');
48+
49+
switch (packageName) {
50+
case '@ui5/webcomponents':
51+
case '@ui5/webcomponents-fiori': {
52+
return ['ui5-webcomponents-react', clean, ...titleParts].join(' / ');
53+
}
54+
default: {
55+
// replace first segment if multiple, else prepend
56+
if (titleParts.length > 1) {
57+
return [clean, ...titleParts.slice(1)].join(' / ');
58+
} else {
59+
return [clean, ...titleParts].join(' / ');
60+
}
61+
}
62+
}
63+
}
64+
65+
// Replace first segment in Storybook `title:`
66+
function adjustStoryTitle(content, packageName) {
67+
return content.replace(/title:\s*(['"`])([^'"`]+)\1/, (_, quote, title) => {
68+
const parts = title.split(' / ');
69+
const newTitle = resolveFirstSegment(packageName, parts);
70+
return `title: ${quote}${newTitle}${quote}`;
71+
});
72+
}
73+
74+
// Adjust <Meta title="..."/>
75+
function adjustMdxMetaTitle(content, newFirstSegment) {
76+
return content.replace(/<Meta\s+title\s*=\s*(['"`])([^'"`]+)\1\s*\/>/, (m, quote, title) => {
77+
const parts = title.split(' / ');
78+
const newTitle =
79+
parts.length > 1 ? [newFirstSegment, ...parts.slice(1)].join(' / ') : `${newFirstSegment} / ${title}`;
80+
return `<Meta title=${quote}${newTitle}${quote} />`;
81+
});
82+
}
83+
84+
function main() {
85+
const storyFiles = getStoryFiles(ROOT_DIR);
86+
const mdxFiles = Object.keys(MDX_META_REPLACEMENTS)
87+
.map((rel) => path.join(ROOT_DIR, rel))
88+
.filter((p) => fs.existsSync(p));
89+
90+
const allFiles = [...storyFiles, ...mdxFiles];
91+
92+
if (!allFiles.length) {
93+
console.log('No story or MDX files found.');
94+
return;
95+
}
96+
97+
// Backup originals
98+
const backups = allFiles.map((file) => ({
99+
file,
100+
content: fs.readFileSync(file, 'utf-8'),
101+
}));
102+
103+
// Update stories
104+
storyFiles.forEach((file) => {
105+
const original = backups.find((b) => b.file === file).content;
106+
const packageName = getPackageName(original);
107+
if (!packageName) return; // skip if no package tag
108+
const updated = adjustStoryTitle(original, packageName);
109+
fs.writeFileSync(file, updated, 'utf-8');
110+
});
111+
112+
// Update mdx
113+
mdxFiles.forEach((absPath) => {
114+
const original = backups.find((b) => b.file === absPath).content;
115+
const rel = path.relative(ROOT_DIR, absPath).replace(/\\/g, '/');
116+
const newFirstSegment = MDX_META_REPLACEMENTS[rel];
117+
const updated = adjustMdxMetaTitle(original, newFirstSegment);
118+
fs.writeFileSync(absPath, updated, 'utf-8');
119+
});
120+
121+
// Build Sb
122+
execSync(`npx storybook build -o ${OUTPUT_DIR}`, { stdio: 'inherit' });
123+
124+
// Restore originals
125+
backups.forEach((b) => fs.writeFileSync(b.file, b.content, 'utf-8'));
126+
127+
console.log(`Storybook built in '${OUTPUT_DIR}' and source files restored.`);
128+
}
129+
130+
main();

0 commit comments

Comments
 (0)