Conservar los enlaces de los PDFs de un documento LaTeX compilado con pdfpages (un apaño con Elisp y pdftk)
- ¿Qué tenemos?
- Un documento
*.tex*
«maestro» que contiene múltiples ordenes de\includepdf
y su correspondiente tabla de contenido. - ¿Qué queremos obtener?
- Un PDF resultante, exactamente igual al que obtenemos con el
paquete
pdfpages
, sólo que ahora se conservarán los enlaces activos de los PDFs incluidos. La tabla de contenido no tendrá enlaces, pero nuestro nuevo PDF sí contará con marcadores para navegación interna. Cada nuevo marcador será un título de sección que corresponde a su PDF incrustado.
La función en Elisp que he escrito requiere del programa pdftk
. Y, por supuesto, que
estemos dentro de GNU Emacs ☺.
La idea es ejecutar un bucle que va añadiendo los marcadores a cada sub-PDF1. Toda la
información que necesita la función (títulos de sección para crear los marcadores y
nombre/ruta de cada PDF incluido) la extrae del archivo maestro *tex
. No necesita más, y
no importa si los sub-pdf están en otros directorios, etc. Es decir, que esta función
obtiene lo que precisa de las órdenes \includepdf
y \addcontenstsline
, dentro de nuestro
documento, y no se va a vendimiar en otros sitios.
La función es muy sencilla de usar: dentro de nuestro ducumento maestro (y una vez
compilado de manera normal para asegurarnos de que todos los PDFs están incluidos),
llamamos a la función mi-pdf-con-enlaces
. Al instante se nos pedirá en el minibúfer que
introduzcamos un rango de páginas previas hasta el primer PDF incrustado. Es decir, que si
el primer PDF incrustado empieza en la pág. 10, introducimos el rango «1-9». ¡Y ya está!. En
un periquete tenemos disponible nuestro PDF, exactamente igual que el que obtenemos
compilando con pdfpages, pero con todos los enlaces conservados y los marcadores de
navegación interna con los títulos de sección.
Definimos, primero, estas dos funciones previas para obtener el nombre/ruta cada PDF y el título de las secciones:
(defun extrae-pdf-seccion () (save-excursion (re-search-backward "addcontentsline{" nil t) (re-search-forward "addcontentsline{" nil t) (sp-beginning-of-next-sexp 2) (let ((punto (point))) (sp-end-of-sexp) (save-restriction (narrow-to-region punto (point)) (buffer-string))))) (defun extrae-pdf-ruta () (save-excursion (re-search-forward "pdf}" nil t) (re-search-backward "{" nil t) (forward-char 1) (let ((punto (point))) (sp-end-of-sexp) (save-restriction (narrow-to-region punto (point)) (buffer-string)))))
Y nuestra función principal:
(defun mi-pdf-con-enlaces () (interactive) (let* ((dir-temp "/tmp/pdftk_trabajo") (marcadores (concat dir-temp "/" "marcadores.txt")) (buf (file-name-sans-extension (buffer-name))) (prim-pags (read-from-minibuffer "Páginas previas: ")) (resultado (format "%s_web.pdf" buf))) (shell-command (concat "rm -rf " dir-temp)) (shell-command (concat "mkdir -p " dir-temp)) ;; primero extraemos las primeras páginas (shell-command (concat "pdftk A=" buf ".pdf" " cat A" prim-pags " output " dir-temp "/" buf ".pdf")) ;; obtenemos nombre de sección y ruta de cada PDF con un bucle (save-excursion (goto-char (point-min)) (while (re-search-forward "includepdf" nil t) (let ((seccion (extrae-pdf-seccion)) (pdf (expand-file-name (extrae-pdf-ruta)))) (write-region (concat "BookmarkBegin" "\nBookmarkTitle:" " " seccion "\nBookmarkLevel: 1" "\nBookmarkPageNumber: 1") nil marcadores) (shell-command (concat "pdftk " pdf ;; necesario para marcadores con acentos y demás " update_info_utf8 " marcadores " output " dir-temp "/" (file-name-base pdf) ".pdf"))))) ;; Y producimos el PDF final, que debe incluir ya los marcadores correctamente (shell-command (concat "pdftk " dir-temp "/" "*.pdf " " cat output " resultado))))
Conservar los enlaces de los PDF incluidos en LaTeX (una solución con Elisp y pdftk) from Juan Manuel Macías Chaín on Vimeo.
∞
Publicado: 06/08/20
Última actualización: 21/01/22
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.