-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogseq_block_move.cljs
96 lines (88 loc) · 3.47 KB
/
logseq_block_move.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
(ns logseq-block-move
(:require ["fs" :as fs]
["path" :as path]
["util" :as util]
[nbb.core]
[clojure.string :as string]
[cldwalker.nbb-clis.mldoc :as mldoc]))
(defn- handle-heading-node
[acc attr node f]
(cond
(f attr)
(-> acc
(assoc :remove-level (:level attr)
:last-operation :remove)
(update :remove conj node))
;; Remove children of ast node
(some-> (:remove-level acc) (< (:level attr)))
(-> acc
(assoc :last-operation :remove)
(update :remove conj node))
:else
(-> acc
(dissoc :remove-level)
(update :keep conj node)
(assoc :last-operation :keep))))
(defn- remove-by-fn
"Splits given markdown ast based on f and returns a map of :keep and :remove
ast nodes. When f evaluates to true, ast node is put in :remove and otherwise
node is put in :keep. Non-heading nodes like property_drawer are placed
wherever their heading is."
[f ast]
(reduce
(fn [acc [[node-type attr] _position :as node]]
;; This assumes Heading node is the only one that sets a level.
;; There are a number of node types that belong to the previous header node
;; including Paragraph, Property_Drawer and Timestamp
(if (not= "Heading" node-type)
(if (= :keep (:last-operation acc))
(-> acc
(update :keep conj node)
(assoc :last-operation :keep))
(-> acc
(update :remove conj node)
(assoc :last-operation :remove)))
(handle-heading-node acc attr node f)))
{:keep [] :remove []}
ast))
(defn move-input-to-output [input output config f]
(let [md-ast (mldoc/file-ast input config)
{:keys [keep remove]} (remove-by-fn f md-ast)]
(if (empty? remove)
(println (util/format "%s -> %s - Did not occur as there are 0 nodes to move"
input output))
(println (util/format "%s -> %s - %s of %s nodes moved"
input output (count remove) (+ (count keep) (count remove)))))
(if (empty? keep)
(fs/rmSync input)
(fs/writeFileSync input
(string/replace
(mldoc/ast-export-markdown keep config mldoc/default-references)
#"\s+(\n|$)"
"$1")))
(when (seq remove)
(fs/writeFileSync output
(mldoc/ast-export-markdown remove config mldoc/default-references)))))
(defn -main*
[args]
(let [[input output tag] args
config (mldoc/default-config)
remove-f #(contains? (set (:title %)) ["Tag" [["Plain" tag]]])]
(if (.isDirectory (fs/lstatSync input))
(do
(when-not (fs/existsSync output) (fs/mkdirSync output))
(doseq [input-file (js->clj (fs/readdirSync input))]
(move-input-to-output (path/join input input-file)
(path/join output input-file)
config
remove-f)))
(move-input-to-output input output config remove-f))))
(defn -main
[args]
(if (not= 3 (count args))
(println "Usage: logseq-block-move IN OUT TAG\n\nMoves blocks and their children"
"tagged with TAG from IN file to OUT file.\nIf IN is a directory,"
"all files in directory have operation done and written to OUT directory.")
(-main* args)))
(when (= nbb.core/*file* (:file (meta #'-main)))
(-main *command-line-args*))