Novedades
Notas de versión de acs2md, de más reciente a más antigua. El comportamiento de conversión proviene del motor ADF compartido de Climakers, así que la mayoría de los cambios de salida se aplican también a acp2md.
v1.0.12
Restaurar desde una copia de seguridad
acs2md ahora puede devolver contenido a Confluence, no solo sacarlo. space restore compara una copia de seguridad con el espacio, muestra el plan, pide confirmación y después restaura página a página, empezando por los padres: las páginas y carpetas que Confluence ya no tiene (--mode missing, el valor por defecto), las páginas editadas desde entonces (--mode changed) o ambas (--mode all). --create-space reconstruye un espacio perdido, o una copia con una clave nueva. El progreso se guarda después de cada página, así que una restauración interrumpida se reanuda donde se detuvo; una página que ya está en el espacio con su título se adopta en lugar de crearse dos veces, y los enlaces entre páginas restauradas pasan a apuntar a sus nuevos ID cuando todas existen. page restore hace lo mismo para una sola página, desde una copia de seguridad de espacio o desde un archivo escrito por page get.
space restore y page restore son los únicos comandos que escriben en Confluence. Nunca eliminan, envían a la papelera, archivan ni mueven nada, nunca sobrescriben una propiedad de contenido en la que una aplicación guarda su estado, y --dry-run muestra el plan sin escribir. El mensaje de la versión que escribe una restauración nombra la fecha de la copia de seguridad, nunca una ruta local. Consulta Restaurar un espacio y Restaurar páginas.
Comprobar un espacio frente a su copia de seguridad
space check informa, página a página, de lo que ha cambiado desde una copia de seguridad: páginas editadas, renombradas o movidas; páginas en la papelera, archivadas, movidas a otro espacio o desaparecidas; páginas nuevas; y lo mismo para las carpetas y para el nombre y la página de inicio del espacio. --deep compara los cuerpos de las páginas, -f json genera un informe legible por máquina y --fail-on-drift hace que una tarea programada falle cuando el espacio se ha desviado. Las copias de seguridad anteriores a los manifiestos se comparan hasta donde lo permiten. No cambia nada ni en Confluence ni en la copia de seguridad. Consulta Comprobar frente a una copia de seguridad.
Tras un space restore, una página o carpeta restaurada tiene un ID nuevo; space check la asocia a su original a través del archivo de progreso de la restauración y la informa como ok. page check hace la misma comparación para una sola página respaldada: su estado, versión y cuerpo, y los adjuntos y etiquetas que ya no tiene.
space get toma una copia de seguridad restaurable
Junto a los cuerpos de página, space get escribe ahora .backup-manifest.json —el ID, el título, el estado, el padre, la posición, la versión y el hash del cuerpo de cada página, el nombre, el tipo, la descripción y la página de inicio del espacio, y cada carpeta de Confluence bajo la que están las páginas— y guarda por defecto adjuntos, etiquetas y propiedades de contenido. Cada uno cuesta llamadas adicionales a la API; --include-attachments=false, --include-labels=false, --include-properties=false y --manifest=false los desactivan. Los adjuntos que no han cambiado no se descargan de nuevo en la siguiente ejecución. Consulta Copias de seguridad restaurables.
space get guarda ahora storage por defecto (antes era
atlas_doc_format), porque storage se refiere a los adjuntos y a las páginas
por nombre, lo que sobrevive a una restauración que les da ID nuevos. Pasa
--format atlas_doc_format para el comportamiento anterior. Un directorio
que ya contiene una copia de seguridad conserva su formato salvo que pases
--format, así que una copia programada existente nunca mezcla archivos
.html y .json. La primera ejecución de v1.0.12 sobre una copia de
seguridad existente descarga cada página una vez más para completar el
manifiesto; las siguientes vuelven a omitir las páginas sin cambios.
page get mantiene atlas_doc_format como valor por defecto.
page get --attachments-dir <dir> descarga los adjuntos de una página en <dir>/<page-id>/ y los describe, de modo que una página concreta puede respaldarse y restaurarse con sus archivos.
Cada petición tiene un plazo
El nuevo http.client.request_timeout (por defecto 10m, 0 lo desactiva) limita una petición desde que se envía hasta que se lee toda la respuesta, incluidos sus reintentos y las esperas de Retry-After. Antes, una conexión bloqueada dejaba colgada la ejecución hasta Ctrl-C. Los archivos de configuración existentes no tienen la clave y reciben el valor por defecto; doctor muestra el valor en una nueva fila HTTP request timeout. El mensaje “Timed out waiting for the Confluence API” nombra ahora este ajuste en lugar de http.client.max_timeout, que limita el backoff de los reintentos y no termina una petición lenta. Consulta Cada petición tiene un plazo.
Correcciones
- Los comandos ya no se quedan colgados cuando stdin queda abierta. Todos los comandos que reciben un ID, un título, una URL de página o una clave de espacio leían la entrada estándar hasta el final siempre que no fuera un terminal, incluso con el valor ya en la línea de comandos. Desde un runner de CI, una sesión ssh o una herramienta que mantiene stdin abierta, el comando esperaba para siempre. Ahora stdin solo se lee cuando falta el argumento, así que
echo MYSPACE | acs2md space get by-keysigue funcionando. - Volver a activar con una clave renovada funciona. Una suscripción renovada conserva su clave, pero
license activate --license-key <la misma clave>la rechazaba con “license has expired” una vez vista la caducidad en local. Ahora el comando pregunta a la tienda y actualiza la licencia instalada cuando la tienda informa de que la clave vuelve a estar activa. --forcehace lo que prometía su ayuda con una clave.license activate --license-key <clave-nueva> --forcesustituye una licencia activa, liberando antes su puesto; antes, el flag solo se aplicaba a los archivos de licencia. Consulta Volver a ejecutaractivate.- Los árboles de comandos se regeneran desde los binarios. La referencia de acp2md se había quedado atrás y le faltaban los flags de
page convert,page countypage properties; el listado detree --shortde este manual muestra ahora tambiénpage check,page restore,space checkyspace restore.
Por dentro
Las escrituras pasan por un cliente HTTP separado que respeta Retry-After solo en 429 y nunca reintenta a ciegas, así que una creación de página cuya respuesta se perdió se busca en lugar de enviarse dos veces. El estado de sincronización, el manifiesto y las descargas de adjuntos se publican a través de un archivo temporal y un renombrado, así que una descarga que falla a medias no deja nada atrás. Compilado con Go 1.27.3.
v1.0.10
Saber cuándo hay algo que instalar
acs2md doctor informa de la versión más reciente disponible para ti en una nueva fila Latest version, junto con el comando que la instala; la comprobación nunca hace fallar el diagnóstico y dice “could not check” sin conexión. Después de un comando ordinario, acs2md también consulta el servicio de actualizaciones como máximo una vez al día, espera como máximo dos segundos e imprime una sola línea en stderr cuando existe una versión más reciente. El aviso nunca aparece en CI, bajo sudo, cuando stderr no es un terminal, ni después de update, license, doctor y config. Desactívalo con acs2md config set update.notice false. Consulta El aviso diario de nueva versión.
acs2md update también sigue funcionando cuando se alcanza el límite diario de descargas de la tienda —cada archivo puede descargarse diez veces al día— y, a partir de ahí, obtiene la misma versión desde el almacenamiento de versiones propio de Climakers, una vez al día por instalación.
La activación es más estable en Linux
Los archivos de licencia se cifran contra un identificador de máquina, y en Linux ese identificador sobrevive ahora a las actualizaciones del kernel y del microcódigo y a los cambios de tamaño de las VM. Las licencias activadas antes de esta versión siguen funcionando: una licencia de suscripción pasa al nuevo identificador la primera vez que se abre, y una licencia local firmada conserva el identificador para el que se emitió. No hace falta volver a activar nada. macOS no se ve afectado.
Correcciones
acs2md updateve una versión nueva de inmediato. Justo después de una publicación,updatepodía informar de la versión anterior durante varios minutos porque el servicio de actualizaciones respondía desde una copia en caché. Instalar, yupdate --check --force, consultan ahora el servicio directamente, así que una versión se ofrece en menos de un minuto desde su publicación; unupdate --checksin más puede tardar hasta dos minutos.
v1.0.9
Correcciones
license activate --license-key <archivo>dice qué flag recibe un archivo. Pasar un archivo de licencia a--license-keyrespondía “invalid license key format: expected UUID v4”; ahora explica que un archivo de licencia se activa con--license-filee imprime el comando exacto.
v1.0.8
Nada de lo que usas cambia: el motor de actualización pasó a un módulo compartido de Climakers, que ajat también usa ahora, y update se comporta exactamente igual que antes.
v1.0.7
Las licencias sin conexión también se actualizan
Una licencia local emitida por licensegen con una clave de firma lleva una firma que el servicio de actualizaciones verifica por sí mismo, así que los clientes sin conexión reciben acs2md update como todos los demás; sus descargas provienen del almacenamiento de versiones de Climakers en lugar de la tienda. Las licencias locales emitidas antes de que existiera la firma se rechazan con “this local license is not signed” y una pista para activar un archivo reemitido. Consulta Tu suscripción y las versiones anteriores.
v1.0.6
Actualizaciones desde la propia herramienta
acs2md update instala la versión más reciente que incluye tu licencia: consulta en Climakers si hay una versión más reciente, la descarga, verifica su suma SHA-256 y reemplaza el binario en ejecución. En macOS instala el paquete firmado y notarizado y se ejecuta como sudo acs2md update; en Linux reemplaza el binario en su sitio y nunca usa sudo. --check informa sin cambiar nada, --version v1.1.0 instala una versión concreta (que es también la forma de volver atrás), --yes omite la confirmación y es obligatorio en CI, y --format json es para scripts. Cuando termina una suscripción, las versiones publicadas antes de esa fecha siguen siendo instalables. El comando no necesita credenciales de Confluence y no cuenta para el límite de comandos de la licencia. Consulta Actualizar acs2md.
La salida de --format json cambió en dos aspectos
La salida JSON la produce ahora encoding/json/v2 de Go. Dos diferencias visibles, ambas deliberadas:
- una lista o un mapa vacíos se imprimen como
[]/{}en lugar denull, así que una página sin etiquetas es"labels": []y no"labels": null; <,>y&dentro de las cadenas ya no se escapan, así que un título comoQ&A <draft>se lee tal como está escrito.
El orden de las claves, la indentación y el salto de línea final no cambian, y los archivos de estado de sincronización siguen siendo legibles por versiones anteriores. Los scripts que comprueban null deberían comprobar una lista vacía.
Notas de plataforma
- Se requiere macOS 13 (Ventura) o posterior. La cadena de herramientas de Go con la que se compila esta versión dejó de admitir versiones anteriores de macOS.
- Se respetan
SSL_CERT_FILEySSL_CERT_DIRen macOS. Cuando alguna está definida, las raíces de certificados se cargan desde esas rutas en lugar del almacén de la plataforma, el comportamiento que Linux siempre tuvo. Las configuraciones de proxy corporativo que definen estas variables para otras herramientas verán que aquí también se aplican;GODEBUG=x509sslcertoverrideplatform=0restaura el comportamiento anterior.
v1.0.5
Esta versión cambió la salida Markdown por defecto en las páginas que
contienen paneles y para quien use --include-metadata. Las dos acciones de
abajo no hacen nada si nunca escribiste el ajuste correspondiente.
Acción: revisa image.max_size_bytes
El valor por defecto bajó a 2 MB, pero una configuración escrita antes de esta versión casi con seguridad fija el antiguo 10485760, lo bastante permisivo como para incrustar un fondo de página y producir un archivo que ningún editor maquetará. La configuración gana a los valores por defecto, así que sigue imponiéndose:
acs2md config get image.max_size_bytes # 10485760 significa que el valor antiguo está fijado
acs2md config set image.max_size_bytes 2097152acp2md lee su propia configuración, así que ejecuta el mismo par allí si lo usas.
Acción: --resolve-users y --link-mentions ahora vienen activados
El front matter lleva nombres visibles y las menciones enlazan a los perfiles de las personas. Cuando una exportación se publica fuera de la organización, --resolve-users=false conserva los IDs de cuenta opacos.
La conversión de espacios se ejecuta en paralelo
space convert ahora convierte 4 páginas a la vez por defecto. La conversión está limitada por la red, así que solapar unas cuantas páginas oculta la mayor parte de la latencia por página. Con --concurrency 1 se restaura la conversión estrictamente secuencial.
La salida es idéntica con cualquier valor: las páginas se recogen en el orden de entrada, sin importar qué worker termine primero, así que la estructura de directorios, --rewrite-links y los totales del resumen no cambian. Consulta Rendimiento.
Se respeta Retry-After
Cuando Confluence responde a una petición limitada con 429 o 503 e indica un retardo, el cliente espera ahora exactamente ese tiempo en lugar de adivinarlo. Esto es lo que hace seguro subir --concurrency: es el servidor quien marca el ritmo, en vez de que el cliente lo descubra fallando.
Un retardo superior a 60 segundos se muestra en vez de esperarse, así que un comando nunca parece colgado, y la espera es interrumpible.
Los valores por defecto del backoff cambiaron, y actualizar no llega a una
instalación existente. Subieron de 10ms/100ms a 500ms/30s, pero un
archivo de configuración materializa todos los valores por defecto al crearse
y la configuración gana a los valores por defecto. Una instalación antigua
conserva un presupuesto total de 70 ms repartido en tres intentos, incapaz de
sobrevivir a una ventana real de limitación. Ejecuta acs2md doctor para
comprobarlo y consulta
Reintentos y límite de peticiones.
Las imágenes se pueden escribir como archivos sidecar
--image-sidecars guarda cada imagen en attachments/<page-id>/ junto al Markdown y la enlaza de forma relativa, en lugar de incrustar una URI de datos en base64. La exportación sigue siendo autónoma en ambos casos: lo que cambia es la longitud de línea.
En una página real: 1.440.451 B y una línea de 244.311 caracteres en base64, frente a 12.100 B y 379 caracteres con sidecars. En un espacio completo además se deduplica: una imagen reutilizada en diez páginas se guarda una sola vez.
--obsidian lo activa, porque el base64 era lo último de ese preajuste que no se renderizaba en Obsidian.
Salida para Obsidian
Un preajuste completo — callouts, anclajes de encabezado que Obsidian resuelve y archivos sidecar de imagen — además de --wikilinks, --inline-tags, --panel-style y --media-dimensions. Consulta Bóvedas de Obsidian.
Los paneles se renderizan como alerts de GitHub
> [!NOTE], > [!TIP], > [!WARNING] y > [!CAUTION] sustituyen a la cita con emoji anterior. Los alerts se renderizan tanto en GitHub como en Obsidian. Los tipos de panel sin equivalente conservan la forma con emoji. --panel-style=emoji restaura la salida antigua.
El front matter es YAML válido
--include-metadata emite ahora YAML determinista y correctamente entrecomillado, que Obsidian lee como Properties y que Jekyll, Hugo y Pandoc interpretan:
| Antes | Ahora |
|---|---|
Title, AuthorID, CreatedAt, ID, LastOwnerID, OwnerID, ParentID, ParentType, Position, SpaceID, Status, SubType, VersionAuthorID, VersionCreatedAt, VersionMessage, VersionMinorEdit, VersionNumber | title, tags, author, created, updated, source, space, status, version, id, parent_id, owner_id |
Las fechas son YYYY-MM-DD, tags procede de las labels de Confluence de la página, source es la URL de navegador y los campos vacíos se omiten. Los campos eliminados eran contabilidad interna de Confluence que ningún consumidor de Markdown usaba.
Las labels se recuperan automáticamente
Con el front matter activado, tags se rellena sin pasar --include-labels. En space convert las labels no forman parte del listado masivo de páginas, así que --include-labels (por defecto true) controla una petición adicional por página; ponlo a false para evitar ese coste.
Los enlaces de encabezado se resuelven en el renderizador para el que exportas
La tabla de contenidos emitía anclajes de tipo slug al estilo de GitHub sin importar el destino. --panel-style=obsidian (y por tanto --obsidian) emite ahora anclajes que Obsidian resuelve.
Cada comando informa de cuánto ha tardado
✅ Sync complete!
✅ Converted: 835
⏱️ Took: 2m 14sLa cifra cubre el comando completo, incluidas las llamadas a la API y las descargas de imágenes. Los comandos de página imprimen el tiempo en stderr, nunca en stdout, para que las redirecciones y los pipelines sigan limpios.
Un segundo Ctrl+C fuerza la salida
La primera interrupción cancela de forma limpia y deja que se replieguen las páginas ya en vuelo, lo cual no es instantáneo cuando se están convirtiendo varias a la vez. Antes, cualquier Ctrl+C adicional se descartaba y una ejecución que parecía atascada no se podía detener.
Correcciones
--debugno producía salida alguna. Fijaba el nivel de log pero dejaba el destino en su valor por defecto, que lo descarta todo. Ahora escribe en stderr salvo que--log-fileindique otra cosa.- Un
log.level,log.formatolog.fileinválido bloqueaba todos los comandos, incluidos los comandosconfigque lo reparan. Ahora recurren a unos ajustes de log que funcionan durante esa ejecución e indican qué clave cambiar. - Una opción global colocada antes de un comando exento hacía que este exigiera licencia o validara la configuración.
acs2md --log-file x.log doctortomaba--log-filecomo nombre de comando, así quedoctor— el comando que se ejecuta para diagnosticar problemas de licencia — se negaba a arrancar en una máquina sin licencia. space get --syncpodía borrar archivos fuera del directorio de salida.- Dos guardados concurrentes podían corromper el estado de sincronización, porque cada guardado escribía a través del mismo nombre temporal fijo.
- Un
http.client.proxyinválido ahora es un error, no un aviso seguido de continuar. Enviar el tráfico directo en silencio cuando se pidió enrutarlo es, en una red corporativa, motivo para detenerse.
Consulta también
- Convertir espacios — la referencia completa de opciones
- Restaurar un espacio — el ciclo de copia de seguridad, comprobación y restauración
- Actualizar acs2md — instalar una versión desde la propia herramienta
- Configuración — reintentos, plazos, proxy y credenciales