From 26410655d98e091e1c5f4cbd182a6a9692b77362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madeleine=20Sydney=20=C5=9Alaga?= Date: Thu, 5 Mar 2026 14:20:58 -0700 Subject: [PATCH] fix: tikz svgs Fixes #9 --- doerg/our-tex.nix | 1 + .../net/deertopia/doerg/preview-template.tex | 53 +++++++++++++++++-- doerg/src/net/deertopia/doerg/render.clj | 2 +- doerg/src/net/deertopia/doerg/tex.clj | 51 +++++++++++------- doerg/src/net/deertopia/doerg/tex/native.clj | 2 +- 5 files changed, 83 insertions(+), 26 deletions(-) diff --git a/doerg/our-tex.nix b/doerg/our-tex.nix index fa70de0..c78c5a8 100644 --- a/doerg/our-tex.nix +++ b/doerg/our-tex.nix @@ -39,5 +39,6 @@ texlive.combine { collection-fontsrecommended # Essential fonts. etoolbox # For Org-mode exports. caption + standalone ; } diff --git a/doerg/resources/net/deertopia/doerg/preview-template.tex b/doerg/resources/net/deertopia/doerg/preview-template.tex index b250e4b..46dcd51 100644 --- a/doerg/resources/net/deertopia/doerg/preview-template.tex +++ b/doerg/resources/net/deertopia/doerg/preview-template.tex @@ -1,13 +1,56 @@ -\documentclass{article} -\usepackage{amsmath} +\documentclass[tikz,dvisvgm]{standalone} \usepackage[active,tightpage,auctex,dvips]{preview} -\usepackage{fontspec} +\usepackage{amsmath} +\usepackage{amssymb} \usepackage{ifxetex} \usepackage{syd-plex} \usepackage{quiver} -\usepackage{tikz-cd} +\usepackage{tikz} +\usepackage{amscd} + +\newcommand{\catname}[1]{\textbf{#1}} +\newcommand{\C}[1]{\catname{#1}} + +% Specific categories +\newcommand{\Set}{\catname{Set}} +\newcommand{\Cat}{\catname{Cat}} +\newcommand{\CAT}{\catname{CAT}} +\newcommand{\Grp}{\catname{Grp}} + +% Common objects and functions +\newcommand{\Ob}{\operatorname{Ob}} +\newcommand{\op}{\text{op}} +\newcommand{\opof}[1]{{#1}^{\text{op}}} +% \id{x} is the identity morphism on x. +\newcommand{\id}[1]{1_{#1}} +% \Id{C} is the identity functor on C. +\newcommand{\Id}[1]{1_{#1}} +\newcommand{\Mor}{\operatorname{Mor}} +\newcommand{\homset}[3]{{{#1} \left[ {#2} \to {#3} \right]}} + +% Constructions of categories. +\newcommand{\FunctorCategory}[2]{\left[#1, #2\right]} +\newcommand{\Funct}[2]{\FunctorCategory{#1}{#2}} % Deprecated. +\newcommand{\ArrowCategory}[1]{{#1}^\to} + +% Semantic aliases +\newcommand{\monicto}{\rightarrowtail} +\newcommand{\epicto}{\twoheadrightarrow} +\newcommand{\naturalto}{\Rightarrow} +\newcommand{\isoto}{\cong} +\newcommand{\equivto}{\simeq} + +\newcommand{\naturaltrans}[2]{#1 \naturalto #2} % Deprecated. +\newcommand{\horizontalcompose}{\ast} + +% Optics +\newcommand{\opticname}[1]{\textbf{#1}} +\newcommand{\optic}[3]{\opticname{#1}^\prime\;#2\;#3} +\newcommand{\Optic}[5]{\opticname{#1}\;#2\;#3\;#4\;#5} \begin{document} -\setlength\abovedisplayskip{0pt} +\setlength\abovedisplayskip{0pt} % Remove padding before equation environments. +%% \color[rgb]{0.000,0.000,0.004}\special{dvisvgm:currentcolor on}\setcounter{equation}{0}% + % {{contents}} \end{document} diff --git a/doerg/src/net/deertopia/doerg/render.clj b/doerg/src/net/deertopia/doerg/render.clj index dd1dc57..c025f7a 100644 --- a/doerg/src/net/deertopia/doerg/render.clj +++ b/doerg/src/net/deertopia/doerg/render.clj @@ -150,7 +150,7 @@ fut-res (deref fut ms ::timed-out)] (if (= fut-res ::timed-out) (do (l/warnf "Giving up on rendering TeX snippets after %.3f seconds." - (* ms 1000)) + (/ ms 1000)) (future-cancel fut) (doseq [[_snippet p] snippet-promises] (deliver p ::timed-out))) diff --git a/doerg/src/net/deertopia/doerg/tex.clj b/doerg/src/net/deertopia/doerg/tex.clj index e72a10f..f8e42ca 100644 --- a/doerg/src/net/deertopia/doerg/tex.clj +++ b/doerg/src/net/deertopia/doerg/tex.clj @@ -4,7 +4,8 @@ [babashka.fs :as fs] [clojure.string :as str] [hiccup2.core :as hiccup] - [clojure.tools.logging :as l])) + [clojure.tools.logging :as l] + [clojure.tools.logging.readable :as lr])) (defn- read-and-patch-generated-svg [{:keys [file height depth]}] ;; dvisvgm writes standalone SVG files, to which we need to make a @@ -28,26 +29,38 @@ (format "%s style=\"%s\"" s (format "height:%.4fem;vertical-align:%.4fem;display:inline-block" - height (- depth))))))) + height (- depth))))) + ;; Stupid hack. --currentcolor on dvisvgm should be enough, but + ;; it doesn't get e.g. TikZ arrows. + (str/replace #"stroke=['\"]#000['\"]" "stroke=\"currentColor\""))) + +(def ^:dynamic *save-snippets?* false) (defn render-snippets [snippet-promises] - (fs/with-temp-dir [svg-dir {:prefix "doerg-svg-"}] - (let [rendered-snippets - (delay (->> snippet-promises - (map first) - (apply native/render svg-dir)))] - (doseq [[snippet p] snippet-promises] - (try (let [temml (temml/render snippet)] - (->> (if (temml/erroneous-output? temml) - (let [tex (get @rendered-snippets snippet)] - (if (:errors tex) - temml - (read-and-patch-generated-svg tex))) - temml) - hiccup/raw (deliver p))) - (catch Exception e - (l/error e "Error in TeX thread") - (throw e))))))) + (with-redefs [fs/delete-tree + (fn + ([path] + (l/warnf "refusing to delete %s" path)) + ([path opts] + (lr/warnf "refusing to delete %s with opts %s" + path opts)))] + (fs/with-temp-dir [svg-dir {:prefix "doerg-svg-"}] + (let [rendered-snippets + (delay (->> snippet-promises + (map first) + (apply native/render svg-dir)))] + (doseq [[snippet p] snippet-promises] + (try (let [temml (temml/render snippet)] + (->> (if (temml/erroneous-output? temml) + (let [tex (get @rendered-snippets snippet)] + (if (:errors tex) + temml + (read-and-patch-generated-svg tex))) + temml) + hiccup/raw (deliver p))) + (catch Exception e + (l/error e "Error in TeX thread") + (throw e)))))))) (comment (let [snippets (for [x ["\\(\\ifxetex blah \\fi\\)" diff --git a/doerg/src/net/deertopia/doerg/tex/native.clj b/doerg/src/net/deertopia/doerg/tex/native.clj index cddbb11..0243982 100644 --- a/doerg/src/net/deertopia/doerg/tex/native.clj +++ b/doerg/src/net/deertopia/doerg/tex/native.clj @@ -93,7 +93,7 @@ (invoke {:dir output-dir} dvisvgm "--page=1-" "--optimize" "--clipjoin" - "--relative" "--no-fonts" "-v3" + "--relative" "--no-fonts" "-v3" "--currentcolor" "--message=processing page {?pageno}: output written to {?svgpath}" "--bbox=preview" "-o" "%9p.svg" file)))