f648349e82
* Diatixisify! * First pass at Typedoc generation for TS SDK * Remove overview pages * Fix typos and remove codebase references from docs Fix typos across network and developer docs: Quorum, available, cryptosystem, transaction, proportional, Standalone. Remove TODO placeholder from dVPN protocol page. Strip GitHub source links from network docs to decouple documentation from repo structure. * Expand thin landing pages across network and developer docs - Add intro content to network overview, infrastructure, and reference landing pages - Expand developer index with "where to start" guide - Add usage instructions and explanations to all five TS playground pages - Expand WebSocket client page with setup and message format examples * Restructure Rust SDK developer docs - Delete redundant mixnet example, message-helpers, and message-types subpages - Delete client-pool architecture and example subpages (content folded into landing) - Delete tcpproxy troubleshooting (folded into landing page) - Add deprecation notices to TcpProxy pages, pointing to Stream module - Add stream module docs: landing page, architecture, tutorial, and 4 example pages - Add mixnet and client-pool tutorials - Add SDK tour page - Update navigation and landing pages with docs.rs links * Restructure TS SDK developer docs - Merge overview, installation, and getting started into TS SDK landing page - Fold FAQ content into bundling/troubleshooting section - Delete redundant overview, installation, start, and FAQ pages - Update internal links in browsers.mdx and native.mdx - Update navigation and example page imports * Flatten and expand APIs section - Collapse nested API subpages into single pages with inline Redoc embeds - Rewrite introduction as landing page with decision table - Add endpoint categories, quick curl examples to each API page - Mark Explorer API as deprecated - Move NS API deployment guide to operators/performance-and-testing - Fix dangling /apis/nym-api/mainnet link in network-components - Remove sandbox endpoints from all API pages * Add redirects for moved and deleted pages - Add 25 redirects covering TS SDK, Rust SDK, APIs, and network sections - Fix dangling /developers/typescript/start link in operators changelog * Replace individual example doc pages with GitHub-linked tables, expand tutorials - replace individual example doc pages with GitHub-linked tables - expand mixnet tutorial with persistent identity and split_sender sections - add tcpproxy tutorial - rename "API Reference" to "TypeDoc Reference" in TS SDK sidebar - rename "Misc" to "Extras" in developer sidebar, move VPN CLI up - remove echo server from tools - update message-queue callout to reference actual modules - fix mixnet/examples redirect collision * Add SEO frontmatter, validate encryption standards, clean up URLs - add title/description/schemaType/section/lastUpdated frontmatter to 48 pages across developers, network, and APIs sections - remove network/.archive/ directory (compare against develop instead) - update nymtech.net → nym.com for website/blog links (keep infra URLs) - add native proxy "in progress" callout for Rust/C/Go * API-scraper update (#6598) * read nodes and locations * update python-prebuild.sh * Address PR #6494 review feedback - Use "mode" consistently instead of "role" on nym-nodes page - Replace "staking" with "bonding" for NYM token collateral - Wire up auto-scraped node counts via TimeNow + nodes-count.json - Fix broken licensing images: download CC icons locally, replace inline HTML - Fix 9 stale redirects pointing through deleted /network/architecture path * Fix linkcheck errors - Fix stale cross-links: /network/concepts/ → /network/mixnet-mode/ - Replace README.md references with globals.md in TypeDoc output - Add entryFileName: globals to typedoc.json configs to prevent recurrence * Fix remaining stale /network/architecture links - zk-nym-overview: architecture/nyx#nym-api → /network/infrastructure/nyx#nym-api - setup: network/architecture → /network/overview * Remove accidentally re-included architecture.md file from rebase * Standardize tutorials, document examples, add llms.txt, apply tone fixes - Expand Rust SDK tutorials with step-by-step structure; document all SDK examples across mixnet, client-pool, and tcpproxy pages - Add llms.txt generation script, wire into build and CI workflows - Apply tone/style fixes: deduplicate callouts, vary sentence structure, standardize voice consistency across changed pages * Consolidate redundant network overview docs * Trim dev docs: git-first imports, stream notice, collapse TcpProxy * Update tutorial * Refresh auto-generated API and command outputs * Update network section docs * Update developer and API docs: reusable components, stream protocol, conventions, tutorial fixes * Fix Rust SDK tutorial bugs: setup_env, port conflicts, logging, open_stream race condition * Update stream.mdx * Remove docs.rs link from Stream overview for the moment * add llms.txt and llms-full.txt note to readme --------- Co-authored-by: import this <97586125+serinko@users.noreply.github.com>
177 lines
5.3 KiB
JavaScript
177 lines
5.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Generates public/llms-full.txt by walking pages/, reading _meta.json
|
|
* for ordering, and concatenating all MDX/MD content as clean Markdown
|
|
* with per-page frontmatter (Next.js llms-full.txt format).
|
|
*
|
|
* Run from repo root or documentation/docs/:
|
|
* node documentation/scripts/next-scripts/generate-llms-txt.mjs
|
|
*/
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const PAGES_DIR = path.resolve(__dirname, '../../docs/pages');
|
|
const OUTPUT_FILE = path.resolve(__dirname, '../../docs/public/llms-full.txt');
|
|
const SITE_URL = 'https://nym.com/docs';
|
|
|
|
// Directories to skip entirely (auto-generated API reference, archives, etc.)
|
|
const SKIP_DIRS = new Set(['api', 'archive', 'playground']);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/** Read _meta.json for ordered keys; fall back to alphabetical. */
|
|
function getPageOrder(dir) {
|
|
const metaPath = path.join(dir, '_meta.json');
|
|
if (fs.existsSync(metaPath)) {
|
|
try {
|
|
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
return Object.keys(meta);
|
|
} catch { /* fall through */ }
|
|
}
|
|
return fs.readdirSync(dir)
|
|
.filter(f => !f.startsWith('_') && !f.startsWith('.'))
|
|
.map(f => f.replace(/\.mdx?$/, ''))
|
|
.filter((v, i, a) => a.indexOf(v) === i)
|
|
.sort();
|
|
}
|
|
|
|
/** Extract title from frontmatter or first H1. */
|
|
function extractTitle(content, fallback) {
|
|
const fm = content.match(/^---[\s\S]*?title:\s*["']?(.+?)["']?\s*$/m);
|
|
if (fm) return fm[1];
|
|
const h1 = content.match(/^#\s+(.+)$/m);
|
|
if (h1) return h1[1];
|
|
return fallback.replace(/[-_]/g, ' ');
|
|
}
|
|
|
|
/** Extract description from frontmatter. */
|
|
function extractDescription(content) {
|
|
const fm = content.match(/^---[\s\S]*?description:\s*["']?(.+?)["']?\s*$/m);
|
|
return fm ? fm[1] : '';
|
|
}
|
|
|
|
/** Strip frontmatter, imports, and JSX from MDX, leaving clean Markdown. */
|
|
function stripMdx(content) {
|
|
let s = content;
|
|
|
|
// Frontmatter
|
|
s = s.replace(/^---[\s\S]*?---\n*/m, '');
|
|
|
|
// Import statements
|
|
s = s.replace(/^import\s+.*$/gm, '');
|
|
|
|
// Self-closing JSX tags: <Component ... />
|
|
s = s.replace(/^\s*<\w[\w.-]*(?:\s[^>]*)?\s*\/>\s*$/gm, '');
|
|
|
|
// JSX block tags on their own line: <Callout type="info">, </Callout>, etc.
|
|
// Keep the children — only remove the tag lines themselves.
|
|
s = s.replace(/^\s*<\/?\w[\w.-]*(?:\s[^>]*)?\s*>\s*$/gm, '');
|
|
|
|
// Collapse 3+ blank lines → 2
|
|
s = s.replace(/\n{3,}/g, '\n\n');
|
|
|
|
return s.trim();
|
|
}
|
|
|
|
/** Convert file path to URL. */
|
|
function fileToUrl(filePath) {
|
|
let rel = path.relative(PAGES_DIR, filePath)
|
|
.replace(/\.mdx?$/, '')
|
|
.replace(/\/index$/, '');
|
|
return `${SITE_URL}/${rel}`;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Recursive page collector
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function collectPages(dir) {
|
|
const pages = [];
|
|
const order = getPageOrder(dir);
|
|
|
|
for (const key of order) {
|
|
const subDir = path.join(dir, key);
|
|
|
|
// Skip excluded directories
|
|
if (SKIP_DIRS.has(key) && fs.existsSync(subDir) && fs.statSync(subDir).isDirectory()) {
|
|
continue;
|
|
}
|
|
|
|
// Find the page file (.mdx preferred over .md)
|
|
let filePath = null;
|
|
for (const ext of ['.mdx', '.md']) {
|
|
const p = path.join(dir, `${key}${ext}`);
|
|
if (fs.existsSync(p)) { filePath = p; break; }
|
|
}
|
|
|
|
// Or an index file inside a subdirectory
|
|
if (!filePath && fs.existsSync(subDir) && fs.statSync(subDir).isDirectory()) {
|
|
for (const ext of ['.mdx', '.md']) {
|
|
const p = path.join(subDir, `index${ext}`);
|
|
if (fs.existsSync(p)) { filePath = p; break; }
|
|
}
|
|
}
|
|
|
|
if (filePath) {
|
|
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
const title = extractTitle(raw, key);
|
|
const description = extractDescription(raw);
|
|
const body = stripMdx(raw);
|
|
|
|
if (body.length > 0) {
|
|
pages.push({ title, description, url: fileToUrl(filePath), body });
|
|
}
|
|
}
|
|
|
|
// Recurse into subdirectory
|
|
if (fs.existsSync(subDir) && fs.statSync(subDir).isDirectory()) {
|
|
pages.push(...collectPages(subDir));
|
|
}
|
|
}
|
|
|
|
return pages;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Main
|
|
// ---------------------------------------------------------------------------
|
|
|
|
console.log(`Scanning ${PAGES_DIR} ...`);
|
|
const pages = collectPages(PAGES_DIR);
|
|
|
|
const lines = [];
|
|
|
|
// Global header
|
|
lines.push(`# Nym Documentation\n`);
|
|
lines.push(`@version: 1.20.4`);
|
|
lines.push(`@generated: ${new Date().toISOString().split('T')[0]}`);
|
|
lines.push(`@pages: ${pages.length}`);
|
|
lines.push(`@source: https://github.com/nymtech/nym/tree/develop/documentation/docs`);
|
|
lines.push('');
|
|
|
|
// Per-page blocks
|
|
for (const page of pages) {
|
|
lines.push('---');
|
|
lines.push(`title: ${page.title}`);
|
|
if (page.description) {
|
|
lines.push(`description: ${page.description}`);
|
|
}
|
|
lines.push(`url: ${page.url}`);
|
|
lines.push('---');
|
|
lines.push('');
|
|
lines.push(page.body);
|
|
lines.push('');
|
|
}
|
|
|
|
const output = lines.join('\n');
|
|
fs.writeFileSync(OUTPUT_FILE, output);
|
|
|
|
const sizeKb = (Buffer.byteLength(output, 'utf-8') / 1024).toFixed(0);
|
|
console.log(`Wrote ${pages.length} pages to ${OUTPUT_FILE} (${sizeKb} KB)`);
|