Skip to content

Commit ecad455

Browse files
megayulogseq-cldwalker
authored andcommitted
feat: add support for Template, Math blocks and Cards in exporter
1 parent 309070f commit ecad455

3 files changed

Lines changed: 66 additions & 8 deletions

File tree

deps/graph-parser/src/logseq/graph_parser/exporter.cljs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,6 @@
693693
(get-page-uuid page-names-to-uuids ((some-fn ::original-name :block/name) block) {:block block})
694694
(:block/uuid block))
695695
properties-text-values))
696-
;; TODO: Add import support for :template. Ignore for now as they cause invalid property types
697696
(if (contains? props :template)
698697
{}
699698
(let [props' (-> (update-built-in-property-values
@@ -782,6 +781,8 @@
782781
(cond-> block
783782
true
784783
(merge block-properties)
784+
(:template properties')
785+
(update :block/tags (fnil conj []) :logseq.class/Template)
785786
(seq classes-from-properties)
786787
;; Add a map of {:block.temp/new-class TAG} to be processed later
787788
(update :block/tags
@@ -944,6 +945,7 @@
944945
use in build-block-tx. This walk is only done once for perf reasons"
945946
[config ast-blocks]
946947
(let [results (atom {:simple-queries []
948+
:cards []
947949
:asset-links []
948950
:embeds []
949951
:zotero-imported-files {}
@@ -980,6 +982,10 @@
980982
parsed-path (common-util/safe-read-string relative-path)]
981983
(when (string? parsed-path)
982984
(swap! results update :zotero-linked-files conj parsed-path)))
985+
(and (vector? x)
986+
(= "Macro" (first x))
987+
(= "cards" (:name (second x))))
988+
(swap! results update :cards conj x)
983989
(and (vector? x)
984990
(= "Macro" (first x))
985991
(= "query" (:name (second x))))
@@ -1032,7 +1038,20 @@
10321038
(assoc :block/collapsed? true)))]
10331039
{:block block'
10341040
:pvalues-tx pvalues-tx'})
1035-
{:block block})))
1041+
(if-let [cards-macro (first (:cards walked-ast-blocks))]
1042+
(let [query (-> (:arguments (second cards-macro)) first string/trim)
1043+
props {:logseq.property/query query}
1044+
{:keys [block-properties pvalues-tx]}
1045+
(build-properties-and-values props db page-names-to-uuids
1046+
(select-keys block [:block/properties-text-values :block/name :block/title :block/uuid])
1047+
options)
1048+
block'
1049+
(-> (update block :block/tags (fnil conj []) :logseq.class/Cards)
1050+
(merge block-properties
1051+
{:block/title (string/trim (string/replace-first title #"\{\{cards(.*)\}\}" ""))}))]
1052+
{:block block'
1053+
:pvalues-tx pvalues-tx})
1054+
{:block block}))))
10361055

10371056
(defn- handle-block-properties
10381057
"Does everything page properties does and updates a couple of block specific attributes"
@@ -1390,6 +1409,23 @@
13901409
:block/tags [:logseq.class/Quote-block]})
13911410
block))
13921411

1412+
(defn- handle-math
1413+
"If a block's entire content is a single displayed math formula, convert to #Math-block node.
1414+
Detects blocks whose title is entirely delimited by $$ markers."
1415+
[block _opts]
1416+
(let [title (string/trim (:block/title block))]
1417+
(if (and (string/starts-with? title "$$")
1418+
(string/ends-with? title "$$")
1419+
(> (count title) 4)
1420+
;; ensure there's no nested $$ pair (i.e. not two separate inline formulas)
1421+
(not (string/includes? (subs title 2 (- (count title) 2)) "$$")))
1422+
(let [math-content (string/trim (subs title 2 (- (count title) 2)))]
1423+
(merge block
1424+
{:block/title math-content
1425+
:logseq.property.node/display-type :math
1426+
:block/tags [:logseq.class/Math-block]}))
1427+
block)))
1428+
13931429
(defn- split-title-by-code-fences
13941430
"Parses a block title string line-by-line, splitting into non-code text parts
13951431
and code fence segments. All code fences are extracted regardless of whether
@@ -1492,6 +1528,7 @@
14921528
(update-block-tags db (:user-options options) per-file-state (:all-idents import-state))
14931529
(handle-embeds page-names-to-uuids walked-ast-blocks (select-keys options [:log-fn]))
14941530
(handle-quotes (select-keys options [:log-fn]))
1531+
(handle-math (select-keys options [:log-fn]))
14951532
(update-block-marker options)
14961533
(update-block-priority options)
14971534
add-missing-timestamps

deps/graph-parser/test/logseq/graph_parser/exporter_test.cljs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@
222222
(is (= 5 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Task]] @conn))))
223223
(is (= 4 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Query]] @conn))))
224224
(is (= 2 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Card]] @conn))))
225+
(is (= 1 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Cards]] @conn))))
226+
(is (= 2 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Code-block]] @conn))))
227+
(is (= 1 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Math-block]] @conn))))
228+
(is (= 1 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Template]] @conn))))
225229
(is (= 5 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Quote-block]] @conn))))
226230
(is (= 7 (count (d/q '[:find ?b :where [?b :block/tags :logseq.class/Pdf-annotation]] @conn))))
227231

@@ -331,11 +335,6 @@
331335
(mapv :db/id (:block/refs (db-test/find-block-by-content @conn #"ref to"))))
332336
"block with a block-ref has correct :block/refs")
333337

334-
(let [b (db-test/find-block-by-content @conn #"MEETING TITLE")]
335-
(is (= {}
336-
(and b (db-test/readable-properties b)))
337-
":template properties are ignored to not invalidate its property types"))
338-
339338
(is (= 20221126
340339
(-> (db-test/readable-properties (db-test/find-block-by-content @conn "only deadline"))
341340
:logseq.property/deadline
@@ -418,6 +417,26 @@
418417
(db-test/readable-properties (db-test/find-block-by-content @conn "card 1")))
419418
"None of the card properties are imported since they are deprecated")
420419

420+
;; Cards (flashcard browser)
421+
(is (= {:block/tags [:logseq.class/Cards]
422+
:logseq.property/query "(tags #Card)"}
423+
(db-test/readable-properties (find-block-by-property-value @conn :logseq.property/query "(tags #Card)")))
424+
"cards macro block has correct Cards class and query property")
425+
426+
;; Math blocks
427+
(is (= {:block/tags [:logseq.class/Math-block]
428+
:logseq.property.node/display-type :math}
429+
(db-test/readable-properties (db-test/find-block-by-content @conn "E=mc^2")))
430+
"Math block has correct Math-block class and display-type")
431+
(is (= "E=mc^2" (:block/title (db-test/find-block-by-content @conn "E=mc^2")))
432+
"Math block title has delimiters stripped")
433+
434+
;; Templates
435+
(let [b (db-test/find-block-by-content @conn #"MEETING TITLE")]
436+
(is (= {:block/tags [:logseq.class/Template]}
437+
(and b (db-test/readable-properties b)))
438+
"Template block is tagged as Template class"))
439+
421440
;; Assets
422441
(is (= {:block/tags [:logseq.class/Asset]
423442
:logseq.property.asset/type "png"

deps/graph-parser/test/resources/exporter-test-graph/journals/2026_03_01.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@
3030
echo "bye"
3131
exit
3232
```
33-
after code snippet
33+
after code snippet
34+
- $$E=mc^2$$
35+
- {{cards (tags #Card)}}

0 commit comments

Comments
 (0)