enhance(editor): support dollar autopair for markdown math (#12618)

* feat(editor): add support for dollar sign in autopair feature

* fix(editor): handle dollar autopair for markdown math

* feat(help): add inline math example

* fix(editor): double dollar autopair behavior
This commit is contained in:
megayu
2026-05-12 16:09:06 +08:00
committed by GitHub
parent e63bc56750
commit 7cb9144422
5 changed files with 80 additions and 8 deletions

View File

@@ -37,7 +37,7 @@
[:td.text-right [:code (t :help/context-menu-action)]]]]])
(defn markdown-syntax []
(let [list [:bold :italics :del :mark :latex :code :link :pre :img]
(let [list [:bold :italics :del :mark :math :latex :code :link :pre :img]
title (t :help/markdown-syntax)
learn-more "https://www.markdownguide.org/basic-syntax"
raw {:bold (str "**" (t :format/bold) "**")
@@ -45,6 +45,7 @@
:link "[Link](https://www.example.com)"
:del (str "~~" (t :format/strikethrough) "~~")
:mark (str "^^" (t :format/highlight) "^^")
:math (str (t :help/inline-math-example-prefix) " $E = mc^2$")
:latex "$$E = mc^2$$"
:code (str "`" (t :format/code) "`")
:pre "```clojure\n (println \"Hello world!\")\n```"
@@ -55,6 +56,7 @@
:link [:a {:href "https://www.example.com"} (t :ui/link)]
:del [:del (t :format/strikethrough)]
:mark [:mark (t :format/highlight)]
:math [:span (t :help/inline-math-example-prefix) " " (latex/latex "E = mc^2" false false)]
:latex (latex/latex "E = mc^2" true false)
:code [:code (t :format/code)]
:pre (highlight/highlight "help-highlight" {:data-lang "clojure"} "(println \"Hello world!\")")

View File

@@ -1486,6 +1486,7 @@
"~" "~"
"*" "*"
"_" "_"
"$" "$"
"^" "^"
"=" "="
"/" "/"
@@ -1501,14 +1502,13 @@
(def delete-map
(assoc autopair-map
"$" "$"
":" ":"))
(defn- autopair
[input-id prefix _format _option]
(let [value (get autopair-map prefix)
(let [suffix (get autopair-map prefix)
selected (util/get-selected-text)
postfix (str selected value)
postfix (str selected suffix)
value (str prefix postfix)
input (gdom/getElement input-id)]
(when value
@@ -2649,6 +2649,11 @@
(= "#" (util/nth-safe value (dec pos))))
(state/clear-editor-action!)
(and (= "$" key) (string/blank? (util/get-selected-text)))
(do
(util/stop e)
(commands/simple-insert! input-id "$$" {:backward-pos 1}))
(and (contains? (set/difference (set (keys reversed-autopair-map))
#{"`"})
key)
@@ -2693,10 +2698,6 @@
(double-chars-typed? value pos key sym))
(state/pub-event! [:editor/new-property])
(let [sym "$"]
(double-chars-typed? value pos key sym))
(commands/simple-insert! input-id "$$" {:backward-pos 2})
(let [sym "^"]
(double-chars-typed? value pos key sym))
(commands/simple-insert! input-id "^^" {:backward-pos 2})

View File

@@ -799,6 +799,7 @@
:help/feature "Feature request"
:help/forum-community "Forum community"
:help/handbook "Handbook"
:help/inline-math-example-prefix "inline"
:help/learn-more "Learn more"
:help/markdown-syntax "Markdown syntax"
:help/open-link-in-sidebar "Open link in sidebar"

View File

@@ -795,6 +795,7 @@
:help/feature "功能建议"
:help/forum-community "论坛讨论"
:help/handbook "手册"
:help/inline-math-example-prefix "行内"
:help/learn-more "了解更多"
:help/markdown-syntax "Markdown 语法"
:help/open-link-in-sidebar "在侧边栏打开"

View File

@@ -8,6 +8,7 @@
[frontend.test.helper :as test-helper]
[frontend.util :as util]
[frontend.util.cursor :as cursor]
[goog.dom :as gdom]
[logseq.outliner.core :as outliner-core]))
(use-fixtures :each test-helper/start-and-destroy-db)
@@ -188,6 +189,72 @@
:cursor-pos 2
:key "a"}))))
(deftest keydown-not-matched-handler-wraps-selected-text-with-single-dollar
(let [content (atom nil)
cursor-pos (atom nil)
selection-range (atom nil)
input #js {:id "edit-block-test"
:value "inline math"
:setSelectionRange (fn [start end]
(reset! selection-range [start end]))}
event #js {:key "$"
:ctrlKey false
:metaKey false}
selected "math"]
(with-redefs [state/get-edit-input-id (constantly "edit-block-test")
state/get-input (constantly input)
state/get-editor-action (constantly nil)
state/set-state! (constantly nil)
state/set-block-content-and-last-pos! (fn [_input-id value' pos']
(reset! content value')
(reset! cursor-pos pos'))
gdom/getElement (constantly input)
util/get-selected-text (constantly selected)
util/stop (constantly nil)
cursor/pos (constantly 7)
cursor/move-cursor-to (fn [_ pos' & _]
(reset! cursor-pos pos'))]
((editor/keydown-not-matched-handler :markdown) event nil)
(is (= "inline $math$" @content))
(is (= 8 @cursor-pos))
(is (= [8 12] @selection-range)))))
(defn- keydown-dollar-without-selection-result
[{:keys [value cursor-pos]}]
(let [content (atom nil)
cursor-pos' (atom nil)
input #js {:id "edit-block-test"
:value value}
event #js {:key "$"
:ctrlKey false
:metaKey false}]
(with-redefs [state/get-edit-input-id (constantly "edit-block-test")
state/get-input (constantly input)
state/get-editor-action (constantly nil)
state/set-state! (constantly nil)
state/set-block-content-and-last-pos! (fn [_input-id value' pos']
(reset! content value')
(reset! cursor-pos' pos'))
gdom/getElement (constantly input)
util/get-selected-text (constantly "")
util/stop (constantly nil)
cursor/pos (constantly cursor-pos)
cursor/move-cursor-to (fn [_ pos' & _]
(reset! cursor-pos' pos'))]
((editor/keydown-not-matched-handler :markdown) event nil)
{:content @content
:cursor-pos @cursor-pos'})))
(deftest keydown-not-matched-handler-expands-dollar-delimiters-without-selection
(is (= {:content "inline $$"
:cursor-pos 8}
(keydown-dollar-without-selection-result {:value "inline "
:cursor-pos 7})))
(is (= {:content "inline $$$$"
:cursor-pos 9}
(keydown-dollar-without-selection-result {:value "inline $$"
:cursor-pos 8}))))
(defn- handle-last-input-handler
"Spied version of editor/handle-last-input"
[{:keys [value cursor-pos]}]