Skip to content

Commit 6633952

Browse files
committed
updated script file
1 parent 66d7e38 commit 6633952

File tree

4 files changed

+61
-67
lines changed

4 files changed

+61
-67
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Optimism Docs",
55
"scripts": {
66
"lint": "eslint . --ext mdx --max-warnings 0 && pnpm spellcheck:lint",
7-
"fix": "eslint . --ext mdx --fix && pnpm spellcheck:fix",
7+
"fix": "eslint . --ext mdx --fix && pnpm spellcheck:fix && pnpm check-breadcrumbs",
88
"spellcheck:lint": "cspell lint \"**/*.mdx\"",
99
"spellcheck:fix": "cspell --words-only --unique \"**/*.mdx\" | sort --ignore-case | uniq > words.txt",
1010
"linkcheck": "lychee --config ./lychee.toml --quiet \"./pages\"",

utils/breadcrumbs.ts

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,70 @@ import * as path from 'path';
33
import matter from 'gray-matter';
44

55
const rootDir = path.join(process.cwd(), 'pages');
6-
const errors: string[] = [];
6+
const warnings: string[] = [];
77

8-
interface PageInfo {
9-
title: string;
10-
url: string;
11-
}
8+
// ANSI color codes
9+
const YELLOW = '\x1b[33m';
10+
const RESET = '\x1b[0m';
11+
const BOLD = '\x1b[1m';
1212

13-
async function getReferencedPages(breadcrumbContent: string): Promise<string[]> {
14-
// Extract URLs from Card components in the breadcrumb file
15-
const cardRegex = /<Card[^>]*href="([^"]+)"[^>]*>/g;
16-
const urls: string[] = [];
17-
let match;
18-
19-
while ((match = cardRegex.exec(breadcrumbContent)) !== null) {
20-
urls.push(match[1]);
13+
// Pages to exclude from checks
14+
const excludedPages = [
15+
'400.mdx',
16+
'500.mdx',
17+
'index.mdx',
18+
'404.mdx'
19+
];
20+
21+
async function getReferencedPagesFromBreadcrumb(breadcrumbPath: string): Promise<string[]> {
22+
try {
23+
const content = await fs.readFile(breadcrumbPath, 'utf-8');
24+
const cardMatches = content.match(/<Card[^>]*href="([^"]+)"[^>]*>/g) || [];
25+
return cardMatches.map(match => {
26+
const hrefMatch = match.match(/href="([^"]+)"/);
27+
return hrefMatch ? hrefMatch[1] : '';
28+
}).filter(Boolean);
29+
} catch (error) {
30+
return [];
2131
}
22-
23-
return urls;
2432
}
2533

2634
async function checkDirectory(dirPath: string): Promise<void> {
2735
const entries = await fs.readdir(dirPath, { withFileTypes: true });
36+
const currentDir = path.basename(dirPath);
2837

29-
// First, find the breadcrumb file for this directory
30-
const dirName = path.basename(dirPath);
31-
const breadcrumbFile = path.join(dirPath, `${dirName}.mdx`);
32-
let referencedPages: string[] = [];
33-
34-
try {
35-
const breadcrumbContent = await fs.readFile(breadcrumbFile, 'utf-8');
36-
referencedPages = await getReferencedPages(breadcrumbContent);
37-
} catch (error) {
38-
// Only check for missing references if not in root directory
39-
if (dirPath !== rootDir) {
40-
errors.push(`Missing breadcrumb file for directory: ${path.relative(rootDir, dirPath)}`);
41-
return;
38+
// Skip the root directory check
39+
if (dirPath !== rootDir) {
40+
const breadcrumbPath = path.join(dirPath, `${currentDir}.mdx`);
41+
const referencedPages = await getReferencedPagesFromBreadcrumb(breadcrumbPath);
42+
43+
// Check all .mdx and .md files in the current directory
44+
for (const entry of entries) {
45+
if (entry.isFile() &&
46+
(entry.name.endsWith('.mdx') || entry.name.endsWith('.md')) &&
47+
!excludedPages.includes(entry.name) &&
48+
entry.name !== `${currentDir}.mdx`) {
49+
50+
const pageName = entry.name.replace(/\.(md|mdx)$/, '');
51+
const relativePath = `/stack/${path.relative(rootDir, dirPath)}/${pageName}`.replace(/\\/g, '/');
52+
53+
if (!referencedPages.includes(relativePath)) {
54+
const humanReadableName = pageName.split('-')
55+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
56+
.join(' ');
57+
58+
warnings.push(
59+
`Page "${humanReadableName}" at path "${relativePath}" is not listed in the breadcrumb navigation of ${currentDir}.mdx`
60+
);
61+
}
62+
}
4263
}
4364
}
4465

45-
// Check each entry in the directory
66+
// Process subdirectories
4667
for (const entry of entries) {
47-
if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue;
48-
49-
const fullPath = path.join(dirPath, entry.name);
50-
51-
if (entry.isDirectory()) {
52-
// Recursively check subdirectories
53-
await checkDirectory(fullPath);
54-
} else if ((entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) &&
55-
entry.name !== `${dirName}.mdx`) {
56-
// Check if this page is referenced in the breadcrumb
57-
const relativePath = '/' + path.relative(rootDir, fullPath)
58-
.replace(/\.(md|mdx)$/, '');
59-
60-
if (!referencedPages.includes(relativePath)) {
61-
errors.push(`Page not referenced in breadcrumb: ${relativePath}`);
62-
}
68+
if (entry.isDirectory() && !entry.name.startsWith('_') && !entry.name.startsWith('.')) {
69+
await checkDirectory(path.join(dirPath, entry.name));
6370
}
6471
}
6572
}
@@ -68,15 +75,15 @@ async function main() {
6875
try {
6976
await checkDirectory(rootDir);
7077

71-
if (errors.length > 0) {
72-
console.error('Breadcrumb check failed:');
73-
errors.forEach(error => console.error(`- ${error}`));
78+
if (warnings.length > 0) {
79+
console.log(`${YELLOW}${BOLD}Missing pages in breadcrumb navigation:${RESET}`);
80+
warnings.forEach(warning => console.log(`${YELLOW}- ${warning}${RESET}`));
7481
process.exit(1);
7582
} else {
76-
console.log('All pages are properly referenced in breadcrumb navigation.');
83+
console.log('All pages are properly listed in their respective breadcrumb navigation files.');
7784
}
7885
} catch (error) {
79-
console.error('Error checking breadcrumbs:', error);
86+
console.log(`${YELLOW}${BOLD}Error checking breadcrumbs:${RESET}`, error);
8087
process.exit(1);
8188
}
8289
}

utils/create-breadcrumbs.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,15 @@ function toTitleCase(str: string): string {
1818
}
1919

2020
function extractFirstParagraph(content: string): string {
21-
// Remove frontmatter
21+
2222
content = content.replace(/^---[\s\S]*?---/, '');
2323

24-
// Remove import statements
2524
content = content.replace(/^import[\s\S]*?\n/gm, '');
26-
27-
// Remove HTML/MDX tags
25+
2826
content = content.replace(/<[^>]+>/g, ' ');
29-
30-
// Remove markdown links but keep text
27+
3128
content = content.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
3229

33-
// Remove headers
3430
content = content.replace(/^#.+$/gm, '');
3531

3632
const paragraphs = content.split(/\n\n+/);

words.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Allocs
1111
allocs
1212
altda
1313
ANDI
14-
Ankr
1514
Apeworx
1615
Arweave
1716
authrpc
@@ -148,7 +147,6 @@ Holesky
148147
holesky
149148
IGNOREPRICE
150149
ignoreprice
151-
Immunefi
152150
implicity
153151
Inator
154152
inator
@@ -197,7 +195,6 @@ minsuggestedpriorityfee
197195
Mintable
198196
Mintplex
199197
MIPSEVM
200-
Mitigations
201198
Monitorism
202199
Moralis
203200
Mordor
@@ -291,8 +288,6 @@ Protip
291288
Proxied
292289
proxyd
293290
pseudorandomly
294-
Pyth
295-
Pyth's
296291
QRNG
297292
Quicknode
298293
quicknode
@@ -326,9 +321,6 @@ safedb
326321
Schnorr
327322
secp
328323
SELFDESTRUCT
329-
SEPOLIA
330-
Sepolia
331-
sepolia
332324
seqnr
333325
SEQUENCERHTTP
334326
sequencerhttp
@@ -398,7 +390,6 @@ VMDEBUG
398390
vmdebug
399391
VMODULE
400392
vmodule
401-
voxel
402393
wagmi
403394
Warpcast
404395
xlarge

0 commit comments

Comments
 (0)