mirror of https://github.com/logseq/logseq
enhance: hide logbook drawer when editing
parent
422c2de99d
commit
3a98f92dff
|
@ -48,6 +48,7 @@
|
|||
[frontend.util :as util]
|
||||
[frontend.util.clock :as clock]
|
||||
[frontend.util.property :as property]
|
||||
[frontend.util.drawer :as drawer]
|
||||
[goog.dom :as gdom]
|
||||
[goog.object :as gobj]
|
||||
[lambdaisland.glogi :as log]
|
||||
|
@ -1713,8 +1714,9 @@
|
|||
(editor-handler/unhighlight-blocks!)
|
||||
(let [block (or (db/pull [:block/uuid (:block/uuid block)]) block)
|
||||
f #(let [cursor-range (util/caret-range (gdom/getElement block-id))
|
||||
content (property/remove-built-in-properties (:block/format block)
|
||||
content)]
|
||||
content (-> (property/remove-built-in-properties (:block/format block)
|
||||
content)
|
||||
(drawer/remove-logbook))]
|
||||
;; save current editing block
|
||||
(let [{:keys [value] :as state} (editor-handler/get-state)]
|
||||
(editor-handler/save-block! state value))
|
||||
|
@ -2391,7 +2393,7 @@
|
|||
|
||||
:else
|
||||
[:div.text-sm.mt-2.ml-2.font-medium.opacity-50 "Empty"])]
|
||||
collapsed?))]))))
|
||||
{:default-collapsed? collapsed?}))]))))
|
||||
|
||||
(defn admonition
|
||||
[config type options result]
|
||||
|
@ -2463,7 +2465,8 @@
|
|||
[:div (apply str lines)
|
||||
[:div.opacity-50.font-medium {:style {:width 95}}
|
||||
":END:"]]
|
||||
true)]]]
|
||||
{:default-collapsed? true
|
||||
:title-trigger? true})]]]
|
||||
|
||||
["Properties" m]
|
||||
[:div.properties
|
||||
|
@ -2746,7 +2749,8 @@
|
|||
(block-parents config (state/get-current-repo) (:block/uuid block)
|
||||
(:block/format block)
|
||||
false)])
|
||||
(blocks-container blocks (assoc config :breadcrumb-show? false))])))])))]
|
||||
(blocks-container blocks (assoc config :breadcrumb-show? false))]))
|
||||
{})])))]
|
||||
|
||||
(and (:group-by-page? config)
|
||||
(vector? (first blocks)))
|
||||
|
@ -2762,7 +2766,8 @@
|
|||
[:div
|
||||
(page-cp config page)
|
||||
(when alias? [:span.text-sm.font-medium.opacity-50 " Alias"])]
|
||||
(blocks-container blocks config))])))]
|
||||
(blocks-container blocks config)
|
||||
{})])))]
|
||||
|
||||
:else
|
||||
(blocks-container blocks config))])
|
||||
|
|
|
@ -44,4 +44,4 @@
|
|||
{}
|
||||
page))))
|
||||
(interpose [:span.mx-2.opacity-30 "/"]))])]
|
||||
true)])))
|
||||
{:default-collapsed? true})])))
|
||||
|
|
|
@ -74,7 +74,9 @@
|
|||
[:h1.title
|
||||
(util/capitalize-all title)]]
|
||||
|
||||
(blocks-cp repo page format))
|
||||
(blocks-cp repo page format)
|
||||
|
||||
{})
|
||||
|
||||
(when intro? (widgets/add-graph))
|
||||
|
||||
|
|
|
@ -276,7 +276,8 @@
|
|||
(for [[original-name name] pages]
|
||||
[:li {:key (str "tagged-page-" name)}
|
||||
[:a {:href (rfe/href :page {:name name})}
|
||||
original-name]])] false)]])))
|
||||
original-name]])]
|
||||
{:default-collapsed? false})]])))
|
||||
|
||||
(defn page-menu
|
||||
[repo t page page-name page-original-name title journal? public? developer-mode?]
|
||||
|
|
|
@ -122,7 +122,8 @@
|
|||
:editor-box editor/box}
|
||||
{})]
|
||||
(content/content page-name
|
||||
{:hiccup ref-hiccup}))]))
|
||||
{:hiccup ref-hiccup}))]
|
||||
{}))
|
||||
|
||||
(when (or (> n-ref 0)
|
||||
(seq filter-state))
|
||||
|
@ -150,7 +151,9 @@
|
|||
:filters filters}
|
||||
{})]
|
||||
(content/content page-name
|
||||
{:hiccup ref-hiccup}))]))]]))))
|
||||
{:hiccup ref-hiccup}))]
|
||||
|
||||
{}))]]))))
|
||||
|
||||
(rum/defcs unlinked-references-aux
|
||||
< rum/reactive db-mixins/query
|
||||
|
@ -191,4 +194,4 @@
|
|||
"s"))
|
||||
"Unlinked References")]
|
||||
(fn [] (unlinked-references-aux page-name n-ref))
|
||||
true)]]))))
|
||||
{:default-collapsed? true})]]))))
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[frontend.db.query-react :as react]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.property :as property]
|
||||
[frontend.util.drawer :as drawer]
|
||||
[frontend.util.persist-var :as persist-var]
|
||||
[frontend.db :as db]
|
||||
[frontend.state :as state]
|
||||
|
@ -635,7 +636,8 @@
|
|||
[block-id]
|
||||
(when-let [block (db/entity [:block/uuid block-id])]
|
||||
(when-let [content (:block/content block)]
|
||||
(let [content (property/remove-built-in-properties (:block/format block) content)]
|
||||
(let [content (-> (property/remove-built-in-properties (:block/format block) content)
|
||||
(drawer/remove-logbook))]
|
||||
(editor-handler/save-block!
|
||||
(state/get-current-repo)
|
||||
block-id
|
||||
|
|
|
@ -228,8 +228,9 @@
|
|||
|
||||
:else
|
||||
(subs content 0 pos))
|
||||
content (property/remove-built-in-properties (:block/format block)
|
||||
content)]
|
||||
content (-> (property/remove-built-in-properties (:block/format block)
|
||||
content)
|
||||
(drawer/remove-logbook))]
|
||||
(clear-selection!)
|
||||
(state/set-editing! edit-input-id content block text-range move-cursor?))))))
|
||||
|
||||
|
@ -289,6 +290,47 @@
|
|||
(= :block/uuid (first x))
|
||||
(nil? (db/entity x)))) refs))
|
||||
|
||||
(defn- with-marker-time
|
||||
[content block format new-marker old-marker]
|
||||
(if (and (state/enable-timetracking?) new-marker)
|
||||
(try
|
||||
(let [logbook-exists? (and (:block/body block) (drawer/get-logbook (:block/body block)))
|
||||
new-marker (string/trim (string/lower-case (name new-marker)))
|
||||
old-marker (when old-marker (string/trim (string/lower-case (name old-marker))))
|
||||
new-content (cond
|
||||
(or (and (nil? old-marker) (or (= new-marker "doing")
|
||||
(= new-marker "now")))
|
||||
(and (= old-marker "todo") (= new-marker "doing"))
|
||||
(and (= old-marker "later") (= new-marker "now"))
|
||||
(and (= old-marker new-marker "now") (not logbook-exists?))
|
||||
(and (= old-marker new-marker "doing") (not logbook-exists?)))
|
||||
(clock/clock-in format content)
|
||||
|
||||
(or
|
||||
(and (= old-marker "doing") (= new-marker "todo"))
|
||||
(and (= old-marker "now") (= new-marker "later"))
|
||||
(and (contains? #{"now" "doing"} old-marker)
|
||||
(= new-marker "done")))
|
||||
(clock/clock-out format content)
|
||||
|
||||
:else
|
||||
content)]
|
||||
new-content)
|
||||
(catch js/Error _e
|
||||
content))
|
||||
content))
|
||||
|
||||
(defn- with-timetracking
|
||||
[block value]
|
||||
(if (and (state/enable-timetracking?)
|
||||
(not= (:block/content block) value))
|
||||
(let [new-marker (first (util/safe-re-find marker/bare-marker-pattern (or value "")))
|
||||
new-value (with-marker-time value block (:block/format block)
|
||||
new-marker
|
||||
(:block/marker block))]
|
||||
new-value)
|
||||
value))
|
||||
|
||||
(defn wrap-parse-block
|
||||
[{:block/keys [content format parent left page uuid pre-block? level] :as block}]
|
||||
(let [block (or (and (:db/id block) (db/pull (:db/id block))) block)
|
||||
|
@ -297,6 +339,8 @@
|
|||
content (if (and (seq properties) real-content (not= real-content content))
|
||||
(property/with-built-in-properties properties content format)
|
||||
content)
|
||||
content (drawer/with-logbook block content)
|
||||
content (with-timetracking block content)
|
||||
first-block? (= left page)
|
||||
ast (mldoc/->edn (string/trim content) (mldoc/default-config format))
|
||||
first-elem-type (first (ffirst ast))
|
||||
|
@ -373,7 +417,8 @@
|
|||
format (or format (state/get-preferred-format))
|
||||
page (db/entity repo (:db/id page))
|
||||
block-id (when (map? properties) (get properties :id))
|
||||
content (property/remove-built-in-properties format content)]
|
||||
content (-> (property/remove-built-in-properties format content)
|
||||
(drawer/remove-logbook))]
|
||||
(cond
|
||||
(another-block-with-same-id-exists? uuid block-id)
|
||||
(notification/show!
|
||||
|
@ -577,46 +622,6 @@
|
|||
:value value
|
||||
:pos pos}))))
|
||||
|
||||
(defn- with-marker-time
|
||||
[content block format new-marker old-marker]
|
||||
(if (and (state/enable-timetracking?) new-marker)
|
||||
(try
|
||||
(let [logbook-exists? (and (:block/body block) (clock/get-logbook (:block/body block)))
|
||||
new-marker (string/trim (string/lower-case (name new-marker)))
|
||||
old-marker (when old-marker (string/trim (string/lower-case (name old-marker))))
|
||||
new-content (cond
|
||||
(or (and (nil? old-marker) (or (= new-marker "doing")
|
||||
(= new-marker "now")))
|
||||
(and (= old-marker "todo") (= new-marker "doing"))
|
||||
(and (= old-marker "later") (= new-marker "now"))
|
||||
(and (= old-marker new-marker "now") (not logbook-exists?))
|
||||
(and (= old-marker new-marker "doing") (not logbook-exists?)))
|
||||
(clock/clock-in format content)
|
||||
|
||||
(or
|
||||
(and (= old-marker "doing") (= new-marker "todo"))
|
||||
(and (= old-marker "now") (= new-marker "later"))
|
||||
(and (contains? #{"now" "doing"} old-marker)
|
||||
(= new-marker "done")))
|
||||
(clock/clock-out format content)
|
||||
|
||||
:else
|
||||
content)]
|
||||
new-content)
|
||||
(catch js/Error _e
|
||||
content))
|
||||
content))
|
||||
|
||||
(defn- with-timetracking
|
||||
[block value]
|
||||
(if (state/enable-timetracking?)
|
||||
(let [new-marker (first (util/safe-re-find marker/bare-marker-pattern (or value "")))
|
||||
new-value (with-marker-time value block (:block/format block)
|
||||
new-marker
|
||||
(:block/marker block))]
|
||||
new-value)
|
||||
value))
|
||||
|
||||
(defn insert-new-block!
|
||||
([state]
|
||||
(insert-new-block! state nil))
|
||||
|
@ -631,7 +636,6 @@
|
|||
block (or (db/pull [:block/uuid block-id])
|
||||
block)
|
||||
repo (or (:block/repo block) (state/get-current-repo))
|
||||
value (with-timetracking block value)
|
||||
block-self? (block-self-alone-when-insert? config block-id)
|
||||
input (gdom/getElement (state/get-edit-input-id))
|
||||
pos (cursor/pos input)
|
||||
|
@ -877,7 +881,9 @@
|
|||
(when-let [sibling-block-id (dom/attr sibling-block "blockid")]
|
||||
(when-let [block (db/pull repo '[*] [:block/uuid (uuid sibling-block-id)])]
|
||||
(let [original-content (util/trim-safe (:block/content block))
|
||||
new-value (str (property/remove-built-in-properties format original-content) " " (string/triml value))
|
||||
value' (-> (property/remove-built-in-properties format original-content)
|
||||
(drawer/remove-logbook))
|
||||
new-value (str value' " " (string/triml value))
|
||||
tail-len (count (string/triml value))
|
||||
pos (max
|
||||
(if original-content
|
||||
|
@ -1296,8 +1302,7 @@
|
|||
|
||||
(defn save-block-aux!
|
||||
[block value format opts]
|
||||
(let [value (string/trim value)
|
||||
value (with-timetracking block value)]
|
||||
(let [value (string/trim value)]
|
||||
;; FIXME: somehow frontend.components.editor's will-unmount event will loop forever
|
||||
;; maybe we shouldn't save the block/file in "will-unmount" event?
|
||||
(save-block-if-changed! block value
|
||||
|
@ -1356,6 +1361,7 @@
|
|||
(defn- clean-content!
|
||||
[format content]
|
||||
(->> (text/remove-level-spaces content format)
|
||||
(drawer/remove-logbook)
|
||||
(property/remove-properties format)
|
||||
string/trim))
|
||||
|
||||
|
@ -3146,7 +3152,8 @@
|
|||
(when-let [block (db/pull [:block/uuid (uuid block-ref-id)])]
|
||||
(let [block-content (:block/content block)
|
||||
format (or (:block/format block) :markdown)
|
||||
block-content-without-prop (property/remove-properties format block-content)]
|
||||
block-content-without-prop (-> (property/remove-properties format block-content)
|
||||
(drawer/remove-logbook))]
|
||||
(when-let [input (state/get-input)]
|
||||
(when-let [current-block-content (gobj/get input "value")]
|
||||
(let [block-content* (str (subs current-block-content 0 start)
|
||||
|
@ -3185,7 +3192,8 @@
|
|||
ref-block (db/entity [:block/uuid ref-id])
|
||||
block-ref-content (->> (or (:block/content ref-block)
|
||||
"")
|
||||
(property/remove-built-in-properties (:block/format ref-block)))
|
||||
(property/remove-built-in-properties (:block/format ref-block))
|
||||
(drawer/remove-logbook))
|
||||
content (string/replace-first (:block/content block) match
|
||||
block-ref-content)]
|
||||
(save-block! (state/get-current-repo)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
(:refer-clojure :exclude [empty?])
|
||||
(:require [frontend.text :as text]
|
||||
[frontend.util.property :as property]
|
||||
[frontend.util.drawer :as drawer]
|
||||
[frontend.db :as db]
|
||||
[frontend.state :as state]
|
||||
[cljs-bean.core :as bean]
|
||||
|
@ -17,7 +18,7 @@
|
|||
(defn block->index
|
||||
[{:block/keys [uuid content format page] :as block}]
|
||||
(when-let [result (->> (text/remove-level-spaces content format)
|
||||
(property/remove-built-in-properties format))]
|
||||
(drawer/remove-logbook))]
|
||||
{:id (:db/id block)
|
||||
:uuid (str uuid)
|
||||
:page page
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
(state/set-editor-in-composition! true))))
|
||||
props (assoc props
|
||||
:on-change (fn [e] (when-not (state/editor-in-composition?)
|
||||
(on-change e)))
|
||||
(on-change e)))
|
||||
:on-composition-start on-composition
|
||||
:on-composition-update on-composition
|
||||
:on-composition-end on-composition)]
|
||||
|
@ -103,8 +103,8 @@
|
|||
child [:div
|
||||
{:style {:display "flex" :flex-direction "row"}}
|
||||
[:div {:style {:margin-right "8px"}} title]
|
||||
;; [:div {:style {:position "absolute" :right "8px"}}
|
||||
;; icon]
|
||||
;; [:div {:style {:position "absolute" :right "8px"}}
|
||||
;; icon]
|
||||
]]
|
||||
(rum/with-key
|
||||
(menu-link new-options child)
|
||||
|
@ -213,7 +213,7 @@
|
|||
:key (name k)}
|
||||
(fn [state]
|
||||
(notification-content state (:content v) (:status v) k)))))
|
||||
contents)))))
|
||||
contents)))))
|
||||
|
||||
(defn checkbox
|
||||
[option]
|
||||
|
@ -312,7 +312,7 @@
|
|||
keydown-handler (partial handle-global-keystroke true)
|
||||
keyup-handler (partial handle-global-keystroke false)
|
||||
clear-all #(do (set-global-active-keystroke "")
|
||||
(reset! active-keystroke #{}))]
|
||||
(reset! active-keystroke #{}))]
|
||||
(.addEventListener js/window "keydown" keydown-handler)
|
||||
(.addEventListener js/window "keyup" keyup-handler)
|
||||
(.addEventListener js/window "blur" clear-all)
|
||||
|
@ -382,15 +382,15 @@
|
|||
[:div {:key idx}
|
||||
(let [chosen? (= @current-idx idx)]
|
||||
(menu-link
|
||||
{:id (str "ac-" idx)
|
||||
:class (when chosen? "chosen")
|
||||
:on-mouse-enter #(reset! current-idx idx)
|
||||
:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(if (and (gobj/get e "shiftKey") on-shift-chosen)
|
||||
(on-shift-chosen item)
|
||||
(on-chosen item)))}
|
||||
(if item-render (item-render item chosen?) item)))]]
|
||||
{:id (str "ac-" idx)
|
||||
:class (when chosen? "chosen")
|
||||
:on-mouse-enter #(reset! current-idx idx)
|
||||
:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(if (and (gobj/get e "shiftKey") on-shift-chosen)
|
||||
(on-shift-chosen item)
|
||||
(on-chosen item)))}
|
||||
(if item-render (item-render item chosen?) item)))]]
|
||||
|
||||
(if get-group-name
|
||||
(if-let [group-name (get-group-name item)]
|
||||
|
@ -421,13 +421,13 @@
|
|||
(defn keyboard-shortcut [sequence]
|
||||
[:div.keyboard-shortcut
|
||||
(map-indexed (fn [i key]
|
||||
[:code {:key i}
|
||||
;; Display "cmd" rather than "meta" to the user to describe the Mac
|
||||
;; mod key, because that's what the Mac keyboards actually say.
|
||||
(if (or (= :meta key) (= "meta" key))
|
||||
(util/meta-key-name)
|
||||
(name key))])
|
||||
sequence)])
|
||||
[:code {:key i}
|
||||
;; Display "cmd" rather than "meta" to the user to describe the Mac
|
||||
;; mod key, because that's what the Mac keyboards actually say.
|
||||
(if (or (= :meta key) (= "meta" key))
|
||||
(util/meta-key-name)
|
||||
(name key))])
|
||||
sequence)])
|
||||
|
||||
(defonce modal-show? (atom false))
|
||||
(rum/defc modal-overlay
|
||||
|
@ -577,21 +577,28 @@
|
|||
(when (true? (last args))
|
||||
(reset! (get state ::collapsed?) true)))
|
||||
state)}
|
||||
[state header content default-collapsed?]
|
||||
[state header content {:keys [default-collapsed? title-trigger?]}]
|
||||
(let [control? (get state ::control?)
|
||||
collapsed? (get state ::collapsed?)]
|
||||
collapsed? (get state ::collapsed?)
|
||||
on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(swap! collapsed? not))]
|
||||
[:div.flex.flex-col
|
||||
[:div.content
|
||||
[:div.flex-1.flex-row.foldable-title {:on-mouse-over #(reset! control? true)
|
||||
:on-mouse-out #(reset! control? false)}
|
||||
[:div.flex-1.flex-row.foldable-title (cond->
|
||||
{:on-mouse-over #(reset! control? true)
|
||||
:on-mouse-out #(reset! control? false)}
|
||||
title-trigger?
|
||||
(assoc :on-mouse-down on-mouse-down
|
||||
:class "cursor"))
|
||||
[:div.flex.flex-row.items-center
|
||||
[:a.block-control.opacity-50.hover:opacity-100.mr-2
|
||||
{:style {:width 14
|
||||
:height 16
|
||||
:margin-left -24}
|
||||
:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(swap! collapsed? not))}
|
||||
(cond->
|
||||
{:style {:width 14
|
||||
:height 16
|
||||
:margin-left -24}}
|
||||
(not title-trigger?)
|
||||
(assoc :on-mouse-down on-mouse-down))
|
||||
[:span {:class (if @control? "control-show" "control-hide")}
|
||||
(rotating-arrow @collapsed?)]]
|
||||
(if (fn? header)
|
||||
|
@ -642,8 +649,8 @@
|
|||
(on-change value)))}
|
||||
(for [{:keys [label value selected]} options]
|
||||
[:option (cond->
|
||||
{:key label
|
||||
:value (or value label)}
|
||||
{:key label
|
||||
:value (or value label)}
|
||||
selected
|
||||
(assoc :selected selected))
|
||||
label])])
|
||||
|
@ -674,10 +681,10 @@
|
|||
(assoc :html (if (or open? mounted?)
|
||||
(try
|
||||
(when-let [html (:html opts)]
|
||||
(if (fn? html)
|
||||
(html)
|
||||
[:div.pr-3.py-1
|
||||
html]))
|
||||
(if (fn? html)
|
||||
(html)
|
||||
[:div.pr-3.py-1
|
||||
html]))
|
||||
(catch js/Error e
|
||||
(log/error :exception e)
|
||||
[:div]))
|
||||
|
@ -700,7 +707,7 @@
|
|||
(let [*loading? (:loading? state)]
|
||||
[:div [(when @*loading? [:span.flex.items-center [svg/loading " ... loading"]])
|
||||
(ReactTweetEmbed
|
||||
{:id id
|
||||
:class "contents"
|
||||
:options {:theme (when (= (state/sub :ui/theme) "dark") "dark")}
|
||||
:on-tweet-load-success #(reset! *loading? false)})]]))
|
||||
{:id id
|
||||
:class "contents"
|
||||
:options {:theme (when (= (state/sub :ui/theme) "dark") "dark")}
|
||||
:on-tweet-load-success #(reset! *loading? false)})]]))
|
||||
|
|
|
@ -48,16 +48,9 @@
|
|||
(str clock-out-log "\n"))))
|
||||
content))
|
||||
|
||||
(defn get-logbook
|
||||
[body]
|
||||
(-> (filter (fn [v] (and (vector? v)
|
||||
(= (first v) "Drawer")
|
||||
(= (second v) "logbook"))) body)
|
||||
first))
|
||||
|
||||
(defn clock-summary
|
||||
[body string?]
|
||||
(when-let [logbook (get-logbook body)]
|
||||
(when-let [logbook (drawer/get-logbook body)]
|
||||
(when-let [clock-lines (last logbook)]
|
||||
(let [times (map #(string/trim (last (string/split % "=>"))) clock-lines)
|
||||
hours (map #(int (first (string/split % ":"))) times)
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
[typ]
|
||||
(util/format ":%s:" (string/upper-case typ)))
|
||||
|
||||
(defonce drawer-end ":end:")
|
||||
(defonce drawer-end ":END:")
|
||||
|
||||
(defonce logbook-start ":LOGBOOK:")
|
||||
|
||||
(defn build-drawer-str
|
||||
([typ]
|
||||
|
@ -22,7 +24,7 @@
|
|||
[format content typ]
|
||||
(let [ast (mldoc/->edn content (mldoc/default-config format))
|
||||
typ-drawer (ffirst (filter (fn [x]
|
||||
(mldoc/typ-drawer? x typ)) ast))]
|
||||
(mldoc/typ-drawer? x typ)) ast))]
|
||||
typ-drawer))
|
||||
|
||||
(defn insert-drawer
|
||||
|
@ -30,45 +32,101 @@
|
|||
(when (string? content)
|
||||
(try
|
||||
(let [ast (mldoc/->edn content (mldoc/default-config format))
|
||||
has-properties? (some (fn [x] (mldoc/properties? x)) ast)
|
||||
has-typ-drawer? (some (fn [x] (mldoc/typ-drawer? x typ)) ast)
|
||||
lines (string/split-lines content)
|
||||
title (first lines)
|
||||
body (string/join "\n" (rest lines))
|
||||
start-idx (.indexOf lines (drawer-start typ))
|
||||
end-idx (let [[before after] (split-at start-idx lines)]
|
||||
(+ (count before) (.indexOf after drawer-end)))
|
||||
result (cond
|
||||
(not has-typ-drawer?)
|
||||
(let [drawer (build-drawer-str typ value)]
|
||||
(if has-properties?
|
||||
(cond
|
||||
(= :org format)
|
||||
(let [prop-start-idx (.indexOf lines property/properties-start)
|
||||
prop-end-idx (.indexOf lines property/properties-end)
|
||||
properties (subvec lines prop-start-idx (inc prop-end-idx))
|
||||
after (subvec lines (inc prop-end-idx))]
|
||||
(string/join "\n" (concat [title] properties [drawer] after)))
|
||||
has-properties? (some (fn [x] (mldoc/properties? x)) ast)
|
||||
has-typ-drawer? (some (fn [x] (mldoc/typ-drawer? x typ)) ast)
|
||||
lines (string/split-lines content)
|
||||
title (first lines)
|
||||
body (string/join "\n" (rest lines))
|
||||
start-idx (.indexOf lines (drawer-start typ))
|
||||
end-idx (let [[before after] (split-at start-idx lines)]
|
||||
(+ (count before) (.indexOf after drawer-end)))
|
||||
result (cond
|
||||
(not has-typ-drawer?)
|
||||
(let [drawer (build-drawer-str typ value)]
|
||||
(if has-properties?
|
||||
(cond
|
||||
(= :org format)
|
||||
(let [prop-start-idx (.indexOf lines property/properties-start)
|
||||
prop-end-idx (.indexOf lines property/properties-end)
|
||||
properties (subvec lines prop-start-idx (inc prop-end-idx))
|
||||
after (subvec lines (inc prop-end-idx))]
|
||||
(string/join "\n" (concat [title] properties [drawer] after)))
|
||||
|
||||
:else
|
||||
(let [properties-count (count (second (first (second ast))))
|
||||
before (subvec lines 0 (inc properties-count))
|
||||
after (rest lines)]
|
||||
(string/join "\n" (concat before [drawer] after))))
|
||||
(str title "\n" drawer body)))
|
||||
:else
|
||||
(let [properties-count (count (second (first (second ast))))
|
||||
before (subvec lines 0 (inc properties-count))
|
||||
after (rest lines)]
|
||||
(string/join "\n" (concat before [drawer] after))))
|
||||
(str title "\n" drawer body)))
|
||||
|
||||
(and has-typ-drawer?
|
||||
(>= start-idx 0) (> end-idx 0) (> end-idx start-idx))
|
||||
(let [before (subvec lines 0 start-idx)
|
||||
middle (conj
|
||||
(subvec lines (inc start-idx) end-idx)
|
||||
value)
|
||||
after (subvec lines (inc end-idx))
|
||||
lines (concat before [(drawer-start typ)] middle [drawer-end] after)]
|
||||
(string/join "\n" lines))
|
||||
:else
|
||||
content)]
|
||||
(and has-typ-drawer?
|
||||
(>= start-idx 0) (> end-idx 0) (> end-idx start-idx))
|
||||
(let [before (subvec lines 0 start-idx)
|
||||
middle (conj
|
||||
(subvec lines (inc start-idx) end-idx)
|
||||
value)
|
||||
after (subvec lines (inc end-idx))
|
||||
lines (concat before [(drawer-start typ)] middle [drawer-end] after)]
|
||||
(string/join "\n" lines))
|
||||
:else
|
||||
content)]
|
||||
(string/trimr result))
|
||||
(catch js/Error e
|
||||
(js/console.error e)
|
||||
content))))
|
||||
|
||||
(defn contains-logbook?
|
||||
[content]
|
||||
(and (util/safe-re-find (re-pattern (str "(?i)" logbook-start)) content)
|
||||
(util/safe-re-find (re-pattern (str "(?i)" drawer-end)) content)))
|
||||
|
||||
;; TODO: DRY
|
||||
(defn remove-logbook
|
||||
[content]
|
||||
(if (contains-logbook? content)
|
||||
(let [lines (string/split-lines content)
|
||||
[title-lines body] (split-with (fn [l]
|
||||
(not (string/starts-with? (string/upper-case (string/triml l)) ":LOGBOOK:")))
|
||||
lines)
|
||||
body (drop-while (fn [l]
|
||||
(let [l' (string/lower-case (string/trim l))]
|
||||
(or
|
||||
(not (string/starts-with? l' ":end:"))
|
||||
(string/blank? l))))
|
||||
body)
|
||||
body (if (and (seq body)
|
||||
(string/starts-with? (string/lower-case (string/triml (first body))) ":end:"))
|
||||
(let [line (string/replace (first body) #"(?i):end:\s?" "")]
|
||||
(if (string/blank? line)
|
||||
(rest body)
|
||||
(cons line (rest body))))
|
||||
body)]
|
||||
(->> (concat title-lines body)
|
||||
(string/join "\n")))
|
||||
content))
|
||||
|
||||
(defn get-logbook
|
||||
[body]
|
||||
(-> (filter (fn [v] (and (vector? v)
|
||||
(= (first v) "Drawer")
|
||||
(= (second v) "logbook"))) body)
|
||||
first))
|
||||
|
||||
(defn with-logbook
|
||||
[block content]
|
||||
(let [body (:block/body block)
|
||||
logbook (get-logbook body)]
|
||||
(if logbook
|
||||
(let [clocks (last logbook)
|
||||
logbook (->> (concat [":LOGBOOK:"] clocks [":END:"])
|
||||
(remove string/blank?)
|
||||
(string/join "\n"))
|
||||
lines (string/split-lines content)]
|
||||
(if (:block/title block)
|
||||
(str (first lines)
|
||||
"\n"
|
||||
logbook
|
||||
"\n"
|
||||
(string/join "\n" (rest lines)))
|
||||
content))
|
||||
content)))
|
||||
|
|
Loading…
Reference in New Issue