Mudar la documentación de librsvg a gi-docgen

Translations: en - Tags: documentation, gnome, librsvg

Las herramientas de documentación para librsvg son bastante antiguas. La página de manual para man(1) está escrita a mano en troff, y la documentación de referencia para biblioteca en C todavía usa nuestro venerable gtk-doc.

Como parte de la modernización de todo librsvg, acabo de convertir la página de manual en un documento reStructuredText, y la documentación de referencia para C en gi-docgen. Este artículo describe cómo lo hice.

Puedes ver la documentación nueva de librsvg aquí.

De man a rst

La página de manual para rsvg-convert estaba escrita en troff, que es bastante engorroso. La verborrea que sigue define un párrafo cortito y una tabla:

.P
You can also specify dimensions as CSS lengths, for example
.B 10px
or \"
.BR 8.5in .
The unit specifiers supported are as follows:
.RS
.TS
tab (@);
l lx.
px@T{
pixels (the unit specifier can be omitted)
T}
in@T{
inches
T}
cm@T{
centimeters
T}
mm@T{
millimeters
T}
pt@T{
points, 1/72 inch
T}
pc@T{
picas, 1/6 inch
T}
.TE

Eso, nunca jamás. Hoy en día tenemos herramientas mejores como rst2man, que toma un documento en reStructuredText — texto plano con monerías — y lo convierte en una página de manual en troff. Tan solo tuve que usar una instrucción como esta:

pandoc --from=man --to=rst rsvg-convert.1 > rsvg-convert.rst

y después ajustar la salida un poco:

You can also specify dimensions as CSS lengths, for example ``10px`` or
``8.5in``. The unit specifiers supported are as follows:

   == ==========================================
   px pixels (the unit specifier can be omitted)
   in inches
   cm centimeters
   mm millimeters
   pt points, 1/72 inch
   pc picas, 1/6 inch
   == ==========================================

Mucho más legible, ¿no?

He aprendido que Pandoc is fabuloso. Magia pura, súper recomendable.

En algún punto espero poder integrar la página de manual en un instructivo más lindo para rsvg-convert. Ya no es un programita trivial, y las opciones que soporta tienen algunas combinaciones interesantes que podrían ilustrarse mejor que con man(1).

De gtk-doc a gi-docgen

Recomiendo que leas la descripción inicial de gi-docgen de Emmanuele, pues incluye la historia de gtk-doc, una lista de sus desventajas, y cómo gi-docgen es una herramienta más sencilla que aprovecha el hecho que GObject Introspection ya extgrae la documentación del código fuente y así hace la mayor parte del trabajo que hacía gtk-doc.

Resumen de cómo funciona gi-docgen:

  • El código en C tiene comentarios de documentación en formato Markdown, con anotaciones para GObject Introspection. (Nota: librsvg no tiene código en C para la biblioteca, entonces esos comentarios están en los encabezados .h que se instalan para usarse desde los programas en C).

  • La biblioteca se compila y se le hace introspección. En este paso, g-ir-scanner(1) extrae las anotaciones y documentación del código fuente y lo pone como parte del archivo XML MiBiblioteca.gir.

  • Escribes un archivo de configuración pequeñito para decirle a gi-docgen la estructura de tu documentaicón. A diferencia de gtk-doc, no hay que escribir un esqueleto en DocBook ni nada complicado. Si hay capítulos independientes se escriben como archivos Markdown, y el archivo de configuración nada más le indica a gi-docgen el orden en que deben aparecer. Gi-docgen incluye todas las clases, funciones, métodos, macros, etc. del código en la documentación que genera.

  • ... y corre muy rápido. Gtk-doc siempre fue lento porque utiliza xsltproc y algunas hojas de estilo complicadas para convertir un DocBook en HTML. Gi-docgen es mucho más directo.

Hacer la conversión

A diferencia del paso casi automático de pandoc para la página de manual, convertí los comentarios de documentación de DocBook a Markdown a mano. Para librsvg esto me tomó una tarde cafeinada moderadamente; es un trabajillo detallado, pero nada del otro mundo.

Puedes asumir que va a haber buenos mensajes de error por parte de gi-docgen cuando algo sale mal, a diferencia de gtk-doc, cuyos errores siempre me parecieron inescrutables.

Algunas pistas:

  • Las hiperligas que en DocBook se veían como <ulink url="blabla.html">bla bla</ulink> se convierten en Markdown como [bla bla](blabla.html).

  • Gi-docgen permite referencias a métodos como [method@Gtk.Button.set_child] - puedes ver la documentación de ligas para ver los otros tipos que soporta.

  • Puedes pulir los detalles gradualmente con atributos para la introspección.

  • No hay una traducción directa de todas las etiquetas semánticas de DocBook, que son extremadamente detalladas, a Markdown. Por ejemplo, yo sustituí tanto <literal>foobar</literal> como <filename>/foo/bar</filename> por `foobar` y `/foo/bar`, respectivamente (i.e. el texto que quería mostrar, entre comillas sencillas invertidas, para indicar texto literal).

Librsvg tenía varios bloques de texto literal en los comentarios de gtk-doc, delimitados así:

/**
 * blah_blah():
 *
 * Por ejemplo:
 *
 * |[
 * el texto literal va aquí
 * ]|
 *
 * Etc. etc.
 */

Eso puede ir entre ``` comillas sencillas invertidas triples in Markdown:

/**
 * blah_blah():
 *
 * Por ejemplo:
 *
 * ```
 * el texto literal va aquí
 * ```
 *
 * Etc. etc.
 */

Errores que encontré

La primera vez que corrí gi-docgen de forma manual me escupió esto:

$ gi-docgen check Rsvg-2.0.gir 
INFO: Loading config file: None
INFO: Search paths: ['/home/federico/src/librsvg/gi-docgen/_build', '/home/federico/.local/share/gir-1.0', '/home/federico/.local/share/flatpak/exports/share/gir-1.0', '/var/lib/flatpak/exports/share/gir-1.0', '/usr/local/share/gir-1.0', '/usr/share/gir-1.0']
INFO: Elapsed time 1.601 seconds
WARNING: Symbol 'Rsvg.HandleFlags' at <unknown>:0 is not documented
WARNING: Return value for symbol 'Rsvg.Handle.get_dimensions_sub' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.get_geometry_for_element' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.get_geometry_for_layer' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.get_position_sub' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.render_document' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.render_element' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.render_layer' is not documented
WARNING: Return value for symbol 'Rsvg.Handle.set_stylesheet' is not documented
WARNING: Symbol 'Rsvg.Handle.base-uri' at <unknown>:0 is not documented
WARNING: Symbol 'Rsvg.Handle.dpi-x' at <unknown>:0 is not documented
WARNING: Symbol 'Rsvg.Handle.dpi-y' at <unknown>:0 is not documented
WARNING: Symbol 'Rsvg.cleanup' at include/librsvg/rsvg.h:447 is not documented
WARNING: Symbol 'Rsvg.DEPRECATED_FOR' at include/librsvg/rsvg.h:47 is not documented
WARNING: Parameter 'f' of symbol 'Rsvg.DEPRECATED_FOR' is not documented

Los avisos como WARNING: Return value ... is not documented son fáciles de arreglar; los bloques de comentarios tenían sus descripciones respectivas, pero les faltaba la anotación de Returns:.

Los avisos como WARNING: Symbol 'Rsvg.Handle.base-uri' at <unknown>:0 is not documented son diferentes. Se refieren a propiedades de GObject, que estaban documentadas así:

/**
 * RsvgHandle::base-uri:
 *
 * Base URI, to be used to resolve relative references for resources.  See the section
 * "Security and locations of referenced files" for details.
 */

¡Pero ahí hay un error de sintaxis! La línea con el nombre del símbolo debe usar sólo unos dos puntos entre el nombre de la clase y el nombre de la propiedad, e.g. RsvgHandle:base-uri en vez de RsvgHandle::base-uri. Ese caso, así como las otras propiedades que salían como no documentadas, tenían el mismo error.

El primer aviso, WARNING: Symbol 'Rsvg.HandleFlags' at <unknown>:0 is not documented, resultó ser que había dos comentarios de documentación con el mismo título para RsvgHandleFlags, pero el segundo estaba vacío — y el último es el que gana. Dejé sólo uno de ellos con la documentación y ya.

Escribir capítulos independientes

Librsvg tenía algunos capítulos como doc/foo.xml, doc/bar.xml que se incluian en la documentación de referencia; esos eran un <chapter> de DocBook cada uno. Pude convertirlos a Markdown con pandoc de forma individual, y luego nada más hubo que ponerles un Title: en la primera línea de cada archivo .md — así es como gk-docgen sabe qué texto poner en el índice al principio de la documentación.

Title: Overview of Librsvg

# Overview of Librsvg

Librsvg is a library for rendering Scalable Vector Graphics files (SVG).
Blah blah blah blah.

Scripts de compilación

Hay muchos ejemplos de cómo usar gi-docgen con meson; puedes ver por ejemplo el caso de gtk.

¡Sin embargo, librsvg todavía usa Autotools! Puedes utilizar estos pedacitgos:

Publicar la documentación

Gtk-doc supone que ocurre magia en algún lugar en developer.gnome.org para generar la documentación en HTML en publicarla. Gi-docgen supone que cada proyecto publica su propia documentación con las páginas de Gitlab.

Así, es como se publica la documentación de librsvg — puedes ver cómo se genera en .gitlab-ci.yml. Observa que hay dos jobs: el de reference genera la documentación en HTML con gi-docgen en un directorio public/Rsvg-2.0, y el de pages la integra con la documentación el API en Rust para publicar todo junto.

Ligar la documentación al sitio principal

Por último, la documentación de librsvg está ligada desde el GNOME Platform Introduction. Mandé un merge request al proyecto de developer-www para actualizar esa liga, y ya.

¡Eso es todo! Espero que esta sea una buena referencia para quien quiera migrar la documentación de una biblioteca de gtk-doc a gti-docgen — que es una herramienta mucho más cómoda.