Skip to content

Commit

Permalink
Parse Block formulas
Browse files Browse the repository at this point in the history
  • Loading branch information
zampino committed May 2, 2024
1 parent fe4ba1c commit 7da275c
Show file tree
Hide file tree
Showing 22 changed files with 80 additions and 26 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified classes/nextjournal/markdown/parser2/types$footnote_init.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified classes/nextjournal/markdown/parser2/types/BlockFormula.class
Binary file not shown.
Binary file modified classes/nextjournal/markdown/parser2/types/Footnote.class
Binary file not shown.
Binary file modified classes/nextjournal/markdown/parser2/types/FootnoteRef.class
Binary file not shown.
Binary file modified classes/nextjournal/markdown/parser2/types/InlineFormula.class
Binary file not shown.
Binary file modified classes/nextjournal/markdown/parser2/types__init.class
Binary file not shown.
5 changes: 2 additions & 3 deletions src/nextjournal/markdown/commonmark.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
[nextjournal.markdown.parser2.types]
[nextjournal.markdown.parser2.footnotes :as footnotes]
[nextjournal.markdown.parser2.formulas :as formulas])
(:import (org.commonmark.parser Parser Parser$ParserExtension Parser$Builder)
(org.commonmark.parser.delimiter DelimiterProcessor)
(:import (org.commonmark.parser Parser)
(org.commonmark.ext.task.list.items TaskListItemsExtension TaskListItemMarker)
(org.commonmark.node Node Nodes AbstractVisitor
(org.commonmark.node Node AbstractVisitor
;;;;;;;;;; node types ;;;;;;;;;;;;;;;;;;
Document
BlockQuote
Expand Down
65 changes: 47 additions & 18 deletions src/nextjournal/markdown/parser2/formulas.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
(ns nextjournal.markdown.parser2.formulas
(:require [clojure.string :as str])
(:import (java.util Set)
(java.util.regex Matcher)
(nextjournal.markdown.parser2.types InlineFormula BlockFormula)
(org.commonmark.parser Parser$ParserExtension Parser$Builder SourceLine)
(org.commonmark.parser.beta InlineContentParser InlineContentParserFactory ParsedInline InlineParserState)
Expand All @@ -22,16 +24,43 @@
(.next scanner)
(ParsedInline/of (new InlineFormula content) (.position scanner))))))))

(def ^BlockParser block-parser
(let [block-formula (new BlockFormula "formula text")]
(defn block-formula-delimiter-matcher ^Matcher [^ParserState state]
(let [^SourceLine line (.getLine state)
next-non-space (.getNextNonSpaceIndex state)]
(re-matcher block-formula-delimiter-regex (subs (.getContent line) next-non-space))))

(defn close-block-formula? [state !lines]
;; we allow 1-liner blocks like A)
;; text
;;
;; $$\\bigoplus$$
;;
;; or blocks delimited by $$ B)
;;
;; $$
;; \\bigoplus
;; $$
(or #_A (when-some [l (last @!lines)] (str/ends-with? (str/trimr l) "$$"))
#_B (some? (re-find (block-formula-delimiter-matcher state)))))

(defn block-parser ^BlockParser []
(let [block-formula (new BlockFormula)
!lines (atom [])]
(proxy [AbstractBlockParser] []
(isContainer [] false)
(canContain [_other] false)
(getBlock [] block-formula)
(addLine [^SourceLine line]
(when-some [l (not-empty (str/trim (.getContent line)))]
(swap! !lines conj l)))
(closeBlock []
(.setLiteral block-formula (let [formula-body (str/join \newline @!lines)]
(cond-> formula-body
(str/ends-with? formula-body "$$")
(subs 0 (- (count formula-body) 2))))))
(tryContinue [^ParserState state]
(let [non-space (.getNextNonSpaceIndex state)]
;; ends at the next delimiter
(if (.isBlank state)
(if (close-block-formula? state !lines)
(BlockContinue/finished)
(BlockContinue/atIndex non-space)))))))

Expand All @@ -40,13 +69,10 @@
(tryStart [^ParserState state _matchedBlockParser]
(if (<= 4 (.getIndent state))
(BlockStart/none)
(let [^SourceLine line (.getLine state)
line-content (.getContent line)
next-non-space (.getNextNonSpaceIndex state)
candidate-content (subs line-content next-non-space)
m (re-matcher block-formula-delimiter-regex candidate-content)]
(let [next-non-space (.getNextNonSpaceIndex state)
m (block-formula-delimiter-matcher state)]
(if (re-find m)
(.atIndex (BlockStart/of (into-array [block-parser]))
(.atIndex (BlockStart/of (into-array [(block-parser)]))
(+ next-non-space (.end m)))
(BlockStart/none)))))))

Expand All @@ -59,14 +85,17 @@
(create [_] (inline-formula-parser)))))))

(comment

(class (re-matcher #"" ""))
(nextjournal.markdown.commonmark/parse "
# Ok
This is an $\\mathit{inline}$ formula
# Title
This is an $\\mathit{inline}$ formula
$$
\\bigoplus
$$
$$
\\begin{equation}
\\dfrac{1}{128\\pi^{2}}
\\end{equation}
$$
* a $\\int_a^b\\phi(t)dt$ with discount
* and what"))
* a $\\int_a^b\\phi(t)dt$ with discount
* and what"))
12 changes: 7 additions & 5 deletions src/nextjournal/markdown/parser2/types.clj
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@
(gen-class
:name nextjournal.markdown.parser2.types.BlockFormula
:extends org.commonmark.node.CustomBlock
:constructors {[String] []}
:constructors {[] []}
:init init
:state state
:methods [[getLiteral [] String]]
:prefix "block-formula-")
:prefix "block-formula-"
:methods [[getLiteral [] String]
[setLiteral [String] String]])

(defn block-formula-init [lit] [[] (ref {:literal lit})])
(defn block-formula-getLiteral [this] (:literal @(.state this)))
(defn block-formula-init [] [[] (atom nil)])
(defn block-formula-getLiteral [this] @(.state this))
(defn block-formula-setLiteral [this val] (reset! (.state this) val))

(gen-class
:name nextjournal.markdown.parser2.types.Footnote
Expand Down
24 changes: 24 additions & 0 deletions test/nextjournal/markdown_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,31 @@ $$p(z\\\\mid x) = \\\\frac{p(x\\\\mid z)p(z)}{p(x)}.$$\n\n
## SubTitle
")))))


(deftest formulas
(is (match? {:type :doc
:content [{:type :heading}
{:type :paragraph
:content [{:type :text, :text "This is an "}
{:type :formula, :text "\\mathit{inline}"}
{:type :text, :text " formula."}]}
{:type :block-formula, :text string?}
{:type :block-formula, :text "\\bigoplus"}]}
(md/parse "# Title
This is an $\\mathit{inline}$ formula.
$$
\\begin{equation}
\\dfrac{1}{128\\pi^{2}}
\\end{equation}
$$
$$\\bigoplus$$
"))))

(comment
(clojure.test/run-test-var #'formulas)

(doseq [[n v] (ns-publics *ns*)] (ns-unmap *ns* n))
(clojure.test/run-tests)
(run-tests 'nextjournal.markdown-test)
Expand Down

0 comments on commit 7da275c

Please sign in to comment.