Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ Never use `98865`—that is a deprecated chain ID.
## Rules

1. **Alphabetize everything** - Object properties in code examples and ### parameter headings must be alphabetically ordered
13. **Install code-groups must include npm, pnpm, and bun** - Every `:::code-group` with install commands must have all three tabs: `npm`, `pnpm`, and `bun`. Use `npm install`, `pnpm add`, and `bun add` respectively.
12. **No `// @noErrors` in twoslash** - NEVER use `// @noErrors` in twoslash code blocks. All snippets must typecheck against the installed mppx types. If a snippet fails, fix the snippet or bump the mppx version — do not suppress the error.
2. **No code-groups for variants** - Use separate ### sections under ## Usage for different usage patterns (e.g., `### With MCP Transport`), not `:::code-group`
3. **Keep descriptions concise** - One line for the intro, brief explanations for parameters
Expand Down
88 changes: 88 additions & 0 deletions scripts/check-install-tabs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";

const PAGES_DIR = join(import.meta.dirname, "../src/pages");
const REQUIRED_TABS = ["npm", "pnpm", "bun"] as const;

/**
* Recursively find all .mdx files under a directory.
*/
function findMdxFiles(dir: string): string[] {
const results: string[] = [];
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const fullPath = join(dir, entry.name);
if (entry.isDirectory()) {
results.push(...findMdxFiles(fullPath));
} else if (entry.name.endsWith(".mdx")) {
results.push(fullPath);
}
}
return results;
}

/**
* Find install code-groups in MDX content and check they have all three tabs.
* Returns an array of violations with line numbers and missing tabs.
*/
function checkInstallTabs(
content: string,
): Array<{ line: number; missing: string[] }> {
const lines = content.split("\n");
const violations: Array<{ line: number; missing: string[] }> = [];

for (let i = 0; i < lines.length; i++) {
// Look for a bash [npm] block that contains an install command
const line = lines[i];
if (!/^```bash \[npm\]/.test(line)) continue;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect install groups without an npm tab

checkInstallTabs only validates blocks after matching ````bash [npm], so an install code-group that accidentally omits the npm tab is skipped entirely. In that case the test passes even though the new policy requires all three tabs (npm`, `pnpm`, and `bun`), so this guardrail can miss real violations.

Useful? React with 👍 / 👎.


// Check the next line for an install command (npm install / npx)
const cmdLine = lines[i + 1] ?? "";
const isInstall =
/^\$?\s*npm install\b/.test(cmdLine) || /^\$?\s*npx\b/.test(cmdLine);
if (!isInstall) continue;

// Scan the surrounding code-group for which tabs exist
const found = new Set<string>(["npm"]);

// Scan forward until ::: closing
for (let j = i + 1; j < lines.length; j++) {
if (/^:::$/.test(lines[j].trim())) break;
const tabMatch = lines[j].match(/^```bash \[(npm|pnpm|bun)\]/);
if (tabMatch) found.add(tabMatch[1]);
}

const missing = REQUIRED_TABS.filter((t) => !found.has(t));
if (missing.length > 0) {
violations.push({ line: i + 1, missing });
}
}

return violations;
}

describe("install code-groups must include npm, pnpm, and bun", () => {
const files = findMdxFiles(PAGES_DIR);

for (const file of files) {
const relative = file.slice(PAGES_DIR.length + 1);
const content = readFileSync(file, "utf-8");
const violations = checkInstallTabs(content);

if (violations.length > 0) {
it(`${relative}`, () => {
const messages = violations.map(
(v) =>
`line ${v.line}: missing ${v.missing.map((t) => `[${t}]`).join(", ")} tab(s)`,
);
expect(violations).toHaveLength(0);
// Show details on failure:
expect.fail(`Install code-group missing tabs:\n${messages.join("\n")}`);
});
}
}

it("found mdx files to check", () => {
expect(files.length).toBeGreaterThan(0);
});
});
3 changes: 3 additions & 0 deletions src/pages/payment-methods/card/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ npm install mpp-card
```bash [pnpm]
pnpm add mpp-card
```
```bash [bun]
bun add mpp-card
```
:::

## How it works
Expand Down
3 changes: 3 additions & 0 deletions src/pages/payment-methods/lightning/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ npm install @buildonspark/lightning-mpp-sdk
```bash [pnpm]
pnpm add @buildonspark/lightning-mpp-sdk
```
```bash [bun]
bun add @buildonspark/lightning-mpp-sdk
```
:::

## Payments on Lightning
Expand Down
3 changes: 3 additions & 0 deletions src/pages/payment-methods/solana/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ npm install @solana/mpp mppx @solana/kit
```bash [pnpm]
pnpm add @solana/mpp mppx @solana/kit
```
```bash [bun]
bun add @solana/mpp mppx @solana/kit
```
:::

## Why Solana
Expand Down
Loading