Skip to content

Principios del Modo de Ocultación: Por Qué el Cálculo de Ancho es Tan Importante

Lo Que Aprenderás

  • Entender cómo funciona el modo de ocultación de OpenCode
  • Saber por qué las herramientas de formateo normales desalinean las tablas en modo de ocultación
  • Dominar el algoritmo de cálculo de ancho del plugin (tres pasos)
  • Entender el papel de Bun.stringWidth

Tu Dilema Actual

Escribes código con OpenCode y la IA genera una tabla hermosa:

markdown
| Campo | Tipo | Descripción |
|--- | --- | ---|
| **name** | string | Nombre de usuario |
| age | number | Edad |

En la vista de código fuente se ve bastante ordenada. Pero al cambiar al modo de vista previa, la tabla está desalineada:

| Campo     | Tipo   | Descripción   |
|--- | --- | ---|
| name | string | Nombre de usuario |    ← ¿Por qué se acortó?
| age      | number | Edad   |

¿Dónde está el problema? Modo de ocultación.

Qué es el Modo de Ocultación

OpenCode habilita por defecto el Modo de Ocultación (Concealment Mode), que oculta los símbolos de sintaxis Markdown al renderizar:

Código FuenteVisualización en Modo de Ocultación
**negrita**negrita(4 caracteres)
*cursiva*cursiva(4 caracteres)
~~tachado~~tachado(6 caracteres)
`código`código(4 caracteres + color de fondo)

Beneficios del Modo de Ocultación

Te permite concentrarte en el contenido en sí, en lugar de ser distraído por un montón de símbolos ** y *.

Por Qué las Herramientas de Formateo Normales Tienen Problemas

Las herramientas normales de formateo de tablas calculan el ancho considerando **name** como 8 caracteres:

** n a m e ** = 8 caracteres

Pero en modo de ocultación, el usuario ve name, que solo tiene 4 caracteres.

El resultado es: la herramienta de formateo alinea según 8 caracteres, pero el usuario ve 4 caracteres, por lo que la tabla naturalmente se desalinea.

Idea Central: Calcular "Ancho de Visualización" en Lugar de "Longitud de Caracteres"

La idea central de este plugin es: calcular el ancho que el usuario realmente ve, no el número de caracteres en el código fuente.

El algoritmo se divide en tres pasos:

Paso 1: Proteger bloques de código(los símbolos dentro de bloques de código no se eliminan)
Paso 2: Eliminar símbolos Markdown(**、*、~~, etc.)
Paso 3: Usar Bun.stringWidth para calcular el ancho final

Sígueme: Entender el Algoritmo de Tres Pasos

Paso 1: Proteger Bloques de Código

Por Qué

Los símbolos Markdown dentro del código en línea (envuelto en comillas invertidas) son "literales", el usuario verá los 8 caracteres **bold**, no los 4 caracteres bold.

Por lo tanto, antes de eliminar los símbolos Markdown, primero hay que "esconder" el contenido de los bloques de código.

Implementación en Código Fuente

typescript
// Paso 1: Extraer y proteger código en línea
const codeBlocks: string[] = []
let textWithPlaceholders = text.replace(/`(.+?)`/g, (match, content) => {
  codeBlocks.push(content)
  return `\x00CODE${codeBlocks.length - 1}\x00`
})

Cómo Funciona

EntradaDespués del ProcesamientoArray codeBlocks
`**bold**`\x00CODE0\x00["**bold**"]
`a` and `b`\x00CODE0\x00 and \x00CODE1\x00["a", "b"]

Reemplaza los bloques de código con marcadores de posición especiales como \x00CODE0\x00, de modo que al eliminar los símbolos Markdown más tarde no se dañen accidentalmente.

Paso 2: Eliminar Símbolos Markdown

Por Qué

En modo de ocultación, **negrita** se muestra como negrita, *cursiva* se muestra como cursiva. Al calcular el ancho, hay que eliminar estos símbolos.

Implementación en Código Fuente

typescript
// Paso 2: Eliminar símbolos Markdown de partes que no son código
let visualText = textWithPlaceholders
let previousText = ""

while (visualText !== previousText) {
  previousText = visualText
  visualText = visualText
    .replace(/\*\*\*(.+?)\*\*\*/g, "$1") // ***negrita cursiva*** → texto
    .replace(/\*\*(.+?)\*\*/g, "$1")     // **negrita** → negrita
    .replace(/\*(.+?)\*/g, "$1")         // *cursiva* → cursiva
    .replace(/~~(.+?)~~/g, "$1")         // ~~tachado~~ → tachado
    .replace(/!\[([^\]]*)\]\(([^)]+)\)/g, "$1")     // ![alt](url) → alt
    .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)") // [texto](url) → texto (url)
}

¿Por Qué Usar un Bucle While?

Para manejar sintaxis anidada. Por ejemplo ***negrita cursiva***:

Ronda 1: ***negrita cursiva*** → **negrita cursiva**(eliminar la capa más externa ***)
Ronda 2: **negrita cursiva** → *negrita cursiva*(eliminar **)
Ronda 3: *negrita cursiva* → negrita cursiva(eliminar *)
Ronda 4: negrita cursiva = negrita cursiva(sin cambios, salir del bucle)
Procesamiento de Imágenes y Enlaces
  • Imagen ![alt](url): OpenCode solo muestra el texto alt, por lo que se reemplaza con alt
  • Enlace [texto](url): Se muestra como texto (url), conservando la información de la URL

Paso 3: Restaurar Bloques de Código + Calcular Ancho

Por Qué

El contenido de los bloques de código debe devolverse, y luego usar Bun.stringWidth para calcular el ancho de visualización final.

Implementación en Código Fuente

typescript
// Paso 3: Restaurar contenido de bloques de código
visualText = visualText.replace(/\x00CODE(\d+)\x00/g, (match, index) => {
  return codeBlocks[parseInt(index)]
})

return Bun.stringWidth(visualText)

¿Por Qué Usar Bun.stringWidth?

Bun.stringWidth puede calcular correctamente:

Tipo de CarácterEjemploNúmero de CaracteresAncho de Visualización
ASCIIabc33
Chino你好24(cada uno ocupa 2 espacios)
Emoji😀12(ocupa 2 espacios)
Carácter de Ancho Ceroa\u200Bb32(los caracteres de ancho cero no ocupan espacio)

El text.length normal solo puede contar el número de caracteres, no puede manejar estos casos especiales.

Ejemplo Completo

Supongamos que el contenido de la celda es: **`code`** and *text*

Paso 1: Proteger Bloques de Código

Entrada:**`code`** and *text*
Salida:**\x00CODE0\x00** and *text*
codeBlocks = ["code"]

Paso 2: Eliminar Símbolos Markdown

Ronda 1: **\x00CODE0\x00** and *text* → \x00CODE0\x00 and text
Ronda 2: Sin cambios, salir

Paso 3: Restaurar Bloques de Código + Calcular Ancho

Después de restaurar:code and text
Ancho:Bun.stringWidth("code and text") = 13

Finalmente, el plugin alinea esta celda según un ancho de 13 caracteres, en lugar de los 22 caracteres del código fuente.

Punto de Control

Después de completar esta lección, deberías poder responder:

  • [ ] ¿Qué símbolos oculta el modo de ocultación?(Respuesta: Símbolos de sintaxis Markdown como **, *, ~~, etc.)
  • [ ] ¿Por qué proteger primero los bloques de código?(Respuesta: Los símbolos dentro de los bloques de código son literales y no deben eliminarse)
  • [ ] ¿Por qué usar un bucle while para eliminar símbolos?(Respuesta: Para manejar sintaxis anidada, como ***negrita cursiva***
  • [ ] ¿En qué es mejor Bun.stringWidth que text.length?(Respuesta: Puede calcular correctamente el ancho de visualización de chino, emoji, caracteres de ancho cero, etc.)

Advertencia de Trampas

Malentendidos Comunes

Malentendido: Los ** dentro de los bloques de código también se eliminarán

Realidad: No. El plugin primero protege el contenido de los bloques de código con marcadores de posición, elimina los símbolos de otras partes y luego los restaura.

Por lo tanto, el ancho de `**bold**` es 8(**bold**),no 4(bold)。

Resumen de Esta Lección

PasoFunciónCódigo Clave
Proteger bloques de códigoEvitar que los símbolos dentro de los bloques de código se eliminen por errortext.replace(/\(.+?)`/g, ...)`
Eliminar MarkdownCalcular el contenido de visualización real en modo de ocultaciónMúltiples reemplazos con regex
Calcular anchoManejar caracteres especiales como chino, emoji, etc.Bun.stringWidth()

Próxima Lección

En la próxima lección aprenderemos Especificaciones de Tablas.

Aprenderás:

  • Qué tipo de tablas pueden ser formateadas
  • Las 4 reglas de validación de tablas
  • Cómo evitar errores de "tabla inválida"

Apéndice: Referencia de Código Fuente

Haz clic para expandir y ver la ubicación del código fuente

Última actualización: 2026-01-26

FunciónRuta del ArchivoNúmero de Línea
Entrada de cálculo de ancho de visualizaciónindex.ts151-159
Protección de bloques de códigoindex.ts168-173
Eliminación de símbolos Markdownindex.ts175-188
Restauración de bloques de códigoindex.ts190-193
Llamada a Bun.stringWidthindex.ts195

Funciones Clave:

  • calculateDisplayWidth(): Entrada de cálculo de ancho con caché
  • getStringWidth(): Algoritmo central, elimina símbolos Markdown y calcula el ancho de visualización

Constantes Clave:

  • \x00CODE{n}\x00: Formato de marcador de posición para bloques de código