From f0d666c15a6437d369a6b5773b639bb0377b5e33 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:31:09 +0100 Subject: [PATCH 01/18] update breadcrumb script --- pages/stack/beta-features/beta-features.mdx | 16 ++ pages/stack/fault-proofs/fault-proofs.mdx | 20 ++ pages/stack/features/features.mdx | 15 ++ pages/stack/interop/interop.mdx | 19 ++ pages/stack/research/research.mdx | 15 ++ pages/stack/rollup/rollup.mdx | 17 ++ pages/stack/security/security.mdx | 16 ++ pages/stack/transactions/transactions.mdx | 20 ++ utils/create-breadcrumbs.ts | 199 +++++++++++++++----- 9 files changed, 288 insertions(+), 49 deletions(-) create mode 100644 pages/stack/beta-features/beta-features.mdx create mode 100644 pages/stack/fault-proofs/fault-proofs.mdx create mode 100644 pages/stack/features/features.mdx create mode 100644 pages/stack/interop/interop.mdx create mode 100644 pages/stack/research/research.mdx create mode 100644 pages/stack/rollup/rollup.mdx create mode 100644 pages/stack/security/security.mdx create mode 100644 pages/stack/transactions/transactions.mdx diff --git a/pages/stack/beta-features/beta-features.mdx b/pages/stack/beta-features/beta-features.mdx new file mode 100644 index 000000000..bfdd3a164 --- /dev/null +++ b/pages/stack/beta-features/beta-features.mdx @@ -0,0 +1,16 @@ +--- +title: Beta Features +description: Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Beta Features + +Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features section of the OP Stack ecosystem. + + + + + \ No newline at end of file diff --git a/pages/stack/fault-proofs/fault-proofs.mdx b/pages/stack/fault-proofs/fault-proofs.mdx new file mode 100644 index 000000000..0f49365ab --- /dev/null +++ b/pages/stack/fault-proofs/fault-proofs.mdx @@ -0,0 +1,20 @@ +--- +title: Fault Proofs +description: Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security, Mips in the Fault Proofs section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Fault Proofs + +Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security, Mips in the Fault Proofs section of the OP Stack ecosystem. + + + + + + + + + \ No newline at end of file diff --git a/pages/stack/features/features.mdx b/pages/stack/features/features.mdx new file mode 100644 index 000000000..7f5e479cd --- /dev/null +++ b/pages/stack/features/features.mdx @@ -0,0 +1,15 @@ +--- +title: Features +description: Documentation covering Send Raw Transaction Conditional in the Features section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Features + +Documentation covering Send Raw Transaction Conditional in the Features section of the OP Stack ecosystem. + + + + \ No newline at end of file diff --git a/pages/stack/interop/interop.mdx b/pages/stack/interop/interop.mdx new file mode 100644 index 000000000..76d4d8a95 --- /dev/null +++ b/pages/stack/interop/interop.mdx @@ -0,0 +1,19 @@ +--- +title: Interop +description: Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Interop + +Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem. + + + + + + + + \ No newline at end of file diff --git a/pages/stack/research/research.mdx b/pages/stack/research/research.mdx new file mode 100644 index 000000000..c530c1be8 --- /dev/null +++ b/pages/stack/research/research.mdx @@ -0,0 +1,15 @@ +--- +title: Research +description: Documentation covering Block Time Research in the Research section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Research + +Documentation covering Block Time Research in the Research section of the OP Stack ecosystem. + + + + \ No newline at end of file diff --git a/pages/stack/rollup/rollup.mdx b/pages/stack/rollup/rollup.mdx new file mode 100644 index 000000000..15d96a31c --- /dev/null +++ b/pages/stack/rollup/rollup.mdx @@ -0,0 +1,17 @@ +--- +title: Rollup +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... +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Rollup + +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... + + + + + + \ No newline at end of file diff --git a/pages/stack/security/security.mdx b/pages/stack/security/security.mdx new file mode 100644 index 000000000..d770098b3 --- /dev/null +++ b/pages/stack/security/security.mdx @@ -0,0 +1,16 @@ +--- +title: Security +description: Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Security + +Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem. + + + + + \ No newline at end of file diff --git a/pages/stack/transactions/transactions.mdx b/pages/stack/transactions/transactions.mdx new file mode 100644 index 000000000..c084cfc8f --- /dev/null +++ b/pages/stack/transactions/transactions.mdx @@ -0,0 +1,20 @@ +--- +title: Transactions +description: Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Transaction Flow, Withdrawal Flow in the Transactions section of the OP Stack ecosystem. +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# Transactions + +Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Transaction Flow, Withdrawal Flow in the Transactions section of the OP Stack ecosystem. + + + + + + + + + \ No newline at end of file diff --git a/utils/create-breadcrumbs.ts b/utils/create-breadcrumbs.ts index 7bfab9804..b6f2cf11f 100644 --- a/utils/create-breadcrumbs.ts +++ b/utils/create-breadcrumbs.ts @@ -2,85 +2,186 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import matter from 'gray-matter'; -const targetFolders: string[] = ['builders', 'chain', 'stack', 'connect']; const rootDir: string = path.join(__dirname, '..', 'pages'); interface FileInfo { title: string; url: string; + description?: string; + content: string; } -function updateOPTerminology(description: string): string { +function toTitleCase(str: string): string { + return str.split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(' '); +} - if (description.includes('OP Stack')) { - return description; - } +function extractFirstParagraph(content: string): string { + // Remove frontmatter + content = content.replace(/^---[\s\S]*?---/, ''); + + // Remove import statements + content = content.replace(/^import[\s\S]*?\n/gm, ''); + + // Remove HTML/MDX tags + content = content.replace(/<[^>]+>/g, ' '); + + // Remove markdown links but keep text + content = content.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); + + // Remove headers + content = content.replace(/^#.+$/gm, ''); - // Replace variations of "OP Mainnet" with "OP Stack" - return description - .replace(/\bOP Mainnet\b/gi, 'OP Stack') - .replace(/\bOptimism Mainnet\b/gi, 'OP Stack') - .replace(/\bOptimism mainnet\b/gi, 'OP Stack'); + const paragraphs = content.split(/\n\n+/); + const firstParagraph = paragraphs.find(p => { + const cleaned = p.trim(); + return cleaned.length > 30 && // Minimum length + !cleaned.startsWith('import') && + !cleaned.startsWith('export'); + }); + + if (firstParagraph) { + const cleaned = firstParagraph.replace(/\s+/g, ' ').trim(); + return cleaned.length > 150 ? cleaned.slice(0, 147) + '...' : cleaned; + } + + return ''; } -const updateBreadcrumbFile = async (filePath: string): Promise => { - try { - const content = await fs.readFile(filePath, 'utf-8'); - const { data: frontMatter, content: fileContent } = matter(content); +async function generateFolderDescription(files: FileInfo[]): Promise { + if (files.length === 0) { + return 'Documentation for this section is coming soon.'; + } - if (frontMatter.description && - frontMatter.description.match(/\bOP Mainnet\b|\bOptimism Mainnet\b/gi) && - !frontMatter.description.includes('OP Stack')) { + const overviewFile = files.find(file => + file.url.toLowerCase().includes('overview') || + file.url.toLowerCase().includes('introduction') + ); - frontMatter.description = updateOPTerminology(frontMatter.description); - + if (overviewFile && overviewFile.content) { + const desc = extractFirstParagraph(overviewFile.content); + if (desc) return desc; + } - const updatedContent = matter.stringify(fileContent, frontMatter); - await fs.writeFile(filePath, updatedContent); - console.log(`Updated description in breadcrumb file: ${filePath}`); + const folderName = toTitleCase(path.basename(path.dirname(files[0].url))); + const topics = files.map(file => toTitleCase(path.basename(file.url))).join(', '); + + return `Documentation covering ${topics} in the ${folderName} section of the OP Stack ecosystem.`; +} + +async function getContentFiles(folderPath: string): Promise { + const files = await fs.readdir(folderPath); + const fileInfos: FileInfo[] = []; + const folderName = path.basename(folderPath); + + for (const file of files) { + if (file.startsWith('_') || + file === `${folderName}.mdx` || + file.startsWith('.') || + file.endsWith('.tsx') || + file.endsWith('.json')) { + continue; + } + + const filePath = path.join(folderPath, file); + const stats = await fs.stat(filePath); + + if (!stats.isDirectory() && (file.endsWith('.md') || file.endsWith('.mdx'))) { + try { + const content = await fs.readFile(filePath, 'utf-8'); + const { data: frontMatter } = matter(content); + const fileName = path.basename(file, path.extname(file)); + const fileTitle = frontMatter.title || toTitleCase(fileName); + const relativeUrl = `/${path.relative(rootDir, filePath)}`.replace(/\.(md|mdx)$/, ''); + + fileInfos.push({ + title: fileTitle, + url: relativeUrl, + description: frontMatter.description, + content: content + }); + } catch (error) { + console.error(`Error processing file ${file}:`, error); + } } - } catch (error) { - console.error(`Error processing file ${filePath}:`, error); } -}; -const processFolder = async (folderPath: string): Promise => { + return fileInfos; +} + +async function createBreadcrumb(folderPath: string, folderName: string): Promise { + const files = await getContentFiles(folderPath); + const title = toTitleCase(folderName); + const description = await generateFolderDescription(files); + + let content = `--- +title: ${title} +description: ${description} +lang: en-US +--- + +import { Card, Cards } from 'nextra/components' + +# ${title} + +${description} + +`; + + if (files.length > 0) { + content += '\n'; + files.forEach(({ title: fileTitle, url }) => { + content += ` \n`; + }); + content += ''; + } else { + content += 'Documentation for this section is coming soon.'; + } + + return content; +} + +async function processStackSubfolders(stackPath: string): Promise { try { - const files = await fs.readdir(folderPath); + const entries = await fs.readdir(stackPath, { withFileTypes: true }); - for (const file of files) { - const filePath = path.join(folderPath, file); - const stats = await fs.stat(filePath); - - if (stats.isDirectory()) { - - const breadcrumbFile = path.join(folderPath, `${file}.mdx`); - try { - await fs.access(breadcrumbFile); - await updateBreadcrumbFile(breadcrumbFile); - } catch (error) { + for (const entry of entries) { + if (!entry.isDirectory() || entry.name.startsWith('_')) { + continue; + } - } - + const subfolderPath = path.join(stackPath, entry.name); + const breadcrumbPath = path.join(subfolderPath, `${entry.name}.mdx`); - await processFolder(filePath); + console.log(`Processing stack subfolder: ${entry.name}`); + + try { + const content = await createBreadcrumb(subfolderPath, entry.name); + await fs.writeFile(breadcrumbPath, content); + console.log(`Created/Updated breadcrumb for: ${entry.name}`); + } catch (error) { + console.error(`Error creating breadcrumb for ${entry.name}:`, error); } } } catch (error) { - console.error(`Error processing folder ${folderPath}:`, error); + console.error('Error processing stack subfolders:', error); } -}; +} const main = async (): Promise => { - console.log('Starting breadcrumb description update process...'); + console.log('Starting stack subfolder breadcrumb update process...'); console.log('Root directory:', rootDir); - for (const folder of targetFolders) { - const folderPath = path.join(rootDir, folder); - await processFolder(folderPath); + try { + const stackPath = path.join(rootDir, 'stack'); + await fs.access(stackPath); + await processStackSubfolders(stackPath); + console.log('Finished updating stack subfolder breadcrumbs.'); + } catch (error) { + console.error('Error in main process:', error); + process.exit(1); } - - console.log('Finished updating breadcrumb descriptions.'); }; main().catch(error => { From 2a8ea4971e3dc52ed75058e722a19a942c2e0254 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:31:20 +0100 Subject: [PATCH 02/18] updated breadcrumb notes --- notes/breadcrumbs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/breadcrumbs.md b/notes/breadcrumbs.md index e30512e7f..da1007655 100644 --- a/notes/breadcrumbs.md +++ b/notes/breadcrumbs.md @@ -26,7 +26,7 @@ pnpm create-breadcrumbs 2. **After Running** * Review generated `.mdx` files in each folder - * Check updated descriptions + * Check updated descriptions, plese update the description. * Verify Card components and links ## Common Issues From 52b93cfd5349aaf890b8ccb633d621fdf3c9bc03 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:40:59 +0100 Subject: [PATCH 03/18] Update notes/breadcrumbs.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- notes/breadcrumbs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/breadcrumbs.md b/notes/breadcrumbs.md index da1007655..e6f8b3b83 100644 --- a/notes/breadcrumbs.md +++ b/notes/breadcrumbs.md @@ -26,7 +26,7 @@ pnpm create-breadcrumbs 2. **After Running** * Review generated `.mdx` files in each folder - * Check updated descriptions, plese update the description. + * Check updated descriptions, please update the description. * Verify Card components and links ## Common Issues From 2595a8f06a4df3ecec2eba118885bd4a02fcb06d Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:41:16 +0100 Subject: [PATCH 04/18] Update pages/stack/beta-features/beta-features.mdx Co-authored-by: Bradley Camacho <42678939+bradleycamacho@users.noreply.github.com> --- pages/stack/beta-features/beta-features.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/beta-features/beta-features.mdx b/pages/stack/beta-features/beta-features.mdx index bfdd3a164..28cedff3b 100644 --- a/pages/stack/beta-features/beta-features.mdx +++ b/pages/stack/beta-features/beta-features.mdx @@ -6,7 +6,7 @@ lang: en-US import { Card, Cards } from 'nextra/components' -# Beta Features +# Beta features Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features section of the OP Stack ecosystem. From 28bc2d904b5c6100f181abd603e8da7f0c78afb9 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:46:34 +0100 Subject: [PATCH 05/18] add workflow --- .github/workflows/check-breadcrumbs.yml | 91 +++++++++++++++++++++ package.json | 1 + pages/stack/beta-features/beta-features.mdx | 3 +- pages/stack/fault-proofs/fault-proofs.mdx | 7 +- pages/stack/features/features.mdx | 2 +- pages/stack/interop/interop.mdx | 6 +- pages/stack/research/research.mdx | 2 +- pages/stack/rollup/rollup.mdx | 4 +- pages/stack/security/security.mdx | 3 +- pages/stack/transactions/transactions.mdx | 7 +- utils/check-breadcrumbs.ts | 0 words.txt | 1 + 12 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/check-breadcrumbs.yml create mode 100644 utils/check-breadcrumbs.ts diff --git a/.github/workflows/check-breadcrumbs.yml b/.github/workflows/check-breadcrumbs.yml new file mode 100644 index 000000000..d2e70713f --- /dev/null +++ b/.github/workflows/check-breadcrumbs.yml @@ -0,0 +1,91 @@ +```yaml +name: Check Breadcrumbs + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + paths: + - 'pages/**/*.mdx' + - 'pages/**/*.md' + +jobs: + check-breadcrumbs: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '20.x' + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install dependencies + run: pnpm install + + - name: Create check-breadcrumbs script + run: | + cat > utils/check-breadcrumbs.ts << 'EOL' + import * as fs from 'fs/promises'; + import * as path from 'path'; + + const rootDir = path.join(process.cwd(), 'pages'); + const errors: string[] = []; + + async function checkDirectory(dirPath: string): Promise { + const entries = await fs.readdir(dirPath, { withFileTypes: true }); + + for (const entry of entries) { + if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue; + + const fullPath = path.join(dirPath, entry.name); + + if (entry.isDirectory()) { + // Skip if it's the root directory + if (fullPath === rootDir) continue; + + // Check if breadcrumb file exists for this directory + const breadcrumbFile = path.join(dirPath, `${entry.name}.mdx`); + try { + await fs.access(breadcrumbFile); + } catch { + const relativePath = path.relative(rootDir, dirPath); + errors.push(`Missing breadcrumb file for directory: ${relativePath}/${entry.name}`); + } + + // Recursively check subdirectories + await checkDirectory(fullPath); + } + } + } + + async function main() { + try { + await checkDirectory(rootDir); + + if (errors.length > 0) { + console.error('Breadcrumb check failed:'); + errors.forEach(error => console.error(`- ${error}`)); + process.exit(1); + } else { + console.log('All directories have breadcrumb files.'); + } + } catch (error) { + console.error('Error checking breadcrumbs:', error); + process.exit(1); + } + } + + main(); + EOL + + - name: Run breadcrumb check + run: pnpm ts-node utils/check-breadcrumbs.ts + +``` \ No newline at end of file diff --git a/package.json b/package.json index 6f0b17b6a..868eb0a41 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "spellcheck:fix": "cspell --words-only --unique \"**/*.mdx\" | sort --ignore-case | uniq > words.txt", "linkcheck": "lychee --config ./lychee.toml --quiet \"./pages\"", "create-breadcrumbs":"npx ts-node --skip-project utils/create-breadcrumbs.ts", + "check-breadcrumbs":"npx ts-node --skip-project utils/check-breadcrumbs.ts", "index:docs": "npx ts-node --skip-project utils/algolia-indexer.ts", "dev": "next dev", "build": "next build", diff --git a/pages/stack/beta-features/beta-features.mdx b/pages/stack/beta-features/beta-features.mdx index bfdd3a164..24257e8e3 100644 --- a/pages/stack/beta-features/beta-features.mdx +++ b/pages/stack/beta-features/beta-features.mdx @@ -12,5 +12,6 @@ Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features sectio + - \ No newline at end of file + diff --git a/pages/stack/fault-proofs/fault-proofs.mdx b/pages/stack/fault-proofs/fault-proofs.mdx index 0f49365ab..4da08bb26 100644 --- a/pages/stack/fault-proofs/fault-proofs.mdx +++ b/pages/stack/fault-proofs/fault-proofs.mdx @@ -12,9 +12,14 @@ Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security + + + + + - \ No newline at end of file + diff --git a/pages/stack/features/features.mdx b/pages/stack/features/features.mdx index 7f5e479cd..84cad55a4 100644 --- a/pages/stack/features/features.mdx +++ b/pages/stack/features/features.mdx @@ -12,4 +12,4 @@ Documentation covering Send Raw Transaction Conditional in the Features section - \ No newline at end of file + diff --git a/pages/stack/interop/interop.mdx b/pages/stack/interop/interop.mdx index 76d4d8a95..952e51872 100644 --- a/pages/stack/interop/interop.mdx +++ b/pages/stack/interop/interop.mdx @@ -12,8 +12,12 @@ Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersi + + + + - \ No newline at end of file + diff --git a/pages/stack/research/research.mdx b/pages/stack/research/research.mdx index c530c1be8..1a485ee0f 100644 --- a/pages/stack/research/research.mdx +++ b/pages/stack/research/research.mdx @@ -12,4 +12,4 @@ Documentation covering Block Time Research in the Research section of the OP Sta - \ No newline at end of file + diff --git a/pages/stack/rollup/rollup.mdx b/pages/stack/rollup/rollup.mdx index 15d96a31c..ca95c2564 100644 --- a/pages/stack/rollup/rollup.mdx +++ b/pages/stack/rollup/rollup.mdx @@ -12,6 +12,8 @@ The big idea that makes Optimism possible is the Optimistic Rollup. We'll go thr + + - \ No newline at end of file + diff --git a/pages/stack/security/security.mdx b/pages/stack/security/security.mdx index d770098b3..fbf62b199 100644 --- a/pages/stack/security/security.mdx +++ b/pages/stack/security/security.mdx @@ -12,5 +12,6 @@ Documentation covering Faq, Pause in the Security section of the OP Stack ecosys + - \ No newline at end of file + diff --git a/pages/stack/transactions/transactions.mdx b/pages/stack/transactions/transactions.mdx index c084cfc8f..02d703c69 100644 --- a/pages/stack/transactions/transactions.mdx +++ b/pages/stack/transactions/transactions.mdx @@ -12,9 +12,14 @@ Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Tra + + + + + - \ No newline at end of file + diff --git a/utils/check-breadcrumbs.ts b/utils/check-breadcrumbs.ts new file mode 100644 index 000000000..e69de29bb diff --git a/words.txt b/words.txt index 5be79af1c..82aba8f3d 100644 --- a/words.txt +++ b/words.txt @@ -359,6 +359,7 @@ SUPERCHAIN Superchain superchain Superchain's +Superchainerc Superchains Superscan Supersim From cac24589f20225c0a8f48afaafc4576159b8409d Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:48:54 +0100 Subject: [PATCH 06/18] fix code issues --- .github/workflows/check-breadcrumbs.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-breadcrumbs.yml b/.github/workflows/check-breadcrumbs.yml index d2e70713f..b1a7895a5 100644 --- a/.github/workflows/check-breadcrumbs.yml +++ b/.github/workflows/check-breadcrumbs.yml @@ -1,4 +1,4 @@ -```yaml + name: Check Breadcrumbs on: @@ -86,6 +86,4 @@ jobs: EOL - name: Run breadcrumb check - run: pnpm ts-node utils/check-breadcrumbs.ts - -``` \ No newline at end of file + run: pnpm ts-node utils/check-breadcrumbs.ts \ No newline at end of file From a3d3a4cff26d11855b0e5acd80345be441a04297 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 1 Nov 2024 15:54:40 +0100 Subject: [PATCH 07/18] updated the workflow file --- .github/workflows/check-breadcrumbs.yml | 59 +------------------------ 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/.github/workflows/check-breadcrumbs.yml b/.github/workflows/check-breadcrumbs.yml index b1a7895a5..a077cf137 100644 --- a/.github/workflows/check-breadcrumbs.yml +++ b/.github/workflows/check-breadcrumbs.yml @@ -1,4 +1,3 @@ - name: Check Breadcrumbs on: @@ -29,61 +28,5 @@ jobs: - name: Install dependencies run: pnpm install - - name: Create check-breadcrumbs script - run: | - cat > utils/check-breadcrumbs.ts << 'EOL' - import * as fs from 'fs/promises'; - import * as path from 'path'; - - const rootDir = path.join(process.cwd(), 'pages'); - const errors: string[] = []; - - async function checkDirectory(dirPath: string): Promise { - const entries = await fs.readdir(dirPath, { withFileTypes: true }); - - for (const entry of entries) { - if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue; - - const fullPath = path.join(dirPath, entry.name); - - if (entry.isDirectory()) { - // Skip if it's the root directory - if (fullPath === rootDir) continue; - - // Check if breadcrumb file exists for this directory - const breadcrumbFile = path.join(dirPath, `${entry.name}.mdx`); - try { - await fs.access(breadcrumbFile); - } catch { - const relativePath = path.relative(rootDir, dirPath); - errors.push(`Missing breadcrumb file for directory: ${relativePath}/${entry.name}`); - } - - // Recursively check subdirectories - await checkDirectory(fullPath); - } - } - } - - async function main() { - try { - await checkDirectory(rootDir); - - if (errors.length > 0) { - console.error('Breadcrumb check failed:'); - errors.forEach(error => console.error(`- ${error}`)); - process.exit(1); - } else { - console.log('All directories have breadcrumb files.'); - } - } catch (error) { - console.error('Error checking breadcrumbs:', error); - process.exit(1); - } - } - - main(); - EOL - - name: Run breadcrumb check - run: pnpm ts-node utils/check-breadcrumbs.ts \ No newline at end of file + run: pnpm check-breadcrumbs \ No newline at end of file From 5ced9a3525f56a13f08d49a1bd8f8438e643fea3 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 14:28:04 +0100 Subject: [PATCH 08/18] updated check breadcrumb script --- .github/workflows/breadcrumbs.yml | 32 +++++++++++++++++++++ package.json | 2 +- pages/stack/beta-features/beta-features.mdx | 5 ++-- pages/stack/fault-proofs/fault-proofs.mdx | 7 +---- pages/stack/features/features.mdx | 2 +- pages/stack/interop/interop.mdx | 6 +--- pages/stack/research/research.mdx | 2 +- pages/stack/rollup/rollup.mdx | 4 +-- pages/stack/security/security.mdx | 3 +- pages/stack/transactions/transactions.mdx | 7 +---- 10 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/breadcrumbs.yml diff --git a/.github/workflows/breadcrumbs.yml b/.github/workflows/breadcrumbs.yml new file mode 100644 index 000000000..a077cf137 --- /dev/null +++ b/.github/workflows/breadcrumbs.yml @@ -0,0 +1,32 @@ +name: Check Breadcrumbs + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + paths: + - 'pages/**/*.mdx' + - 'pages/**/*.md' + +jobs: + check-breadcrumbs: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '20.x' + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install dependencies + run: pnpm install + + - name: Run breadcrumb check + run: pnpm check-breadcrumbs \ No newline at end of file diff --git a/package.json b/package.json index 868eb0a41..708767dc9 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "spellcheck:lint": "cspell lint \"**/*.mdx\"", "spellcheck:fix": "cspell --words-only --unique \"**/*.mdx\" | sort --ignore-case | uniq > words.txt", "linkcheck": "lychee --config ./lychee.toml --quiet \"./pages\"", - "create-breadcrumbs":"npx ts-node --skip-project utils/create-breadcrumbs.ts", + "breadcrumbs":"npx ts-node --skip-project utils/create-breadcrumbs.ts", "check-breadcrumbs":"npx ts-node --skip-project utils/check-breadcrumbs.ts", "index:docs": "npx ts-node --skip-project utils/algolia-indexer.ts", "dev": "next dev", diff --git a/pages/stack/beta-features/beta-features.mdx b/pages/stack/beta-features/beta-features.mdx index 011c86b66..bfdd3a164 100644 --- a/pages/stack/beta-features/beta-features.mdx +++ b/pages/stack/beta-features/beta-features.mdx @@ -6,12 +6,11 @@ lang: en-US import { Card, Cards } from 'nextra/components' -# Beta features +# Beta Features Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features section of the OP Stack ecosystem. - - + \ No newline at end of file diff --git a/pages/stack/fault-proofs/fault-proofs.mdx b/pages/stack/fault-proofs/fault-proofs.mdx index 4da08bb26..0f49365ab 100644 --- a/pages/stack/fault-proofs/fault-proofs.mdx +++ b/pages/stack/fault-proofs/fault-proofs.mdx @@ -12,14 +12,9 @@ Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security - - - - - - + \ No newline at end of file diff --git a/pages/stack/features/features.mdx b/pages/stack/features/features.mdx index 84cad55a4..7f5e479cd 100644 --- a/pages/stack/features/features.mdx +++ b/pages/stack/features/features.mdx @@ -12,4 +12,4 @@ Documentation covering Send Raw Transaction Conditional in the Features section - + \ No newline at end of file diff --git a/pages/stack/interop/interop.mdx b/pages/stack/interop/interop.mdx index 952e51872..76d4d8a95 100644 --- a/pages/stack/interop/interop.mdx +++ b/pages/stack/interop/interop.mdx @@ -12,12 +12,8 @@ Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersi - - - - - + \ No newline at end of file diff --git a/pages/stack/research/research.mdx b/pages/stack/research/research.mdx index 1a485ee0f..c530c1be8 100644 --- a/pages/stack/research/research.mdx +++ b/pages/stack/research/research.mdx @@ -12,4 +12,4 @@ Documentation covering Block Time Research in the Research section of the OP Sta - + \ No newline at end of file diff --git a/pages/stack/rollup/rollup.mdx b/pages/stack/rollup/rollup.mdx index ca95c2564..15d96a31c 100644 --- a/pages/stack/rollup/rollup.mdx +++ b/pages/stack/rollup/rollup.mdx @@ -12,8 +12,6 @@ The big idea that makes Optimism possible is the Optimistic Rollup. We'll go thr - - - + \ No newline at end of file diff --git a/pages/stack/security/security.mdx b/pages/stack/security/security.mdx index fbf62b199..d770098b3 100644 --- a/pages/stack/security/security.mdx +++ b/pages/stack/security/security.mdx @@ -12,6 +12,5 @@ Documentation covering Faq, Pause in the Security section of the OP Stack ecosys - - + \ No newline at end of file diff --git a/pages/stack/transactions/transactions.mdx b/pages/stack/transactions/transactions.mdx index 02d703c69..c084cfc8f 100644 --- a/pages/stack/transactions/transactions.mdx +++ b/pages/stack/transactions/transactions.mdx @@ -12,14 +12,9 @@ Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Tra - - - - - - + \ No newline at end of file From f782dab6e38de309f9a1694f21324eb2efc2f1d3 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 14:30:18 +0100 Subject: [PATCH 09/18] updated script --- .github/workflows/check-breadcrumbs.yml | 32 ---------------- package.json | 2 +- utils/breadcrumbs.ts | 51 +++++++++++++++++++++++++ utils/check-breadcrumbs.ts | 0 4 files changed, 52 insertions(+), 33 deletions(-) delete mode 100644 .github/workflows/check-breadcrumbs.yml create mode 100644 utils/breadcrumbs.ts delete mode 100644 utils/check-breadcrumbs.ts diff --git a/.github/workflows/check-breadcrumbs.yml b/.github/workflows/check-breadcrumbs.yml deleted file mode 100644 index a077cf137..000000000 --- a/.github/workflows/check-breadcrumbs.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Check Breadcrumbs - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - paths: - - 'pages/**/*.mdx' - - 'pages/**/*.md' - -jobs: - check-breadcrumbs: - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Set up Node.js - uses: actions/setup-node@v2 - with: - node-version: '20.x' - - - name: Install pnpm - run: npm install -g pnpm - - - name: Install dependencies - run: pnpm install - - - name: Run breadcrumb check - run: pnpm check-breadcrumbs \ No newline at end of file diff --git a/package.json b/package.json index 708767dc9..2e9eabf66 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "spellcheck:fix": "cspell --words-only --unique \"**/*.mdx\" | sort --ignore-case | uniq > words.txt", "linkcheck": "lychee --config ./lychee.toml --quiet \"./pages\"", "breadcrumbs":"npx ts-node --skip-project utils/create-breadcrumbs.ts", - "check-breadcrumbs":"npx ts-node --skip-project utils/check-breadcrumbs.ts", + "check-breadcrumbs":"npx ts-node --skip-project utils/breadcrumbs.ts", "index:docs": "npx ts-node --skip-project utils/algolia-indexer.ts", "dev": "next dev", "build": "next build", diff --git a/utils/breadcrumbs.ts b/utils/breadcrumbs.ts new file mode 100644 index 000000000..175eeedcd --- /dev/null +++ b/utils/breadcrumbs.ts @@ -0,0 +1,51 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +const rootDir = path.join(process.cwd(), 'pages'); +const errors: string[] = []; + +async function checkDirectory(dirPath: string): Promise { + const entries = await fs.readdir(dirPath, { withFileTypes: true }); + + for (const entry of entries) { + if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue; + + const fullPath = path.join(dirPath, entry.name); + + if (entry.isDirectory()) { + // Skip if it's the root directory + if (fullPath === rootDir) continue; + + // Check if breadcrumb file exists for this directory + const breadcrumbFile = path.join(dirPath, `${entry.name}.mdx`); + try { + await fs.access(breadcrumbFile); + } catch { + const relativePath = path.relative(rootDir, dirPath); + errors.push(`Missing breadcrumb file for directory: ${relativePath}/${entry.name}`); + } + + // Recursively check subdirectories + await checkDirectory(fullPath); + } + } +} + +async function main() { + try { + await checkDirectory(rootDir); + + if (errors.length > 0) { + console.error('Breadcrumb check failed:'); + errors.forEach(error => console.error(`- ${error}`)); + process.exit(1); + } else { + console.log('All directories have breadcrumb files.'); + } + } catch (error) { + console.error('Error checking breadcrumbs:', error); + process.exit(1); + } +} + +main(); \ No newline at end of file diff --git a/utils/check-breadcrumbs.ts b/utils/check-breadcrumbs.ts deleted file mode 100644 index e69de29bb..000000000 From 66d7e38975739a169838b5cff793ba3dabe2c02c Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 14:38:31 +0100 Subject: [PATCH 10/18] updated breadcrumbs script --- utils/breadcrumbs.ts | 59 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/utils/breadcrumbs.ts b/utils/breadcrumbs.ts index 175eeedcd..13efab02f 100644 --- a/utils/breadcrumbs.ts +++ b/utils/breadcrumbs.ts @@ -1,32 +1,65 @@ import * as fs from 'fs/promises'; import * as path from 'path'; +import matter from 'gray-matter'; const rootDir = path.join(process.cwd(), 'pages'); const errors: string[] = []; +interface PageInfo { + title: string; + url: string; +} + +async function getReferencedPages(breadcrumbContent: string): Promise { + // Extract URLs from Card components in the breadcrumb file + const cardRegex = /]*href="([^"]+)"[^>]*>/g; + const urls: string[] = []; + let match; + + while ((match = cardRegex.exec(breadcrumbContent)) !== null) { + urls.push(match[1]); + } + + return urls; +} + async function checkDirectory(dirPath: string): Promise { const entries = await fs.readdir(dirPath, { withFileTypes: true }); + // First, find the breadcrumb file for this directory + const dirName = path.basename(dirPath); + const breadcrumbFile = path.join(dirPath, `${dirName}.mdx`); + let referencedPages: string[] = []; + + try { + const breadcrumbContent = await fs.readFile(breadcrumbFile, 'utf-8'); + referencedPages = await getReferencedPages(breadcrumbContent); + } catch (error) { + // Only check for missing references if not in root directory + if (dirPath !== rootDir) { + errors.push(`Missing breadcrumb file for directory: ${path.relative(rootDir, dirPath)}`); + return; + } + } + + // Check each entry in the directory for (const entry of entries) { if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue; const fullPath = path.join(dirPath, entry.name); if (entry.isDirectory()) { - // Skip if it's the root directory - if (fullPath === rootDir) continue; - - // Check if breadcrumb file exists for this directory - const breadcrumbFile = path.join(dirPath, `${entry.name}.mdx`); - try { - await fs.access(breadcrumbFile); - } catch { - const relativePath = path.relative(rootDir, dirPath); - errors.push(`Missing breadcrumb file for directory: ${relativePath}/${entry.name}`); - } - // Recursively check subdirectories await checkDirectory(fullPath); + } else if ((entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) && + entry.name !== `${dirName}.mdx`) { + // Check if this page is referenced in the breadcrumb + const relativePath = '/' + path.relative(rootDir, fullPath) + .replace(/\.(md|mdx)$/, ''); + + if (!referencedPages.includes(relativePath)) { + errors.push(`Page not referenced in breadcrumb: ${relativePath}`); + } } } } @@ -40,7 +73,7 @@ async function main() { errors.forEach(error => console.error(`- ${error}`)); process.exit(1); } else { - console.log('All directories have breadcrumb files.'); + console.log('All pages are properly referenced in breadcrumb navigation.'); } } catch (error) { console.error('Error checking breadcrumbs:', error); From 6633952ee6ad07317885dbec2fda637d61565e8b Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 15:16:10 +0100 Subject: [PATCH 11/18] updated script file --- package.json | 2 +- utils/breadcrumbs.ts | 107 +++++++++++++++++++----------------- utils/create-breadcrumbs.ts | 10 +--- words.txt | 9 --- 4 files changed, 61 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index 2e9eabf66..8d3429ef8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Optimism Docs", "scripts": { "lint": "eslint . --ext mdx --max-warnings 0 && pnpm spellcheck:lint", - "fix": "eslint . --ext mdx --fix && pnpm spellcheck:fix", + "fix": "eslint . --ext mdx --fix && pnpm spellcheck:fix && pnpm check-breadcrumbs", "spellcheck:lint": "cspell lint \"**/*.mdx\"", "spellcheck:fix": "cspell --words-only --unique \"**/*.mdx\" | sort --ignore-case | uniq > words.txt", "linkcheck": "lychee --config ./lychee.toml --quiet \"./pages\"", diff --git a/utils/breadcrumbs.ts b/utils/breadcrumbs.ts index 13efab02f..f93225dc7 100644 --- a/utils/breadcrumbs.ts +++ b/utils/breadcrumbs.ts @@ -3,63 +3,70 @@ import * as path from 'path'; import matter from 'gray-matter'; const rootDir = path.join(process.cwd(), 'pages'); -const errors: string[] = []; +const warnings: string[] = []; -interface PageInfo { - title: string; - url: string; -} +// ANSI color codes +const YELLOW = '\x1b[33m'; +const RESET = '\x1b[0m'; +const BOLD = '\x1b[1m'; -async function getReferencedPages(breadcrumbContent: string): Promise { - // Extract URLs from Card components in the breadcrumb file - const cardRegex = /]*href="([^"]+)"[^>]*>/g; - const urls: string[] = []; - let match; - - while ((match = cardRegex.exec(breadcrumbContent)) !== null) { - urls.push(match[1]); +// Pages to exclude from checks +const excludedPages = [ + '400.mdx', + '500.mdx', + 'index.mdx', + '404.mdx' +]; + +async function getReferencedPagesFromBreadcrumb(breadcrumbPath: string): Promise { + try { + const content = await fs.readFile(breadcrumbPath, 'utf-8'); + const cardMatches = content.match(/]*href="([^"]+)"[^>]*>/g) || []; + return cardMatches.map(match => { + const hrefMatch = match.match(/href="([^"]+)"/); + return hrefMatch ? hrefMatch[1] : ''; + }).filter(Boolean); + } catch (error) { + return []; } - - return urls; } async function checkDirectory(dirPath: string): Promise { const entries = await fs.readdir(dirPath, { withFileTypes: true }); + const currentDir = path.basename(dirPath); - // First, find the breadcrumb file for this directory - const dirName = path.basename(dirPath); - const breadcrumbFile = path.join(dirPath, `${dirName}.mdx`); - let referencedPages: string[] = []; - - try { - const breadcrumbContent = await fs.readFile(breadcrumbFile, 'utf-8'); - referencedPages = await getReferencedPages(breadcrumbContent); - } catch (error) { - // Only check for missing references if not in root directory - if (dirPath !== rootDir) { - errors.push(`Missing breadcrumb file for directory: ${path.relative(rootDir, dirPath)}`); - return; + // Skip the root directory check + if (dirPath !== rootDir) { + const breadcrumbPath = path.join(dirPath, `${currentDir}.mdx`); + const referencedPages = await getReferencedPagesFromBreadcrumb(breadcrumbPath); + + // Check all .mdx and .md files in the current directory + for (const entry of entries) { + if (entry.isFile() && + (entry.name.endsWith('.mdx') || entry.name.endsWith('.md')) && + !excludedPages.includes(entry.name) && + entry.name !== `${currentDir}.mdx`) { + + const pageName = entry.name.replace(/\.(md|mdx)$/, ''); + const relativePath = `/stack/${path.relative(rootDir, dirPath)}/${pageName}`.replace(/\\/g, '/'); + + if (!referencedPages.includes(relativePath)) { + const humanReadableName = pageName.split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + + warnings.push( + `Page "${humanReadableName}" at path "${relativePath}" is not listed in the breadcrumb navigation of ${currentDir}.mdx` + ); + } + } } } - // Check each entry in the directory + // Process subdirectories for (const entry of entries) { - if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue; - - const fullPath = path.join(dirPath, entry.name); - - if (entry.isDirectory()) { - // Recursively check subdirectories - await checkDirectory(fullPath); - } else if ((entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) && - entry.name !== `${dirName}.mdx`) { - // Check if this page is referenced in the breadcrumb - const relativePath = '/' + path.relative(rootDir, fullPath) - .replace(/\.(md|mdx)$/, ''); - - if (!referencedPages.includes(relativePath)) { - errors.push(`Page not referenced in breadcrumb: ${relativePath}`); - } + if (entry.isDirectory() && !entry.name.startsWith('_') && !entry.name.startsWith('.')) { + await checkDirectory(path.join(dirPath, entry.name)); } } } @@ -68,15 +75,15 @@ async function main() { try { await checkDirectory(rootDir); - if (errors.length > 0) { - console.error('Breadcrumb check failed:'); - errors.forEach(error => console.error(`- ${error}`)); + if (warnings.length > 0) { + console.log(`${YELLOW}${BOLD}Missing pages in breadcrumb navigation:${RESET}`); + warnings.forEach(warning => console.log(`${YELLOW}- ${warning}${RESET}`)); process.exit(1); } else { - console.log('All pages are properly referenced in breadcrumb navigation.'); + console.log('All pages are properly listed in their respective breadcrumb navigation files.'); } } catch (error) { - console.error('Error checking breadcrumbs:', error); + console.log(`${YELLOW}${BOLD}Error checking breadcrumbs:${RESET}`, error); process.exit(1); } } diff --git a/utils/create-breadcrumbs.ts b/utils/create-breadcrumbs.ts index b6f2cf11f..c57c66ff4 100644 --- a/utils/create-breadcrumbs.ts +++ b/utils/create-breadcrumbs.ts @@ -18,19 +18,15 @@ function toTitleCase(str: string): string { } function extractFirstParagraph(content: string): string { - // Remove frontmatter + content = content.replace(/^---[\s\S]*?---/, ''); - // Remove import statements content = content.replace(/^import[\s\S]*?\n/gm, ''); - - // Remove HTML/MDX tags + content = content.replace(/<[^>]+>/g, ' '); - - // Remove markdown links but keep text + content = content.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); - // Remove headers content = content.replace(/^#.+$/gm, ''); const paragraphs = content.split(/\n\n+/); diff --git a/words.txt b/words.txt index 82aba8f3d..d8b872516 100644 --- a/words.txt +++ b/words.txt @@ -11,7 +11,6 @@ Allocs allocs altda ANDI -Ankr Apeworx Arweave authrpc @@ -148,7 +147,6 @@ Holesky holesky IGNOREPRICE ignoreprice -Immunefi implicity Inator inator @@ -197,7 +195,6 @@ minsuggestedpriorityfee Mintable Mintplex MIPSEVM -Mitigations Monitorism Moralis Mordor @@ -291,8 +288,6 @@ Protip Proxied proxyd pseudorandomly -Pyth -Pyth's QRNG Quicknode quicknode @@ -326,9 +321,6 @@ safedb Schnorr secp SELFDESTRUCT -SEPOLIA -Sepolia -sepolia seqnr SEQUENCERHTTP sequencerhttp @@ -398,7 +390,6 @@ VMDEBUG vmdebug VMODULE vmodule -voxel wagmi Warpcast xlarge From dc924824475e08946febe1fb27609ba678640bc1 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 15:42:43 +0100 Subject: [PATCH 12/18] updated breadcrumbs --- .../stack/{beta-features => }/beta-features.mdx | 0 pages/stack/{fault-proofs => }/fault-proofs.mdx | 0 pages/stack/{features => }/features.mdx | 0 pages/stack/{interop => }/interop.mdx | 7 +++++-- pages/stack/{research => }/research.mdx | 0 pages/stack/{rollup => }/rollup.mdx | 0 pages/stack/security.mdx | 9 ++++----- pages/stack/security/security.mdx | 16 ---------------- pages/stack/transactions.mdx | 11 ++++++++--- utils/breadcrumbs.ts | 4 +++- words.txt | 4 +--- 11 files changed, 21 insertions(+), 30 deletions(-) rename pages/stack/{beta-features => }/beta-features.mdx (100%) rename pages/stack/{fault-proofs => }/fault-proofs.mdx (100%) rename pages/stack/{features => }/features.mdx (100%) rename pages/stack/{interop => }/interop.mdx (50%) rename pages/stack/{research => }/research.mdx (100%) rename pages/stack/{rollup => }/rollup.mdx (100%) delete mode 100644 pages/stack/security/security.mdx diff --git a/pages/stack/beta-features/beta-features.mdx b/pages/stack/beta-features.mdx similarity index 100% rename from pages/stack/beta-features/beta-features.mdx rename to pages/stack/beta-features.mdx diff --git a/pages/stack/fault-proofs/fault-proofs.mdx b/pages/stack/fault-proofs.mdx similarity index 100% rename from pages/stack/fault-proofs/fault-proofs.mdx rename to pages/stack/fault-proofs.mdx diff --git a/pages/stack/features/features.mdx b/pages/stack/features.mdx similarity index 100% rename from pages/stack/features/features.mdx rename to pages/stack/features.mdx diff --git a/pages/stack/interop/interop.mdx b/pages/stack/interop.mdx similarity index 50% rename from pages/stack/interop/interop.mdx rename to pages/stack/interop.mdx index 76d4d8a95..c16130077 100644 --- a/pages/stack/interop/interop.mdx +++ b/pages/stack/interop.mdx @@ -1,6 +1,6 @@ --- title: Interop -description: Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem. +description: Documentation covering Cross Chain Message, Explainer, Message Passing, Op Supervisor, Superchain Erc20, Superchain Weth, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem. lang: en-US --- @@ -8,12 +8,15 @@ import { Card, Cards } from 'nextra/components' # Interop -Documentation covering Cross Chain Message, Explainer, Superchain Erc20, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem. +Documentation covering Cross Chain Message, Explainer, Message Passing, Op Supervisor, Superchain Erc20, Superchain Weth, Supersim, Transfer Superchainerc20 in the Interop section of the OP Stack ecosystem. + + + \ No newline at end of file diff --git a/pages/stack/research/research.mdx b/pages/stack/research.mdx similarity index 100% rename from pages/stack/research/research.mdx rename to pages/stack/research.mdx diff --git a/pages/stack/rollup/rollup.mdx b/pages/stack/rollup.mdx similarity index 100% rename from pages/stack/rollup/rollup.mdx rename to pages/stack/rollup.mdx diff --git a/pages/stack/security.mdx b/pages/stack/security.mdx index 11e8a0d7c..d770098b3 100644 --- a/pages/stack/security.mdx +++ b/pages/stack/security.mdx @@ -1,6 +1,6 @@ --- title: Security -description: This section provides information on op stack security faqs and pausing the bridge. +description: Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem. lang: en-US --- @@ -8,10 +8,9 @@ import { Card, Cards } from 'nextra/components' # Security -This section provides information on op stack security faqs and pausing the bridge. +Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem. - - + - + \ No newline at end of file diff --git a/pages/stack/security/security.mdx b/pages/stack/security/security.mdx deleted file mode 100644 index d770098b3..000000000 --- a/pages/stack/security/security.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Security -description: Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem. -lang: en-US ---- - -import { Card, Cards } from 'nextra/components' - -# Security - -Documentation covering Faq, Pause in the Security section of the OP Stack ecosystem. - - - - - \ No newline at end of file diff --git a/pages/stack/transactions.mdx b/pages/stack/transactions.mdx index 929eea7c7..4d96e5736 100644 --- a/pages/stack/transactions.mdx +++ b/pages/stack/transactions.mdx @@ -8,8 +8,13 @@ import { Card, Cards } from 'nextra/components' # Transactions -This section provides information on . You'll find reference to help you understand and work with these topics. +This section provides information on transactions fees. - - + + + + + + + \ No newline at end of file diff --git a/utils/breadcrumbs.ts b/utils/breadcrumbs.ts index f93225dc7..d433df892 100644 --- a/utils/breadcrumbs.ts +++ b/utils/breadcrumbs.ts @@ -48,7 +48,9 @@ async function checkDirectory(dirPath: string): Promise { entry.name !== `${currentDir}.mdx`) { const pageName = entry.name.replace(/\.(md|mdx)$/, ''); - const relativePath = `/stack/${path.relative(rootDir, dirPath)}/${pageName}`.replace(/\\/g, '/'); + // Dynamically construct the path relative to the pages directory + const relativePath = '/' + path.relative(rootDir, path.join(dirPath, pageName)) + .replace(/\\/g, '/'); if (!referencedPages.includes(relativePath)) { const humanReadableName = pageName.split('-') diff --git a/words.txt b/words.txt index 3c944eadb..f4e2c979a 100644 --- a/words.txt +++ b/words.txt @@ -9,7 +9,6 @@ airgap Allnodes Allocs allocs -altda ANDI Apeworx Arweave @@ -76,7 +75,6 @@ datacap DATADIR datadir Dencun -derviation Devnet devnet Devnode @@ -401,4 +399,4 @@ xtensibility ZKPs ZKVM Zora -zora \ No newline at end of file +zora From 8d26531a1d73489bee49123bc03be28378c93675 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 16:30:31 +0100 Subject: [PATCH 13/18] updated creadcrumbs --- pages/builders/app-developers.mdx | 25 +++---- pages/builders/cex-wallet-developers.mdx | 17 ++--- pages/builders/chain-operators.mdx | 20 ++--- pages/builders/node-operators.mdx | 19 ++--- pages/builders/notices.mdx | 8 +- pages/builders/tools.mdx | 13 +--- pages/chain/identity.mdx | 17 ++--- pages/chain/security.mdx | 14 ++-- pages/chain/testing.mdx | 11 +-- pages/connect/contribute.mdx | 14 ++-- pages/connect/resources.mdx | 6 +- pages/stack/transactions.mdx | 12 +-- utils/create-breadcrumbs.ts | 95 +++++++++++++++--------- 13 files changed, 124 insertions(+), 147 deletions(-) diff --git a/pages/builders/app-developers.mdx b/pages/builders/app-developers.mdx index 4bf0f90ce..cd64c14c0 100644 --- a/pages/builders/app-developers.mdx +++ b/pages/builders/app-developers.mdx @@ -1,28 +1,21 @@ --- title: App Developers +description: If you're a developer looking to build on OP Stack, you've come to the right place. In this area of the Optimism Docs you'll find everything you ... lang: en-US -description: Essential resources for app developers building on the OP Stack, including guides for deploying contracts, handling transactions, and cross-chain messaging. --- import { Card, Cards } from 'nextra/components' # App Developers -Welcome to the App Developers section, where you'll find essential resources for deploying contracts, handling transactions, cross-chain messaging, and more. -Access quick-start guides, tutorials, and tools to help you build applications on the OP Stack efficiently +If you're a developer looking to build on OP Mainnet, you've come to the right place. In this area of the Optimism Docs you'll find everything you ... - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/pages/builders/cex-wallet-developers.mdx b/pages/builders/cex-wallet-developers.mdx index 0ac230932..60be92c71 100644 --- a/pages/builders/cex-wallet-developers.mdx +++ b/pages/builders/cex-wallet-developers.mdx @@ -1,19 +1,16 @@ --- -title: CEX Wallet Developers -description: >- - This section provides information on supporting OP Stack in your exchange and - supporting OP Stack in your wallet. You'll find guide to help you... +title: Cex Wallet Developers +description: Documentation covering Cex Support, Wallet Support in the Cex Wallet Developers section of the OP Stack ecosystem. lang: en-US --- import { Card, Cards } from 'nextra/components' -# CEX Wallet Developers +# Cex Wallet Developers -This section provides information on supporting op mainnet in your exchange and supporting op mainnet in your wallet. You'll find guide to help you understand and work with these topics. +Documentation covering Cex Support, Wallet Support in the Cex Wallet Developers section of the OP Stack ecosystem. - - - - + + + \ No newline at end of file diff --git a/pages/builders/chain-operators.mdx b/pages/builders/chain-operators.mdx index 872c69d26..281d53ae1 100644 --- a/pages/builders/chain-operators.mdx +++ b/pages/builders/chain-operators.mdx @@ -1,31 +1,23 @@ --- title: Chain Operators +description: Documentation covering Architecture, Configuration, Deploy, Features, Hacks, Management, Self Hosted, Tools, Tutorials in the Chain Operators section of the OP Stack ecosystem. lang: en-US -description: Information on chain architecture, configuration, deployment, and management for OP Stack chain operators. --- import { Card, Cards } from 'nextra/components' -# Chain operators +# Chain Operators -This section provides information on chain architecture, configuration, deployment, features, hacks, management, and how to start a self-hosted chain. You'll also find tools, APIs, overviews, guides, and introductions to help you understand and work with these topics. +Documentation covering Architecture, Configuration, Deploy, Features, Hacks, Management, Self Hosted, Tools, Tutorials in the Chain Operators section of the OP Stack ecosystem. - - - - + - - - - - + - - + \ No newline at end of file diff --git a/pages/builders/node-operators.mdx b/pages/builders/node-operators.mdx index bd2ffdeba..7a7a73fc1 100644 --- a/pages/builders/node-operators.mdx +++ b/pages/builders/node-operators.mdx @@ -1,6 +1,6 @@ --- title: Node Operators -description: This section provides information on node architecture, configuration, json rpc api, management, network upgrades, node software releases, how to run... +description: Documentation covering Architecture, Configuration, Json Rpc, Management, Network Upgrades, Releases, Rollup Node, Tutorials in the Node Operators section of the OP Stack ecosystem. lang: en-US --- @@ -8,22 +8,15 @@ import { Card, Cards } from 'nextra/components' # Node Operators -This section provides information on node architecture, configuration, json rpc api, management, network upgrades, node software releases, how to run a node in the superchain and tutorials. You'll find api, guide, overview to help you understand and work with these topics. +Documentation covering Architecture, Configuration, Json Rpc, Management, Network Upgrades, Releases, Rollup Node, Tutorials in the Node Operators section of the OP Stack ecosystem. - - - - + - - - - - - + + - + \ No newline at end of file diff --git a/pages/builders/notices.mdx b/pages/builders/notices.mdx index 53ca1701f..075fd792f 100644 --- a/pages/builders/notices.mdx +++ b/pages/builders/notices.mdx @@ -1,6 +1,6 @@ --- title: Notices -description: This section provides information on preparing for fault proofs breaking changes, preparing for granite breaking changes and deprecation of the... +description: Documentation covering Sdk Deprecation in the Notices section of the OP Stack ecosystem. lang: en-US --- @@ -8,8 +8,8 @@ import { Card, Cards } from 'nextra/components' # Notices -This section offers essential information for builders to stay up-to-date with the latest changes in the OP Stack. +Documentation covering Sdk Deprecation in the Notices section of the OP Stack ecosystem. - - + + \ No newline at end of file diff --git a/pages/builders/tools.mdx b/pages/builders/tools.mdx index 4541d4cd8..e363145df 100644 --- a/pages/builders/tools.mdx +++ b/pages/builders/tools.mdx @@ -1,6 +1,6 @@ --- title: Tools -description: This section provides information on build, connect, fjord fee parameter calculator, monitor, op tools and developer tools. You'll find guide, tool,... +description: Welcome to the Optimism developer tools! lang: en-US --- @@ -8,18 +8,13 @@ import { Card, Cards } from 'nextra/components' # Tools -This section provides information on build, connect, fjord fee parameter calculator, monitor, op tools and developer tools. You'll find guide, tool, overview to help you understand and work with these topics. +Welcome to the Optimism developer tools! - - - - - - + - + \ No newline at end of file diff --git a/pages/chain/identity.mdx b/pages/chain/identity.mdx index 2f9a23ac9..169a444a8 100644 --- a/pages/chain/identity.mdx +++ b/pages/chain/identity.mdx @@ -1,6 +1,6 @@ --- title: Identity -description: This section provides information on about attestations, attestation apps, contracts (eas), individual identity, organizations, identity overview,... +description: This guide explains the role of decentralized identity in the Optimism Collective and its key components. lang: en-US --- @@ -8,22 +8,15 @@ import { Card, Cards } from 'nextra/components' # Identity -This section provides information on about attestations, attestation apps, contracts (eas), individual identity, organizations, identity overview, projects and schemas. You'll find guide, reference, overview to help you understand and work with these topics. +This guide explains the role of decentralized identity in the Optimism Collective and its key components. - - - - - + + - - - - - + \ No newline at end of file diff --git a/pages/chain/security.mdx b/pages/chain/security.mdx index b1a09682c..1bea1f9b1 100644 --- a/pages/chain/security.mdx +++ b/pages/chain/security.mdx @@ -1,8 +1,6 @@ --- title: Security -description: >- - This section provides information on OP Stack security model, privileged roles - in OP Stack and security policy and bug bounty program. +description: Documentation covering Faq, Privileged Roles, Security Policy in the Security section of the OP Stack ecosystem. lang: en-US --- @@ -10,12 +8,10 @@ import { Card, Cards } from 'nextra/components' # Security -This section provides information on op mainnet security model, privileged roles in op mainnet and security policy and bug bounty program. +Documentation covering Faq, Privileged Roles, Security Policy in the Security section of the OP Stack ecosystem. - - - - + + - + \ No newline at end of file diff --git a/pages/chain/testing.mdx b/pages/chain/testing.mdx index 923766e11..237a2d39d 100644 --- a/pages/chain/testing.mdx +++ b/pages/chain/testing.mdx @@ -1,8 +1,6 @@ --- title: Testing -description: >- - This section provides information on running a local development environment - and testing apps for OP Stack. You'll find tutorial, guide to help you... +description: Documentation covering Dev Node, Testing Apps in the Testing section of the OP Stack ecosystem. lang: en-US --- @@ -10,10 +8,9 @@ import { Card, Cards } from 'nextra/components' # Testing -This section provides information on running a local development environment and testing apps for op mainnet. You'll find tutorial, guide to help you understand and work with these topics. +Documentation covering Dev Node, Testing Apps in the Testing section of the OP Stack ecosystem. - - - + + \ No newline at end of file diff --git a/pages/connect/contribute.mdx b/pages/connect/contribute.mdx index 8ef9eb298..3ff89aeac 100644 --- a/pages/connect/contribute.mdx +++ b/pages/connect/contribute.mdx @@ -1,6 +1,6 @@ --- title: Contribute -description: This section provides information on ways to contribute to optimism docs, contribute to the op stack and optimism docs style guide. You'll find... +description: Documentation covering Docs Contribute, Stack Contribute, Style Guide in the Contribute section of the OP Stack ecosystem. lang: en-US --- @@ -8,12 +8,10 @@ import { Card, Cards } from 'nextra/components' # Contribute -This section provides information on ways to contribute to optimism docs, contribute to the op stack and optimism docs style guide. You'll find tutorial, overview, guide to help you understand and work with these topics. +Documentation covering Docs Contribute, Stack Contribute, Style Guide in the Contribute section of the OP Stack ecosystem. - - - - - - + + + + \ No newline at end of file diff --git a/pages/connect/resources.mdx b/pages/connect/resources.mdx index 80b083fe7..659f350e7 100644 --- a/pages/connect/resources.mdx +++ b/pages/connect/resources.mdx @@ -1,6 +1,6 @@ --- title: Resources -description: This section provides information on . You'll find concept to help you understand and work with these topics. +description: Documentation covering Glossary in the Resources section of the OP Stack ecosystem. lang: en-US --- @@ -8,8 +8,8 @@ import { Card, Cards } from 'nextra/components' # Resources -This section provides information on . You'll find concept to help you understand and work with these topics. +Documentation covering Glossary in the Resources section of the OP Stack ecosystem. - + \ No newline at end of file diff --git a/pages/stack/transactions.mdx b/pages/stack/transactions.mdx index 4d96e5736..2656226da 100644 --- a/pages/stack/transactions.mdx +++ b/pages/stack/transactions.mdx @@ -1,6 +1,6 @@ --- title: Transactions -description: This section provides information on . You'll find reference to help you understand and work with these topics. +description: Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Transaction Flow, Transactions, Withdrawal Flow in the Transactions section of the OP Stack ecosystem. lang: en-US --- @@ -8,13 +8,13 @@ import { Card, Cards } from 'nextra/components' # Transactions -This section provides information on transactions fees. +Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Transaction Flow, Transactions, Withdrawal Flow in the Transactions section of the OP Stack ecosystem. - - + - + - + + \ No newline at end of file diff --git a/utils/create-breadcrumbs.ts b/utils/create-breadcrumbs.ts index c57c66ff4..59f2c9cdc 100644 --- a/utils/create-breadcrumbs.ts +++ b/utils/create-breadcrumbs.ts @@ -11,6 +11,17 @@ interface FileInfo { content: string; } +// Pages to exclude +const excludedPages = [ + '400.mdx', + '500.mdx', + 'index.mdx', + '404.mdx', + '_app.tsx', + '_document.tsx', + '_meta.json' +]; + function toTitleCase(str: string): string { return str.split('-') .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) @@ -18,23 +29,27 @@ function toTitleCase(str: string): string { } function extractFirstParagraph(content: string): string { - + // Remove frontmatter content = content.replace(/^---[\s\S]*?---/, ''); + // Remove import statements content = content.replace(/^import[\s\S]*?\n/gm, ''); + // Remove HTML/MDX tags content = content.replace(/<[^>]+>/g, ' '); + // Remove markdown links but keep text content = content.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); + // Remove headers content = content.replace(/^#.+$/gm, ''); const paragraphs = content.split(/\n\n+/); const firstParagraph = paragraphs.find(p => { const cleaned = p.trim(); return cleaned.length > 30 && // Minimum length - !cleaned.startsWith('import') && - !cleaned.startsWith('export'); + !cleaned.startsWith('import') && + !cleaned.startsWith('export'); }); if (firstParagraph) { @@ -45,11 +60,12 @@ function extractFirstParagraph(content: string): string { return ''; } -async function generateFolderDescription(files: FileInfo[]): Promise { +async function generateFolderDescription(folderName: string, files: FileInfo[]): Promise { if (files.length === 0) { - return 'Documentation for this section is coming soon.'; + return `Documentation for ${toTitleCase(folderName)} is coming soon.`; } + // Try to find overview or introduction file const overviewFile = files.find(file => file.url.toLowerCase().includes('overview') || file.url.toLowerCase().includes('introduction') @@ -60,34 +76,30 @@ async function generateFolderDescription(files: FileInfo[]): Promise { if (desc) return desc; } - const folderName = toTitleCase(path.basename(path.dirname(files[0].url))); + // Generate description from files if no overview is found const topics = files.map(file => toTitleCase(path.basename(file.url))).join(', '); - - return `Documentation covering ${topics} in the ${folderName} section of the OP Stack ecosystem.`; + return `Documentation covering ${topics} in the ${toTitleCase(folderName)} section of the OP Stack ecosystem.`; } async function getContentFiles(folderPath: string): Promise { - const files = await fs.readdir(folderPath); + const files = await fs.readdir(folderPath, { withFileTypes: true }); const fileInfos: FileInfo[] = []; const folderName = path.basename(folderPath); for (const file of files) { - if (file.startsWith('_') || - file === `${folderName}.mdx` || - file.startsWith('.') || - file.endsWith('.tsx') || - file.endsWith('.json')) { + if (file.name.startsWith('_') || + file.name.startsWith('.') || + excludedPages.includes(file.name)) { continue; } - const filePath = path.join(folderPath, file); - const stats = await fs.stat(filePath); + const filePath = path.join(folderPath, file.name); - if (!stats.isDirectory() && (file.endsWith('.md') || file.endsWith('.mdx'))) { + if (file.isFile() && (file.name.endsWith('.md') || file.name.endsWith('.mdx'))) { try { const content = await fs.readFile(filePath, 'utf-8'); const { data: frontMatter } = matter(content); - const fileName = path.basename(file, path.extname(file)); + const fileName = path.basename(file.name, path.extname(file.name)); const fileTitle = frontMatter.title || toTitleCase(fileName); const relativeUrl = `/${path.relative(rootDir, filePath)}`.replace(/\.(md|mdx)$/, ''); @@ -98,7 +110,7 @@ async function getContentFiles(folderPath: string): Promise { content: content }); } catch (error) { - console.error(`Error processing file ${file}:`, error); + console.error(`Error processing file ${file.name}:`, error); } } } @@ -106,10 +118,11 @@ async function getContentFiles(folderPath: string): Promise { return fileInfos; } -async function createBreadcrumb(folderPath: string, folderName: string): Promise { +async function createBreadcrumb(parentPath: string, folderName: string): Promise { + const folderPath = path.join(parentPath, folderName); const files = await getContentFiles(folderPath); const title = toTitleCase(folderName); - const description = await generateFolderDescription(files); + const description = await generateFolderDescription(folderName, files); let content = `--- title: ${title} @@ -138,42 +151,52 @@ ${description} return content; } -async function processStackSubfolders(stackPath: string): Promise { +async function processSubfolders(parentPath: string): Promise { try { - const entries = await fs.readdir(stackPath, { withFileTypes: true }); + const entries = await fs.readdir(parentPath, { withFileTypes: true }); for (const entry of entries) { + // Skip if not a directory or starts with underscore if (!entry.isDirectory() || entry.name.startsWith('_')) { continue; } - const subfolderPath = path.join(stackPath, entry.name); - const breadcrumbPath = path.join(subfolderPath, `${entry.name}.mdx`); - - console.log(`Processing stack subfolder: ${entry.name}`); + const folderName = entry.name; + console.log(`Processing folder: ${folderName}`); try { - const content = await createBreadcrumb(subfolderPath, entry.name); + // Create breadcrumb file at the same level as the folder + const breadcrumbPath = path.join(parentPath, `${folderName}.mdx`); + const content = await createBreadcrumb(parentPath, folderName); await fs.writeFile(breadcrumbPath, content); - console.log(`Created/Updated breadcrumb for: ${entry.name}`); + console.log(`Created/Updated breadcrumb for: ${folderName}`); } catch (error) { - console.error(`Error creating breadcrumb for ${entry.name}:`, error); + console.error(`Error creating breadcrumb for ${folderName}:`, error); } } } catch (error) { - console.error('Error processing stack subfolders:', error); + console.error('Error processing folders:', error); } } const main = async (): Promise => { - console.log('Starting stack subfolder breadcrumb update process...'); + console.log('Starting breadcrumb update process...'); console.log('Root directory:', rootDir); try { - const stackPath = path.join(rootDir, 'stack'); - await fs.access(stackPath); - await processStackSubfolders(stackPath); - console.log('Finished updating stack subfolder breadcrumbs.'); + // Process main sections: builders, chain, connect, stack + const mainSections = ['builders', 'chain', 'connect', 'stack']; + for (const section of mainSections) { + const sectionPath = path.join(rootDir, section); + try { + await fs.access(sectionPath); + await processSubfolders(sectionPath); + console.log(`Completed processing ${section} section`); + } catch (error) { + console.log(`Skipping ${section} - directory not found`); + } + } + console.log('Finished updating all breadcrumbs.'); } catch (error) { console.error('Error in main process:', error); process.exit(1); From 3ac9f4266c28cf017d3407fde4167552a96723a0 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 17:22:40 +0100 Subject: [PATCH 14/18] fix lint issues --- pages/builders/app-developers.mdx | 8 +- pages/builders/cex-wallet-developers.mdx | 3 +- pages/builders/chain-operators.mdx | 10 +- pages/builders/node-operators.mdx | 9 +- pages/builders/notices.mdx | 2 +- pages/builders/tools.mdx | 7 +- pages/chain/identity.mdx | 9 +- pages/chain/security.mdx | 4 +- pages/chain/testing.mdx | 3 +- pages/connect/contribute.mdx | 2 +- pages/connect/resources.mdx | 2 +- pages/stack/beta-features.mdx | 3 +- pages/stack/fault-proofs.mdx | 7 +- pages/stack/features.mdx | 2 +- pages/stack/features/_meta.json | 3 +- pages/stack/features/test.mdx | 63 +++++++++++ pages/stack/interop.mdx | 9 +- pages/stack/research.mdx | 2 +- pages/stack/rollup.mdx | 4 +- pages/stack/security.mdx | 3 +- pages/stack/transactions.mdx | 7 +- pages/stack/transactions/transactions.mdx | 7 +- utils/breadcrumbs.ts | 127 +++++++++++++++++----- utils/create-breadcrumbs.ts | 94 ++++++++++++---- 24 files changed, 317 insertions(+), 73 deletions(-) create mode 100644 pages/stack/features/test.mdx diff --git a/pages/builders/app-developers.mdx b/pages/builders/app-developers.mdx index cd64c14c0..c5dc109d2 100644 --- a/pages/builders/app-developers.mdx +++ b/pages/builders/app-developers.mdx @@ -12,10 +12,16 @@ If you're a developer looking to build on OP Mainnet, you've come to the right p + + + + + + - \ No newline at end of file + diff --git a/pages/builders/cex-wallet-developers.mdx b/pages/builders/cex-wallet-developers.mdx index 60be92c71..aedc0e7eb 100644 --- a/pages/builders/cex-wallet-developers.mdx +++ b/pages/builders/cex-wallet-developers.mdx @@ -12,5 +12,6 @@ Documentation covering Cex Support, Wallet Support in the Cex Wallet Developers + - \ No newline at end of file + diff --git a/pages/builders/chain-operators.mdx b/pages/builders/chain-operators.mdx index 281d53ae1..73c0e4bb9 100644 --- a/pages/builders/chain-operators.mdx +++ b/pages/builders/chain-operators.mdx @@ -12,12 +12,20 @@ Documentation covering Architecture, Configuration, Deploy, Features, Hacks, Man + + + + + + + + - \ No newline at end of file + diff --git a/pages/builders/node-operators.mdx b/pages/builders/node-operators.mdx index 7a7a73fc1..9d25972cb 100644 --- a/pages/builders/node-operators.mdx +++ b/pages/builders/node-operators.mdx @@ -12,11 +12,18 @@ Documentation covering Architecture, Configuration, Json Rpc, Management, Networ + + + + + + + - \ No newline at end of file + diff --git a/pages/builders/notices.mdx b/pages/builders/notices.mdx index 075fd792f..27aaaa0ab 100644 --- a/pages/builders/notices.mdx +++ b/pages/builders/notices.mdx @@ -12,4 +12,4 @@ Documentation covering Sdk Deprecation in the Notices section of the OP Stack ec - \ No newline at end of file + diff --git a/pages/builders/tools.mdx b/pages/builders/tools.mdx index e363145df..354ca94dd 100644 --- a/pages/builders/tools.mdx +++ b/pages/builders/tools.mdx @@ -12,9 +12,14 @@ Welcome to the Optimism developer tools! + + + + + - \ No newline at end of file + diff --git a/pages/chain/identity.mdx b/pages/chain/identity.mdx index 169a444a8..87c4b79e5 100644 --- a/pages/chain/identity.mdx +++ b/pages/chain/identity.mdx @@ -12,11 +12,18 @@ This guide explains the role of decentralized identity in the Optimism Collectiv + + + + + + + - \ No newline at end of file + diff --git a/pages/chain/security.mdx b/pages/chain/security.mdx index 1bea1f9b1..e4f10a998 100644 --- a/pages/chain/security.mdx +++ b/pages/chain/security.mdx @@ -12,6 +12,8 @@ Documentation covering Faq, Privileged Roles, Security Policy in the Security se + + - \ No newline at end of file + diff --git a/pages/chain/testing.mdx b/pages/chain/testing.mdx index 237a2d39d..fc2af6d47 100644 --- a/pages/chain/testing.mdx +++ b/pages/chain/testing.mdx @@ -12,5 +12,6 @@ Documentation covering Dev Node, Testing Apps in the Testing section of the OP S + - \ No newline at end of file + diff --git a/pages/connect/contribute.mdx b/pages/connect/contribute.mdx index 3ff89aeac..a7cf78027 100644 --- a/pages/connect/contribute.mdx +++ b/pages/connect/contribute.mdx @@ -14,4 +14,4 @@ Documentation covering Docs Contribute, Stack Contribute, Style Guide in the Con - \ No newline at end of file + diff --git a/pages/connect/resources.mdx b/pages/connect/resources.mdx index 659f350e7..a4ae2c526 100644 --- a/pages/connect/resources.mdx +++ b/pages/connect/resources.mdx @@ -12,4 +12,4 @@ Documentation covering Glossary in the Resources section of the OP Stack ecosyst - \ No newline at end of file + diff --git a/pages/stack/beta-features.mdx b/pages/stack/beta-features.mdx index bfdd3a164..24257e8e3 100644 --- a/pages/stack/beta-features.mdx +++ b/pages/stack/beta-features.mdx @@ -12,5 +12,6 @@ Documentation covering Alt Da Mode, Custom Gas Token in the Beta Features sectio + - \ No newline at end of file + diff --git a/pages/stack/fault-proofs.mdx b/pages/stack/fault-proofs.mdx index 0f49365ab..4da08bb26 100644 --- a/pages/stack/fault-proofs.mdx +++ b/pages/stack/fault-proofs.mdx @@ -12,9 +12,14 @@ Documentation covering Cannon, Challenger, Explainer, Fp Components, Fp Security + + + + + - \ No newline at end of file + diff --git a/pages/stack/features.mdx b/pages/stack/features.mdx index 7f5e479cd..84cad55a4 100644 --- a/pages/stack/features.mdx +++ b/pages/stack/features.mdx @@ -12,4 +12,4 @@ Documentation covering Send Raw Transaction Conditional in the Features section - \ No newline at end of file + diff --git a/pages/stack/features/_meta.json b/pages/stack/features/_meta.json index 1d8a795f7..7b2121ed1 100644 --- a/pages/stack/features/_meta.json +++ b/pages/stack/features/_meta.json @@ -1,3 +1,4 @@ { - "send-raw-transaction-conditional": "SendRawTransactionConditional" + "send-raw-transaction-conditional": "SendRawTransactionConditional", + "test": "Test" } diff --git a/pages/stack/features/test.mdx b/pages/stack/features/test.mdx new file mode 100644 index 000000000..9602e95ef --- /dev/null +++ b/pages/stack/features/test.mdx @@ -0,0 +1,63 @@ +--- +title: Test +lang: en-US +description: Learn about the eth_sendRawTransactionConditional RPC method for conditional transaction inclusion on the OP Stack. +--- + +import { Callout } from 'nextra/components' + +# Test + +A sequencer rpc, `eth_sendRawTransactionConditional`, allowing callers to conditionally include a transaction based on a set of provided options. + +This feature is meant to unblock use cases that require atomic inclusion, otherwise possible on Ethereum through specialized block builders like Flashbots. Some examples: + +* 4337 Bundlers utilizing a shared mempool of UserOperations. Reverted transactions due to conflicting UserOperations would make it too costly for bundlers to operate on L2, forcing the use of private mempools. + +## Specification + +This endpoint is an extension of `eth_sendRawTransaction`, with an extra parameter of "options" with the following structure: + +``` +{ + "knownAccounts": [optional] A map of accounts with expected storage. The key is account address + If the value is hex string, it is the known storage root hash of that account. + If the value is an object, then each member is in the format of "slot": "value", which are explicit slot values within that account storage. + "blockNumberMin": [optional] minimal block number for inclusion + "blockNumberMax": [optional] maximum block number for inclusion + "timestampMin": [optional] minimum block timestamp for inclusion + "timestampMax": [optional] maximum block timestamp for inclusion +} +``` + +The "cost" of a given conditional is *approximately* determined by the number of storage lookups that would be incurred by validating this conditional. There's a predefined max of `1000` that is allowed to prevent DoS. + + + Since the sequencer is not compensated for the additional state checks, otherwise through the GAS of the transaction, a configured rate limit is applied to this cost. + + To also disincentive the use of this endpoint for MEV in comparison to `eth_sendRawTransaction`, the conditional is checked against the parent of the latest block. + + +This conditional is checked once at the RPC layer prior to mempool submission. If rejected against chain state, the RPC will return an error with the following spec + +* error code `-32003` (transaction rejected) with a reason string as to the specific failed check +* error code `-32005` (conditional cost) with a reason string if the conditional cost exceeded the maximum OR the cost was rate limited due to network conditions. + +Successful submission does **NOT** guarantee inclusion! The caller must observe the chain for a receipt with some timeout to determine non-inclusion. The conditional is also re-checked in the block building phase to handle intra-block conflicts. + + + Conditional transactions are tied to the block builder they are submitted to. This means that these transactions **are not gossiped between configured peers!!!** + + If you are running an active/passive setup with replicas that gossip txs to an active sequencer, this endpoint should be fronted by a proxy that can broadcast the request to all replicas. + + +## How to enable + +This feature can be enabled with the addition of a flag to op-geth. + +* `--rollup.sequencertxconditionalenabled` (default: false) a boolean flag which enables the rpc. +* `--rollup.sequencertxconditionalcostratelimit` (default: 5000) an integer flag that sets the rate limit for cost observable per second. + + + It is not advised to publicly expose this sequencer endpoint due to DoS concerns. This supplemental proxy, [op-txproxy](/stack/operators/features/op-txproxy), should be used to apply additional constraints on this endpoint prior to passing through to the sequencer. + diff --git a/pages/stack/interop.mdx b/pages/stack/interop.mdx index c16130077..b7823d3b7 100644 --- a/pages/stack/interop.mdx +++ b/pages/stack/interop.mdx @@ -12,11 +12,18 @@ Documentation covering Cross Chain Message, Explainer, Message Passing, Op Super + + + + + + + - \ No newline at end of file + diff --git a/pages/stack/research.mdx b/pages/stack/research.mdx index c530c1be8..1a485ee0f 100644 --- a/pages/stack/research.mdx +++ b/pages/stack/research.mdx @@ -12,4 +12,4 @@ Documentation covering Block Time Research in the Research section of the OP Sta - \ No newline at end of file + diff --git a/pages/stack/rollup.mdx b/pages/stack/rollup.mdx index 15d96a31c..ca95c2564 100644 --- a/pages/stack/rollup.mdx +++ b/pages/stack/rollup.mdx @@ -12,6 +12,8 @@ The big idea that makes Optimism possible is the Optimistic Rollup. We'll go thr + + - \ No newline at end of file + diff --git a/pages/stack/security.mdx b/pages/stack/security.mdx index d770098b3..fbf62b199 100644 --- a/pages/stack/security.mdx +++ b/pages/stack/security.mdx @@ -12,5 +12,6 @@ Documentation covering Faq, Pause in the Security section of the OP Stack ecosys + - \ No newline at end of file + diff --git a/pages/stack/transactions.mdx b/pages/stack/transactions.mdx index 2656226da..2543d4ed0 100644 --- a/pages/stack/transactions.mdx +++ b/pages/stack/transactions.mdx @@ -12,9 +12,14 @@ Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Tra + + + + + - \ No newline at end of file + diff --git a/pages/stack/transactions/transactions.mdx b/pages/stack/transactions/transactions.mdx index c084cfc8f..02d703c69 100644 --- a/pages/stack/transactions/transactions.mdx +++ b/pages/stack/transactions/transactions.mdx @@ -12,9 +12,14 @@ Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Tra + + + + + - \ No newline at end of file + diff --git a/utils/breadcrumbs.ts b/utils/breadcrumbs.ts index d433df892..71201bfca 100644 --- a/utils/breadcrumbs.ts +++ b/utils/breadcrumbs.ts @@ -15,9 +15,79 @@ const excludedPages = [ '400.mdx', '500.mdx', 'index.mdx', - '404.mdx' + '404.mdx', + 'console', + 'block-explorer', + 'bridge', + 'sdk', + 'faucet', + 'gas', + 'bug-bounty', + 'live-support', + 'governance', + 'changelog', + 'experimental' ]; +// Paths to exclude from checks (full paths) +const excludedPaths = [ + '/builders/app-developers/tools/console', + '/builders/tools/op-tools/block-explorer', + '/builders/tools/op-tools/bridge', + '/builders/tools/op-tools/sdk', + '/builders/tools/op-tools/faucet', + '/builders/tools/op-tools/console', + '/builders/tools/op-tools/gas', + '/chain/security/bug-bounty', + '/connect/live-support', + '/connect/governance', + '/connect/resources/changelog', + '/stack/--- Experimental' +]; + +interface MetaJson { + [key: string]: { + title?: string; + display?: string; + } | string; +} + +function shouldExcludePage(pageName: string, fullPath: string): boolean { + // Check if the page name is in excludedPages + if (excludedPages.includes(pageName)) { + return true; + } + + // Check if the full path is in excludedPaths + if (excludedPaths.includes(fullPath)) { + return true; + } + + // Skip pages with special characters or patterns + if (pageName.includes('---') || pageName.startsWith('_')) { + return true; + } + + return false; +} + +async function getMetaJsonPages(dirPath: string): Promise { + try { + const metaPath = path.join(dirPath, '_meta.json'); + const metaContent = await fs.readFile(metaPath, 'utf-8'); + const meta: MetaJson = JSON.parse(metaContent); + + return Object.keys(meta).filter(key => + !excludedPages.includes(key) && + !key.startsWith('_') && + !key.includes('---') && + typeof meta[key] !== 'string' + ); + } catch (error) { + return []; + } +} + async function getReferencedPagesFromBreadcrumb(breadcrumbPath: string): Promise { try { const content = await fs.readFile(breadcrumbPath, 'utf-8'); @@ -33,42 +103,36 @@ async function getReferencedPagesFromBreadcrumb(breadcrumbPath: string): Promise async function checkDirectory(dirPath: string): Promise { const entries = await fs.readdir(dirPath, { withFileTypes: true }); - const currentDir = path.basename(dirPath); - // Skip the root directory check - if (dirPath !== rootDir) { - const breadcrumbPath = path.join(dirPath, `${currentDir}.mdx`); - const referencedPages = await getReferencedPagesFromBreadcrumb(breadcrumbPath); - - // Check all .mdx and .md files in the current directory - for (const entry of entries) { - if (entry.isFile() && - (entry.name.endsWith('.mdx') || entry.name.endsWith('.md')) && - !excludedPages.includes(entry.name) && - entry.name !== `${currentDir}.mdx`) { - - const pageName = entry.name.replace(/\.(md|mdx)$/, ''); - // Dynamically construct the path relative to the pages directory - const relativePath = '/' + path.relative(rootDir, path.join(dirPath, pageName)) - .replace(/\\/g, '/'); + for (const entry of entries) { + if (entry.isDirectory() && !entry.name.startsWith('_') && !entry.name.startsWith('.')) { + const folderPath = path.join(dirPath, entry.name); + const breadcrumbPath = path.join(dirPath, `${entry.name}.mdx`); + + const metaPages = await getMetaJsonPages(folderPath); + const referencedPages = await getReferencedPagesFromBreadcrumb(breadcrumbPath); + + for (const page of metaPages) { + const expectedPath = `/${path.relative(rootDir, folderPath)}/${page}`; + const normalizedExpectedPath = expectedPath.replace(/\\/g, '/'); - if (!referencedPages.includes(relativePath)) { - const humanReadableName = pageName.split('-') + // Skip if the page or path should be excluded + if (shouldExcludePage(page, normalizedExpectedPath)) { + continue; + } + + if (!referencedPages.some(ref => ref.endsWith(page))) { + const humanReadableName = page.split('-') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); warnings.push( - `Page "${humanReadableName}" at path "${relativePath}" is not listed in the breadcrumb navigation of ${currentDir}.mdx` + `Page "${humanReadableName}" (${normalizedExpectedPath}) is in _meta.json but not referenced in the breadcrumb file ${entry.name}.mdx` ); } } - } - } - - // Process subdirectories - for (const entry of entries) { - if (entry.isDirectory() && !entry.name.startsWith('_') && !entry.name.startsWith('.')) { - await checkDirectory(path.join(dirPath, entry.name)); + + await checkDirectory(folderPath); } } } @@ -82,7 +146,7 @@ async function main() { warnings.forEach(warning => console.log(`${YELLOW}- ${warning}${RESET}`)); process.exit(1); } else { - console.log('All pages are properly listed in their respective breadcrumb navigation files.'); + console.log('All pages listed in _meta.json are properly referenced in their breadcrumb files.'); } } catch (error) { console.log(`${YELLOW}${BOLD}Error checking breadcrumbs:${RESET}`, error); @@ -90,4 +154,7 @@ async function main() { } } -main(); \ No newline at end of file +main().catch(error => { + console.error('Error in main process:', error); + process.exit(1); +}); diff --git a/utils/create-breadcrumbs.ts b/utils/create-breadcrumbs.ts index 59f2c9cdc..370e44bc4 100644 --- a/utils/create-breadcrumbs.ts +++ b/utils/create-breadcrumbs.ts @@ -118,13 +118,66 @@ async function getContentFiles(folderPath: string): Promise { return fileInfos; } -async function createBreadcrumb(parentPath: string, folderName: string): Promise { +async function getExistingBreadcrumbContent(breadcrumbPath: string): Promise<{ + existingContent: string; + existingCards: Set; +} | null> { + try { + const content = await fs.readFile(breadcrumbPath, 'utf-8'); + const cardMatches = content.match(/]*href="([^"]+)"[^>]*>/g) || []; + const existingCards = new Set( + cardMatches.map(match => { + const hrefMatch = match.match(/href="([^"]+)"/); + return hrefMatch ? hrefMatch[1] : ''; + }).filter(Boolean) + ); + return { existingContent: content, existingCards }; + } catch (error) { + return null; + } +} + +async function createOrUpdateBreadcrumb(parentPath: string, folderName: string): Promise { const folderPath = path.join(parentPath, folderName); + const breadcrumbPath = path.join(parentPath, `${folderName}.mdx`); + + // Get current files in the folder const files = await getContentFiles(folderPath); - const title = toTitleCase(folderName); - const description = await generateFolderDescription(folderName, files); - - let content = `--- + + // Check existing breadcrumb + const existing = await getExistingBreadcrumbContent(breadcrumbPath); + + if (existing) { + // If breadcrumb exists, only add new cards + const newCards: string[] = []; + let content = existing.existingContent; + + files.forEach(({ title: fileTitle, url }) => { + if (!existing.existingCards.has(url)) { + newCards.push(` `); + } + }); + + if (newCards.length > 0) { + // Find the closing tag and insert new cards before it + const cardsSectionEnd = content.lastIndexOf(''); + if (cardsSectionEnd !== -1) { + content = content.slice(0, cardsSectionEnd) + + '\n' + newCards.join('\n') + '\n' + + content.slice(cardsSectionEnd); + + await fs.writeFile(breadcrumbPath, content); + console.log(`Added ${newCards.length} new cards to: ${folderName}.mdx`); + } + } else { + console.log(`No new cards needed for: ${folderName}.mdx`); + } + } else { + // If breadcrumb doesn't exist, create new one + const title = toTitleCase(folderName); + const description = await generateFolderDescription(folderName, files); + + let content = `--- title: ${title} description: ${description} lang: en-US @@ -138,17 +191,19 @@ ${description} `; - if (files.length > 0) { - content += '\n'; - files.forEach(({ title: fileTitle, url }) => { - content += ` \n`; - }); - content += ''; - } else { - content += 'Documentation for this section is coming soon.'; + if (files.length > 0) { + content += '\n'; + files.forEach(({ title: fileTitle, url }) => { + content += ` \n`; + }); + content += ''; + } else { + content += 'Documentation for this section is coming soon.'; + } + + await fs.writeFile(breadcrumbPath, content); + console.log(`Created new breadcrumb file: ${folderName}.mdx`); } - - return content; } async function processSubfolders(parentPath: string): Promise { @@ -156,7 +211,6 @@ async function processSubfolders(parentPath: string): Promise { const entries = await fs.readdir(parentPath, { withFileTypes: true }); for (const entry of entries) { - // Skip if not a directory or starts with underscore if (!entry.isDirectory() || entry.name.startsWith('_')) { continue; } @@ -165,13 +219,9 @@ async function processSubfolders(parentPath: string): Promise { console.log(`Processing folder: ${folderName}`); try { - // Create breadcrumb file at the same level as the folder - const breadcrumbPath = path.join(parentPath, `${folderName}.mdx`); - const content = await createBreadcrumb(parentPath, folderName); - await fs.writeFile(breadcrumbPath, content); - console.log(`Created/Updated breadcrumb for: ${folderName}`); + await createOrUpdateBreadcrumb(parentPath, folderName); } catch (error) { - console.error(`Error creating breadcrumb for ${folderName}:`, error); + console.error(`Error processing breadcrumb for ${folderName}:`, error); } } } catch (error) { From e14923fd0b74a1b0be147c26c926a877b9372ff8 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 17:39:12 +0100 Subject: [PATCH 15/18] updated breadcrumb check script --- notes/breadcrumbs.md | 10 +- package.json | 2 +- pages/builders/app-developers/contracts.mdx | 2 + pages/builders/chain-operators/tools.mdx | 4 + pages/stack/features/_meta.json | 3 +- pages/stack/features/test.mdx | 63 -------- utils/breadcrumbs.ts | 154 ++++++++++---------- words.txt | 2 + 8 files changed, 92 insertions(+), 148 deletions(-) delete mode 100644 pages/stack/features/test.mdx diff --git a/notes/breadcrumbs.md b/notes/breadcrumbs.md index e6f8b3b83..c05467848 100644 --- a/notes/breadcrumbs.md +++ b/notes/breadcrumbs.md @@ -11,10 +11,16 @@ Quick guide on using our breadcrumbs automation script for the OP Stack document ## Using the Script -Breadcrumbs for the docs can be generated by running: +* Breadcrumbs for the docs can be generated by running: ```bash -pnpm create-breadcrumbs +pnpm breadcrumbs +``` + +* To check files with missing breadcrumbs, run: + +```bash +pnpm fix ``` ### What to Watch For diff --git a/package.json b/package.json index 8d3429ef8..b1690e4f0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Optimism Docs", "scripts": { - "lint": "eslint . --ext mdx --max-warnings 0 && pnpm spellcheck:lint", + "lint": "eslint . --ext mdx --max-warnings 0 && pnpm spellcheck:lint && pnpm check-breadcrumbs", "fix": "eslint . --ext mdx --fix && pnpm spellcheck:fix && pnpm check-breadcrumbs", "spellcheck:lint": "cspell lint \"**/*.mdx\"", "spellcheck:fix": "cspell --words-only --unique \"**/*.mdx\" | sort --ignore-case | uniq > words.txt", diff --git a/pages/builders/app-developers/contracts.mdx b/pages/builders/app-developers/contracts.mdx index 6c01b91e2..f2836e72d 100644 --- a/pages/builders/app-developers/contracts.mdx +++ b/pages/builders/app-developers/contracts.mdx @@ -18,4 +18,6 @@ This section provides information on Solidity compatibility, contract optimizati + + diff --git a/pages/builders/chain-operators/tools.mdx b/pages/builders/chain-operators/tools.mdx index 1b8103c61..c8018d508 100644 --- a/pages/builders/chain-operators/tools.mdx +++ b/pages/builders/chain-operators/tools.mdx @@ -21,5 +21,9 @@ This section provides information on chain monitoring options, deploying a block + + + + diff --git a/pages/stack/features/_meta.json b/pages/stack/features/_meta.json index 7b2121ed1..1d8a795f7 100644 --- a/pages/stack/features/_meta.json +++ b/pages/stack/features/_meta.json @@ -1,4 +1,3 @@ { - "send-raw-transaction-conditional": "SendRawTransactionConditional", - "test": "Test" + "send-raw-transaction-conditional": "SendRawTransactionConditional" } diff --git a/pages/stack/features/test.mdx b/pages/stack/features/test.mdx deleted file mode 100644 index 9602e95ef..000000000 --- a/pages/stack/features/test.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Test -lang: en-US -description: Learn about the eth_sendRawTransactionConditional RPC method for conditional transaction inclusion on the OP Stack. ---- - -import { Callout } from 'nextra/components' - -# Test - -A sequencer rpc, `eth_sendRawTransactionConditional`, allowing callers to conditionally include a transaction based on a set of provided options. - -This feature is meant to unblock use cases that require atomic inclusion, otherwise possible on Ethereum through specialized block builders like Flashbots. Some examples: - -* 4337 Bundlers utilizing a shared mempool of UserOperations. Reverted transactions due to conflicting UserOperations would make it too costly for bundlers to operate on L2, forcing the use of private mempools. - -## Specification - -This endpoint is an extension of `eth_sendRawTransaction`, with an extra parameter of "options" with the following structure: - -``` -{ - "knownAccounts": [optional] A map of accounts with expected storage. The key is account address - If the value is hex string, it is the known storage root hash of that account. - If the value is an object, then each member is in the format of "slot": "value", which are explicit slot values within that account storage. - "blockNumberMin": [optional] minimal block number for inclusion - "blockNumberMax": [optional] maximum block number for inclusion - "timestampMin": [optional] minimum block timestamp for inclusion - "timestampMax": [optional] maximum block timestamp for inclusion -} -``` - -The "cost" of a given conditional is *approximately* determined by the number of storage lookups that would be incurred by validating this conditional. There's a predefined max of `1000` that is allowed to prevent DoS. - - - Since the sequencer is not compensated for the additional state checks, otherwise through the GAS of the transaction, a configured rate limit is applied to this cost. - - To also disincentive the use of this endpoint for MEV in comparison to `eth_sendRawTransaction`, the conditional is checked against the parent of the latest block. - - -This conditional is checked once at the RPC layer prior to mempool submission. If rejected against chain state, the RPC will return an error with the following spec - -* error code `-32003` (transaction rejected) with a reason string as to the specific failed check -* error code `-32005` (conditional cost) with a reason string if the conditional cost exceeded the maximum OR the cost was rate limited due to network conditions. - -Successful submission does **NOT** guarantee inclusion! The caller must observe the chain for a receipt with some timeout to determine non-inclusion. The conditional is also re-checked in the block building phase to handle intra-block conflicts. - - - Conditional transactions are tied to the block builder they are submitted to. This means that these transactions **are not gossiped between configured peers!!!** - - If you are running an active/passive setup with replicas that gossip txs to an active sequencer, this endpoint should be fronted by a proxy that can broadcast the request to all replicas. - - -## How to enable - -This feature can be enabled with the addition of a flag to op-geth. - -* `--rollup.sequencertxconditionalenabled` (default: false) a boolean flag which enables the rpc. -* `--rollup.sequencertxconditionalcostratelimit` (default: 5000) an integer flag that sets the rate limit for cost observable per second. - - - It is not advised to publicly expose this sequencer endpoint due to DoS concerns. This supplemental proxy, [op-txproxy](/stack/operators/features/op-txproxy), should be used to apply additional constraints on this endpoint prior to passing through to the sequencer. - diff --git a/utils/breadcrumbs.ts b/utils/breadcrumbs.ts index 71201bfca..ff00309d7 100644 --- a/utils/breadcrumbs.ts +++ b/utils/breadcrumbs.ts @@ -2,7 +2,7 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import matter from 'gray-matter'; -const rootDir = path.join(process.cwd(), 'pages'); +const rootDir: string = path.join(__dirname, '..', 'pages'); const warnings: string[] = []; // ANSI color codes @@ -10,6 +10,13 @@ const YELLOW = '\x1b[33m'; const RESET = '\x1b[0m'; const BOLD = '\x1b[1m'; +interface FileInfo { + title: string; + url: string; + description?: string; + content: string; +} + // Pages to exclude from checks const excludedPages = [ '400.mdx', @@ -29,75 +36,55 @@ const excludedPages = [ 'experimental' ]; -// Paths to exclude from checks (full paths) -const excludedPaths = [ - '/builders/app-developers/tools/console', - '/builders/tools/op-tools/block-explorer', - '/builders/tools/op-tools/bridge', - '/builders/tools/op-tools/sdk', - '/builders/tools/op-tools/faucet', - '/builders/tools/op-tools/console', - '/builders/tools/op-tools/gas', - '/chain/security/bug-bounty', - '/connect/live-support', - '/connect/governance', - '/connect/resources/changelog', - '/stack/--- Experimental' -]; +async function getContentFiles(folderPath: string): Promise { + const files = await fs.readdir(folderPath, { withFileTypes: true }); + const fileInfos: FileInfo[] = []; + const folderName = path.basename(folderPath); -interface MetaJson { - [key: string]: { - title?: string; - display?: string; - } | string; -} + for (const file of files) { + if (file.name.startsWith('_') || + file.name.startsWith('.') || + excludedPages.includes(file.name)) { + continue; + } -function shouldExcludePage(pageName: string, fullPath: string): boolean { - // Check if the page name is in excludedPages - if (excludedPages.includes(pageName)) { - return true; - } + const filePath = path.join(folderPath, file.name); - // Check if the full path is in excludedPaths - if (excludedPaths.includes(fullPath)) { - return true; - } + if (file.isFile() && (file.name.endsWith('.md') || file.name.endsWith('.mdx'))) { + try { + const content = await fs.readFile(filePath, 'utf-8'); + const { data: frontMatter } = matter(content); + const fileName = path.basename(file.name, path.extname(file.name)); + const fileTitle = frontMatter.title || fileName; + const relativeUrl = `/${path.relative(rootDir, filePath)}`.replace(/\.(md|mdx)$/, ''); - // Skip pages with special characters or patterns - if (pageName.includes('---') || pageName.startsWith('_')) { - return true; + fileInfos.push({ + title: fileTitle, + url: relativeUrl, + description: frontMatter.description, + content: content + }); + } catch (error) { + console.error(`Error processing file ${file.name}:`, error); + } + } } - return false; -} - -async function getMetaJsonPages(dirPath: string): Promise { - try { - const metaPath = path.join(dirPath, '_meta.json'); - const metaContent = await fs.readFile(metaPath, 'utf-8'); - const meta: MetaJson = JSON.parse(metaContent); - - return Object.keys(meta).filter(key => - !excludedPages.includes(key) && - !key.startsWith('_') && - !key.includes('---') && - typeof meta[key] !== 'string' - ); - } catch (error) { - return []; - } + return fileInfos; } -async function getReferencedPagesFromBreadcrumb(breadcrumbPath: string): Promise { +async function getBreadcrumbCards(breadcrumbPath: string): Promise> { try { const content = await fs.readFile(breadcrumbPath, 'utf-8'); const cardMatches = content.match(/]*href="([^"]+)"[^>]*>/g) || []; - return cardMatches.map(match => { - const hrefMatch = match.match(/href="([^"]+)"/); - return hrefMatch ? hrefMatch[1] : ''; - }).filter(Boolean); + return new Set( + cardMatches.map(match => { + const hrefMatch = match.match(/href="([^"]+)"/); + return hrefMatch ? hrefMatch[1] : ''; + }).filter(Boolean) + ); } catch (error) { - return []; + return new Set(); } } @@ -108,45 +95,52 @@ async function checkDirectory(dirPath: string): Promise { if (entry.isDirectory() && !entry.name.startsWith('_') && !entry.name.startsWith('.')) { const folderPath = path.join(dirPath, entry.name); const breadcrumbPath = path.join(dirPath, `${entry.name}.mdx`); + + // Get all content files in the folder + const files = await getContentFiles(folderPath); - const metaPages = await getMetaJsonPages(folderPath); - const referencedPages = await getReferencedPagesFromBreadcrumb(breadcrumbPath); - - for (const page of metaPages) { - const expectedPath = `/${path.relative(rootDir, folderPath)}/${page}`; - const normalizedExpectedPath = expectedPath.replace(/\\/g, '/'); - - // Skip if the page or path should be excluded - if (shouldExcludePage(page, normalizedExpectedPath)) { - continue; - } + // Get existing cards in breadcrumb + const existingCards = await getBreadcrumbCards(breadcrumbPath); - if (!referencedPages.some(ref => ref.endsWith(page))) { - const humanReadableName = page.split('-') - .map(word => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); - + // Check for missing pages + files.forEach(({ title, url }) => { + if (!existingCards.has(url)) { warnings.push( - `Page "${humanReadableName}" (${normalizedExpectedPath}) is in _meta.json but not referenced in the breadcrumb file ${entry.name}.mdx` + `Page "${title}" at ${url} needs to be added to the breadcrumb file ${entry.name}.mdx` ); } - } - + }); + + // Recursively check subdirectories await checkDirectory(folderPath); } } } async function main() { + console.log('Starting breadcrumb check process...'); + console.log('Root directory:', rootDir); + try { - await checkDirectory(rootDir); - + // Process main sections: builders, chain, connect, stack + const mainSections = ['builders', 'chain', 'connect', 'stack']; + for (const section of mainSections) { + const sectionPath = path.join(rootDir, section); + try { + await fs.access(sectionPath); + await checkDirectory(sectionPath); + console.log(`Completed checking ${section} section`); + } catch (error) { + console.log(`Skipping ${section} - directory not found`); + } + } + if (warnings.length > 0) { console.log(`${YELLOW}${BOLD}Missing pages in breadcrumb navigation:${RESET}`); warnings.forEach(warning => console.log(`${YELLOW}- ${warning}${RESET}`)); process.exit(1); } else { - console.log('All pages listed in _meta.json are properly referenced in their breadcrumb files.'); + console.log('All pages are properly referenced in breadcrumb files.'); } } catch (error) { console.log(`${YELLOW}${BOLD}Error checking breadcrumbs:${RESET}`, error); diff --git a/words.txt b/words.txt index f4e2c979a..632a83cdd 100644 --- a/words.txt +++ b/words.txt @@ -286,6 +286,7 @@ productionize productionized Protip Proxied +Proxyd proxyd pseudorandomly QRNG @@ -376,6 +377,7 @@ txns TXPOOL txpool txproxy +txproxyd uncountered Unprotect unsubmitted From c264bb423190c5685e7c88884d3fab85781bd0eb Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 17:42:19 +0100 Subject: [PATCH 16/18] fix lint issues --- pages/stack/transactions.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/stack/transactions.mdx b/pages/stack/transactions.mdx index 2543d4ed0..42bfac5a8 100644 --- a/pages/stack/transactions.mdx +++ b/pages/stack/transactions.mdx @@ -22,4 +22,6 @@ Documentation covering Cross Domain, Deposit Flow, Fees, Forced Transaction, Tra + + From 1fdff8cf4f1fc767259d0dadfc735a622212e4fe Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 17:43:26 +0100 Subject: [PATCH 17/18] fix lint markdown issues --- words.txt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/words.txt b/words.txt index 632a83cdd..2e0d2c443 100644 --- a/words.txt +++ b/words.txt @@ -9,7 +9,9 @@ airgap Allnodes Allocs allocs +altda ANDI +Ankr Apeworx Arweave authrpc @@ -75,6 +77,7 @@ datacap DATADIR datadir Dencun +derviation Devnet devnet Devnode @@ -147,6 +150,7 @@ Holesky holesky IGNOREPRICE ignoreprice +Immunefi implicity Inator inator @@ -195,6 +199,7 @@ minsuggestedpriorityfee Mintable Mintplex MIPSEVM +Mitigations Monitorism Moralis Mordor @@ -286,9 +291,10 @@ productionize productionized Protip Proxied -Proxyd proxyd pseudorandomly +Pyth +Pyth's QRNG Quicknode quicknode @@ -323,6 +329,9 @@ safedb Schnorr secp SELFDESTRUCT +SEPOLIA +Sepolia +sepolia seqnr SEQUENCERHTTP sequencerhttp @@ -353,7 +362,6 @@ SUPERCHAIN Superchain superchain Superchain's -Superchainerc Superchains Superscan Supersim @@ -377,7 +385,6 @@ txns TXPOOL txpool txproxy -txproxyd uncountered Unprotect unsubmitted @@ -393,6 +400,7 @@ VMDEBUG vmdebug VMODULE vmodule +voxel wagmi Warpcast xlarge @@ -401,4 +409,4 @@ xtensibility ZKPs ZKVM Zora -zora +zora \ No newline at end of file From be06f2d2533fa0f08b1637fbd722e0715f114fa6 Mon Sep 17 00:00:00 2001 From: krofax Date: Mon, 4 Nov 2024 17:49:36 +0100 Subject: [PATCH 18/18] fix lint issues --- words.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/words.txt b/words.txt index 2e0d2c443..a7c0cdb64 100644 --- a/words.txt +++ b/words.txt @@ -362,6 +362,7 @@ SUPERCHAIN Superchain superchain Superchain's +Superchainerc Superchains Superscan Supersim @@ -385,6 +386,7 @@ txns TXPOOL txpool txproxy +txproxyd uncountered Unprotect unsubmitted