Marcadores invisibles en archivos PDF usando pdflatex

Marcadores invisibles en archivos PDF usando pdflatex

Lo estoy usando latexdiffpara mostrar los cambios que hago en un texto grande (más de 200 páginas). Sin embargo, la mayoría de mis cambios afectan sólo a unas pocas páginas, por lo que no quiero que mis lectores revisen 200 páginas buscando las raras páginas donde se realizaron correcciones tipográficas aisladas: sólo alrededor de 30 páginas de las 200 contendrán cambios.

Me gustaría:

  1. Inserte marcadores de PDF ocultos en las páginas donde se producen cambios
  2. compilar con pdflatex
  3. Ejecute un script que filtre las páginas que no contienen los marcadores de PDF ocultos

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

¿Alguien podría recomendar:

  • un paquete tex para insertar "marcadores" de algún tipo en un archivo PDF
  • un paquete de Python para leer archivos PDF (y buscar dichos marcadores)

Respuesta1

Lo primero que pensé fue utilizar las operaciones de archivos de E/S, por ejemplo, \writeo \immediate\write, pero me encontré con un problema conocido con los objetos flotantes y su comportamiento. También tuve problemas con los objetos flotantes con contador propio cuando no había \globalprefijo.

Prefiero utilizar referencias cruzadas directamente donde se garantiza una escritura protegida. Puedo ofrecerle esta solución con la ayuda de LuaTeX. Los pasos procesados ​​son:

  • Escribimos un documento normal y marcamos una posición. Para los fines de esta publicación, es una marca visible y es un número de página. La definición utiliza \labelun comando normal con un prefijo determinado, por ejemplo malipivo. Nombré el archivo filter.texy el comando \writeme. El comando utiliza su propio contador y eso asegura la unicidad del marcador en el \labelcomando.
  • El filter.texarchivo se procesa varias veces dependiendo del material tipográfico real; en este ejemplo, es dos veces. Después de la primera ejecución, obtenemos un documento con dos signos de interrogación rojos (fila 1 en la vista previa), después de la segunda ejecución, obtenemos referencias cruzadas correctamente tipografiadas (fila 2 en la vista previa).

Este es el 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 después de la primera ejecución filter.pdf después de la segunda ejecución

El contenido del filter.auxarchivo se ve así:

\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}}

De hecho, puede ver que hay algún objeto flotante a medida que los números se intercambian con sus homólogos de números de página ( malipivo10<-> malipivo9; 7<-> 8). Necesitamos procesar este archivo auxiliar de alguna manera y extraer las páginas de filter.pdf. Usé LuaTeX y el pdfpagespaquete.

  • Al principio pensé que necesitaba ordenar las líneas, pero parece que no es necesario, ya está ordenado por números de página, no por marcadores.

  • Sin embargo, necesitaba extraer líneas con malipivoel prefijo incluido y omitir las demás. Utilicé string.finddesde LuaTeX. Hay una nota en la terminal de este paso que dice Testing note on page 1....

  • Luego necesitaba extraer los números de página para obtenerlos 1 1 2 2 2 2 4 4 7 8, usé la string.gsubfunción.

  • Tuve que asegurarme de que cada página se incluya solo una vez, por lo que deberíamos obtener esta secuencia de números 1 2 4 7 8después de eliminar los duplicados.

  • Mi siguiente paso fue agregar comas, lo hice mientras concatenaba la cadena temporal. Estamos llegando a 1,2,4,7,8.

  • El resto fue relativamente fácil. Hice un comando LaTeX para obtenerlo \includepdf[pages={1,2,4,7,8},fitpaper]{filter.pdf}y lo envié al cuerpo del documento.

Creé una función simple en LuaTeX nombrada testmecon dos parámetros, el primer parámetro solicita el archivo probado ( filter), el código usa sus archivos auxy pdf, y el segundo parámetro solicita un prefijo que estábamos usando (en teoría, podría haber más prefijos), usé malipivo. La composición tipográfica real la realiza \directlua{testme("filter","malipivo")}.

Adjunto el código ( filtered.tex) para ejecutarlo lualatexuna vez y finalmente una vista previa de las páginas seleccionadas ( filtered.pdf) que fueron marcadas en el 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

Respuesta2

Bien, escribí un primer borrador de un canal de trabajo.

  • Según la sugerencia de @ChristianH, utilicépdfcomentario
  • Para el guión utilicé:
    • pdfmineropara leer las anotaciones en PDF
    • pdfrwpara escribir las páginas seleccionadas

El código está aquí: https://gist.github.com/ivanistheone/219dad11a30efef82b7e

información relacionada