Skip to content

Commit f0d666c

Browse files
committed
update breadcrumb script
1 parent 18116a4 commit f0d666c

File tree

9 files changed

+288
-49
lines changed

9 files changed

+288
-49
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: Beta Features
3+
description: Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Beta Features
10+
11+
Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="Alt-DA Mode explainer" href="/stack/beta-features/alt-da-mode" />
15+
<Card title="Custom Gas token explainer" href="/stack/beta-features/custom-gas-token" />
16+
</Cards>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: Fault Proofs
3+
description: Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security, Mips in the Fault Proofs section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Fault Proofs
10+
11+
Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security, Mips in the Fault Proofs section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="Fault proof VM - Cannon" href="/stack/fault-proofs/cannon" />
15+
<Card title="OP-Challenger explainer" href="/stack/fault-proofs/challenger" />
16+
<Card title="Fault proofs explainer" href="/stack/fault-proofs/explainer" />
17+
<Card title="FP System components" href="/stack/fault-proofs/fp-components" />
18+
<Card title="Fault proofs Mainnet security" href="/stack/fault-proofs/fp-security" />
19+
<Card title="Fault proof VM - MIPS.sol" href="/stack/fault-proofs/mips" />
20+
</Cards>

pages/stack/features/features.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: Features
3+
description: Documentation covering Send Raw Transaction Conditional in the Features section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Features
10+
11+
Documentation covering Send Raw Transaction Conditional in the Features section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="SendRawTransactionConditional explainer" href="/stack/features/send-raw-transaction-conditional" />
15+
</Cards>

pages/stack/interop/interop.mdx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
title: Interop
3+
description: Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Interop
10+
11+
Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="Anatomy of a cross-chain message" href="/stack/interop/cross-chain-message" />
15+
<Card title="Interoperability explainer" href="/stack/interop/explainer" />
16+
<Card title="SuperchainERC20" href="/stack/interop/superchain-erc20" />
17+
<Card title="Supersim multichain development environment" href="/stack/interop/supersim" />
18+
<Card title="How to transfer a SuperchainERC20" href="/stack/interop/transfer-superchainERC20" />
19+
</Cards>

pages/stack/research/research.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: Research
3+
description: Documentation covering Block Time Research in the Research section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Research
10+
11+
Documentation covering Block Time Research in the Research section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="Block time research" href="/stack/research/block-time-research" />
15+
</Cards>

pages/stack/rollup/rollup.mdx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
title: Rollup
3+
description: The big idea that makes Optimism possible is the Optimistic Rollup. We'll go through a brief explainer of *how* Optimistic Rollups work at a high l...
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Rollup
10+
11+
The big idea that makes Optimism possible is the Optimistic Rollup. We'll go through a brief explainer of *how* Optimistic Rollups work at a high l...
12+
13+
<Cards>
14+
<Card title="Derivation pipeline" href="/stack/rollup/derivation-pipeline" />
15+
<Card title="Sequencer outages" href="/stack/rollup/outages" />
16+
<Card title="Rollup protocol overview" href="/stack/rollup/overview" />
17+
</Cards>

pages/stack/security/security.mdx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: Security
3+
description: Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Security
10+
11+
Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="OP Stack security FAQs" href="/stack/security/faq" />
15+
<Card title="Pausing the bridge" href="/stack/security/pause" />
16+
</Cards>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: Transactions
3+
description: Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Transaction Flow, Withdrawal Flow in the Transactions section of the OP Stack ecosystem.
4+
lang: en-US
5+
---
6+
7+
import { Card, Cards } from 'nextra/components'
8+
9+
# Transactions
10+
11+
Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Transaction Flow, Withdrawal Flow in the Transactions section of the OP Stack ecosystem.
12+
13+
<Cards>
14+
<Card title="Cross-Domain" href="/stack/transactions/cross-domain" />
15+
<Card title="Deposit flow" href="/stack/transactions/deposit-flow" />
16+
<Card title="Transaction fees on OP Mainnet" href="/stack/transactions/fees" />
17+
<Card title="Forced transaction" href="/stack/transactions/forced-transaction" />
18+
<Card title="Transaction Flow" href="/stack/transactions/transaction-flow" />
19+
<Card title="Withdrawal flow" href="/stack/transactions/withdrawal-flow" />
20+
</Cards>

utils/create-breadcrumbs.ts

Lines changed: 150 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,186 @@ import * as fs from 'fs/promises';
22
import * as path from 'path';
33
import matter from 'gray-matter';
44

5-
const targetFolders: string[] = ['builders', 'chain', 'stack', 'connect'];
65
const rootDir: string = path.join(__dirname, '..', 'pages');
76

87
interface FileInfo {
98
title: string;
109
url: string;
10+
description?: string;
11+
content: string;
1112
}
1213

13-
function updateOPTerminology(description: string): string {
14+
function toTitleCase(str: string): string {
15+
return str.split('-')
16+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
17+
.join(' ');
18+
}
1419

15-
if (description.includes('OP Stack')) {
16-
return description;
17-
}
20+
function extractFirstParagraph(content: string): string {
21+
// Remove frontmatter
22+
content = content.replace(/^---[\s\S]*?---/, '');
23+
24+
// Remove import statements
25+
content = content.replace(/^import[\s\S]*?\n/gm, '');
26+
27+
// Remove HTML/MDX tags
28+
content = content.replace(/<[^>]+>/g, ' ');
29+
30+
// Remove markdown links but keep text
31+
content = content.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
32+
33+
// Remove headers
34+
content = content.replace(/^#.+$/gm, '');
1835

19-
// Replace variations of "OP Mainnet" with "OP Stack"
20-
return description
21-
.replace(/\bOP Mainnet\b/gi, 'OP Stack')
22-
.replace(/\bOptimism Mainnet\b/gi, 'OP Stack')
23-
.replace(/\bOptimism mainnet\b/gi, 'OP Stack');
36+
const paragraphs = content.split(/\n\n+/);
37+
const firstParagraph = paragraphs.find(p => {
38+
const cleaned = p.trim();
39+
return cleaned.length > 30 && // Minimum length
40+
!cleaned.startsWith('import') &&
41+
!cleaned.startsWith('export');
42+
});
43+
44+
if (firstParagraph) {
45+
const cleaned = firstParagraph.replace(/\s+/g, ' ').trim();
46+
return cleaned.length > 150 ? cleaned.slice(0, 147) + '...' : cleaned;
47+
}
48+
49+
return '';
2450
}
2551

26-
const updateBreadcrumbFile = async (filePath: string): Promise<void> => {
27-
try {
28-
const content = await fs.readFile(filePath, 'utf-8');
29-
const { data: frontMatter, content: fileContent } = matter(content);
52+
async function generateFolderDescription(files: FileInfo[]): Promise<string> {
53+
if (files.length === 0) {
54+
return 'Documentation for this section is coming soon.';
55+
}
3056

31-
if (frontMatter.description &&
32-
frontMatter.description.match(/\bOP Mainnet\b|\bOptimism Mainnet\b/gi) &&
33-
!frontMatter.description.includes('OP Stack')) {
57+
const overviewFile = files.find(file =>
58+
file.url.toLowerCase().includes('overview') ||
59+
file.url.toLowerCase().includes('introduction')
60+
);
3461

35-
frontMatter.description = updateOPTerminology(frontMatter.description);
36-
62+
if (overviewFile && overviewFile.content) {
63+
const desc = extractFirstParagraph(overviewFile.content);
64+
if (desc) return desc;
65+
}
3766

38-
const updatedContent = matter.stringify(fileContent, frontMatter);
39-
await fs.writeFile(filePath, updatedContent);
40-
console.log(`Updated description in breadcrumb file: ${filePath}`);
67+
const folderName = toTitleCase(path.basename(path.dirname(files[0].url)));
68+
const topics = files.map(file => toTitleCase(path.basename(file.url))).join(', ');
69+
70+
return `Documentation covering ${topics} in the ${folderName} section of the OP Stack ecosystem.`;
71+
}
72+
73+
async function getContentFiles(folderPath: string): Promise<FileInfo[]> {
74+
const files = await fs.readdir(folderPath);
75+
const fileInfos: FileInfo[] = [];
76+
const folderName = path.basename(folderPath);
77+
78+
for (const file of files) {
79+
if (file.startsWith('_') ||
80+
file === `${folderName}.mdx` ||
81+
file.startsWith('.') ||
82+
file.endsWith('.tsx') ||
83+
file.endsWith('.json')) {
84+
continue;
85+
}
86+
87+
const filePath = path.join(folderPath, file);
88+
const stats = await fs.stat(filePath);
89+
90+
if (!stats.isDirectory() && (file.endsWith('.md') || file.endsWith('.mdx'))) {
91+
try {
92+
const content = await fs.readFile(filePath, 'utf-8');
93+
const { data: frontMatter } = matter(content);
94+
const fileName = path.basename(file, path.extname(file));
95+
const fileTitle = frontMatter.title || toTitleCase(fileName);
96+
const relativeUrl = `/${path.relative(rootDir, filePath)}`.replace(/\.(md|mdx)$/, '');
97+
98+
fileInfos.push({
99+
title: fileTitle,
100+
url: relativeUrl,
101+
description: frontMatter.description,
102+
content: content
103+
});
104+
} catch (error) {
105+
console.error(`Error processing file ${file}:`, error);
106+
}
41107
}
42-
} catch (error) {
43-
console.error(`Error processing file ${filePath}:`, error);
44108
}
45-
};
46109

47-
const processFolder = async (folderPath: string): Promise<void> => {
110+
return fileInfos;
111+
}
112+
113+
async function createBreadcrumb(folderPath: string, folderName: string): Promise<string> {
114+
const files = await getContentFiles(folderPath);
115+
const title = toTitleCase(folderName);
116+
const description = await generateFolderDescription(files);
117+
118+
let content = `---
119+
title: ${title}
120+
description: ${description}
121+
lang: en-US
122+
---
123+
124+
import { Card, Cards } from 'nextra/components'
125+
126+
# ${title}
127+
128+
${description}
129+
130+
`;
131+
132+
if (files.length > 0) {
133+
content += '<Cards>\n';
134+
files.forEach(({ title: fileTitle, url }) => {
135+
content += ` <Card title="${fileTitle}" href="${url}" />\n`;
136+
});
137+
content += '</Cards>';
138+
} else {
139+
content += 'Documentation for this section is coming soon.';
140+
}
141+
142+
return content;
143+
}
144+
145+
async function processStackSubfolders(stackPath: string): Promise<void> {
48146
try {
49-
const files = await fs.readdir(folderPath);
147+
const entries = await fs.readdir(stackPath, { withFileTypes: true });
50148

51-
for (const file of files) {
52-
const filePath = path.join(folderPath, file);
53-
const stats = await fs.stat(filePath);
54-
55-
if (stats.isDirectory()) {
56-
57-
const breadcrumbFile = path.join(folderPath, `${file}.mdx`);
58-
try {
59-
await fs.access(breadcrumbFile);
60-
await updateBreadcrumbFile(breadcrumbFile);
61-
} catch (error) {
149+
for (const entry of entries) {
150+
if (!entry.isDirectory() || entry.name.startsWith('_')) {
151+
continue;
152+
}
62153

63-
}
64-
154+
const subfolderPath = path.join(stackPath, entry.name);
155+
const breadcrumbPath = path.join(subfolderPath, `${entry.name}.mdx`);
65156

66-
await processFolder(filePath);
157+
console.log(`Processing stack subfolder: ${entry.name}`);
158+
159+
try {
160+
const content = await createBreadcrumb(subfolderPath, entry.name);
161+
await fs.writeFile(breadcrumbPath, content);
162+
console.log(`Created/Updated breadcrumb for: ${entry.name}`);
163+
} catch (error) {
164+
console.error(`Error creating breadcrumb for ${entry.name}:`, error);
67165
}
68166
}
69167
} catch (error) {
70-
console.error(`Error processing folder ${folderPath}:`, error);
168+
console.error('Error processing stack subfolders:', error);
71169
}
72-
};
170+
}
73171

74172
const main = async (): Promise<void> => {
75-
console.log('Starting breadcrumb description update process...');
173+
console.log('Starting stack subfolder breadcrumb update process...');
76174
console.log('Root directory:', rootDir);
77175

78-
for (const folder of targetFolders) {
79-
const folderPath = path.join(rootDir, folder);
80-
await processFolder(folderPath);
176+
try {
177+
const stackPath = path.join(rootDir, 'stack');
178+
await fs.access(stackPath);
179+
await processStackSubfolders(stackPath);
180+
console.log('Finished updating stack subfolder breadcrumbs.');
181+
} catch (error) {
182+
console.error('Error in main process:', error);
183+
process.exit(1);
81184
}
82-
83-
console.log('Finished updating breadcrumb descriptions.');
84185
};
85186

86187
main().catch(error => {

0 commit comments

Comments
 (0)