Marcadores invisíveis em PDFs usando pdflatex

Marcadores invisíveis em PDFs usando pdflatex

Estou usando latexdiffpara mostrar as alterações que faço em um texto grande (mais de 200 páginas). A maioria das minhas alterações afetam apenas algumas páginas, por isso não quero que meus leitores vasculhem 200 páginas procurando as raras páginas onde foram feitas correções isoladas de erros de digitação: apenas cerca de 30 pp das 200 conterão alterações.

Eu gostaria de:

  1. Insira marcadores PDF ocultos nas páginas onde ocorrem alterações
  2. Compilar com pdflatex
  3. Execute um script que filtre as páginas que não contêm os marcadores PDF ocultos

    book.tex -latexdiff-> book_diff.tex -pdftex-> 200pp.pdf -script-> 30pp.pdf

Alguém poderia recomendar:

  • um pacote tex para inserir algum tipo de "marcadores" em um arquivo PDF
  • um pacote python para ler PDFs (e procurar por esses marcadores)

Responder1

Meu primeiro pensamento foi usar as operações de arquivo de E/S, por exemplo, \writeor \immediate\write, mas enfrentei um problema conhecido com objetos flutuantes e seu comportamento. Também tive problemas com objetos flutuantes com contador próprio quando não havia \globalprefixo.

Prefiro usar referências cruzadas diretamente onde uma gravação protegida é garantida. Posso lhe oferecer esta solução com a ajuda do LuaTeX. As etapas processadas são:

  • Compomos um documento normal e marcamos uma posição. Para o propósito deste post é uma marca visível e é um número de página. A definição usa \labelcomando regular com um determinado prefixo, por exemplo malipivo. Nomeei o arquivo filter.texe o comando \writeme. O comando utiliza contador próprio e isso garante a exclusividade do marcador no \labelcomando.
  • O filter.texarquivo é processado diversas vezes dependendo do material tipográfico real, neste exemplo são duas vezes. Após a primeira execução, obtemos um documento com dois pontos de interrogação vermelhos (linha 1 na visualização), após a segunda execução, obtemos referências cruzadas formatadas corretamente (linha 2 na visualização).

Este é o código:

%! *latex filter.tex
%! Run me twice or even more times to get references right.
\def\myprefixis{malipivo}

\documentclass[a4paper]{article}
\usepackage{tikz}
\usepackage[numbers]{kantlipsum}
\newcount\mycounter 
\mycounter=0
% Our own marker...
% Save the reference and mark it...
\def\writeme{%
\global\advance\mycounter by 1%
\label{\myprefixis\the\mycounter}%
\begin{tikzpicture}%
\begin{pgfinterruptboundingbox}%
\node[red,font=\bfseries\Huge,scale=4]{\pageref{\myprefixis\the\mycounter}};%
\end{pgfinterruptboundingbox}%
\end{tikzpicture}%
  }% End of \writeme...

\begin{document}
\section{My experiment}
\kant[1-2]\writeme
\kant[14]\writeme
\kant[15-16]\writeme
\kant[25]\writeme\ There is a typo and\writeme\ one more\writeme
\kant[26-32]\writeme
\kant[46]\writeme
\begin{figure}[p]
\kant[51] I am floating.\writeme
\end{figure}
\kant[52-61]\writeme
\end{document}

filter.pdf após a primeira execução filter.pdf após a segunda execução

O conteúdo do filter.auxarquivo é assim:

\relax 
\@writefile{toc}{\contentsline {section}{\numberline {1}My experiment}{1}}
\newlabel{malipivo1}{{1}{1}}
\newlabel{malipivo2}{{1}{1}}
\newlabel{malipivo3}{{1}{2}}
\newlabel{malipivo4}{{1}{2}}
\newlabel{malipivo5}{{1}{2}}
\newlabel{malipivo6}{{1}{2}}
\newlabel{malipivo7}{{1}{4}}
\newlabel{malipivo8}{{1}{4}}
\newlabel{malipivo10}{{1}{7}}
\newlabel{malipivo9}{{1}{8}}

Na verdade, você pode ver que há algum objeto flutuante à medida que os números são trocados por seus equivalentes de número de página ( malipivo10<-> malipivo9; 7<-> 8). Precisamos processar esse arquivo auxiliar de alguma forma e extrair as páginas do arquivo filter.pdf. Usei LuaTeX e o pdfpagespacote.

  • A princípio pensei que precisava ordenar as linhas, mas parece que não é necessário, já está ordenado pelos números das páginas, não pelos marcadores.

  • Porém, precisei extrair linhas com malipivoprefixo incluído e pular as demais. Usei string.finddo LuaTeX. Há uma nota no terminal desta etapa dizendo Testing note on page 1....

  • Então precisei extrair os números das páginas para obter 1 1 2 2 2 2 4 4 7 8, usei a string.gsubfunção.

  • Tive que garantir que cada página seria incluída apenas uma vez, portanto deveríamos obter essa sequência de números 1 2 4 7 8após remover as duplicatas.

  • Meu próximo passo foi adicionar vírgulas, fiz isso enquanto concatenava a string temporária. Estamos chegando 1,2,4,7,8.

  • O resto foi relativamente fácil. Eu criei um comando LaTeX para obtê-lo \includepdf[pages={1,2,4,7,8},fitpaper]{filter.pdf}e enviá-lo para o corpo do documento.

Eu criei uma função simples no LuaTeX chamada testmecom dois parâmetros, o primeiro parâmetro está pedindo o arquivo testado ( filter), o código usa seus arquivos auxe pdf, e o segundo parâmetro está pedindo um prefixo que estávamos usando (em teoria, poderia haver mais prefixos), usei malipivo. A composição tipográfica real é feita por \directlua{testme("filter","malipivo")}.

Incluo o código ( filtered.tex) a ser executado lualatexuma vez e por fim uma prévia das páginas selecionadas ( filtered.pdf) que foram marcadas no código original ( filter.tex).

%! lualatex filtered.tex
%! run me only once
\documentclass{article}
\usepackage{pdfpages}
\usepackage{luacode}

\begin{document}

\begin{luacode*}
function testme (filtering, thekey)
-- Initializing variables...
local myinput=filtering..".aux" -- Where are the reference?
local myinputpdf=filtering..".pdf" -- Where are the real PDF pages?
local mylines="" -- List of pages to get is?
local mycount=0 -- How many tested reference do we have?
local lastcount="" -- What is the previous reference?
-- The core of the function...
for mylinetemp in io.lines(myinput) do -- Read input file line by line
  test=string.find(mylinetemp,thekey) -- Is a unique key involved? 
  if test~=nil then -- Yes, the key is present there...
    myline=string.gsub(mylinetemp,"\\newlabel{"..thekey..".-}{{.-}{(.-)}}", "%1", 1) -- Find a group with page reference.
    print("Testing note on page "..myline.."...") -- Print information to the terminal
    mycount=mycount+1 -- Increase a number of tested references
    if mycount==1 then -- Save the first value as the starting value
      mylines=myline -- Start the resulting string
      lastcount=myline -- Remember the last occurance
    else -- Add value to the list if not already stored in the list
      if lastcount~=myline then -- But only if last two values differ (aka uniq)
        mylines=mylines..","..myline -- Add comma and value to the string (aka join)
        lastcount=myline -- Remember this occurance as the last one for next testing
      end -- of if not lastcount
    end -- of if mycount
  end -- of if thekey is involved
end -- of myline
-- Print the results and generate PDF via regular typesetting...
local keyresult="\\includepdf[pages={"..mylines.."},fitpaper]{"..myinputpdf.."}"
print(keyresult)
tex.print(keyresult)
end -- of function testme
\end{luacode*}

% The tested file, e.g. filter.{aux,pdf}, and its reference label prefix.
\directlua{testme("filter","malipivo")}

\end{document}

filtrado.pdf

Responder2

Ok, então escrevi um primeiro rascunho de um pipeline funcional.

  • Conforme sugestão de @ChristianH, useipdfcomentar
  • Para o script, usei:

O código está aqui: https://gist.github.com/ivanistheone/219dad11a30efef82b7e

informação relacionada