Parcourir la source

fix(editor): back/forward cursor for emoji char

charlie il y a 4 ans
Parent
commit
9c89c6395b

+ 16 - 0
src/main/frontend/util.cljc

@@ -695,6 +695,22 @@
              (dec current-pos))))
        (dec current-pos))))
 
+#?(:cljs
+   ;; for widen char
+   (defn safe-inc-current-pos-from-start
+     [input current-pos]
+     (if-let [len (and (string? input) (.-length input))]
+       (when-let [input (and (>= len 2) (<= current-pos len)
+                             (.substr input current-pos 20))]
+         (try
+           (let [^js splitter (GraphemeSplitter.)
+                 ^js input (.splitGraphemes splitter input)]
+             (+ current-pos (.-length (.shift input))))
+           (catch js/Error e
+             (js/console.error e)
+             (inc current-pos))))
+       (inc current-pos))))
+
 #?(:cljs
    (defn kill-line-before!
      [input]

+ 6 - 2
src/main/frontend/util/cursor.cljs

@@ -70,7 +70,9 @@
   ([input n]
    (when input
      (let [{:keys [pos]} (get-caret-pos input)
-           pos (+ pos n)]
+           pos (if (= n 1)
+                 (util/safe-inc-current-pos-from-start (.-value input) pos)
+                 (+ pos n))]
        (move-cursor-to input pos)))))
 
 (defn move-cursor-backward
@@ -79,7 +81,9 @@
   ([input n]
    (when input
      (let [{:keys [pos]} (get-caret-pos input)
-           pos (- pos n)]
+           pos (if (= n 1)
+                 (util/safe-dec-current-pos-from-end (.-value input) pos)
+                 (- pos n))]
        (move-cursor-to input pos)))))
 
 (defn- get-input-content&pos

+ 13 - 7
src/test/frontend/util_test.cljs

@@ -1,16 +1,22 @@
 (ns frontend.util-test
   (:require [cljs.test :refer [deftest is testing]]
-            [frontend.util :refer [find-first safe-dec-current-pos-from-end]]))
+            [frontend.util :as util]))
 
 (deftest test-find-first
   (testing "find-first"
-    (is (= 1 (find-first identity [1])))))
+    (is (= 1 (util/find-first identity [1])))))
 
 (deftest test-delete-emoji-current-pos
   (testing "safe current position from end for emoji"
-    (is (= 3 (safe-dec-current-pos-from-end "abc😀d" 5)))
-    (is (= 3 (safe-dec-current-pos-from-end "abc😀" 5)))
-    (is (= 0 (safe-dec-current-pos-from-end "😀" 2)))
-    (is (= 4 (safe-dec-current-pos-from-end "abcde" 5)))
-    (is (= 1 (safe-dec-current-pos-from-end "中文" 2)))))
+    (is (= 3 (util/safe-dec-current-pos-from-end "abc😀d" 5)))
+    (is (= 3 (util/safe-dec-current-pos-from-end "abc😀" 5)))
+    (is (= 0 (util/safe-dec-current-pos-from-end "😀" 2)))
+    (is (= 4 (util/safe-dec-current-pos-from-end "abcde" 5)))
+    (is (= 1 (util/safe-dec-current-pos-from-end "中文" 2))))
+
+  (testing "safe current position from start for emoji"
+    (is (= 5 (util/safe-inc-current-pos-from-start "abc😀d" 3)))
+    (is (= 2 (util/safe-inc-current-pos-from-start "😀" 0)))
+    (is (= 2 (util/safe-inc-current-pos-from-start "abcde" 1)))
+    (is (= 1 (util/safe-inc-current-pos-from-start "中文" 0)))))