mirror of https://github.com/logseq/logseq
refactor: unify heading UX for both markdown and org mode
parent
9c7b4ea201
commit
8b144269f7
|
@ -62,9 +62,6 @@
|
|||
;; first block that's not a heading or unordered list
|
||||
:block/pre-block? {}
|
||||
|
||||
;; heading's level (the block must be a heading)
|
||||
:block/heading-level {}
|
||||
|
||||
;; scheduled day
|
||||
:block/scheduled {}
|
||||
|
||||
|
@ -116,7 +113,6 @@
|
|||
:block/deadline
|
||||
:block/repeated?
|
||||
:block/pre-block?
|
||||
:block/heading-level
|
||||
:block/type
|
||||
:block/properties
|
||||
:block/properties-order
|
||||
|
|
|
@ -541,6 +541,16 @@
|
|||
blocks)]
|
||||
(with-path-refs blocks)))
|
||||
|
||||
(defn- with-heading-property
|
||||
[properties markdown-heading? size]
|
||||
(let [properties (if markdown-heading?
|
||||
(assoc properties :heading size)
|
||||
properties)]
|
||||
(if (true? (:heading properties))
|
||||
;; default-level 2
|
||||
(assoc properties :heading 2)
|
||||
properties)))
|
||||
|
||||
(defn- construct-block
|
||||
[block properties timestamps body encoded-content format pos-meta with-id? {:keys [block-pattern supported-formats db date-formatter]}]
|
||||
(let [id (get-custom-id-or-new-id properties)
|
||||
|
@ -551,18 +561,17 @@
|
|||
markdown-heading? (and (:size block) (= :markdown format))
|
||||
block (if markdown-heading?
|
||||
(assoc block
|
||||
:type :heading
|
||||
:level (if unordered? (:level block) 1)
|
||||
:heading-level (or (:size block) 6))
|
||||
:level (if unordered? (:level block) 1))
|
||||
block)
|
||||
block (cond->
|
||||
(assoc block
|
||||
:uuid id
|
||||
:refs ref-pages-in-properties
|
||||
:format format
|
||||
:meta pos-meta)
|
||||
(seq (:properties properties))
|
||||
(assoc :properties (:properties properties)
|
||||
(-> (assoc block
|
||||
:uuid id
|
||||
:refs ref-pages-in-properties
|
||||
:format format
|
||||
:meta pos-meta)
|
||||
(dissoc :size))
|
||||
(or (seq (:properties properties)) markdown-heading?)
|
||||
(assoc :properties (with-heading-property (:properties properties) markdown-heading? (:size block))
|
||||
:properties-text-values (:properties-text-values properties)
|
||||
:properties-order (vec (:properties-order properties)))
|
||||
|
||||
|
|
|
@ -115,10 +115,9 @@
|
|||
:block/priority 4
|
||||
:block/deadline 1
|
||||
:block/collapsed? 22
|
||||
:block/heading-level 60
|
||||
:block/repeated? 1}
|
||||
(->> [:block/scheduled :block/priority :block/deadline :block/collapsed?
|
||||
:block/heading-level :block/repeated?]
|
||||
:block/repeated?]
|
||||
(map (fn [attr]
|
||||
[attr
|
||||
(ffirst (d/q [:find (list 'count '?b) :where ['?b attr]]
|
||||
|
|
|
@ -132,13 +132,11 @@
|
|||
[:editor/set-heading heading]
|
||||
[:editor/move-cursor-to-end]])
|
||||
|
||||
(defn- markdown-headings
|
||||
(defn- headings
|
||||
[]
|
||||
(let [format (state/get-preferred-format)]
|
||||
(when (= (name format) "markdown")
|
||||
(mapv (fn [level]
|
||||
(let [heading (str "h" level)]
|
||||
[heading (->heading (apply str (repeat level "#")))])) (range 1 7)))))
|
||||
(mapv (fn [level]
|
||||
(let [heading (str "h" level)]
|
||||
[heading (->heading level)])) (range 1 7)))
|
||||
|
||||
(defonce *matched-commands (atom nil))
|
||||
(defonce *initial-commands (atom nil))
|
||||
|
@ -241,7 +239,7 @@
|
|||
;; ["Upload an image" [[:editor/click-hidden-file-input :id]]]
|
||||
)]
|
||||
|
||||
(markdown-headings)
|
||||
(headings)
|
||||
|
||||
;; time & date
|
||||
|
||||
|
@ -593,19 +591,33 @@
|
|||
(property/goto-properties-end format current-input)
|
||||
(cursor/move-cursor-backward current-input 3)))))
|
||||
|
||||
(defonce markdown-heading-pattern #"^#+\s+")
|
||||
(defn set-markdown-heading
|
||||
[content heading]
|
||||
(let [heading-str (apply str (repeat heading "#"))]
|
||||
(if (util/safe-re-find markdown-heading-pattern content)
|
||||
(string/replace-first content
|
||||
markdown-heading-pattern
|
||||
(str heading-str " "))
|
||||
(str heading-str " " (string/triml content)))))
|
||||
|
||||
(defn clear-markdown-heading
|
||||
[content]
|
||||
[:pre (string? content)]
|
||||
(string/replace-first content
|
||||
markdown-heading-pattern
|
||||
""))
|
||||
|
||||
(defmethod handle-step :editor/set-heading [[_ heading]]
|
||||
(when-let [input-id (state/get-edit-input-id)]
|
||||
(when-let [current-input (gdom/getElement input-id)]
|
||||
(let [edit-content (gobj/get current-input "value")
|
||||
heading-pattern #"^#+\s+"
|
||||
new-value (cond
|
||||
(util/safe-re-find heading-pattern edit-content)
|
||||
(string/replace-first edit-content
|
||||
heading-pattern
|
||||
(str heading " "))
|
||||
:else
|
||||
(str heading " " (string/triml edit-content)))]
|
||||
(state/set-edit-content! input-id new-value)))))
|
||||
(let [current-block (state/get-edit-block)
|
||||
format (:block/format current-block)]
|
||||
(if (= format :markdown)
|
||||
(let [edit-content (gobj/get current-input "value")
|
||||
new-content (set-markdown-heading edit-content heading)]
|
||||
(state/set-edit-content! input-id new-content))
|
||||
(state/pub-event! [:editor/set-org-mode-heading current-block heading]))))))
|
||||
|
||||
(defmethod handle-step :editor/search-page [[_]]
|
||||
(state/set-editor-action! :page-search))
|
||||
|
|
|
@ -1839,7 +1839,7 @@
|
|||
(declare block-content)
|
||||
|
||||
(defn build-block-title
|
||||
[config {:block/keys [title marker pre-block? properties level heading-level]
|
||||
[config {:block/keys [title marker pre-block? properties]
|
||||
:as t}]
|
||||
(let [config (assoc config :block t)
|
||||
slide? (boolean (:slide? config))
|
||||
|
@ -1856,14 +1856,9 @@
|
|||
priority (priority-cp t)
|
||||
tags (block-tags-cp t)
|
||||
bg-color (:background-color properties)
|
||||
heading-level (or (and heading-level
|
||||
(<= heading-level 6)
|
||||
heading-level)
|
||||
(and (get properties :heading)
|
||||
(<= level 6)
|
||||
level))
|
||||
elem (if heading-level
|
||||
(keyword (str "h" heading-level
|
||||
heading (:heading properties)
|
||||
elem (if heading
|
||||
(keyword (str "h" heading
|
||||
(when block-ref? ".inline")))
|
||||
:span.inline)]
|
||||
(->elem
|
||||
|
@ -2289,7 +2284,7 @@
|
|||
|
||||
(rum/defcs block-content-or-editor < rum/reactive
|
||||
(rum/local true ::hide-block-refs?)
|
||||
[state config {:block/keys [uuid format] :as block} edit-input-id block-id heading-level edit?]
|
||||
[state config {:block/keys [uuid format] :as block} edit-input-id block-id edit?]
|
||||
(let [*hide-block-refs? (get state ::hide-block-refs?)
|
||||
hide-block-refs? @*hide-block-refs?
|
||||
editor-box (get config :editor-box)
|
||||
|
@ -2307,7 +2302,6 @@
|
|||
:block-id uuid
|
||||
:block-parent-id block-id
|
||||
:format format
|
||||
:heading-level heading-level
|
||||
:on-hide (fn [value event]
|
||||
(when (= event :esc)
|
||||
(editor-handler/save-block! (editor-handler/get-state) value)
|
||||
|
@ -2574,7 +2568,7 @@
|
|||
block (if ref?
|
||||
(merge block (db/pull-block (:db/id block)))
|
||||
block)
|
||||
{:block/keys [uuid children pre-block? top? refs heading-level level format content properties]} block
|
||||
{:block/keys [uuid children pre-block? top? refs level format content properties]} block
|
||||
config (if navigated? (assoc config :id (str navigating-block)) config)
|
||||
block (merge block (block/parse-title-and-body uuid format pre-block? content))
|
||||
blocks-container-id (:blocks-container-id config)
|
||||
|
@ -2583,7 +2577,7 @@
|
|||
config (if (nil? (:query-result config))
|
||||
(assoc config :query-result (atom nil))
|
||||
config)
|
||||
heading? (or (:heading properties) (and heading-level (<= heading-level 6)))
|
||||
heading? (:heading properties)
|
||||
*control-show? (get state ::control-show?)
|
||||
db-collapsed? (util/collapsed? block)
|
||||
collapsed? (cond
|
||||
|
@ -2665,7 +2659,7 @@
|
|||
(when @*show-left-menu?
|
||||
(block-left-menu config block))
|
||||
|
||||
(block-content-or-editor config block edit-input-id block-id heading-level edit?)
|
||||
(block-content-or-editor config block edit-input-id block-id edit?)
|
||||
|
||||
(when @*show-right-menu?
|
||||
(block-right-menu config block edit?))]
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
:on-click editor-handler/copy-block-embeds}
|
||||
"Copy block embeds"
|
||||
nil)
|
||||
|
||||
|
||||
[:hr.menu-separator]
|
||||
|
||||
(ui/menu-link
|
||||
|
@ -100,8 +100,7 @@
|
|||
"#787f97"
|
||||
"#978626"
|
||||
"#49767b"
|
||||
"#264c9b"
|
||||
"#793e3e"])
|
||||
"#264c9b"])
|
||||
|
||||
(defonce *template-including-parent? (atom nil))
|
||||
|
||||
|
@ -163,22 +162,36 @@
|
|||
(rum/defc ^:large-vars/cleanup-todo block-context-menu-content
|
||||
[_target block-id]
|
||||
(when-let [block (db/entity [:block/uuid block-id])]
|
||||
(let [properties (:block/properties block)
|
||||
heading? (true? (:heading properties))]
|
||||
(let [format (:block/format block)]
|
||||
[:.menu-links-wrapper
|
||||
[:div.flex-row.flex.justify-between.pb-2.pt-1.px-2
|
||||
[:div.flex-row.flex.justify-between
|
||||
[:div.flex.flex-row.justify-between.pb-2.pt-1.px-2.items-center
|
||||
[:div.flex.flex-row.justify-between.flex-1
|
||||
(for [color block-background-colors]
|
||||
[:a.m-2.shadow-sm
|
||||
{:on-click (fn [_e]
|
||||
(editor-handler/set-block-property! block-id "background-color" color))}
|
||||
[:div.heading-bg {:style {:background-color color}}]])
|
||||
[:a.m-2.shadow-sm
|
||||
{:title (t :remove-background)
|
||||
:on-click (fn [_e]
|
||||
(editor-handler/remove-block-property! block-id "background-color"))}
|
||||
[:div.heading-bg.remove "-"]]]]
|
||||
|
||||
[:div.heading-bg {:style {:background-color color}}]])]
|
||||
[:a.m-2.shadow-sm
|
||||
{:title (t :remove-background)
|
||||
:on-click (fn [_e]
|
||||
(editor-handler/remove-block-property! block-id "background-color"))}
|
||||
[:div.heading-bg.remove "-"]]]
|
||||
|
||||
[:div.flex.flex-row.justify-between.pb-2.pt-1.px-2.items-center
|
||||
[:div.flex.flex-row.justify-between.flex-1
|
||||
(for [i (range 1 7)]
|
||||
(ui/button
|
||||
(str "H" i)
|
||||
:on-click (fn [_e]
|
||||
(editor-handler/set-heading! block-id format i))
|
||||
:intent "link"
|
||||
:small? true))]
|
||||
[:a.m-2
|
||||
{:title (t :remove-heading)
|
||||
:on-click (fn [_e]
|
||||
(editor-handler/remove-heading! block-id format))}
|
||||
[:div.heading-bg.remove "-"]]]
|
||||
|
||||
[:hr.menu-separator]
|
||||
|
||||
(ui/menu-link
|
||||
|
@ -232,17 +245,6 @@
|
|||
|
||||
[:hr.menu-separator]
|
||||
|
||||
(ui/menu-link
|
||||
{:key "Convert heading"
|
||||
:on-click (fn [_e]
|
||||
(if heading?
|
||||
(editor-handler/remove-block-property! block-id :heading)
|
||||
(editor-handler/set-block-property! block-id :heading true)))}
|
||||
(if heading?
|
||||
"Convert back to a block"
|
||||
"Convert to a heading")
|
||||
nil)
|
||||
|
||||
(block-template block-id)
|
||||
|
||||
(if (srs/card-block? block)
|
||||
|
|
|
@ -568,7 +568,7 @@
|
|||
|
||||
(rum/defcs box < rum/reactive
|
||||
{:init (fn [state]
|
||||
(assoc state ::heading-level (:heading-level (first (:rum/args state)))
|
||||
(assoc state
|
||||
::id (str (random-uuid))))
|
||||
:did-mount (fn [state]
|
||||
(state/set-editor-args! (:rum/args state))
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
:block/created-at
|
||||
:block/updated-at
|
||||
:block/file
|
||||
:block/heading-level
|
||||
{:block/page [:db/id :block/name :block/original-name :block/journal-day]}
|
||||
{:block/_parent ...}])
|
||||
|
||||
|
|
|
@ -316,9 +316,10 @@
|
|||
(block/parse-title-and-body uuid format pre-block? (:block/content block)))
|
||||
properties (:block/properties block)
|
||||
real-content (:block/content block)
|
||||
content (if (and (seq properties) real-content (not= real-content content))
|
||||
(property/with-built-in-properties properties content format)
|
||||
content)
|
||||
content (let [properties (if (= format :markdown) (dissoc properties :heading) properties)]
|
||||
(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)
|
||||
|
@ -1939,6 +1940,7 @@
|
|||
(property/insert-properties format content props))
|
||||
ast (mldoc/->edn content* (gp-mldoc/default-config format))
|
||||
blocks (block/extract-blocks ast content* format {})
|
||||
_ (prn {:block (first blocks)})
|
||||
fst-block (first blocks)
|
||||
fst-block (if (and keep-uuid? (uuid? (:uuid block)))
|
||||
(assoc fst-block :block/uuid (:uuid block))
|
||||
|
@ -3465,3 +3467,21 @@
|
|||
;; has children
|
||||
(first (:block/_parent (db/entity (:db/id block)))))
|
||||
(util/collapsed? block)))
|
||||
|
||||
(defn set-heading!
|
||||
[block-id format heading]
|
||||
(if (= format :markdown)
|
||||
(let [repo (state/get-current-repo)
|
||||
block (db/entity [:block/uuid block-id])
|
||||
content' (commands/set-markdown-heading (:block/content block) heading)]
|
||||
(save-block! repo block-id content'))
|
||||
(set-block-property! block-id "heading" heading)))
|
||||
|
||||
(defn remove-heading!
|
||||
[block-id format]
|
||||
(remove-block-property! block-id "heading")
|
||||
(when (= format :markdown)
|
||||
(let [repo (state/get-current-repo)
|
||||
block (db/entity [:block/uuid block-id])
|
||||
content' (commands/clear-markdown-heading (:block/content block))]
|
||||
(save-block! repo block-id content'))))
|
||||
|
|
|
@ -611,6 +611,10 @@
|
|||
template
|
||||
{:target page}))))))
|
||||
|
||||
(defmethod handle :editor/set-org-mode-heading [[_ block heading]]
|
||||
(when-let [id (:block/uuid block)]
|
||||
(editor-handler/set-heading! id :org heading)))
|
||||
|
||||
(defmethod handle :file-sync-graph/restore-file [[_ graph page-entity content]]
|
||||
(when (db/get-db graph)
|
||||
(let [file (:block/file page-entity)]
|
||||
|
|
|
@ -482,7 +482,6 @@
|
|||
[:block/id
|
||||
:block/page-name
|
||||
:block/properties
|
||||
:block/heading-level
|
||||
:block/format
|
||||
:block/children
|
||||
:block/content]))})
|
||||
|
|
|
@ -52,13 +52,6 @@
|
|||
(.scrollBy (util/app-scroll-container-node) #js {:top (- 10 delta)})))
|
||||
[:div.action-bar
|
||||
[:div.action-bar-commands
|
||||
(when-not (= (:block/format block) :org)
|
||||
(action-command "heading" "Heading"
|
||||
#(let [properties (:block/properties block)
|
||||
heading? (true? (:heading properties))]
|
||||
(if heading?
|
||||
(editor-handler/remove-block-property! uuid :heading)
|
||||
(editor-handler/set-block-property! uuid :heading true)))))
|
||||
(action-command "infinity" "Card" #(srs/make-block-a-card! (:block/uuid block)))
|
||||
(action-command "copy" "Copy" #(editor-handler/copy-selection-blocks false))
|
||||
(action-command "cut" "Cut" #(editor-handler/cut-selection-blocks true))
|
||||
|
|
|
@ -29,13 +29,14 @@
|
|||
content))
|
||||
|
||||
(defn transform-content
|
||||
[{:block/keys [collapsed? format pre-block? unordered content heading-level left page parent]} level {:keys [heading-to-list?]}]
|
||||
(let [content (or content "")
|
||||
[{:block/keys [collapsed? format pre-block? unordered content left page parent properties]} level {:keys [heading-to-list?]}]
|
||||
(let [heading (:heading properties)
|
||||
markdown? (= :markdown format)
|
||||
content (or content "")
|
||||
pre-block? (or pre-block?
|
||||
(and (= page parent left) ; first block
|
||||
(= :markdown format)
|
||||
markdown?
|
||||
(string/includes? (first (string/split-lines content)) ":: ")))
|
||||
markdown? (= format :markdown)
|
||||
content (cond
|
||||
pre-block?
|
||||
(let [content (string/trim content)]
|
||||
|
@ -45,7 +46,7 @@
|
|||
(let [markdown-top-heading? (and markdown?
|
||||
(= parent page)
|
||||
(not unordered)
|
||||
heading-level)
|
||||
heading)
|
||||
[prefix spaces-tabs]
|
||||
(cond
|
||||
(= format :org)
|
||||
|
@ -57,10 +58,10 @@
|
|||
["" ""]
|
||||
|
||||
:else
|
||||
(let [level (if (and heading-to-list? heading-level)
|
||||
(if (> heading-level 1)
|
||||
(dec heading-level)
|
||||
heading-level)
|
||||
(let [level (if (and heading-to-list? heading)
|
||||
(if (> heading 1)
|
||||
(dec heading)
|
||||
heading)
|
||||
level)
|
||||
spaces-tabs (->>
|
||||
(repeat (dec level) (state/get-export-bullet-indentation))
|
||||
|
|
|
@ -245,7 +245,7 @@ html.is-mobile {
|
|||
.ui__button {
|
||||
@apply flex items-center px-3 py-2 border border-transparent
|
||||
text-sm leading-4 font-medium rounded-md text-white
|
||||
focus:outline-none transition ease-in-out duration-150 mt-1;
|
||||
focus:outline-none transition ease-in-out duration-150;
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
|
@ -355,4 +355,4 @@ html.is-mobile {
|
|||
|
||||
.ui__icon {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue