fix: latex paragraphs again lol
All checks were successful
build / build (push) Successful in 4s

This commit was merged in pull request #17.
This commit is contained in:
2026-03-17 21:24:36 -06:00
parent 1629efb378
commit 7805de06f2
7 changed files with 127 additions and 49 deletions

View File

@@ -554,4 +554,11 @@ figure.fullwidth figcaption {
; align-items: center ; align-items: center
; justify-content: center ; justify-content: center
; display: flex ; display: flex
; max-width: 55%
; width: 55%
}
p > .latex-fragment.display-math
{ max-width: 100%
; width: 100%
} }

View File

@@ -232,23 +232,35 @@
;; TODO: Construct `:contents-begin` and `:contents-end` data ;; TODO: Construct `:contents-begin` and `:contents-end` data
;; by spanning the children. ;; by spanning the children.
first-section (merge {:type "section" first-section (merge {:type "section"
:children first-section-nodes} :children (vec first-section-nodes)}
(apply element-bounds first-section-nodes)) (apply element-bounds first-section-nodes))
new-children (concat top-level-nodes new-children (vec (concat top-level-nodes
(list first-section) (list first-section)
rest)] rest))]
(assoc node :children new-children))) (assoc node :children new-children)))
(defn separated-by-explicit-paragraph-break? (defn- newline-final-paragraph?
"Returh truthy if each successive pair of elements is separated by "Is `e` a paragraph, and does it end with a newline?"
at least one explicit paragraph break; i.e. a blank line." [e]
(and (of-type? e "paragraph")
(some-> (-> e :position :end :column)
(= 1))))
(defn consequtive-elements?
"Returh truthy if each successive pair of elements is NOT separated
by at least one explicit paragraph break; i.e. a blank line."
[& elements] [& elements]
(match elements (match elements
[e e & es] ([(e :guard newline-final-paragraph?) e & es] :seq)
(and (< (-> e :position :end :line) (and (= (-> e :position :end :line)
(-> e :position :start :line)) (-> e :position :start :line))
(recur es)) (recur es))
:else true)) ([e e & es] :seq)
(and (= (-> e :position :end :line inc)
(-> e :position :start :line))
(recur es))
([_] :seq) true
([] :seq) true))
(defn swallow (defn swallow
([predator prey] ([predator prey]
@@ -259,6 +271,22 @@
([predator prey & more-prey] ([predator prey & more-prey]
(reduce swallow predator (cons prey more-prey)))) (reduce swallow predator (cons prey more-prey))))
(defn- paragraph-followed-by-tex? [children]
(match children
[(para :guard #(of-type? % "paragraph"))
(tex :guard #(of-type? % "latex-environment"))
& _]
(consequtive-elements? para tex)
:else false))
(defn- paragraph-followed-by-paragraph? [children]
(match children
[(para :guard #(of-type? % "paragraph"))
(para :guard #(of-type? % "paragraph"))
& _]
(consequtive-elements? para para)
:else false))
(defn gather-latex-paragraphs [node] (defn gather-latex-paragraphs [node]
(->> node (->> node
(sp/transform (sp/transform
@@ -271,16 +299,14 @@
;; If there are no blank lines separating the paragraph ;; If there are no blank lines separating the paragraph
;; from the LaTeX environment, the LaTeX environment ;; from the LaTeX environment, the LaTeX environment
;; shall become a child of the paragraph. ;; shall become a child of the paragraph.
([(para :guard #(of-type? % "paragraph")) ([para tex & rest] :guard paragraph-followed-by-tex?)
(tex :guard #(of-type? % "latex-environment"))
& rest]
:guard #(apply separated-by-explicit-paragraph-break? %))
(recur acc (vec (cons (swallow para tex) rest))) (recur acc (vec (cons (swallow para tex) rest)))
;; CASE: ;; CASE: Similar to the paragraph-followed-by-tex case,
([(para :guard #(of-type? % "paragraph")) ;; but instead of swallowing the entire second element,
(para :guard #(of-type? % "paragraph")) ;; we swallow the /children/ of the second element,
& rest] ;; since paragraphs cannot be nested.
:guard #(apply separated-by-explicit-paragraph-break? %)) ([para para & rest]
:guard paragraph-followed-by-paragraph?)
(recur acc (vec (cons (apply swallow para (:children para)) (recur acc (vec (cons (apply swallow para (:children para))
rest))) rest)))
;; CASE: Irrelevant or empty! ;; CASE: Irrelevant or empty!

View File

@@ -9,9 +9,7 @@
[net.deertopia.doerg.html :as doerg-html] [net.deertopia.doerg.html :as doerg-html]
[hiccup2.core :as hiccup] [hiccup2.core :as hiccup]
[clojure.pprint] [clojure.pprint]
;; #_
[net.deertopia.doerg.tex :as tex] [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.temml :as tex-temml]
[clojure.zip :as z] [clojure.zip :as z]
[babashka.fs :as fs])) [babashka.fs :as fs]))

View File

@@ -11,7 +11,8 @@
(defn- parse-resource [path] (defn- parse-resource [path]
(-> (str "net/deertopia/doerg/element_test/" path) (-> (str "net/deertopia/doerg/element_test/" path)
io/resource slurp sut/read-string)) io/resource slurp
(sut/read-string)))
(t/deftest known-greater-elements (t/deftest known-greater-elements
(t/testing "known greater elements satisfy `greater-element?`" (t/testing "known greater elements satisfy `greater-element?`"
@@ -44,32 +45,47 @@
true))) true)))
(t/deftest first-paragraph-under-first-section (t/deftest first-paragraph-under-first-section
(t/testing "first paragraph should belong to a section" (t/is (-> (parse-resource "first-paragraph-under-first-section.org")
(t/is (-> (parse-resource "first-paragraph-under-first-section.org") first-paragraph-belongs-to-first-section?)))
first-paragraph-belongs-to-first-section?))
(t/is (not (-> (parse-resource "first-paragraph-under-heading.org")
first-paragraph-belongs-to-first-section?)))))
(defn walk-types [type & types] (t/deftest first-paragraph-under-heading
(t/is (-> (parse-resource "first-paragraph-under-heading.org")
first-paragraph-belongs-to-first-section?
not)))
(defn- walk-types [type & types]
[sut/postorder-walker #(apply sut/of-type? % type types)]) [sut/postorder-walker #(apply sut/of-type? % type types)])
(defn- paragraph-ends-with-latex? [doc] (t/deftest paragraph-ending-with-latex
(let [type (-> (sp/select-first [(walk-types "paragraph") (let [doc (parse-resource "paragraph-ending-with-latex.org")
type (-> (sp/select-first [(walk-types "paragraph")
(sp/must :children) (sp/must :children)
sp/LAST] sp/LAST]
doc) doc)
sut/type)] sut/type)]
(t/is type "latex-environment"))) (t/is (= "latex-environment" type))))
(defn- paragraph-has-latex? [doc] (t/deftest paragraph-surrounding-latex
(t/is (sp/select-first [(walk-types "paragraph") (let [doc (parse-resource "paragraph-surrounding-latex.org")
(sp/must :children) children (->> doc
sp/ALL (sp/select-first [(walk-types "paragraph")])
#(sut/of-type? % "latex-environment")] :children
doc))) (map sut/type))]
(t/is (= ["text" "latex-environment" "text"]
children))))
(defn- paragraph-has-multiple-latex? [doc] (t/deftest paragraph-ending-in-bold-surrounding-latex
(let [paragraphs (sp/select (walk-types "paragraph") doc)] (let [doc (parse-resource "paragraph-ending-in-bold-surrounding-latex.org")
children (->> doc
(sp/select-first [(walk-types "paragraph")])
:children
(map sut/type))]
(t/is (= ["text" "bold" "latex-environment" "text"]
children))))
(t/deftest paragraph-with-multiple-latex
(let [doc (parse-resource "paragraph-with-multiple-latex.org")
paragraphs (sp/select (walk-types "paragraph") doc)]
(t/is (= 2 (count paragraphs))) (t/is (= 2 (count paragraphs)))
(let [[p p] paragraphs] (let [[p p] paragraphs]
(doseq [[p ts] [[p ["text" "latex-environment" (doseq [[p ts] [[p ["text" "latex-environment"
@@ -79,13 +95,21 @@
(t/is (= ts (sp/select [(sp/must :children) (t/is (= ts (sp/select [(sp/must :children)
sp/ALL (sp/view sut/type)] p))))))) sp/ALL (sp/view sut/type)] p)))))))
(t/deftest paragraph-separation (t/deftest paragraph-with-separate-latex
(t/testing "paragraph ending with latex" (let [doc (parse-resource "paragraph-with-separate-latex.org")
(-> (parse-resource "paragraph-ending-with-latex.org") cs (sp/select [(walk-types "section")
paragraph-ends-with-latex?)) (sp/must :children)
(t/testing "paragraph surrounding latex" sp/ALL
(-> (parse-resource "paragraph-surrounding-latex.org") (sp/view sut/type)]
paragraph-has-latex?)) doc)]
(t/testing "paragraph with interleaved latex" (t/is (= ["paragraph" "latex-environment"] cs))))
(-> (parse-resource "paragraph-with-multiple-latex.org")
paragraph-has-multiple-latex?))) (t/deftest paragraph-surrounding-separate-latex
(let [doc (parse-resource "paragraph-surrounding-separate-latex.org")
cs (sp/select [(walk-types "section")
(sp/must :children)
sp/ALL
(sp/view sut/type)]
doc)]
(t/is (= ["paragraph" "latex-environment" "paragraph"] cs))))

View File

@@ -0,0 +1,7 @@
#+title: bold-final paragraph surrounding latex
first part of *paragraph*
\begin{equation*}
\text{some \LaTeX \}:)}
\end{equation*}
last part of paragraph

View File

@@ -0,0 +1,9 @@
#+title: paragraphs surrounding separate latex
a paragraph!
\begin{gather*}
\text{and now, an unrelated latex fragment}
\end{gather*}
more unrelated text

View File

@@ -0,0 +1,7 @@
#+title: paragraph with separate latex
a paragraph!
\begin{gather*}
\text{and now, an unrelated latex fragment}
\end{gather*}