Depois de muuuuito ralar atrás de uma solução para o port do meu artigo sobre modelagem de motores (muitos dias já perdidos nessa brincadeira), consegui uma solução aceitável.

É fato que existem muitas deficiências das linguagens de markup simplificadas em relação a algumas já estabelecidas. Não dá pra comparar a expressividade de um HTML ou LaTeX com as do Markdown ou reStructuredText.

Apesar deste último até permitir muita coisa quando usado através do Sphinx, uma parte grande (grande demais) destes recursos não são nativos ao Docutils. Infelizmente, o Pelican usa o Docutils diretamente, sem recorrer ao Sphinx. Ou seja: muita coisa é perdida no processo, pois muitos recursos são do próprio Sphinx ou de plugins dele. Da mesma forma, não é tão simples portar os plugins do Sphinx para o Pelican, pois muitos usam recursos inerentes da ferramenta e o port passa a ficar complicado. Afinal, o código do Docutils é bem embolado .

Enfim, fiz alguns testes para tentar descobrir qual linguagem suportada seria mais adequada ao artigo, feito originalmente em LaTeX. Tecnicamente o ponto de partida seria o mesmo: o arquivo original que usei para escrever o artigo ou o arquivo do wiki (DokuWiki) que eu estou convertendo.

Dos meus testes, o resultado foi uma solução mista. Converti o arquivo LaTeX tanto para Markdown quanto pra ReST, e descobri que devido à quase completa ausência de referências cruzadas do Markdown, seria muito mais provável obter melhor resultado com o ReST. Já as figuras, reaproveitei as que eu usei no wiki, que outrora eu havia convertido para SVG.

Enfim, fiquei com um arquivo ReST (todo quebrado, diga-se de passagem) e alguns PNG e SVG. Ajustei os metadados e comecei a quebrar a cabeça. Uma olhada geral me indicou que meus problemas principais seriam as figuras e as equações.

Figuras

Em primeiro lugar, as figuras estavam quebradas porque, bem, a sintaxe estava bem ruim após a conversão. Eu tinha coisas do tipo

.. figure:: Modelo
   :alt: Parte elétrica (esquerda) e análogo elétrico da parte mecânica
   (direita).

   Parte elétrica (esquerda) e análogo elétrico da parte mecânica
   (direita).

Não muito útil, primeiro pela óbvia duplicidade de informações, segundo pela falta de qualquer forma de referenciar a imagem e terceiro porque o nome do arquivo não indicava arquivo nenhum (no LaTeX é possível/obrigatório omitir as extensões dos arquivos de imagens).

Depois de renomear o arquivo para algo mais útil e de vários testes, fiquei com o seguinte resultado

.. _fig_analogo:

.. figure:: {filename}./modelo-motor.png
   :alt: Parte elétrica (esquerda) e análogo elétrico da parte mecânica (direita).

Isto resolveu o terceiro problema (com o prefixo necessário ao Pelican) e resolveu parcialmente o primeiro e segundo problemas.

O primeiro problema foi resolvido parcialmente porque apesar de eu poder referenciar a imagem a partir de qualquer lugar usando o link para fig_analogo_, eu ainda não possuía a numeração automática que queria.

A segunda solução foi apenas retirar uma das descrições duplicadas, mas usar o tag :alt: fez a informação não ficar mais rapidamente identificável e eu ainda não tinha a numeração automática.

Busquei muitas soluções na internet, mas o mais próximo que encontrei foi o plugin Better Figures & Images, que diz possuir o seguinte recurso:

Inserts automatic figure numbers into figure captions, if FIGURE_NUMBERS == True in global config, or figure_numbers exists in article metadata.

No entanto, este plugin não funciona com SVG (que é colocado em um tag <object> pelo Pelican) e ainda adiciona a palavra "Figure" antes do número, o que é bom em termos da palavra estar ali, mas para artigos em português obviamente não fica certo.

Depois de muito cavucar, acabei tomando o caminho de aprender a fazer um plugin e fiz um similar, mas com os recursos que eu queria (e usando o lxml em vez do BeautifulSoup).

TODO: colocar em um repositório e colocar um link.

O resultado foi um plugin que processa o conteúdo quando já está em HTML, coloca o texto alt como um <span> e adiciona o mesmo texto, mas permitindo que o prefixo seja configurável no pelicanconf.py.

Ainda, o plugin busca no texto todos os links que fazem referência ao anchor (tag <a>) da figura, e substitui o texto pelo número da figura. Assim, no caso do exemplo anterior, o fig_analogo_ do documento, que antes se transformaria no HTML

<a class="reference internal" href="#fig-analogo">fig_analogo</a>

se transforma em

<a class="reference internal" href="#fig-analogo">1</a>

É claro, o trabalho até chegar nesta forma de resolver o problema não foi tão simples quanto parece.

Equações

O segundo problema deu mais trabalho do que o primeiro, pois foi necessário entender como os três sistemas (Pelican, Docutils e MathJax) interagem entre si.

Comecei observando como a diretiva .. math:: respondia a algumas entradas. Curiosamente, esta diretiva do ReST coloca a equação entre \begin{equation*} e \end{equation*}.

Depois de muito procurar, descobri que a função do Docutils que coloca os tags de ambiente no início e fim se encontra no arquivo docutils/utils/math/__init__.py:

def pick_math_environment(code, numbered=False):
    """Return the right math environment to display `code`.

    The test simply looks for line-breaks (``\\``) outside environments.
    Multi-line formulae are set with ``align``, one-liners with
    ``equation``.

    If `numbered` evaluates to ``False``, the "starred" versions are used
    to suppress numbering.
    """
    # cut out environment content:
    chunks = code.split(r'\begin{')
    toplevel_code = ''.join([chunk.split(r'\end{')[-1]
                             for chunk in chunks])
    if toplevel_code.find(r'\\') >= 0:
        env = 'align'
    else:
        env = 'equation'
    if not numbered:
        env += '*'
    return env

Observe que, estranhamente, esta função suporta sim a numeração! No entanto, buscando mais fundo descobri que tal função sequer é chamada com o kwarg numbered definido, ficando então com seu valor-padrão False.

Do arquivo docutils/writers/html4css1/__init__.py:

def visit_math_block(self, node):
    # print node.astext().encode('utf8')
    math_env = pick_math_environment(node.astext())
    self.visit_math(node, math_env=math_env)

Droga! Eu poderia modificar diretamente aqui, mas esse hack com certeza provavelmente quebraria com qualquer atualização, sem que eu perceba. Assim, resolvi fazer um plugin também.

Inicialmente, tentei portar a diretiva do Sphinx, sem sucesso. Depois tentei criar minhas próprias diretivas para equações e referências a equações, mas também não tive muito sucesso (o Docutils realmente tem uma péssima documentação, e "use the source" sempre foi uma desculpa esfarrapada).

Enfim, depois de muito bater a cabeça, acabei na solução mais simples e menos elegante: mais um plugin para manipular o conteúdo em HTML. Percebi com alguns testes que o recurso de referências do próprio MathJax funcionava, porém ele quebrava com meus plugins do Liquid Tags. Os desativei e as referências usando os tags \label{} e \ref{} no próprio MathJax começaram a funcionar.

A partir daí foi mais fácil. Pensei primeiro em simplesmente substituir os equation* por equation, mas isto poderia quebrar algumas coisas. Então fiz o plugin buscar pelos \begin{equation*} e \end{equation*} e os substituí. De quebra, deixei mais elegante ao substituir somente caso eu encontre algum \label{} dentro, afinal não tem sentido colocar numeração em equações que nem serão referenciadas.