Ebook

El contenido de este tutorial se encuentra en formato electrónico y a la venta en Amazon (https://www.amazon.es/dp/B07518QBR4) siendo los beneficios que se pudieran obtener de la misma destinados a alguna organización sin ánimo de lucro orientada a la infancia.

Overview

Este es un manual superbásico de Asciidoctor orientado sobre todo a incluirlo en tus proyectos. Veremos cómo puedes usarlo para generar documentación únicamente (sin java, ni nada parecido), cómo integrarlo en tu proyecto Maven y/o Gradle y por último como usarlo en un generador de blogs estático (JBake, Jekill, etc)

Si quieres/necesitas crear un libro, documentar un proyecto, tus pensamientos, o cualquier otra cosa y lo quieres hacer de una forma en que el editor NO te distraiga aplicando formatos y formateando tu texto todo el tiempo, o si quieres tener todo tu texto organizado, o si necesitáis trabajar en grupo, etc. Microsoft Word y similares (OpenOffice?) NO es lo que necesitas.

Para que te hagas una idea de lo que pretendo todo este proyecto está escrito en Asciidoctor
Este manual no pretende ser un tutorial exhaustivo ni tan siquiera puedo asegurar que todo lo que diga en él sea exacto. Simplemente se basa en la experiencia que he ido acumulando durante estos años en los que lo he usado en diferentes proyectos.
Todo el código es abierto y puedes usarlo como quieras. Si quieres sugerir un cambio o hacer una aportación puedes hacerlo creando un Issue en el mismo proyecto: https://gitlab.com/jorge-aguilera/tutoasciidoc

AsciiDoctor

Lo primero es saber qué es y para qué sirve AsciiDoctor.

Si has escrito un README.md sabrás que has usado la sintáxis de Markdown. Mediante esta sintáxis sencilla el procesador sabe cómo convertir este documento en algo más visual que entienda un navegador. Asciidoctor es parecido en el hecho de que es sencillo de escribir/leer, puedes editarlo con un editor de texto simple como el notepad de windows o hasta con vi si sabes como guardar un documento en este editor.

Sin embargo Asciidoctor va mucho más allá. Además de una sintaxis completa para escribir documentos, estos se pueden convertir a HTML o Pdf de forma sencilla, escribir un libro listo para ser publicado en Amazon o incluso generar presentaciones con Deck.js, etc. Así mismo si eres programador podrás usarlo en tus proyectos (Maven, Gradle, e incluso Ant) haciendo que estos tengan una documentación decente y actualizada.

Entorno de trabajo

Asciidoctor puede ser descargado e instalado desde su página oficial como un ejecutable, si usas Ruby como una gema , o si usas java puedes usar AsciidoctorJ con plugins para Maven y Gradle.

Si no eres programador (Java) probablemente tu primera opción sea instalarte la versión ejecutable, sin embargo para este tutorial vamos a seguir la línea de usarlo mediante Maven pues nos va a permitir organizar nuestro proyecto de documentación mucho mejor y nos va a dar más opciones.

Tranquilo, no necesitas conocimientos de programación (estos los usaremos para los últimos capítulos). Simplemente vamos a usar herramientas habituales que usan "ellos"

Necesitamos tener instalado:

  • Java (una versión reciente, tampoco necesitas la ultimísima)

  • Maven. Instalación superfácil: descarte el zip de https://maven.apache.org, descomprime, configura un par de variables de entorno tal como dicen en la página y listo.

  • Descargar este proyecto. Puedes clonarlo si usas git ( git clone git@gitlab.com:jorge-aguilera/tutoasciidoc.git) o descargar el zip https://gitlab.com/jorge-aguilera/tutoasciidoc/repository/archive.zip?ref=master y descomprimirlo en cualquier directorio

  • Un editor de texto simple. (Word NO es un editor de texto, es una tortura) Con editor de texto simple me refiero desde el notepad de windows, al vi de Linux, o algo más visual como Atom que incluye un plugin para poder previsualizar lo que vas escribiendo en AsciiDoctor

Para ver que todo está correcto ejecuta desde una consola del sistema en el directorio donde hayas descomprimido el proyecto:

mvn clean install

(si todo va bien deberías ver en consola algo así)
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building tuto-asciidoc 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ tuto-asciidoc ---
[INFO] Deleting /home/jorge/proyectos/tutoasciidoc/target
...
...
...
[INFO] BUILD SUCCESS
[INFO] --------------

Si no tenías instalado Maven previamente probablemente te dé tiempo a prepararte un café porque lo primero que va a hacer va a ser bajarse media Internet ;)

Si la ejecución fue correcta, en el directorio target/generated-docs deberías tener un fichero index.html y si lo abrés con un navegador deberías estar leyendo este mismo contenido.

Ejemplos

Simple

Ejemplo de un documento supersimple de Asciidoctor.

ejemplos/ejemplo1.adoc
Primer ejemplo de Asciidoctor.

*esto en negrita*

_esto en cursiva_

est**o** tiene negrita solo la o

Y si queremos que lo renderize tal cual pues \*usamos* una barra en el primero

.Una lista con titulo
- una lista de elementos 1
- una lista de elementos 2

* una sublista de elementos de 2
* una sublista de elementos de 2

.Esto es una lista ordenada
. fijate en que usamos el punto
. en lugar del guión

.Y esto una lista etiquetada
UNO:: El primer numero
DOS:: El que va después
MONO:: Qué pinta un mono
en una lista
etiquetada (fijate que la linea está separada
en el fichero para mejorar su edición)

y este es el resultado:

Primer ejemplo de Asciidoctor.

esto en negrita

esto en cursiva

esto tiene negrita solo la o

Y si queremos que lo renderize tal cual pues *usamos* una barra en el primero

Una lista con titulo
  • una lista de elementos 1

  • una lista de elementos 2

    • una sublista de elementos de 2

    • una sublista de elementos de 2

Esto es una lista ordenada
  1. fijate en que usamos el punto

  2. en lugar del guión

Y esto una lista etiquetada
UNO

El primer numero

DOS

El que va después

MONO

Qué pinta un mono en una lista etiquetada (fijate que la linea está separada en el fichero para mejorar su edición)

Imágenes, citas, advertencias, etc

Imágenes

Puedes incluir imágenes homer inline mediante image:homer.jpg[] (dos puntos una sola vez)

Si escribes los dos puntos dos veces es un bloque de imagen y debe ir en una linea

image::homer.jpg[]
homer
Citas

Si quieres incluir la cita de alguien famoso usa un bloque "quote"

[quote, Homer, en algún capítulo]
Para empezar presionar cualquier tecla ¿ Dónde está la tecla "cualquier" ?

y se verá así

Para empezar presionar cualquier tecla ¿ Dónde está la tecla "cualquier" ?
— Homer
en algún capítulo
Iconos

tus textos ganan si le pones iconos de aviso. Para ello etiqueta un bloque con las palabras NOTE, WARNING, etc y dos puntos

Este bloque es un NOTE
Este bloque es un WARNING

O puedes usar insertar iconos mediante icon:tags[] icon:money[] para que se inserten entre el texto:

A todos nos gusta el

Include

Este documento no está escrito en un único fichero sino que está compuesto de muchos ficheros más pequeños para poder reutilizarlos y que sea más cómoda la edición. Para ello simplemente usamos el comando include::ruta_al_fichero

Tablas

Una de las cosas que más escribo/escribimos son tablas en diferentes formatos: con título, alineadas a un lado, centradas unas otras no, columnas con mayor tamaño que las demás, etc.

ejemplos/tablas.adoc
|===

| Cell in column 1, row 1 | Cell in column 2, row 1

| Cell in column 1, row 2 | Cell in column 2, row 2

| Cell in column 1, row 3 | Cell in column 2, row 3

|===


[cols="3*"]
.Tabla con titulo
|===
|si queremos poner cada celda
|en una linea
|mejor indicarle en la cabecera cuantas columnas son

|si queremos poner cada celda
|en una linea
|mejor indicarle en la cabecera cuantas columnas son
|===

[cols="1,2,1"]
.Tabla repartiendo espacio
|===
|si queremos poner cada celda
|en una linea
|mejor indicarle en la cabecera cuantas columnas son

|si queremos poner cada celda
|en una linea
|mejor indicarle en la cabecera cuantas columnas son
|===

[cols="<,^,>"]
.Tabla alineando
|===
|a la izquierda
|centrada
|a la derecha

|a la izquierda
|centrada
|a la derecha
|===


[cols=".<2,.^5,^.>3"]
.Tabla copiada de la docu oficial
|===
|Cell in column 1, row 1 with lots and lots and lots and lots of content
|Cell in column 2, row 1
|Cell in column 3, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2
|Cell in column 3, row 2 and another bucket of content, and then a jelly roll of content
|===


Lógicamente podemos indicar nuestras cabeceras si así se lo decimos:

[cols=2*,options="header"]
|===
|Name of Column 1
|Name of Column 2

|Cell in column 1, row 1
|Cell in column 2, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2
|===

Lo cual se verá así:

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 1, row 3

Cell in column 2, row 3

Table 1. Tabla con titulo

si queremos poner cada celda

en una linea

mejor indicarle en la cabecera cuantas columnas son

si queremos poner cada celda

en una linea

mejor indicarle en la cabecera cuantas columnas son

Table 2. Tabla repartiendo espacio

si queremos poner cada celda

en una linea

mejor indicarle en la cabecera cuantas columnas son

si queremos poner cada celda

en una linea

mejor indicarle en la cabecera cuantas columnas son

Table 3. Tabla alineando

a la izquierda

centrada

a la derecha

a la izquierda

centrada

a la derecha

Table 4. Tabla copiada de la docu oficial

Cell in column 1, row 1 with lots and lots and lots and lots of content

Cell in column 2, row 1

Cell in column 3, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 3, row 2 and another bucket of content, and then a jelly roll of content

Lógicamente podemos indicar nuestras cabeceras si así se lo decimos:

Name of Column 1 Name of Column 2

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Artículo

Escribir un simple artículo puede resultar tedioso si pierdes el tiempo en formatearlo. Sin embargo, con Asciidoctor te centras en el contenido y te olvidas del resto.

Cabecera

En la cabecera del fichero establecemos los atributos del artículo:

ejemplos/ejemplo_articulo.adoc
= Una brecha en WordPress desestabiliza el mundo
Jorge Aguilera González <jorge.aguiler@puravida-software.com>
v1.0 2016-04-27
:size: A4
:encode: UTF-8
:lang: es
:docinfo:
:doctype: article
:icons: font
:toc: nop
:toclevels: 0
:chapter-label:
:pygments-style: tango
:source-highlighter: coderay
:pdf-style: base

Por regla general todos los documentos de Asciidoctor comienzan con una cabecera donde configuramos el documento:

  • Comenzamos la primera linea con el carácter "=" y tras un espacio en blanco indicamos el título (y el subtítulo si así queremos separados por ":")

  • Nombre(s) del autor(es)

  • Fecha del documento

  • Sucesión de atributos (demasiados para recordarlos todos) unos generales, otros más específicos según generemos un pdf, un html, un docbook, etc.

Preámbulo

Los bloques de texto que vienen a continuación de la cabecera se consideran el preámbulo y se les aplicará un formato u otro según el tipo de documento (artículo en este caso) y destino (html, pdf, etc).

...
:pdf-style: base


En este documento se comenta el artículo publicado en Wordfence,
sitio dedicado a la seguridad en WordPress, donde se detallan los
posibles fallos de seguridad en la web de Mossack Fonseca que han
permitido la publicación de miles de documentos sobre personas
y empresas que utilizaban sus servicios.

...

Secciones

Las secciones en Asciidoctor se denotan con una secuencia consecutiva de "=". Tantos "=" pongas, tanto nivel en la jerarquía introduces.

En el articulo de ejemplo utilizo únicamente niveles de primer orden, pero puedes crear tantos como necesites
...
este caso pone de relieve una falta de alineación del departamenteo de IT con el
resto de los departamentos de la empresa (usualmente marketing o ventas) la cual
se discutirá más adelante.

Brechas de seguridad en MF
--------------------------

...

Una vez que tengas escrito tu artículo Asciidoctor generará un HTML, Pdf, ePub, o el formato que indiques.

Ejemplo Projecto con Maven

Vamos a crear un proyecto de documentación básico donde el objetivo último es crear un PDF con varios capítulos. Queremos tener cada uno de ellos en ficheros diferentes para facilitar la edición/colaboración por separado.

Si te has descargado el proyecto todos los ficheros a los que se hace referencia están en la carpeta src/steps y son proyectos que puedes compilar de forma independiente con "mvn clean install" en cada uno de ellos.

Inicio

Crear un directorio de trabajo y tomando este directorio como raíz:

Ejecutaremos

mvn clean install

Si todo ha ido bien en el directorio target/generated-docs deberías tener tu documento index.html listo.

Organizando capítulos

Para poder trabajar en nuestro proyecto de documentación organizaremos nuestro documento principal en capítulos, escribiendo cada uno de ellos en ficheros separados:

  • Crear un directorio en la carpeta src/main/asciidoc/chapter1

  • Crear un fichero en esta carpeta llamado chapter1.asciidoc (o puedes usar este como base )

Fijate que la extensión del documento es diferente a la de index. Aunque para Asciidoctor la extensión no es importante nosotros la vamos a usar para distinguir entre el documento principal y los include. En el fichero pom.xml configuramos que únicamente genere los que tengan extensión .adoc y estos a su vez referenciarán a los demás.
  • Modificar nuestro index.adoc e incluir nuestro primer capítulo al final del documento.

include::chapter1/chapter1.asciidoc[]

y volveremos a generar nuestra documentación:

mvn clean install

Ejemplo Projecto con Gradle

Gradle es un gestor de tareas y dependencias al estilo de Maven pero mucho más moderno y flexible. Aunque Maven sigue presente en muchos proyectos en mi opinión el primero pronto le sustituirá por completo.

Al igual que con Maven podemos crear un proyecto de documentación de una manera muy simple (y al igual que con Maven podremos incluir este proceso de documentación en el pipeline de nuestra aplicación).

Si hiciste un clon de este proyecto, el directorio correspondiente a este capítulo lo encontrarás en src/steps/gradle

Instalar Gradle

Sigue los pasos de la página oficial

Básicamente, al estilo de Maven, es un zip a descomprimir y un par de variables de entorno

Preparar nuestro directorio

En un directorio nuevo ejecutaremos:

gradle init

Lo cual nos preparará dicho directorio con los ficheros necesarios para empezar un proyecto Gradle.

Build

Sustituiremos el fichero build.gradle por este build.gradle

desde una consola en el directorio que acabamos de crear ejecutaremos:

gradle asciidoctor

Nuesta docu

Por desgracia el plugin de Maven y el de Gradle no comparten la misma ruta donde buscar los documentos (ni la misma de donde generarlos) por lo que deberemos colocar nuestros ficheros de documentación en el directorio src/docs/asciidoc

Desde este directorio podemos organizar nuestros capítulos al estilo de como lo hicimos con Maven.

Generar

./gradlew asciidoctor  (en linux)

gradlew.bat asciidoctor (en windows)

Si es la primera vez que ejecutas Gradle en tu sistema tal vez se baje la otra parte de Internet que no te bajaste con Maven pero el resultado al final debería ser el mismo, salvo que ahora tu documentación estará en build/asciidoc

Este es el proyecto mínimo que necesitamos para generar nuestra documentación con gradle. Como iremos viendo tanto el fichero pom.xml como build.gradle crecerán con dependencias y configuraciones pero esto es lo mínimo que se requiere para empezar.

Mismo contenido, diferente resultado

Una de las funcionalidades que más uso es la de generar el mismo contenido en diferentes formatos (por ahora sólo HTML y Pdf aunque quiero probar ePub).

Con Asciidoctor, un mismo contenido puedes volcarlo a HTML, Pdf, Docbook, ePub, ayuda man, etc (bueno, con algunas limitaciones en cada caso) simplemente indicándole qué "backend" queremos usar. Si usas la línea de comandos se lo indicas mediante una opción pero nosotros lo vamos a usar mediante la configuración de nuestro proyecto de documentación.

Con Maven

Para poder generar formato Pdf tenemos que adjuntar una extensión al plugin:

pom.xml
<?xml
....
   <plugin>
    <groupId>org.asciidoctor</groupId>
    <artifactId>asciidoctor-maven-plugin</artifactId>
    <version>1.5.3</version>
    <dependencies>      (1)
        <dependency>
            <groupId>org.asciidoctor</groupId>
            <artifactId>asciidoctorj-pdf</artifactId>
            <version>1.5.0-alpha.11</version> (2)
        </dependency>
    </dependencies>
1 Añadimos una dependencia al plugin
2 Deberíamos configurar la versión para mayor comodidad pero por hacerlo simple

y añadir una nueva "ejecución" indicándole que el backend ahora sea pdf:

pom.xml
  <execution>   (1)
    <id>generate-pdf</id>
    <phase>generate-resources</phase>
    <goals>
        <goal>process-asciidoc</goal>
    </goals>
    <configuration>
        <backend>pdf</backend>   (2)
        <doctype>book</doctype>
        <sourceDocumentExtensions>adoc</sourceDocumentExtensions>
        <attributes>
        </attributes>
    </configuration>
 </execution>
1 añadimos un nuevo bloque de execution justo detrás del existente
2 indicamos que el backend a usar es pdf
Si lo prefieres, aquí tienes un pom.xml completo
Fíjate que las configuraciones para cada execution son diferentes. Podemos configurar cada resultado de forma diferente, no sólo por el backend, sino usar unos iconos diferentes en cada uno de ellos, mostrar títulos, numeraciones, etc

Con Gradle

De forma análoga incluiremos una dependencia en nuestro build.gradle y crearemos una tarea para generar Html y otra para ejecutar Pdf. Además si queremos podemos hacer que la tarea genérica buid ejecute las dos seguidas:

build.gradle
dependencies{
    asciidoctor 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.11' (1)
}

task buildHtml(type:org.asciidoctor.gradle.AsciidoctorTask){  (2)
    backends 'html5'
    attributes \
        'build-gradle': file('build.gradle'),
        'source-highlighter': 'coderay',
        'toc': 'left',
        'icons': 'font',
        'setanchors': '',
        'idprefix': '',
        'idseparator': '-',
        'docinfo1': ''
    sources{
        include 'index.adoc'
    }
}

// de forma análoga buildPdf con backend 'pdf'

build.dependsOn = ['buildHtml','buildPdf']  (3)
1 Podemos configurar mediante variables la versión para hacerlo más elegante
2 Una tarea de gradle específica para generar el html5
3 Build ejecutará las dos tareas
Con gradle podríamos indicar los dos backends en una sóla tarea, simplemente de esta forma estamos usando dos tareas si quisieramos configurarlas de forma diferente.
El formato que aplica Asciidoctor al Pdf puede que se te quede "corto" y lo quieras personalizar. No es difícil pero tiene su truco, si te interesa puedo añadirlo al tutorial.

Anotaciones en linea

En determinadas ocasiones incluiremos una cierta cantidad de texto del que querremos comentar algunas partes de él, pero si lo incluimos en el mismo el lector podría perder el hilo argumental y si los incluimos como notas al pie de página le obligamos a tener que ir a otra parte del documento. Para estos casos usaremos anotaciones en línea

Veamoslo con un ejemplo:

Supongamos que estamos escribiendo una receta y para ciertos ingrendientes y/o pasos queremos incluir algún comentario justo al final de la misma.

La tortilla de patatas se remonta a siglos blablablabala para lo que
necesitaremos:

[source]
---
Lista de ingrendientes:

- 3 huevos <1>
- 4 patatas <2>
- sal <3>
---
<1> o 2 si son de corral
<2> que no sean muy grandes
<3> una pizca

Batiremos los huevos en un bol grande

Lo que debería generar algo parecido a:

La tortilla de patatas se remonta a siglos blablablabala para lo que necesitaremos:

Lista de ingrendientes:

- 3 huevos (1)
- 4 patatas (2)
- sal (3)
1 o 2 si son de corral
2 que no sean muy grandes
3 una pizca

Batiremos los huevos en un bol grande

Básicamente crearemos un bloque "verbatin" (marcado por [source] y entre guiones) y marcaremos cada línea que queramos comentar con <n> donde n es un número a referenciar justo al finalizar el bloque

Esta técnica la podemos utilizar por ejemplo para incluir aclaraciones en nuestro código (java, xml, C, etc).

Para ello simplemente en nuestro código marcaremos las líneas que queremos aclarar usando el comentario oportuno según el lenguaje y lo incluiremos en el bloque mediante el procesador "include" que ya vimos:

NuestraClase.java
class MyClass{ //<1>
   int sum //<2>
} //<3>

y en nuestro documento asciidoctor:

[source]
---
include::src/NuestraClase.java[]
---
<1> nombre de la clase
<2> acumularemos la suma aqui
<3> recuerda terminar con llave

Diagramas

Una de las extensiones que más me gusta es la de asciidoctor-diagram que te permite generar diagramas de alta calidad partiendo de un bloque de texto asciidoctor.

Diagrama "a mano"

Si escribimos en nuestro documento:

diagramas/uno.adoc
[ditaa,asciidoctor-diagram-process]
....
                   +-------------+
                   | Asciidoctor |-------+
                   |   diagram   |       |
                   +-------------+       | PNG out
                       ^                 |
                       | ditaa in        |
                       |                 v
 +--------+   +--------+----+    /---------------\
 |        |---+ Asciidoctor +--->|               |
 |  Text  |   +-------------+    |   Beautiful   |
 |Document|   |   !magic!   |    |    Output     |
 |     {d}|   |             |    |               |
 +---+----+   +-------------+    \---------------/
     :                                   ^
     |          Lots of work             |
     +-----------------------------------+
....

Obtendremos como resultado:

asciidoctor diagram process

Casos de uso

[plantuml,casos-de-uso-crud,png]
....
left to right direction
skinparam packageStyle rect
title Productos y lugares

actor Usuario as usuario

rectangle red{
    usuario -- (lugares)
    (lugares) <.. (alta lugar) : extend
    (lugares) <.. (modificacion lugar) : extend
    (lugares) <.. (ver lugar) : extend

    (productos) ...> (ver lugar)
    usuario -- (productos)
    (productos) <.. (alta producto) : extend
    (productos) <.. (modificacion producto) : extend
}

....
casos de uso crud

Diagrama de secuencias

[plantuml,secuencia-login,png]
....
title Login
autonumber

actor Anonimo
control Api
control Security
entity Usuario
database Neo4j

Anonimo -> Api  : login username
Api -> Usuario : findByUsername
Usuario -> Neo4j : match n

alt username registered

Usuario --> Api: found
Api -> Api: check password

    alt successfull

        Api -> Security: generate token
        Security --> Api: token
        Api --> Anonimo: token

    else doesn't match

        Api --> Anonimo: 403

    end

else username not registered

Usuario --> Api: not found
Api --> Anonimo: error 403

end
....

[mermaid]
....
gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section A section
        Completed task            :done,    des1, 2014-01-06,2014-01-08
        Active task               :active,  des2, 2014-01-09, 3d
        Future task               :         des3, after des2, 5d
        Future task2               :         des4, after des3, 5d
        section Critical tasks
        Completed task in the critical line :crit, done, 2014-01-06,24h
        Implement parser and jison          :crit, done, after des1, 2d
        Create tests for parser             :crit, active, 3d
        Future task in critical line        :crit, 5d
        Create tests for renderer           :2d
        Add to mermaid                      :1d
....
secuencia login
Failed to generate image: Could not find the 'mermaid' executable in PATH; add it to the PATH or specify its location using the 'mermaid' document attribute
gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section A section
        Completed task            :done,    des1, 2014-01-06,2014-01-08
        Active task               :active,  des2, 2014-01-09, 3d
        Future task               :         des3, after des2, 5d
        Future task2               :         des4, after des3, 5d
        section Critical tasks
        Completed task in the critical line :crit, done, 2014-01-06,24h
        Implement parser and jison          :crit, done, after des1, 2d
        Create tests for parser             :crit, active, 3d
        Future task in critical line        :crit, 5d
        Create tests for renderer           :2d
        Add to mermaid                      :1d

Maven

Para generar diagramas como los anteriores necesitamos modificar nuestro pom.xml para incluir las dependencias necesarias tal como hicimos con la generación de pdf:

<plugin>
    <groupId>org.asciidoctor</groupId>
    <artifactId>asciidoctor-maven-plugin</artifactId>
    <version>1.5.3</version>
    <dependencies>
      <dependency>
        <groupId>org.asciidoctor</groupId>
        <artifactId>asciidoctorj</artifactId>
        <version>1.5.4.1</version>
      </dependency>
      <dependency>
         <groupId>org.asciidoctor</groupId>
         <artifactId>asciidoctorj-diagram</artifactId>
         <version>1.5.0</version>
     </dependency>
    </dependencies>

E indicar al plugin que utilice dicha extensión en la sección de configuración:

<requires>
  <require>asciidoctor-diagram</require>
</requires>

Formulas

Configuración

Para escribir fórmulas simplemente debemos activar en la cabecera (o con atributos en pom.xml o build.gradle) la variable stem

= primera linea del documento
autor
fecha
:atributo1: valor1
..
:stem:  (1)
1 Por defecto activará asciimath pero podemos usar otros como latexmath

Podemos escribir fórmulas "inline":

Desde pequeño aprendes que:

[stem]
++++
sqrt(4) = 2
++++

y que la fórmula del agua

[stem]
++++
H_2O
++++

es la primera que aprendes cuando el colegio se vuelve ya serio

Que se vería como:

Desde pequeño aprendes que:

\$sqrt(4) = 2\$

y que la fórmula del agua

\$H_2O\$

es la primera que aprendes cuando el colegio se vuelve ya serio

Ejemplos varios

A continuación algunos ejemplos para los eruditos:

Cuando

\$a \ne 0\$

hay dos soluciones a

\$ax^2 + bx + c = 0\$

que son

\$x = (-b +- sqrt(b^2-4ac))/(2a)\$

Algunas tonterias sin mucho sentido (o sí?)

\$sum_(i=1)^n i^3=((n(n+1))/2)^2\$
\$+-beta * omega = [[a,b],[c,d]]\$
\$lim_(x->oo) = int_0^1 f(x)dx\$

que serían escritas mediante bloques stem:

Cuando

[stem]
++++
a \ne 0
++++

hay dos soluciones a

[stem]
++++
ax^2 + bx + c = 0
++++

que son

[stem]
++++
x = (-b +- sqrt(b^2-4ac))/(2a)
++++

Algunas tonterias sin mucho sentido (o sí?)

[stem]
++++
sum_(i=1)^n i^3=((n(n+1))/2)^2
++++

[stem]
++++
+-beta * omega = [[a,b],[c,d]]
++++

[stem]
++++
lim_(x->oo) = int_0^1 f(x)dx
++++

Tu toque personal al Pdf

Ya te aviso que no vas a poder "darle la vuelta" al pdf generado añadiendo y quitando lo que quieras. Lo que vas a poder es "personalizar" ciertos aspectos como márgenes y estilos.

Para esta parte tienes un proyecto Maven en la carpeta src/steps/pdf-custom que puede servir como base. Este proyecto genera un pdf con varios capítulos aplicandoles un estilo propio.

Desde este enlace puedes acceder al pdf que vamos a generar en los siguientes apartados

pom.xml

Para indicarle a asciidoctor-pdf que queremos aplicar nuestro tema lo haremos pasándole dos atributos

pom.xml
<configuration>
    <backend>pdf</backend>
    <doctype>book</doctype>
    <sourceDocumentExtensions>adoc</sourceDocumentExtensions>
    <attributes>
        <pdf-stylesdir>theme</pdf-stylesdir>    (1)
        <pdf-style>memoria</pdf-style>          (2)
    </attributes>
</configuration>
1 directorio donde encontrar nuestro tema
2 fichero a utilizar (podemos tener varios en el mismo directorio)

Tema

Para este ejemplo hemos elegido un directorio llamado theme que debe estar un nivel por abajo del principal (asciidoc en nuestro caso). En este directorio ubicaremos las imágenes y ficheros de configuración.

En nuestro caso encontramos un fichero llamado memoria-theme.yml y un directorio con una imagen que servirá para la portada.

La nomenclatura del fichero es importante: nosotros indicamos en configuración memoria y el fichero se llama memoria-theme.yml

Como has adivinado es un fichero de configuración YAML y es el que usará para aplicar el tema y estilos en la generación.

La configuración NO extiende a la que viene por defecto por lo que el fichero debe ser "completo". Puedes usar memoria-theme.yml como partida o el que proporciona Asciidoctor en https://github.com/asciidoctor/asciidoctor-pdf/blob/master/data/themes/default-theme.yml

En este fichero configuraremos aspectos como el estilo, tipo de letra a usar etc. Por ejemplo:

base:
  font:
    color: #333333
    family: Times-Roman
    size: 12

Estaremos estableciendo un font global a usar a lo largo del documento.

Portada

Si editas memoria-theme.yml encontraŕás hacia el final del fichero la siguiente configuración:

title_page:
  align: right
  logo:
    top: 10%                            (1)
    image: images/logo.png       (2)
  title:
    top: 55%
    font_size: $heading_h1_font_size    (3)
    font_color: 999999
    line_height: 0.9
  subtitle:
    font_size: $heading_h3_font_size
    font_style: bold_italic
    line_height: 1
  authors:                              (4)
    margin_top: $base_font_size * 1.25
    font_size: $base_font_size_large
    font_color: 181818
  revision:
    margin_top: $base_font_size * 1.25
1 Queremos ubicar un logo en la parte superior de la página
2 ruta a la imagen a utilizar como logo, relativa al fichero
3 podemos usar variables ya definidas
4 las secciones son las que son. No puedes añadir una que te inventes

Cabecera y pie de página

La cabecera de las páginas es otra parte de la configuración que solemos cambiar:

header:
  height: 0.75in
  line_height: 1
  recto_content:
    center: '{document-title}'      (1)
  verso_content:
    center: '{document-title}'      (2)
1 queremos el titulo centrado en todas las páginas impares
2 lo mismo para las pares

Así como el pie de página:

footer:
  height: 0.75in
  line_height: 1
  recto_content:
    right: |                                (1)
      {chapter-title} | *{page-number}* +   (2)
      {footer-text} {author}
  verso_content:                            (3)
    left: |
      *{page-number}* | {chapter-title} +
      {footer-text} {author}
1 Ojo al carácter | que nos sirve para unir varias líneas en una sólo
2 Las páginas impares queremos que aparezca el titulo, página, y autor a la derecha
3 Mientras que en las pares mostraremos la página, el titulo y el autor

Iconos

Podemos ajustar incluso qué imagen queremos usar para los iconos

admonition:
  icon:
    note:
      name: fa-sticky-note

Posibilidades

Lo mejor para saber qué puedes customizar es que consultes la página https://github.com/asciidoctor/asciidoctor-pdf/blob/master/docs/theming-guide.adoc donde se detallan todos los aspectos que puedes modificar en la generación del pdf.

Sin manos …​. (pero con Docker)

Si has seguido el apartado sobre cómo crear un tema para PDF en este apartado vamos a ver un caso específico, en concreto cómo hacer un trabajo para la Universidad Oberta de Catalunya (UOC) …​ y sin tener que instalar Asciidoctor !!! (vale, hay trampa, necesitas tener instalado Docker pero a estas alturas quién no lo tiene ya instalado?)

Tipo de documento

Para este ejemplo vamos a hacer un informe con una portada donde aparezca el logo, el título del documento, autor, etc así como un índice, glosario, bibliografía etc

Para ello crearemos nuestro documento index.adoc:

= La cría de la chinchilla en cautividad
Jorge Aguilera <jorge.aguilera@puravida-software.com>
2017-02-31
:revnumber: {project-version}
:example-caption!:
:icons: font
:listing-caption: Listado
:sourcedir: ../java
:icons: font
:sectnums:
:toc:
:toclevels: 3
:media: prepress
:chapter-label:
:pdf-style: uoc
:pdf-stylesdir: theme

[abstract]
La cría de la chinchilla no es cosa de risa

{sp} +
{sp} +

[verse]
 A Miriam y Dani, que siempre estuvieron ahí

{sp} +
{sp} +

[quote,Oscar Wilde,1854-1900]
"No existe una mejor prueba del progreso de la civilización que la del progreso de la cooperación."

{sp} +

image::by.png[CreativeCommos,200,50]

Esta obra está licenciada bajo la Licencia Creative Commons Atribución 4.0 Internacional.
Para ver una copia de esta licencia, visita http://creativecommons.org/licenses/by/4.0/

<<<<

== Introducción

=== Contexto y justificación del Trabajo

La chinchilla es un animal que nos lo tomamos a cosa de risa, pero no deberíamos.

<<<<

== Origenes

A ver, ni idea de sus origenes, es simplemente por hacer otra página

== Bibliografia

Para la elaboración de este documento se han consultado los siguientes materiales

[bibliography]

.Ulteo
- [[[ulteo-brochure]]] Brochure: https://www.ulteo.com/main/images/uovd/doc/pdf/Ulteo%20OVD%20Product%20Brochure.pdf
- [[[ulteo-features]]] Feature Summary: https://www.ulteo.com/main/images/uovd/doc/pdf/Ulteo%20OVD%204.0%20Feature%20Summary.pdf

<1>Podemos indicar el tema a utilizar bien en la cabecera o bien por comando <2>Y el directorio donde encontrar el tema.

Theme

Crearemos una subcarpeta llamada "theme" (el nombre no importa pero debería ayudar) y ubicaremos ahí nuestra plantilla. Recuerda que debe tener el sufijo "-theme.yml". En nuestro caso será uoc-theme.yml y puedes descargala desde este steps/uoc/theme/uoc-theme.yml

Este fichero sobreescribe variables del formato estándar creando el estilo que queremos aplicar:

font:
  catalog:
    # Noto Serif supports Latin, Latin-1 Supplement, Latin Extended-A, Greek, Cyrillic, Vietnamese & an assortment of symbols
    Noto Serif:
      normal: notoserif-regular-subset.ttf
      bold: notoserif-bold-subset.ttf
      italic: notoserif-italic-subset.ttf
      bold_italic: notoserif-bold_italic-subset.ttf
    # M+ 1mn supports ASCII and the circled numbers used for conums
    M+ 1mn:
      normal: mplus1mn-regular-ascii-conums.ttf
      bold: mplus1mn-bold-ascii.ttf
      italic: mplus1mn-italic-ascii.ttf
      bold_italic: mplus1mn-bold_italic-ascii.ttf
    # M+ 1p supports Latin, Latin-1 Supplement, Latin Extended, Greek, Cyrillic, Vietnamese, Japanese & an assortment of symbols
    # It also provides arrows for ->, <-, => and <= replacements in case these glyphs are missing from font
    M+ 1p Fallback:
      normal: mplus1p-regular-fallback.ttf
      bold: mplus1p-regular-fallback.ttf
      italic: mplus1p-regular-fallback.ttf
      bold_italic: mplus1p-regular-fallback.ttf
  fallbacks:
    - M+ 1p Fallback

title_page:
  align: right
  logo:
    top: 10%
    image: logoUOC2000.png
  title:
    top: 55%
    font_size: $heading_h1_font_size
    font_color: 999999
    line_height: 0.9
  subtitle:
    font_size: $heading_h3_font_size
    font_style: bold_italic
    line_height: 1
  authors:
    margin_top: $base_font_size * 1.25
    font_size: $base_font_size_large
    font_color: 181818
  revision:
    margin_top: $base_font_size * 1.25

page:
  layout: portrait
  margin: [0.75in, 1in, 0.75in, 1in]
  size: A4
base:
  font_color: #333333
  line_height_length: 17
  line_height: $base_line_height_length / $base_font_size
vertical_rhythm: $base_line_height_length
heading:
  font_color: #FF8000
  font_size: 17
  font_style: bold
  line_height: 1.2
  margin_bottom: $vertical_rhythm
link:
  font_color: #009900
outline_list:
  indent: $base_font_size * 1.5
header:
  height: 0.75in
  line_height: 1
  recto_content:
    center: '{document-title}'
  verso_content:
    center: '{document-title}'
footer:
  height: 0.75in
  line_height: 1
  recto_content:
    right: |
      {chapter-title} | *{page-number}* +
      texto fijo con lo que quieras {author}
  verso_content:
    left: |
      *{page-number}* | {chapter-title} +
      y en la otra pagina otro texto fijo {author}
image:
  align: center
caption:
  align: center
  font_color: #FF0000
  font_size: 10

code:
  font_color: $base_font_color
  font_family: M+ 1mn
  font_size: ceil($base_font_size)
  padding: $code_font_size
  line_height: 1.25
  background_color: f5f5f5
  border_color: cccccc
  border_radius: $base_border_radius
  border_width: 0.75

conum:
  font_family: M+ 1mn
  font_color: $literal_font_color
  font_size: $base_font_size
  line_height: 4 / 3

En esta subcarpeta ubicaremos las imágenes que usaremos en el tema. En nuestro caso el logo (steps/uoc/theme/logoUOC2000.png)

Docker

En este apartado no vamos a explicar qué es Docker pero si no lo tienes instalado ya tardas. Uno de los usos que podemos obtener de tener instalado Docker es que podemos descargar infinidad de "mini-servidores precargados" (menuda burrada he dicho pero para que nos entendamos) de tal forma que con un simple comando podamos levantarlo y que ejecute el aplicativo que tiene instalado.

Asciidoctor cuenta con una imagen (https://github.com/asciidoctor/docker-asciidoctor) que nos permite ejecutar el programa sin necesidad de tenerlo instalado.

Desde el directorio donde hemos guardado nuestro informe (y el subdirectorio theme) ejecutaremos:

$ ▶ docker run --rm -v $(pwd):/documents/ asciidoctor/docker-asciidoctor asciidoctor-pdf index.adoc (1)

Unable to find image 'asciidoctor/docker-asciidoctor:latest' locally  (2)
latest: Pulling from asciidoctor/docker-asciidoctor
1b39978eabd9: Pull complete
88e512fdabea: Pull complete
8f473f54ab74: Pull complete
Digest: sha256:1276b52dbaa9e0bb790ab806c2376aec30fd618e78fca8d48f63224f5db02954
Status: Downloaded newer image for asciidoctor/docker-asciidoctor:latest  (3)
1 -v mapea una carpeta en tu máquina con una en el contenedor. De esta forma asciidoctor puede acceder a tus documentos y solo a esos
2 si es la primera vez que lo usas verás cómo se baja la imagen (mientras te tomas un cafecito)
3 termina silenciosamente si todo ha ido bien

y en el directorio encontrarás un fichero index.pdf con el resultado.

La imagen docker para asciidoctor viene preparada con prácticamente todo lo necesario para generar documentos html, pdf, con diagramas, con fórmulas, presentaciones y un largo etc.

Si por ejemplo nuestro documento contiene diagramas del tipo PlantUML no necesitamos instalar nada:

docker run --rm -v $(pwd):/documents/ asciidoctor/docker-asciidoctor asciidoctor-pdf -r asciidoctor-diagram index.adoc