diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index f993a1c993..21db526bc3 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -1515,10 +1515,10 @@ (defn marker-switch [{:block/keys [marker] :as block}] (when (contains? #{"NOW" "LATER" "TODO" "DOING"} marker) - (let [set-marker-fn (fn [marker] + (let [set-marker-fn (fn [new-marker] (fn [e] (util/stop e) - (editor-handler/set-marker block marker))) + (editor-handler/set-marker block new-marker))) next-marker (case marker "NOW" "LATER" "LATER" "NOW" diff --git a/src/main/frontend/components/editor.cljs b/src/main/frontend/components/editor.cljs index 1315c022f6..974bbd723a 100644 --- a/src/main/frontend/components/editor.cljs +++ b/src/main/frontend/components/editor.cljs @@ -245,7 +245,7 @@ (util/stop e) (if event? (command-handler e) - (command-handler)))} + (command-handler)))} (ui/icon icon {:style {:fontSize ui/icon-size}})]]) (rum/defc mobile-bar < rum/reactive @@ -279,7 +279,7 @@ (mobile-bar-command #(mobile-camera/embed-photo parent-id) "camera") (mobile-bar-command commands/insert-youtube-timestamp "brand-youtube") (mobile-bar-command editor-handler/html-link-format! "link") - (mobile-bar-command history/undo! "rotate" true ) + (mobile-bar-command history/undo! "rotate" true) (mobile-bar-command history/redo! "rotate-clockwise" true) (mobile-bar-command #(do (viewport-fn) (commands/simple-insert! parent-id "<" {})) "code") (mobile-bar-command editor-handler/bold-format! "bold") @@ -295,7 +295,7 @@ (fn [state] (mixins/on-key-down state - { ;; enter + {;; enter 13 (fn [state e] (let [input-value (get state ::input-value) input-option (get @state/state :editor/show-input)] @@ -319,23 +319,23 @@ [:input.form-input.block.w-full.pl-2.sm:text-sm.sm:leading-5 (merge (cond-> - {:key (str "modal-input-" (name id)) - :id (str "modal-input-" (name id)) - :type (or type "text") - :on-change (fn [e] - (swap! input-value assoc id (util/evalue e))) - :auto-complete (if (util/chrome?) "chrome-off" "off")} + {:key (str "modal-input-" (name id)) + :id (str "modal-input-" (name id)) + :type (or type "text") + :on-change (fn [e] + (swap! input-value assoc id (util/evalue e))) + :auto-complete (if (util/chrome?) "chrome-off" "off")} placeholder (assoc :placeholder placeholder) autoFocus (assoc :auto-focus true)) (dissoc input-item :id))]]) (ui/button - "Submit" - :on-click - (fn [e] - (util/stop e) - (on-submit command @input-value pos)))]))))) + "Submit" + :on-click + (fn [e] + (util/stop e) + (on-submit command @input-value pos)))]))))) (rum/defc absolute-modal < rum/static [cp set-default-width? {:keys [top left rect]}] diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 8a66d1d704..0140d29ea8 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -789,21 +789,6 @@ (state/set-edit-content! input-id new-content) (save-block-if-changed! block new-content)))) -(defn set-marker - [{:block/keys [marker content format] :as block} new-marker] - (let [old-header-marker (when (not= format :org) - (re-find (marker/header-marker-pattern true marker) content)) - new-header-marker (when (not-empty old-header-marker) - (string/replace old-header-marker marker new-marker)) - marker (or old-header-marker marker) - new-marker (or new-header-marker new-marker) - new-content (-> - (if (not-empty marker) - (string/replace-first content (re-pattern (str "^" marker)) new-marker) - (str new-marker " " content)) - (string/triml))] - (save-block-if-changed! block new-content))) - (defn- rehighlight-selected-nodes ([] (rehighlight-selected-nodes (state/get-selection-blocks))) @@ -827,18 +812,24 @@ blocks) distinct))) +(defn set-marker + "The set-marker will set a new marker on the selected block. + if the `new-marker` is nil, it will generate it automatically." + ([block] + (set-marker block nil)) + ([{:block/keys [marker content format] :as block} new-marker] + (let [[new-content _] (marker/cycle-marker content marker new-marker format (state/get-preferred-workflow))] + (save-block-if-changed! block new-content)))) + (defn cycle-todos! [] (when-let [blocks (seq (get-selected-blocks-with-children))] - (let [workflow (state/get-preferred-workflow) - ids (->> (distinct (map #(when-let [id (dom/attr % "blockid")] + (let [ids (->> (distinct (map #(when-let [id (dom/attr % "blockid")] (uuid id)) blocks)) (remove nil?))] (doseq [id ids] - (let [block (db/pull [:block/uuid id]) - new-marker (marker/cycle-marker-state workflow (:block/marker block)) - new-marker (if new-marker new-marker "")] - (set-marker block new-marker))) + (let [block (db/pull [:block/uuid id])] + (set-marker block))) (js/setTimeout #(rehighlight-selected-nodes blocks) 0)))) (defn cycle-todo! @@ -852,8 +843,7 @@ content (state/get-edit-content) format (or (db/get-page-format (state/get-current-page)) (state/get-preferred-format)) - [new-content marker] (marker/cycle-marker content format (state/get-preferred-workflow)) - new-content (string/triml new-content) + [new-content marker] (marker/cycle-marker content nil nil format (state/get-preferred-workflow)) new-pos (commands/compute-pos-delta-when-change-marker content marker (cursor/pos current-input))] (state/set-edit-content! edit-input-id new-content) diff --git a/src/main/frontend/util/marker.cljs b/src/main/frontend/util/marker.cljs index e93860507a..73b0c81201 100644 --- a/src/main/frontend/util/marker.cljs +++ b/src/main/frontend/util/marker.cljs @@ -4,7 +4,7 @@ (defn marker-pattern [format] (re-pattern - (str "^" (when-not (= format :org) "(#+\\s+)?") + (str "^" (if (= format :markdown) "(#+\\s+)?" "(\\*+\\s+)?") "(NOW|LATER|TODO|DOING|DONE|WAITING|WAIT|CANCELED|CANCELLED|STARTED|IN-PROGRESS)?\\s?"))) (def bare-marker-pattern @@ -25,23 +25,11 @@ (str (subs content 0 pos) (string/replace-first (subs content pos) (marker-pattern format) - (str marker " ")))] + (str marker (if (empty? marker) "" " "))))] new-content)) -(defn header-marker-pattern - [markdown? marker] - (re-pattern (str "^" (when markdown? "#+\\s+") marker))) - -(defn replace-marker - [content markdown? old-marker new-marker] - (string/replace-first content (header-marker-pattern markdown? old-marker) - (fn [match] - (if (and markdown? (= new-marker "") (string/starts-with? match "#")) - (string/replace match (str " " old-marker) "") - (string/replace match old-marker new-marker))))) - (defn cycle-marker-state - [preferred-workflow marker] + [marker preferred-workflow] (case marker "TODO" "DOING" @@ -61,21 +49,16 @@ (if (= :now preferred-workflow) "LATER" "TODO"))) (defn cycle-marker - [content format preferred-workflow] - (let [markdown? (= :markdown format) - match-fn (fn [marker] (util/safe-re-find (header-marker-pattern markdown? marker) - content))] - (cond - (match-fn "TODO") - [(replace-marker content markdown? "TODO" "DOING") "DOING"] - (match-fn "DOING") - [(replace-marker content markdown? "DOING" "DONE") "DONE"] - (match-fn "LATER") - [(replace-marker content markdown? "LATER" "NOW") "NOW"] - (match-fn "NOW") - [(replace-marker content markdown? "NOW" "DONE") "DONE"] - (match-fn "DONE") - [(replace-marker content markdown? "DONE" "") nil] - :else - (let [marker (if (= :now preferred-workflow) "LATER" "TODO")] - [(add-or-update-marker (string/triml content) format marker) marker])))) + "The cycle-marker will cycle markers sequentially. You can find all its order in `cycle-marker-state`. + + It also accepts the specified `marker` and `new-marker`. + If you don't specify it, it will automatically find it based on `content`. + + Returns [new-content new-marker]." + [content marker new-marker format preferred-workflow] + (let [content (string/triml content) + new-marker (or new-marker + (cycle-marker-state (or marker + (last (util/safe-re-find (marker-pattern format) content))) ; Returns the last matching group (last vec) + preferred-workflow))] + [(add-or-update-marker content format new-marker) new-marker])) diff --git a/src/test/frontend/handler/editor_test.cljs b/src/test/frontend/handler/editor_test.cljs index 1e73ed3259..7acbcf76fd 100644 --- a/src/test/frontend/handler/editor_test.cljs +++ b/src/test/frontend/handler/editor_test.cljs @@ -5,7 +5,7 @@ (deftest extract-nearest-link-from-text-test (testing "Page, block and tag links" (is (= "page1" - (editor/extract-nearest-link-from-text "[[page1]] [[page2]]" 0)) + (editor/extract-nearest-link-from-text "[[page1]] [[page2]]" 0)) "Finds first page link correctly based on cursor position") (is (= "page2" @@ -23,13 +23,13 @@ (testing "Url links" (is (= "https://github.com/logseq/logseq" - (editor/extract-nearest-link-from-text - "https://github.com/logseq/logseq is #awesome :)" 0 editor/url-regex)) + (editor/extract-nearest-link-from-text + "https://github.com/logseq/logseq is #awesome :)" 0 editor/url-regex)) "Finds url correctly") (is (not= "https://github.com/logseq/logseq" - (editor/extract-nearest-link-from-text - "https://github.com/logseq/logseq is #awesome :)" 0)) + (editor/extract-nearest-link-from-text + "https://github.com/logseq/logseq is #awesome :)" 0)) "Doesn't find url if regex not passed") (is (= "https://github.com/logseq/logseq" @@ -43,22 +43,22 @@ "Finds url in org link correctly")) (defn- set-marker - [marker content format new-marker] + [marker content format] (let [actual-content (atom nil)] (with-redefs [editor/save-block-if-changed! (fn [_ content] (reset! actual-content content))] - (editor/set-marker {:block/marker marker :block/content content :block/format format} - new-marker) + (editor/set-marker {:block/marker marker :block/content content :block/format format}) @actual-content))) (deftest set-marker-org - (are [marker content new-marker expect] (= expect (set-marker marker content :org new-marker)) - "TODO" "TODO content" "DOING" "DOING content" - "TODO" "## TODO content" "DOING" "## TODO content" - "DONE" "DONE content" "" "content")) + (are [marker content expect] (= expect (set-marker marker content :org)) + "TODO" "TODO content" "DOING content" + "TODO" "** TODO content" "** DOING content" + "TODO" "## TODO content" "DOING ## TODO content" + "DONE" "DONE content" "content")) (deftest set-marker-markdown - (are [marker content new-marker expect] (= expect (set-marker marker content :markdown new-marker)) - "TODO" "TODO content" "DOING" "DOING content" - "TODO" "## TODO content" "DOING" "## DOING content" - "DONE" "DONE content" "" "content")) + (are [marker content expect] (= expect (set-marker marker content :markdown)) + "TODO" "TODO content" "DOING content" + "TODO" "## TODO content" "## DOING content" + "DONE" "DONE content" "content"))