;;; batch-init.el --- Common Emacs setup for BSPPFit batch export ;;; ;;; $Id: batch-init.el.in 333 2026-09-05 11:52:25Z peter $ ;;; ;;; Generated from batch-init.el.in by configure. ;;; Do not edit batch-init.el directly; edit batch-init.el.in. ;;; ;;; Loaded by Makefile.am via emacs --load before either ;;; --funcall org-latex-export-to-pdf ;;; or ;;; --funcall org-html-export-to-html ;;; ;;; Two configure-substituted values are passed in via environment ;;; variables to avoid shell quoting issues with --eval: ;;; ;;; BSPPFIT_PDF_PROCESS_KIND "latexmk" or "fallback" ;;; BSPPFIT_LUALATEX absolute path to lualatex ;;; BSPPFIT_LATEXMK absolute path to latexmk (kind=latexmk only) ;;; BSPPFIT_PLANTUML_JAR absolute path to plantuml.jar (may be empty) ;;; ;;; One further value is substituted directly into this file's text by ;;; config.status (an "at"-delimited configure substitution marker, ;;; not an environment variable --- there is no per-run choice to make ;;; for it the way there is for the four above, so a literal ;;; substitution at configure time is simpler than plumbing it through ;;; getenv too): the HTML index/home link target, named INDEX_HTML in ;;; configure.ac (not spelled out here with its marker punctuation, ;;; since config.status substitutes every occurrence of that exact ;;; text in this file, comments included). ;;; ;;; Defaults to Index.html; ./configure INDEX=... overrides it (see ;;; configure.ac, "HTML documentation set: index/home navigation link ;;; target"). Before iteration 0.136.0 flattened the source tree, this ;;; was three separate variables (one per directory, each a different ;;; relative distance from Index.html); with every document in one ;;; directory since, one variable is enough. ;;; ;;; batch-init.el.in --- the template shipped in the distribution --- is ;;; part of the project source tree (under SVN); the generated ;;; batch-init.el this comment appears in is a build artifact. (require 'cl-lib) (require 'org) (require 'ob-plantuml) (require 'ox-latex) (require 'ox-html) (require 'ox-publish) ;; Mandatory in batch: confirmation prompts hang headless Emacs. (setq org-confirm-babel-evaluate nil) ;; --------------------------------------------------------------------- ;; LaTeX package load order: float BEFORE hyperref. ;; ;; Preamble.tex needs the float package (the [H] specifier) to pin ;; the illustration galleries at their point of definition. Loaded the ;; obvious way (\usepackage{float} in Preamble.tex), float ends up ;; AFTER hyperref, because Org emits hyperref as the last default ;; package and #+LATEX_HEADER input runs later still. With that order, ;; the float package's \@xfloat redefinition collides with hyperref's ;; float-anchor machinery and the pdf backend emits one ;; ignoring duplicate destination with the name 'figure.N' / 'table.N' ;; warning for EVERY captioned float (69 of them in Taxonomy). The ;; warnings are harmless to the rendered PDF but make lualatex exit ;; non-zero, which Org reports as "PDF file produced with errors" and ;; which a single-pass AUCTeX compile can leave looking broken. ;; ;; Verified fix: load float BEFORE hyperref -> zero duplicate ;; destinations. We inject ("" "float" nil) immediately before the ;; hyperref entry in org-latex-default-packages-alist so EVERY document ;; gets the right order, and drop \usepackage{float} from Preamble.tex. ;; The [H] figure redefinition stays in Preamble.tex; it runs after ;; this preamble emits float, so H is defined when it is used. ;; Iteration 0.76.0. (let ((pos (cl-position "hyperref" org-latex-default-packages-alist :key (lambda (e) (and (listp e) (nth 1 e))) :test (lambda (a b) (and (stringp b) (string-equal a b)))))) (when (and pos (not (cl-find "float" org-latex-default-packages-alist :key (lambda (e) (and (listp e) (nth 1 e))) :test (lambda (a b) (and (stringp b) (string-equal a b)))))) (setq org-latex-default-packages-alist (append (cl-subseq org-latex-default-packages-alist 0 pos) '(("" "float" nil)) (cl-subseq org-latex-default-packages-alist pos))))) ;; --------------------------------------------------------------------- ;; Default table environment: longtable for ALL tables. ;; ;; Plain Org tables export to a tabular inside a table float ([htbp], ;; forced to [H] by Preamble.tex). Floats drift, leave spurious white ;; space when a tall table cannot share a page, and -- being floats -- ;; participate in the figure/table-anchor machinery. longtable breaks ;; tables across pages natively, is NOT a float (so it places exactly ;; where written and never collides with hyperref float anchors), and ;; removes the page-break white space. Per-table #+ATTR_LATEX ;; :environment overrides still win, and :align / :font attributes ;; carry over unchanged. Iteration 0.76.0. (setq org-latex-default-table-environment "longtable") ;; --------------------------------------------------------------------- ;; Do not auto-embed REMOTE image URLs. ;; ;; Org's org-latex-inline-image-rules embeds any link whose target ends ;; in an image extension -- including https URLs -- as \includegraphics ;; or (for .svg) \includesvg. The Illustration Catalogue records source ;; provenance as Wikimedia URLs; one of them ends in ".svg" ;; https://commons.wikimedia.org/wiki/File:Whitworth_Thread.svg ;; so Org turned that CITATION into \includesvg{//commons.../File:...}, ;; and the svg package then aborts with ;; ! Package svg Error: File `File:Whitworth_Thread.svg' is missing. ;; (it is a wiki PAGE, not a raw SVG, and is not a local file). That is ;; the lone ^! error behind the Catalogue's "PDF file produced with ;; errors". Source URLs are meant to be plain hyperlinks (never ;; downloaded -- see the org-persist note above), so we drop the remote ;; protocols from the inline-image rules. Local file: embeds (every ;; figure in the Taxonomy and Journal) are untouched. Iteration 0.76.0. (setq org-latex-inline-image-rules (cl-remove-if (lambda (rule) (member (car rule) '("http" "https"))) org-latex-inline-image-rules)) ;; Suppress remote-resource fetching during export. ;; ;; Org 9.6+ added a security policy for downloading remote resources ;; referenced by URL in exported documents (org-resource-download-policy ;; in some Org versions, org-safe-remote-resources in others). Default ;; behavior under batch export is to either prompt (which hangs the ;; headless Emacs) or to reject the download with an error and retry ;; (which loops indefinitely). ;; ;; Catalogue.org records source URLs for every ;; external illustration considered in the project. Several of them ;; point to Wikimedia Commons SVG/PNG pages. During PDF export Org's ;; link-export path called org-export-link--remote-local-copy to ;; download those URLs as local copies for inclusion; under the ;; "considered unsafe" policy this looped (rather than failing ;; cleanly) and killed the build. ;; ;; The 0.9.5 fix sets org-resource-download-policy to nil so no ;; remote fetch is attempted during export. URLs in the Catalogue ;; are rendered as plain hyperlinks in the resulting PDF/HTML, which ;; is what the document intends (the catalogue records sources, not ;; embeds them). Locally-fetched copies ;; remain available as plain files for actual inclusion. ;; ;; defvar guard: older Emacs that don't define this variable will ;; not error on the setq because we let-bind it conditionally. Most ;; recent Emacs 29+ define it. (when (boundp 'org-resource-download-policy) (setq org-resource-download-policy nil)) (when (boundp 'org-safe-remote-resources) (setq org-safe-remote-resources nil)) ;; The 0.9.5 fix above (org-resource-download-policy / org-safe-remote- ;; resources) did NOT actually stop the loop: the offending code path is ;; org-persist-write:url, invoked when Org tries to cache a remote URL it ;; meets during export. That function raises the "considered unsafe" ;; error which, in batch export, loops rather than failing cleanly --- so ;; the Catalogue PDF (which records many Wikimedia source URLs) could not ;; be built, and Doc/Illustrations was dropped from SUBDIRS (see ;; Doc/Makefile.am). Iteration 0.75.0 fix: override org-persist-write:url ;; to a no-op. The Catalogue records source URLs as plain hyperlinks; it ;; never needs Org to download or cache them, so suppressing the cache ;; write is exactly right and lets the PDF build. Guarded so older Emacs ;; without the function are unaffected. (with-eval-after-load 'org-persist (when (fboundp 'org-persist-write:url) (advice-add 'org-persist-write:url :override (lambda (&rest _) nil)))) (when (fboundp 'org-persist-write:url) (advice-add 'org-persist-write:url :override (lambda (&rest _) nil))) ;; org-persist-gc fallout from the write override above. ;; ;; With org-persist-write:url neutralised, the persistence index keeps a ;; url container entry that was never written to disk (its :file is nil). ;; Org 9.7's org-persist-gc -- registered on kill-emacs-hook -- then runs ;; a string operation on that nil and dies with ;; Error in kill-emacs-hook (org-persist-gc): (wrong-type-argument stringp nil) ;; This fires AFTER the PDF is written, so it does not corrupt output, but ;; it is noisy and was observed on the Catalogue build. A one-shot batch ;; export never needs persistence garbage collection, so we make ;; org-persist-gc a no-op and remove it from kill-emacs-hook. Guarded so ;; older Emacs without the function are unaffected. Iteration 0.76.0. (with-eval-after-load 'org-persist (when (fboundp 'org-persist-gc) (advice-add 'org-persist-gc :override (lambda (&rest _) nil)) (remove-hook 'kill-emacs-hook #'org-persist-gc))) (when (fboundp 'org-persist-gc) (advice-add 'org-persist-gc :override (lambda (&rest _) nil)) (remove-hook 'kill-emacs-hook #'org-persist-gc)) ;; HTML export: stop the warning flood from missing htmlize.el >= 1.34. ;; The fallback to plain text was happening anyway; this just suppresses ;; the per-block complaint. Install htmlize from MELPA and switch this ;; to 'css to get colourised source blocks in HTML output. (setq org-html-htmlize-output-type nil) (setq org-html-validation-link nil) ;; --------------------------------------------------------------------- ;; HTML cleanup. ;; ;; The author line is a two-backend construct (see the AUTHORLINE macro ;; in version.org.in): it carries @@latex:...@@ / @@html:...@@ export ;; snippets so the visible title block can render "author" on line one ;; and "with " small-italic on line two in each backend. ;; ;; That works for the VISIBLE author block, but Org's default ;; builder emits the author as plain text without ;; processing export snippets, so the raw @@latex:...@@ / @@html:...@@ ;; text leaked verbatim into the meta tag. The meta tag is invisible ;; metadata, but it should still be clean. ;; ;; Fix: a custom org-html-meta-tags function that builds the author ;; meta entry from a cleaned author string --- LaTeX-only fragments ;; dropped, the HTML
turned into a comma, any stray tags removed. ;; The visible author block is untouched (it is produced by a different ;; code path that does process the snippets). (defun orgdoc/clean-author-string (info) "Return the document author as plain text for a meta tag. Strips Org export snippets (@@backend:...@@) and inline HTML markup from the parsed :author in INFO." (let* ((author (plist-get info :author)) (raw (if (stringp author) author (org-element-interpret-data author)))) (when raw (let ((s raw)) (setq s (replace-regexp-in-string "@@latex:[^@]*@@" "" s)) (setq s (replace-regexp-in-string "@@html:
@@" ", " s)) (setq s (replace-regexp-in-string "@@html:[^@]*@@" "" s)) (setq s (replace-regexp-in-string "<[^>]+>" "" s)) (setq s (replace-regexp-in-string "[ \t]+" " " s)) (setq s (replace-regexp-in-string " +," "," s)) (string-trim s))))) (defun orgdoc/html-meta-tags (info) "Like `org-html-meta-tags-default' but with a cleaned author string." (let ((clean (orgdoc/clean-author-string info))) (delq nil (list (when (org-string-nw-p clean) (list "name" "author" clean)) (let ((desc (plist-get info :description))) (when (org-string-nw-p desc) (list "name" "description" desc))) '("name" "generator" "Org Mode"))))) (setq org-html-meta-tags #'orgdoc/html-meta-tags) ;; --------------------------------------------------------------------- ;; HTML preamble and postamble: navigation via Org's standard ;; #+HTML_LINK_UP / #+HTML_LINK_HOME keywords. ;; ;; Iteration 0.8.9: switched away from custom #+HTML_PREAMBLE / ;; #+HTML_POSTAMBLE per-file keywords because their handling differs ;; between batch export (loaded via this file) and manual export ;; (Peter exporting one document interactively without loading ;; batch-init.el). The discrepancy meant Catalogue.org's back-link ;; only worked in the batch path. ;; ;; The new approach: every document declares its Index back-link via ;; #+HTML_LINK_UP and #+HTML_LINK_HOME keywords (universally ;; recognised by Org's HTML exporter, batch and manual). Org renders ;; the home/up navigation at the top of the page using ;; org-html-home/up-format. ;; ;; The default org-html-home/up-format renders "UP | HOME" with two ;; links. Below we override it to a single styled "← Index" link, both ;; %s slots resolving to the same Index path declared in the .org ;; files. Manual export (without this customisation) shows "UP | HOME" ;; both pointing at Index --- functional, just less pretty. Peter can ;; mirror this customisation in his ~/.emacs to get identical ;; rendering interactively. ;; ;; Index.org keeps its #+OPTIONS html-preamble:nil html-postamble:nil ;; and does NOT set HTML_LINK_UP / HTML_LINK_HOME, so Index.html does ;; not get a back-link to itself. ;; ;; Author and date display: org-html-postamble defaults to 'auto, ;; which generates author + date + creator from #+AUTHOR and the ;; export timestamp. We do not override it here; manual and batch ;; export produce the same postamble. ;; --------------------------------------------------------------------- ;; The default org-html-home/up-format renders "UP | HOME" with two ;; links. We override it for the batch path to a single styled "← Index" ;; link, and in iteration 0.9.3 we additionally inject a "PDF ↓" link ;; pointing at the same-basename .pdf so end-users can switch to the ;; PDF view of any HTML page they're reading. The PDF link sits on ;; the right side of the same header strip. ;; ;; Implementation: instead of org-html-home/up-format (which is a ;; format string evaluated with no knowledge of the current file's ;; name), we use a per-export FUNCTION assigned to org-html-preamble ;; that knows the current file. The home/up-format mechanism is ;; superseded by this preamble; we still emit Index keywords in each ;; .org file so manual export (which does NOT load this batch-init.el) ;; falls back to Org's stock "UP | HOME" rendering --- functional but ;; without the PDF link. ;; ;; Manual export users can mirror the org-html-preamble setting below ;; in their ~/.emacs to get identical batch-export behaviour ;; interactively. ;; --------------------------------------------------------------------- (defun bsppfit/html-preamble (info) "Build the per-page header strip for BSPPFit HTML pages. INFO is the export communication channel (a plist) supplied by the Org HTML exporter. Emits a nav element with: - left side : ← Index back-link to whatever the document's `#+HTML_LINK_UP' keyword set (skipped if unset). - right side: ↓ PDF link to the same-basename .pdf in the same directory. Index.org itself (which doesn't set HTML_LINK_UP and does set ~#+OPTIONS: html-preamble:nil~) overrides this and emits no preamble." (let* ((up-link (plist-get info :html-link-up)) (in-file (plist-get info :input-file)) (pdf-href (and in-file (concat (file-name-base in-file) ".pdf")))) (concat ""))) (setq org-html-preamble #'bsppfit/html-preamble) ;; Suppress Org's legacy home/up navigation div. In iteration 0.9.3 ;; we kept both org-html-home/up-format AND the new ;; bsppfit/html-preamble active, and Org rendered BOTH at the top of ;; every page --- two consecutive Index back-links. The 0.9.4 fix is ;; to set org-html-home/up-format to an empty string so the legacy ;; div emits nothing; the bsppfit/html-preamble function above is ;; the only header strip rendered. ;; ;; We keep emitting #+HTML_LINK_UP / #+HTML_LINK_HOME in the .org ;; sources so the :html-link-up / :html-link-home plist keys are ;; populated; bsppfit/html-preamble reads them. Manual export ;; (without this batch-init.el) restores Org's default ;; org-html-home/up-format, which renders the stock "UP | HOME" ;; nav; that is the documented manual-vs-batch asymmetry. (setq org-html-home/up-format "") ;; --------------------------------------------------------------------- ;; PlantUML. ;; --------------------------------------------------------------------- (let ((jar (getenv "BSPPFIT_PLANTUML_JAR"))) (when (and jar (not (string-empty-p jar))) (setq org-plantuml-jar-path jar))) (org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t))) ;; --------------------------------------------------------------------- ;; LaTeX multi-pass. ;; ;; The default org-latex-pdf-process runs LaTeX three times. We ;; observed [undefined reference] warnings on documents with several ;; cross-references (TOC + list-of-tables + hyperref anchors), so we ;; either delegate the pass count to latexmk (when available) or run ;; lualatex four times explicitly. ;; --------------------------------------------------------------------- (let* ((kind (getenv "BSPPFIT_PDF_PROCESS_KIND")) (lualatex (or (getenv "BSPPFIT_LUALATEX") "lualatex")) (latexmk (or (getenv "BSPPFIT_LATEXMK") "latexmk"))) (cond ((string-equal kind "latexmk") (setq org-latex-pdf-process (list (concat latexmk " -pdf" " -pdflatex=" lualatex " -interaction=nonstopmode" " -shell-escape" " -output-directory=%o %f")))) (t ; "fallback" or unset (let ((cmd (concat lualatex " -interaction=nonstopmode" " -shell-escape" " -output-directory=%o %f"))) (setq org-latex-pdf-process (list cmd cmd cmd cmd)))))) ;; --------------------------------------------------------------------- ;; Cross-document anchor resolution (HTML export). ;; ;; A link of the form [[file:Other.org::*Heading]] (or ;; [[file:Other.org::anchor]]) sends the resolver into ox-publish.el, ;; which calls org-publish-resolve-external-link. That function ;; consults state bound only during a project publishing run; called ;; from per-file org-html-export-to-html it falls into a degraded ;; branch and emits, once per cross-document link: ;; ;; Reference "*Heading" in file "Other.org" cannot be resolved ;; without publishing ;; ;; The link is still written into the HTML output (Org rewrites ;; .org -> .html via org-html-link-org-files-as-html), but the ;; resolver cannot verify the anchor. v0.5.0 attempted to fix this ;; by defining org-publish-project-alist alone --- that was wrong. ;; The alist tells the resolver where files are, but the resolver ;; only consults it during a project publishing run. ;; ;; v0.6.0 fixes the issue at its cause: HTML export uses ;; org-publish-all (entry point bsppfit/publish-all below) instead of ;; per-file org-html-export-to-html. With the project run actually in ;; progress, the resolver sees the populated state and resolves the ;; anchors. ;; ;; v0.8.0 replaces the auto-generated sitemap with an authored ;; Index.org. The sitemap was a list-of-links; the authored Index ;; provides a versioned subtitle, an introduction, grouped sections, ;; and per-link descriptive content. The :auto-sitemap is dropped ;; from the project entry, and the publishing run produces ;; Index.html from Index.org along with the rest of the documents. ;; --------------------------------------------------------------------- ;; v0.9.1 extends the publish project alist with a unified project ;; covering both Doc/ and Models/ when the environment variable ;; BSPPFIT_TOP_SRCDIR is set (the Doc/Makefile.am and ;; Models/Makefile.am pass it). This unification ensures that ;; cross-document file: links from Models/LibraryOverview.org to ;; Doc/Concept.org (and vice-versa) get their .org -> .html ;; rewriting AND anchor resolution performed by the resolver, ;; avoiding the "cannot resolve without publishing" warnings on ;; HTTP-served deployments. When the env var is not set ;; (interactive Emacs use), the per-directory project entries ;; are still defined so single-directory publishing still works. ;; --------------------------------------------------------------------- ;; v0.9.4 adds the Illustrations sub-directory as a third component ;; of the bsppfit-all unified project. Catalogue.org now publishes via ;; the same org-publish-all path as the other documents, so its ;; cross-references resolve cleanly during the build. ;; --------------------------------------------------------------------- ;; v0.136.0 flattens the whole source tree (formerly Doc/, ;; Doc/Illustrations/, Models/) into one directory. The v0.9.1/v0.9.4 ;; multi-component apparatus above --- the BSPPFIT_TOP_SRCDIR env var, ;; the doc/illus/models path variables, the bsppfit-docs-vs-bsppfit-all ;; distinction --- existed only to give documents in different ;; directories a single unified publishing run to resolve ;; cross-document anchors against. With every document already in the ;; same directory, that distinction has nothing left to unify: a ;; single project entry, publishing from default-directory the way ;; interactive Emacs use always could, now covers every document, in ;; every calling context, with no environment variable needed at all. ;; --------------------------------------------------------------------- (setq org-publish-project-alist `(("bsppfit" :base-directory ,default-directory :base-extension "org" :exclude "version\\.org\\|SessionHandoff\\.org" :publishing-directory ,default-directory :publishing-function org-html-publish-to-html :recursive nil :section-numbers nil :with-toc t :html-link-home "../../ExTBSPPFit.html" :html-link-up "../../ExTBSPPFit.html"))) (defun bsppfit/publish-all () "Build all project documents in one publishing run. Called from Makefile.am as the HTML build entry point. Forces a fresh build (`force' = t) so make-driven rebuilds do not silently skip files whose timestamps are equal." (let ((default-directory (or (getenv "PWD") default-directory))) (org-publish "bsppfit" t))) ;; --------------------------------------------------------------------- ;; Cross-document hyperlink filter (LaTeX export only). ;; ;; Documents reference one another via [[file:Other.org::*Heading]]. ;; On HTML export, Org rewrites .org -> .html automatically (see ;; org-html-link-org-files-as-html, default t). On LaTeX export there ;; is no such automatic rewrite, so a click on a cross-document link ;; in the produced PDF would otherwise resolve to the source .org file ;; rather than the rendered .pdf. ;; ;; The filter rewrites .org -> .pdf inside \href{...} URL targets ;; during LaTeX export. The terminator is one of "::" (Org heading ;; anchor), "#" (HTML-style fragment), or "}" (no anchor). ;; --------------------------------------------------------------------- (defun bsppfit/org-link-org-to-pdf (text backend info) "Rewrite .org -> .pdf inside \\href{} URL targets on LaTeX export." (if (org-export-derived-backend-p backend 'latex) (replace-regexp-in-string "\\.org\\(::\\|#\\|}\\)" ".pdf\\1" text) text)) (add-to-list 'org-export-filter-link-functions #'bsppfit/org-link-org-to-pdf) ;; --------------------------------------------------------------------- ;; Broken-link handling: emit a marker rather than aborting export, so ;; that a single typo in a link does not stop the whole build. The ;; marker is visible in the output and easy to grep for. ;; --------------------------------------------------------------------- (setq org-export-with-broken-links 'mark) ;; --------------------------------------------------------------------- ;; HTML list-of-figures (iteration 0.61.0). ;; ;; Org provides #+TOC: tables and #+TOC: listings, and the LaTeX path ;; honours \listoffigures, but Org has NO native `figures' TOC type ;; for HTML --- so the HTML documents had a list-of-tables but no ;; matching list-of-figures. This filter synthesises one. ;; ;; It runs on the final HTML output, scans for the
blocks Org emits for each captioned image, reads each ;; block's id and its "Figure N: ..." caption, and injects a ;; list-of-figures block immediately before the first outline ;; container --- i.e. directly after the table-of-contents and the ;; native list-of-tables, matching their placement and markup ;; (id="list-of-figures" / "text-list-of-figures", an

heading, ;; and a
    of anchor links). Each entry links to the figure's ;; in-page anchor and shows the caption's first sentence. ;; ;; No-op when the document has no figures, or already contains a ;; list-of-figures. LaTeX export is untouched (it uses \listoffigures ;; from the per-document #+LATEX: header). ;; --------------------------------------------------------------------- (defun bsppfit/html-list-of-figures (html backend info) "Inject an HTML list-of-figures mirroring Org's `#+TOC: tables'. HTML is the final output string, BACKEND the export backend, INFO the communication channel. Returns HTML unchanged for non-HTML backends, documents without figures, or documents that already contain a list-of-figures." (if (and (org-export-derived-backend-p backend 'html) (not (string-match-p "id=\"list-of-figures\"" html))) (let ((case-fold-search t) (items '()) (pos 0)) (while (string-match "
    " html pos) (let ((fid (match-string 1 html)) (after (match-end 0))) (setq pos after) ;; Capture the whole caption paragraph (which may contain ;; inline markup such as from ~verbatim~), then strip ;; tags. The caption

    is:

    ;; Figure N: CAPTION

    . (when (string-match "\\(Figure[^<]*\\)\\(\\(?:.\\|\n\\)*?\\)

    " html after) (let* ((num (string-trim (match-string 1 html))) (raw (match-string 2 html)) ;; Strip any inline HTML tags from the caption body. (cap (string-trim (replace-regexp-in-string "<[^>]*>" "" raw))) (short (if (string-match "\\. " cap) (substring cap 0 (1+ (match-beginning 0))) cap)) (label (replace-regexp-in-string ":?\\s-*$" "" num))) (push (format "
  • %s %s
  • " fid label short) items))))) (if (null items) html (let ((lof (concat "
    \n" "

    List of Figures

    \n" "
    \n
      \n" (mapconcat #'identity (nreverse items) "\n") "\n
    \n
    \n
    \n"))) (if (string-match "