Compare commits
3 Commits
c97b7ab0dc
...
e49f847f20
| Author | SHA1 | Date | |
|---|---|---|---|
| e49f847f20 | |||
| ec4ad7c9c2 | |||
| 762324d9f0 |
0
doerg/doerg-parser/index.js
Normal file → Executable file
0
doerg/doerg-parser/index.js
Normal file → Executable file
6
doerg/doerg-parser/package-lock.json
generated
6
doerg/doerg-parser/package-lock.json
generated
@@ -1,11 +1,17 @@
|
||||
{
|
||||
"name": "doerg-parser",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "doerg-parser",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"uniorg-parse": "^3.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"doerg-parser": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
|
||||
6
doerg/doerg-temml-worker/package-lock.json
generated
6
doerg/doerg-temml-worker/package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "doerg-tex",
|
||||
"name": "doerg-temml-worker",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "doerg-tex",
|
||||
"name": "doerg-temml-worker",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"cbor-x": "^1.6.0",
|
||||
@@ -13,7 +13,7 @@
|
||||
"temml": "^0.13.1"
|
||||
},
|
||||
"bin": {
|
||||
"doerg-tex": "index.js"
|
||||
"doerg-temml-worker": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
|
||||
|
||||
@@ -6,30 +6,38 @@
|
||||
(s/def ::config
|
||||
(s/keys :req [::ibm-plex-web
|
||||
::latex
|
||||
::dvisvgm]))
|
||||
::dvisvgm
|
||||
::doerg-temml-worker
|
||||
::doerg-parser]))
|
||||
|
||||
(s/def ::file
|
||||
#(or (instance? java.io.File %)
|
||||
(string? %)))
|
||||
|
||||
(s/def ::executable #(or (fs/executable? %)
|
||||
(and (fs/relative? %)
|
||||
(fs/which %))))
|
||||
|
||||
(def default
|
||||
{::ibm-plex-web
|
||||
(or (System/getenv "DOERG_IBM_PLEX_WEB")
|
||||
(fs/file (some #(let [x (fs/path % "ibm-plex-web")]
|
||||
(and (fs/exists? x) x))
|
||||
(fs/split-paths (System/getenv "XDG_DATA_DIRS")))))
|
||||
(fs/file (some #(let [x (fs/path % "ibm-plex-web")]
|
||||
(and (fs/exists? x) x))
|
||||
(fs/split-paths (System/getenv "XDG_DATA_DIRS"))))
|
||||
::latex "xelatex"
|
||||
::dvisvgm "dvisvgm"
|
||||
;; TODO: Can we automatically set this to "./doerg-temml-worker/index.js" in
|
||||
;; a development environment?
|
||||
::doerg-temml-worker "doerg-temml-worker"})
|
||||
::doerg-temml-worker "doerg-temml-worker"
|
||||
::doerg-parser "doerg-parser"})
|
||||
|
||||
(def ^:dynamic *cfg* default)
|
||||
|
||||
(s/def ::ibm-plex-web ::file)
|
||||
|
||||
(s/def ::latex ::file)
|
||||
(s/def ::latex ::executable)
|
||||
|
||||
(s/def ::dvisvgm ::file)
|
||||
(s/def ::dvisvgm ::executable)
|
||||
|
||||
(s/def ::doerg-temml-worker ::file)
|
||||
(s/def ::doerg-temml-worker ::executable)
|
||||
|
||||
(s/def ::doerg-parser ::executable)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
:or {in *in*}}]
|
||||
(let [r (-> (p/process
|
||||
{:in in :out :string}
|
||||
"doerg-parser")
|
||||
(::cfg/doerg-parser cfg/*cfg*))
|
||||
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
||||
(if (zero? (:exit r))
|
||||
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
[net.deertopia.doerg.html :as doerg-html]
|
||||
[hiccup2.core :as hiccup]
|
||||
[clojure.pprint]
|
||||
#_
|
||||
;; #_
|
||||
[net.deertopia.doerg.tex :as tex]
|
||||
[net.deertopia.doerg.tex.native :as tex-native]
|
||||
[net.deertopia.doerg.tex.temml :as tex-temml]
|
||||
;; [net.deertopia.doerg.tex.native :as tex-native]
|
||||
;; [net.deertopia.doerg.tex.temml :as tex-temml]
|
||||
[clojure.zip :as z]
|
||||
[babashka.fs :as fs]))
|
||||
|
||||
@@ -143,72 +143,28 @@
|
||||
#(element/of-keyword-type? % "LATEX_HEADER")
|
||||
(sp/view :value)])))
|
||||
|
||||
(defn- read-and-patch-generated-svg [{:keys [file height depth]}]
|
||||
;; dvisvgm writes standalone SVG files, to which we need to make a
|
||||
;; few changes to use them inline within our HTML.
|
||||
;; • XML header: Bad syntax when embedded in an HTML doc. Remove
|
||||
;; it.
|
||||
;; • Width and height: We override these with our own values
|
||||
;; computed by `net.deertopia.doerg.tex` to ensure correct
|
||||
;; positioning relative to the surrounding text. More
|
||||
;; accurately, we remove the height and width attributes from
|
||||
;; the SVG tag, and set the new values for height and
|
||||
;; vertical-align in the style attribute
|
||||
;; • Viewbox: Must be removed entirely for correct positioning.
|
||||
(-> (slurp file)
|
||||
(str/replace-first #"<\?xml version='1.0' encoding='UTF-8'\?>\n?" "")
|
||||
(str/replace-first #" height=['\"][^\"']+[\"']" "")
|
||||
(str/replace-first #" width=['\"][^\"']+[\"']" "")
|
||||
(str/replace-first
|
||||
#"viewBox=['\"][^\"']+[\"']"
|
||||
(fn [s]
|
||||
(format "%s style=\"%s\""
|
||||
s
|
||||
(format "height:%.4fem;vertical-align:%.4fem;display:inline-block"
|
||||
height (- depth)))))))
|
||||
|
||||
(defn render-tex-snippets
|
||||
"Traverse doc, adorning each LaTeX node with a promise resolving to,
|
||||
optimistically, Hiccup-rendered SVG or MathML code."
|
||||
[doc]
|
||||
(let [promises (atom [])
|
||||
(let [snippet-promises (atom [])
|
||||
r (->> doc (sp/transform
|
||||
[element/postorder-walker
|
||||
#(element/of-type?
|
||||
% "latex-fragment" "latex-environment")]
|
||||
(fn [node]
|
||||
(let [p (promise)]
|
||||
(swap! promises #(conj % {:promise p :node node}))
|
||||
(swap! snippet-promises #(conj % [(:value node) p]))
|
||||
(assoc node ::rendered p)))))
|
||||
f (fn []
|
||||
(fs/with-temp-dir [svg-dir {:prefix "doerg-svg"}]
|
||||
(let [rendered-snippets
|
||||
(delay (->> @promises
|
||||
(map #(-> % :node :value))
|
||||
(apply tex-native/render svg-dir)))]
|
||||
(doseq [{:keys [promise node]} @promises]
|
||||
(try (let [{:keys [value]} node
|
||||
temml (tex-temml/render value)]
|
||||
(if (tex-temml/erroneous-output? temml)
|
||||
(let [tex (get @rendered-snippets value)]
|
||||
(if (:errors tex)
|
||||
(deliver promise (hiccup/raw temml))
|
||||
(->> tex
|
||||
read-and-patch-generated-svg
|
||||
hiccup/raw
|
||||
(deliver promise))))
|
||||
(deliver promise (hiccup/raw temml))))
|
||||
(catch Exception e
|
||||
(lr/error e)
|
||||
(throw e)))))))
|
||||
fut (future-call (bound-fn* f))]
|
||||
fut (-> #(tex/render-snippets @snippet-promises)
|
||||
bound-fn* future-call)]
|
||||
;; Time out after eight seconds. With all the LaTeX and IPC, there
|
||||
;; are so many opportunities for things to go wrong </3.
|
||||
(let [fut-res (deref fut (* 10 1000) ::timed-out)]
|
||||
(if (= fut-res ::timed-out)
|
||||
(do (future-cancel fut)
|
||||
(doseq [{:keys [promise]} @promises]
|
||||
(deliver promise ::timed-out)))
|
||||
(doseq [[_snippet p] @snippet-promises]
|
||||
(deliver p ::timed-out)))
|
||||
fut-res))
|
||||
r))
|
||||
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
(fs/delete-if-exists path)
|
||||
(fs/create-sym-link path target))
|
||||
|
||||
(defn reconfigure-doerg! []
|
||||
(alter-var-root
|
||||
#'cfg/*cfg*
|
||||
#(assoc %
|
||||
::cfg/doerg-temml-worker "./doerg-temml-worker/index.js"
|
||||
::cfg/doerg-parser "./doerg-parser/index.js")))
|
||||
|
||||
(defn render-html [& {:keys [src dest]
|
||||
:or {src some-org-file
|
||||
dest "/tmp/doerg-test"}}]
|
||||
|
||||
@@ -1,4 +1,60 @@
|
||||
(ns net.deertopia.doerg.tex
|
||||
(:require [net.deertopia.doerg.tex.native :as native]
|
||||
[net.deertopia.doerg.tex.temml :as temml]
|
||||
[babashka.fs :as fs]))
|
||||
[babashka.fs :as fs]
|
||||
[clojure.string :as str]
|
||||
[hiccup2.core :as hiccup]
|
||||
[clojure.tools.logging :as l]))
|
||||
|
||||
(defn- read-and-patch-generated-svg [{:keys [file height depth]}]
|
||||
;; dvisvgm writes standalone SVG files, to which we need to make a
|
||||
;; few changes to use them inline within our HTML.
|
||||
;; • XML header: Bad syntax when embedded in an HTML doc. Remove
|
||||
;; it.
|
||||
;; • Width and height: We override these with our own values
|
||||
;; computed by `net.deertopia.doerg.tex` to ensure correct
|
||||
;; positioning relative to the surrounding text. More
|
||||
;; accurately, we remove the height and width attributes from
|
||||
;; the SVG tag, and set the new values for height and
|
||||
;; vertical-align in the style attribute
|
||||
;; • Viewbox: Must be removed entirely for correct positioning.
|
||||
(-> (slurp file)
|
||||
(str/replace-first #"<\?xml version='1.0' encoding='UTF-8'\?>\n?" "")
|
||||
(str/replace-first #" height=['\"][^\"']+[\"']" "")
|
||||
(str/replace-first #" width=['\"][^\"']+[\"']" "")
|
||||
(str/replace-first
|
||||
#"viewBox=['\"][^\"']+[\"']"
|
||||
(fn [s]
|
||||
(format "%s style=\"%s\""
|
||||
s
|
||||
(format "height:%.4fem;vertical-align:%.4fem;display:inline-block"
|
||||
height (- depth)))))))
|
||||
|
||||
(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)
|
||||
(deliver p (hiccup/raw temml))
|
||||
(->> tex
|
||||
read-and-patch-generated-svg
|
||||
hiccup/raw
|
||||
(deliver p))))
|
||||
(deliver p (hiccup/raw temml))))
|
||||
(catch Exception e
|
||||
(l/error e "Error in TeX thread")
|
||||
(throw e)))))))
|
||||
|
||||
(comment
|
||||
(let [snippets (for [x ["\\(\\ifxetex blah \\fi\\)"
|
||||
"\\(\\sqrt{x^2 + y^2}\\)"]]
|
||||
[x (promise)])]
|
||||
(temml/binding-worker
|
||||
(render-snippets snippets)
|
||||
(map #(-> % second deref) snippets))))
|
||||
|
||||
@@ -61,7 +61,9 @@
|
||||
(render-display s)
|
||||
(if-let [[_ inner] (re-matches #"(?s)\\\((.*)\\\)" s)]
|
||||
(render-inline inner)
|
||||
(throw (ex-info "weird" {:snippet s}))))))
|
||||
(throw (IllegalArgumentException.
|
||||
(str "`net.deertopia.doerg.tex.temml` argument should"
|
||||
" be enclosed in math delimiters.")))))))
|
||||
|
||||
;; hackky....
|
||||
(defn erroneous-output? [s]
|
||||
|
||||
Reference in New Issue
Block a user