Grupo de Código (Pestañas Multi-Runtime)
<CodeGroup> muestra un único concepto en pestañas sincronizadas en lugar de apilar tres bloques de código separados. Está diseñado para ecosistemas inherentemente multi-superficie -- una característica de Solana es un programa Rust en cadena y un cliente TypeScript y una invocación CLI, y un lector quiere cambiar entre ellos en el lugar en lugar de desplazarse más allá de los tres.
La elección de idioma activo del lector se recuerda y se sincroniza en cada grupo en la página (y sitio) para la sesión, por lo que elegir "TypeScript" una vez mantiene cada grupo mostrando TypeScript.
Pestaña predeterminada del lector (característica opcional). Cuando el sitio habilita preferencias de pestañas predeterminadas, cada grupo distinto aparece en Configuración → "Valores predeterminados de ejemplos de código" con un menú desplegable para elegir la pestaña en la que se abre de forma predeterminada. Esa elección se guarda en el dispositivo del lector, y en su cuenta cuando ha iniciado sesión. La sincronización por sesión anterior todavía se aplica pero nunca sobrescribe el valor predeterminado guardado. Los autores no hacen nada extra -- cualquier
<CodeGroup>que escribas se recoge automáticamente.
Casos de uso
- Solana -- la misma característica como un programa Rust en cadena, un cliente TypeScript y un comando CLI, uno al lado del otro.
- Node.js -- CommonJS vs ESM, o JavaScript plano vs TypeScript.
- Rust --
cargovsrustccrudo, o variantes sincrónicas vs asincrónicas de una API. - Cualquier documento donde una idea tiene múltiples superficies equivalentes y apilar bloques se lee mal.
Cómo crear
Envuelve dos o más bloques de código delimitados en <CodeGroup> y pasa labels como una cadena separada por comas, en el mismo orden que los bloques. Deja una línea en blanco alrededor de cada bloque delimitado.
<CodeGroup labels="Rust, TypeScript client, CLI">
```rust
// on-chain program
```
```ts
// client
```
```bash
solana balance ADDRESS
```
</CodeGroup>Siempre usa la forma de cadena (
labels="A, B, C"). Este repositorio renderiza MDX a través denext-mdx-remote/rsc, que no pasa atributos de expresión JSX -- por lo quelabels={["A", "B"]}(y cualquier otra prop{...}) se elimina silenciosamente y cada pestaña vuelve aTab 1,Tab 2, y así sucesivamente. Por la misma razón, desactiva la sincronización con la cadenasync="false", nuncasync={false}. Mantén las comas fuera de una etiqueta, ya que la cadena se divide en comas.
Cualquier bloque sin una etiqueta coincidente vuelve a Tab 1, Tab 2, y así sucesivamente.
Ejemplo en vivo: Solana (el caso decisivo)
La misma característica "leer el saldo de una cuenta" en las tres superficies de Solana. Elige una pestaña -- los otros grupos en esta página siguen tu elección.
// programs/balance/src/lib.rs -- on-chain Anchor program
use anchor_lang::prelude::*;
declare_id!("Ba1anceReader1111111111111111111111111111111");
#[program]
pub mod balance {
use super::*;
pub fn read(ctx: Context<Read>) -> Result<()> {
let lamports = ctx.accounts.wallet.lamports();
msg!("balance: {} lamports", lamports);
Ok(())
}
}
#[derive(Accounts)]
pub struct Read<'info> {
/// CHECK: read-only balance lookup
pub wallet: AccountInfo<'info>,
}// client.ts -- TypeScript client (@solana/web3.js)
import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const wallet = new PublicKey("So11111111111111111111111111111111111111112");
const lamports = await connection.getBalance(wallet);
console.log(`balance: ${lamports / LAMPORTS_PER_SOL} SOL`);# CLI -- Solana command line
solana balance So11111111111111111111111111111111111111112 \
--url mainnet-betaEjemplo en vivo: Node.js (CJS vs ESM)
// index.cjs
const { readFile } = require("node:fs/promises");
async function main() {
const pkg = await readFile("package.json", "utf8");
console.log(JSON.parse(pkg).name);
}
main();// index.mjs
import { readFile } from "node:fs/promises";
const pkg = await readFile("package.json", "utf8");
console.log(JSON.parse(pkg).name);Ejemplo en vivo: Rust (sincrónico vs asincrónico, sync="false")
Este grupo usa sync="false" porque "sincrónico vs asincrónico" es una distinción única que no debe secuestrar la preferencia de idioma en todo el sitio establecida por los grupos anteriores.
// blocking read with std
use std::fs;
fn main() -> std::io::Result<()> {
let contents = fs::read_to_string("Cargo.toml")?;
println!("{}", contents.lines().count());
Ok(())
}// async read with tokio
use tokio::fs;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let contents = fs::read_to_string("Cargo.toml").await?;
println!("{}", contents.lines().count());
Ok(())
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
labels | cadena separada por comas string (p. ej. "A, B, C") | Tab N | Texto de la pestaña, en el mismo orden que los bloques de código. Usa la forma de cadena -- los atributos de expresión como labels={[...]} son eliminados por el renderizador MDX. |
sync | string ("false" para desactivar) | activado | Recuerda la elección y sincronízala con otros grupos que compartan una etiqueta. Establece sync="false" para conjuntos de pestañas únicos. |
Trampas
- Deja líneas en blanco alrededor de cada bloque de código delimitado dentro de
<CodeGroup>, o MDX no los analizará como bloques separados. - El orden de las etiquetas importa -- las etiquetas se asignan a bloques posicionalmente, no por idioma.
- La sincronización es por texto de etiqueta (sin distinción de mayúsculas y minúsculas). Un grupo solo sigue una elección compartida si tiene una pestaña con esa etiqueta exacta; de lo contrario, mantiene su propia selección.
- Establece
sync="false"(la cadena, nosync={false}) para distinciones que no son una elección de idioma (sincrónico/asincrónico, antes/después) para que no sobrescriban el idioma preferido del lector. - Usa solo atributos de cadena.
next-mdx-remote/rscelimina los atributos de expresión JSX (labels={[...]},sync={false}), por lo que las formas de cadena sin formatolabels="A, B, C"ysync="false"son la única sintaxis confiable.
Alternativas
- Tres bloques de código apilados -- el más simple, pero se lee mal y obliga a desplazarse más allá de superficies irrelevantes.
- Un componente
<Tabs>genérico -- funciona para contenido arbitrario, pero no da a los bloques de código un trato de primera clase (botón de copia por pestaña, memoria de idioma compartida, diseño consciente del monoespaciado). - Páginas separadas por tiempo de ejecución -- apropiado cuando las superficies divergen sustancialmente, pero divide un concepto en la navegación.
Relacionado
- Tabs -- el componente de contenido con pestañas de propósito general.