Selaa lähdekoodia

Merge branch 'feat/db' into enhance/plugin-web

Tienson Qin 1 vuosi sitten
vanhempi
sitoutus
9b282d66ac

+ 40 - 39
.clj-kondo/config.edn

@@ -48,69 +48,70 @@
                              frontend.pubsub]}
                              frontend.pubsub]}
 
 
   :consistent-alias
   :consistent-alias
-  {:aliases {cljs.reader reader
-             cljs-time.core t
+  {:aliases {"/electron/utils" js-utils
+             "path" node-path
              cljs-time.coerce tc
              cljs-time.coerce tc
+             cljs-time.core t
+             cljs.reader reader
+             clojure.string string
              datascript.core d
              datascript.core d
-             datascript.transit dt
              datascript.db ddb
              datascript.db ddb
+             datascript.transit dt
              electron.ipc ipc
              electron.ipc ipc
              electron.utils utils
              electron.utils utils
-             "/electron/utils" js-utils
              frontend.commands commands
              frontend.commands commands
-             frontend.components.block.macros block-macros
-             frontend.components.query query
-             frontend.components.query.result query-result
-             frontend.components.class class-component
-             frontend.components.property property-component
-             frontend.components.title title
              frontend.common.date common-date
              frontend.common.date common-date
              frontend.common.file.core common-file
              frontend.common.file.core common-file
              frontend.common.file.util wfu
              frontend.common.file.util wfu
              frontend.common.missionary-util c.m
              frontend.common.missionary-util c.m
              frontend.common.schema-register sr
              frontend.common.schema-register sr
              frontend.common.search-fuzzy fuzzy
              frontend.common.search-fuzzy fuzzy
+             frontend.components.block.macros block-macros
+             frontend.components.class class-component
+             frontend.components.property property-component
+             frontend.components.query query
+             frontend.components.query.result query-result
+             frontend.components.title title
              frontend.config config
              frontend.config config
              frontend.date date
              frontend.date date
              frontend.db db
              frontend.db db
              frontend.db-mixins db-mixins
              frontend.db-mixins db-mixins
-             frontend.db.query-dsl query-dsl
-             frontend.db.react react
              frontend.db.query-custom query-custom
              frontend.db.query-custom query-custom
+             frontend.db.query-dsl query-dsl
              frontend.db.query-react query-react
              frontend.db.query-react query-react
+             frontend.db.react react
              frontend.db.util db-utils
              frontend.db.util db-utils
              frontend.diff diff
              frontend.diff diff
              frontend.encrypt encrypt
              frontend.encrypt encrypt
              frontend.extensions.sci sci
              frontend.extensions.sci sci
-             frontend.format.mldoc mldoc
              frontend.format.block block
              frontend.format.block block
+             frontend.format.mldoc mldoc
              frontend.fs fs
              frontend.fs fs
-             frontend.fs.memory-fs memory-fs
              frontend.fs.capacitor-fs capacitor-fs
              frontend.fs.capacitor-fs capacitor-fs
+             frontend.fs.memory-fs memory-fs
              frontend.fs.nfs nfs
              frontend.fs.nfs nfs
-             frontend.handler.extract extract
              frontend.handler.common common-handler
              frontend.handler.common common-handler
-             frontend.handler.common.file file-common-handler
-             frontend.handler.common.plugin plugin-common-handler
              frontend.handler.common.developer dev-common-handler
              frontend.handler.common.developer dev-common-handler
+             frontend.handler.common.file file-common-handler
              frontend.handler.common.page page-common-handler
              frontend.handler.common.page page-common-handler
+             frontend.handler.common.plugin plugin-common-handler
              frontend.handler.config config-handler
              frontend.handler.config config-handler
-             frontend.handler.editor.property editor-property
-             frontend.handler.events events
-             frontend.handler.global-config global-config-handler
-             frontend.handler.ui ui-handler
-             frontend.handler.notification notification
-             frontend.handler.page page-handler
              frontend.handler.db-based.editor db-editor-handler
              frontend.handler.db-based.editor db-editor-handler
              frontend.handler.db-based.page db-page-handler
              frontend.handler.db-based.page db-page-handler
              frontend.handler.db-based.property db-property-handler
              frontend.handler.db-based.property db-property-handler
              frontend.handler.db-based.property.util db-pu
              frontend.handler.db-based.property.util db-pu
+             frontend.handler.editor.property editor-property
+             frontend.handler.events events
+             frontend.handler.extract extract
              frontend.handler.file-based.page file-page-handler
              frontend.handler.file-based.page file-page-handler
-             frontend.handler.file-based.property file-property-handler
              frontend.handler.file-based.page-property file-page-property
              frontend.handler.file-based.page-property file-page-property
+             frontend.handler.file-based.property file-property-handler
              frontend.handler.file-based.property.util property-util
              frontend.handler.file-based.property.util property-util
              frontend.handler.file-based.recent file-recent-handler
              frontend.handler.file-based.recent file-recent-handler
              frontend.handler.file-based.repo file-repo-handler
              frontend.handler.file-based.repo file-repo-handler
+             frontend.handler.global-config global-config-handler
+             frontend.handler.notification notification
+             frontend.handler.page page-handler
              frontend.handler.plugin plugin-handler
              frontend.handler.plugin plugin-handler
              frontend.handler.plugin-config plugin-config-handler
              frontend.handler.plugin-config plugin-config-handler
              frontend.handler.property.file property-file
              frontend.handler.property.file property-file
@@ -120,11 +121,12 @@
              frontend.handler.repo-config repo-config-handler
              frontend.handler.repo-config repo-config-handler
              frontend.handler.route route-handler
              frontend.handler.route route-handler
              frontend.handler.search search-handler
              frontend.handler.search search-handler
+             frontend.handler.ui ui-handler
              frontend.idb idb
              frontend.idb idb
              frontend.loader loader
              frontend.loader loader
              frontend.mixins mixins
              frontend.mixins mixins
-             frontend.modules.outliner.ui ui-outliner-tx
              frontend.mobile.util mobile-util
              frontend.mobile.util mobile-util
+             frontend.modules.outliner.ui ui-outliner-tx
              frontend.page page
              frontend.page page
              frontend.persist-db persist-db
              frontend.persist-db persist-db
              frontend.schema.handler.common-config common-config-schema
              frontend.schema.handler.common-config common-config-schema
@@ -137,37 +139,37 @@
              frontend.util.file-based.clock clock
              frontend.util.file-based.clock clock
              frontend.util.file-based.drawer drawer
              frontend.util.file-based.drawer drawer
              frontend.util.page page-util
              frontend.util.page page-util
-             frontend.util.property property
              frontend.util.persist-var persist-var
              frontend.util.persist-var persist-var
+             frontend.util.property property
              frontend.util.text text-util
              frontend.util.text text-util
-             frontend.util.url url-util
              frontend.util.thingatpt thingatpt
              frontend.util.thingatpt thingatpt
+             frontend.util.url url-util
+             frontend.worker.handler.page worker-page
              frontend.worker.pipeline worker-pipeline
              frontend.worker.pipeline worker-pipeline
-             frontend.worker.util worker-util
              frontend.worker.state worker-state
              frontend.worker.state worker-state
-             frontend.worker.handler.page worker-page
+             frontend.worker.util worker-util
              lambdaisland.glogi log
              lambdaisland.glogi log
              logseq.common.config common-config
              logseq.common.config common-config
-             logseq.common.graph common-graph
              logseq.common.date-time-util date-time-util
              logseq.common.date-time-util date-time-util
+             logseq.common.graph common-graph
              logseq.common.path path
              logseq.common.path path
              logseq.common.util common-util
              logseq.common.util common-util
-             logseq.common.util.page-ref page-ref
              logseq.common.util.block-ref block-ref
              logseq.common.util.block-ref block-ref
              logseq.common.util.macro macro-util
              logseq.common.util.macro macro-util
              logseq.common.util.namespace ns-util
              logseq.common.util.namespace ns-util
+             logseq.common.util.page-ref page-ref
              logseq.db ldb
              logseq.db ldb
-             logseq.db.frontend.content db-content
              logseq.db.frontend.class db-class
              logseq.db.frontend.class db-class
+             logseq.db.frontend.content db-content
              logseq.db.frontend.db-ident db-ident
              logseq.db.frontend.db-ident db-ident
+             logseq.db.frontend.entity-plus entity-plus
+             logseq.db.frontend.entity-util entity-util
              logseq.db.frontend.inputs db-inputs
              logseq.db.frontend.inputs db-inputs
              logseq.db.frontend.order db-order
              logseq.db.frontend.order db-order
              logseq.db.frontend.property db-property
              logseq.db.frontend.property db-property
              logseq.db.frontend.property.build db-property-build
              logseq.db.frontend.property.build db-property-build
              logseq.db.frontend.property.type db-property-type
              logseq.db.frontend.property.type db-property-type
              logseq.db.frontend.property.util db-property-util
              logseq.db.frontend.property.util db-property-util
-             logseq.db.frontend.entity-plus entity-plus
-             logseq.db.frontend.entity-util entity-util
              logseq.db.frontend.rules rules
              logseq.db.frontend.rules rules
              logseq.db.frontend.schema db-schema
              logseq.db.frontend.schema db-schema
              logseq.db.frontend.validate db-validate
              logseq.db.frontend.validate db-validate
@@ -175,21 +177,20 @@
              logseq.db.sqlite.util sqlite-util
              logseq.db.sqlite.util sqlite-util
              logseq.db.test.helper db-test
              logseq.db.test.helper db-test
              logseq.graph-parser graph-parser
              logseq.graph-parser graph-parser
-             logseq.graph-parser.text text
-             logseq.graph-parser.db gp-db
              logseq.graph-parser.block gp-block
              logseq.graph-parser.block gp-block
+             logseq.graph-parser.db gp-db
              logseq.graph-parser.mldoc gp-mldoc
              logseq.graph-parser.mldoc gp-mldoc
              logseq.graph-parser.property gp-property
              logseq.graph-parser.property gp-property
+             logseq.graph-parser.text text
              logseq.outliner.batch-tx batch-tx
              logseq.outliner.batch-tx batch-tx
              logseq.outliner.core outliner-core
              logseq.outliner.core outliner-core
+             logseq.outliner.datascript-report ds-report
              logseq.outliner.op outliner-op
              logseq.outliner.op outliner-op
              logseq.outliner.pipeline outliner-pipeline
              logseq.outliner.pipeline outliner-pipeline
              logseq.outliner.validate outliner-validate
              logseq.outliner.validate outliner-validate
-             logseq.outliner.datascript-report ds-report
-             logseq.shui.ui shui
              logseq.shui.popup.core shui-popup
              logseq.shui.popup.core shui-popup
+             logseq.shui.ui shui
              medley.core medley
              medley.core medley
-             "path" node-path
              promesa.core p}}
              promesa.core p}}
 
 
   :namespace-name-mismatch {:level :warning}
   :namespace-name-mismatch {:level :warning}

+ 60 - 0
src/main/frontend/components/profiler.cljs

@@ -0,0 +1,60 @@
+(ns frontend.components.profiler
+  "Profiler UI"
+  (:require [fipp.edn :as fipp]
+            [frontend.handler.profiler :as profiler-handler]
+            [frontend.util :as util]
+            [logseq.shui.ui :as shui]
+            [rum.core :as rum]))
+
+(rum/defcs profiler < rum/reactive
+  (rum/local nil ::reports)
+  (rum/local nil ::register-fn-name)
+  [state]
+  (let [profiling-fns (keys (rum/react profiler-handler/*fn-symbol->origin-fn))
+        *reports (get state ::reports)
+        *register-fn-name (get state ::register-fn-name)]
+    [:div
+     [:b "Profiling fns:"]
+     [:div.pb-4
+      (for [f-name profiling-fns]
+        [:div.flex.flex-row.items-center.gap-2
+         [:pre.select-text (str f-name)]
+         [:a.inline.close.flex.transition-opacity.duration-300.ease-in
+          {:title "Unregister"
+           :on-pointer-down
+           (fn [e]
+             (util/stop e)
+             (profiler-handler/unregister-fn! f-name))}
+          (shui/tabler-icon "x")]])]
+     [:div.flex.flex-row.items-center.gap-2
+      (shui/button
+       {:on-click (fn []
+                    (when-let [fn-sym (some-> @*register-fn-name symbol)]
+                      (profiler-handler/register-fn! fn-sym)))}
+       "Register fn")
+      [:input.form-input.my-2.py-1
+       {:on-change (fn [e] (reset! *register-fn-name (util/evalue e)))
+        :on-focus (fn [e] (let [v (.-value (.-target e))]
+                            (when (= v "input fn name here")
+                              (set! (.-value (.-target e)) ""))))
+        :placeholder "input fn name here"}]]
+     [:hr]
+     [:div.flex.gap-2.flex-wrap.items-center.pb-3
+      (shui/button
+       {:size :sm
+        :on-click (fn [_] (reset! *reports (profiler-handler/profile-report)))}
+       (shui/tabler-icon "refresh") "Refresh reports")
+      (shui/button
+       {:size :sm
+        :on-click (fn [_] (profiler-handler/reset-report!)
+                    (reset! *reports (profiler-handler/profile-report)))}
+       (shui/tabler-icon "x") "Reset reports")]
+     (let [update-time-sum
+           (fn [m] (update-vals m (fn [m2] (update-vals m2 #(.toFixed % 6)))))]
+       [:div.pb-4
+        [:pre.select-text
+         (when @*reports
+           (-> @*reports
+               (update :time-sum update-time-sum)
+               (fipp/pprint {:width 20})
+               with-out-str))]])]))

+ 12 - 2
src/main/frontend/components/right_sidebar.cljs

@@ -22,7 +22,8 @@
             [frontend.db.rtc.debug-ui :as rtc-debug-ui]
             [frontend.db.rtc.debug-ui :as rtc-debug-ui]
             [frontend.handler.route :as route-handler]
             [frontend.handler.route :as route-handler]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
-            [frontend.components.icon :as icon]))
+            [frontend.components.icon :as icon]
+            [frontend.components.profiler :as profiler]))
 
 
 (rum/defc toggle
 (rum/defc toggle
   []
   []
@@ -133,6 +134,10 @@
     [[:.flex.items-center (ui/icon "cloud" {:class "text-md mr-2"}) "(Dev) RTC"]
     [[:.flex.items-center (ui/icon "cloud" {:class "text-md mr-2"}) "(Dev) RTC"]
      (rtc-debug-ui/rtc-debug-ui)]
      (rtc-debug-ui/rtc-debug-ui)]
 
 
+    :profiler
+    [[:.flex.items-center (ui/icon "cloud" {:class "text-md mr-2"}) "(Dev) Profiler"]
+     (profiler/profiler)]
+
     ["" [:span]]))
     ["" [:span]]))
 
 
 (defonce *drag-to
 (defonce *drag-to
@@ -407,7 +412,12 @@
           [:div.text-sm
           [:div.text-sm
            [:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e]
            [:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e]
                                                                        (state/sidebar-add-block! repo "rtc" :rtc))}
                                                                        (state/sidebar-add-block! repo "rtc" :rtc))}
-            "(Dev) RTC"]])]]
+            "(Dev) RTC"]])
+        (when (state/sub [:ui/developer-mode?])
+          [:div.text-sm
+           [:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e]
+                                                                       (state/sidebar-add-block! repo "profiler" :profiler))}
+            "(Dev) Profiler"]])]]
 
 
       [:.sidebar-item-list.flex-1.scrollbar-spacing.px-2
       [:.sidebar-item-list.flex-1.scrollbar-spacing.px-2
        (if @*anim-finished?
        (if @*anim-finished?

+ 67 - 68
src/main/frontend/extensions/calc.cljc

@@ -1,15 +1,15 @@
 (ns frontend.extensions.calc
 (ns frontend.extensions.calc
   (:refer-clojure :exclude [eval numerator denominator])
   (:refer-clojure :exclude [eval numerator denominator])
-  (:require [clojure.string :as str]
-            [frontend.util :as util]
+  (:require #?(:clj [clojure.java.io :as io])
+            #?(:clj [instaparse.core :as insta]
+               :cljs [instaparse.core :as insta :refer-macros [defparser]])
 
 
-            [bignumber.js :as bn]
+            #?(:cljs [rum.core :as rum])
 
 
-            #?(:clj [clojure.java.io :as io])
             #?(:cljs [shadow.resource :as rc])
             #?(:cljs [shadow.resource :as rc])
-            #?(:cljs [rum.core :as rum])
-            #?(:clj [instaparse.core :as insta]
-               :cljs [instaparse.core :as insta :refer-macros [defparser]])))
+            [bignumber.js :as bn]
+            [clojure.string :as string]
+            [frontend.util :as util]))
 
 
 ;; ======================================================================
 ;; ======================================================================
 ;; Interpreter
 ;; Interpreter
@@ -17,9 +17,8 @@
 #?(:clj (def parse (insta/parser (io/resource "grammar/calc.bnf")))
 #?(:clj (def parse (insta/parser (io/resource "grammar/calc.bnf")))
    :cljs (defparser parse (rc/inline "grammar/calc.bnf")))
    :cljs (defparser parse (rc/inline "grammar/calc.bnf")))
 
 
-(def constants {
-  "PI" (bn/BigNumber "3.14159265358979323846")
-  "E"  (bn/BigNumber "2.71828182845904523536")})
+(def constants {"PI" (bn/BigNumber "3.14159265358979323846")
+                "E"  (bn/BigNumber "2.71828182845904523536")})
 
 
 (defn exception? [e]
 (defn exception? [e]
   #?(:clj (instance? Exception e)
   #?(:clj (instance? Exception e)
@@ -34,13 +33,13 @@
 
 
 (defn factorial [n]
 (defn factorial [n]
   (reduce
   (reduce
-    (fn [a b] (.multipliedBy a b))
-    (bn/BigNumber 1)
-    (range 2 (inc n))))
+   (fn [a b] (.multipliedBy a b))
+   (bn/BigNumber 1)
+   (range 2 (inc n))))
 
 
 (defn eval* [env ast]
 (defn eval* [env ast]
   (insta/transform
   (insta/transform
-   {:number     (comp bn/BigNumber #(str/replace % "," ""))
+   {:number     (comp bn/BigNumber #(string/replace % "," ""))
     :percent    (fn percent [a] (-> a (.dividedBy 100.00)))
     :percent    (fn percent [a] (-> a (.dividedBy 100.00)))
     :scientific bn/BigNumber
     :scientific bn/BigNumber
     :mixed-number (fn [whole numerator denominator]
     :mixed-number (fn [whole numerator denominator]
@@ -53,12 +52,12 @@
     :div        (fn div [a b] (-> a (.dividedBy b)))
     :div        (fn div [a b] (-> a (.dividedBy b)))
     :mod        (fn mod [a b] (-> a (.modulo b)))
     :mod        (fn mod [a b] (-> a (.modulo b)))
     :pow        (fn pow [a b] (if (.isInteger b)
     :pow        (fn pow [a b] (if (.isInteger b)
-                                  (.exponentiatedBy a b)
-                                  #?(:clj (java.lang.Math/pow a b)
-                                     :cljs (bn/BigNumber (js/Math.pow a b)))))
+                                (.exponentiatedBy a b)
+                                #?(:clj (java.lang.Math/pow a b)
+                                   :cljs (bn/BigNumber (js/Math.pow a b)))))
     :factorial  (fn fact [a] (if (and (.isInteger a) (.isPositive a) (.isLessThan a 254))
     :factorial  (fn fact [a] (if (and (.isInteger a) (.isPositive a) (.isLessThan a 254))
-                                 (factorial (.toNumber a))
-                                 (bn/BigNumber 'NaN')))
+                               (factorial (.toNumber a))
+                               (bn/BigNumber 'NaN')))
     :abs        (fn abs [a] (.abs a))
     :abs        (fn abs [a] (.abs a))
     :sqrt       (fn sqrt [a] (.sqrt a))
     :sqrt       (fn sqrt [a] (.sqrt a))
     :log        (fn log [a]
     :log        (fn log [a]
@@ -68,24 +67,24 @@
     :exp        (fn exp [a]
     :exp        (fn exp [a]
                   #?(:clj (java.lang.Math/exp a) :cljs (bn/BigNumber (js/Math.exp a))))
                   #?(:clj (java.lang.Math/exp a) :cljs (bn/BigNumber (js/Math.exp a))))
     :sin        (fn sin [a]
     :sin        (fn sin [a]
-                  #?(:clj (java.lang.Math/sin a) :cljs (bn/BigNumber(js/Math.sin a))))
+                  #?(:clj (java.lang.Math/sin a) :cljs (bn/BigNumber (js/Math.sin a))))
     :cos        (fn cos [a]
     :cos        (fn cos [a]
-                  #?(:clj (java.lang.Math/cos a) :cljs (bn/BigNumber(js/Math.cos a))))
+                  #?(:clj (java.lang.Math/cos a) :cljs (bn/BigNumber (js/Math.cos a))))
     :tan        (fn tan [a]
     :tan        (fn tan [a]
-                  #?(:clj (java.lang.Math/tan a) :cljs (bn/BigNumber(js/Math.tan a))))
+                  #?(:clj (java.lang.Math/tan a) :cljs (bn/BigNumber (js/Math.tan a))))
     :atan       (fn atan [a]
     :atan       (fn atan [a]
-                  #?(:clj (java.lang.Math/atan a) :cljs (bn/BigNumber(js/Math.atan a))))
+                  #?(:clj (java.lang.Math/atan a) :cljs (bn/BigNumber (js/Math.atan a))))
     :asin       (fn asin [a]
     :asin       (fn asin [a]
-                  #?(:clj (java.lang.Math/asin a) :cljs (bn/BigNumber(js/Math.asin a))))
+                  #?(:clj (java.lang.Math/asin a) :cljs (bn/BigNumber (js/Math.asin a))))
     :acos       (fn acos [a]
     :acos       (fn acos [a]
-                  #?(:clj (java.lang.Math/acos a) :cljs (bn/BigNumber(js/Math.acos a))))
+                  #?(:clj (java.lang.Math/acos a) :cljs (bn/BigNumber (js/Math.acos a))))
     :assignment (fn assign! [var val]
     :assignment (fn assign! [var val]
                   (if (contains? constants var)
                   (if (contains? constants var)
                     (throw
                     (throw
-                      (ex-info (util/format "Can't redefine constant %s" var) {:var var}))
+                     (ex-info (util/format "Can't redefine constant %s" var) {:var var}))
                     (swap! env assoc var val))
                     (swap! env assoc var val))
                   val)
                   val)
-    :toassign   str/trim
+    :toassign   string/trim
     :comment    (constantly nil)
     :comment    (constantly nil)
     :digits     int
     :digits     int
     :format-fix (fn format [places]
     :format-fix (fn format [places]
@@ -95,21 +94,21 @@
                   (swap! env assoc :mode "sci" :places places)
                   (swap! env assoc :mode "sci" :places places)
                   (get @env "last"))
                   (get @env "last"))
     :format-frac (fn format [max-denominator]
     :format-frac (fn format [max-denominator]
-                  (swap! env dissoc :mode :improper)
-                  (swap! env assoc :mode "frac" :max-denominator max-denominator)
-                  (get @env "last"))
+                   (swap! env dissoc :mode :improper)
+                   (swap! env assoc :mode "frac" :max-denominator max-denominator)
+                   (get @env "last"))
     :format-impf (fn format [max-denominator]
     :format-impf (fn format [max-denominator]
-                  (swap! env assoc :mode "frac" :max-denominator max-denominator :improper true)
-                  (get @env "last"))
+                   (swap! env assoc :mode "frac" :max-denominator max-denominator :improper true)
+                   (get @env "last"))
     :format-norm (fn format [precision]
     :format-norm (fn format [precision]
-                  (swap! env dissoc :mode :places)
-                  (swap! env assoc :precision precision)
-                  (get @env "last"))
+                   (swap! env dissoc :mode :places)
+                   (swap! env assoc :precision precision)
+                   (get @env "last"))
     :base       (fn base [b]
     :base       (fn base [b]
-                  (swap! env assoc :base (str/lower-case b))
+                  (swap! env assoc :base (string/lower-case b))
                   (get @env "last"))
                   (get @env "last"))
     :variable   (fn resolve [var]
     :variable   (fn resolve [var]
-                  (let [var (str/trim var)]
+                  (let [var (string/trim var)]
                     (or (get constants var)
                     (or (get constants var)
                         (get @env var)
                         (get @env var)
                         (throw
                         (throw
@@ -136,12 +135,12 @@
   "Check that number can render without loss of all significant digits,
   "Check that number can render without loss of all significant digits,
    and that the absolute value is less than 1e21."
    and that the absolute value is less than 1e21."
   [num' places]
   [num' places]
-  (or (.isZero num' )
-    (let [mag (.abs num')
-          lower-bound (-> (bn/BigNumber 0.5) (.shiftedBy (- places)))
-          upper-bound (bn/BigNumber 1e21)]
-      (and (-> mag (.isGreaterThanOrEqualTo lower-bound))
-           (-> mag (.isLessThan upper-bound))))))
+  (or (.isZero num')
+      (let [mag (.abs num')
+            lower-bound (-> (bn/BigNumber 0.5) (.shiftedBy (- places)))
+            upper-bound (bn/BigNumber 1e21)]
+        (and (-> mag (.isGreaterThanOrEqualTo lower-bound))
+             (-> mag (.isLessThan upper-bound))))))
 
 
 (defn can-fit?
 (defn can-fit?
   "Check that number can render normally within the given number of digits.
   "Check that number can render normally within the given number of digits.
@@ -152,16 +151,16 @@
 
 
 (defn format-base [val base]
 (defn format-base [val base]
   (let [sign (.-s val)
   (let [sign (.-s val)
-       display-val (if (neg-int? sign) (.abs val) val)]
+        display-val (if (neg-int? sign) (.abs val) val)]
     (str
     (str
-      (when (neg-int? sign) "-")
-      (case base 2 "0b" 8 "0o" 16 "0x")
-      (.toString display-val base))))
+     (when (neg-int? sign) "-")
+     (case base 2 "0b" 8 "0o" 16 "0x")
+     (.toString display-val base))))
 
 
 (defn format-fraction [numerator denominator improper]
 (defn format-fraction [numerator denominator improper]
   (let [whole (.dividedToIntegerBy numerator denominator)]
   (let [whole (.dividedToIntegerBy numerator denominator)]
     (if (or improper (.isZero whole))
     (if (or improper (.isZero whole))
-      (str numerator "/" denominator )
+      (str numerator "/" denominator)
       (str whole " "
       (str whole " "
            (.abs (.modulo numerator denominator)) "/" denominator))))
            (.abs (.modulo numerator denominator)) "/" denominator))))
 
 
@@ -179,40 +178,40 @@
           places (get @env :places)]
           places (get @env :places)]
       (cond
       (cond
         (= base "hex")
         (= base "hex")
-          (format-base val 16)
+        (format-base val 16)
         (= base "oct")
         (= base "oct")
-          (format-base val 8)
+        (format-base val 8)
         (= base "bin")
         (= base "bin")
-          (format-base val 2)
+        (format-base val 2)
 
 
         (= mode "fix")
         (= mode "fix")
-          (if (can-fix? val places)
-            (.toFixed val places)
-            (.toExponential val places))
+        (if (can-fix? val places)
+          (.toFixed val places)
+          (.toExponential val places))
         (= mode "sci")
         (= mode "sci")
-          (.toExponential val places)
+        (.toExponential val places)
         (= mode "frac")
         (= mode "frac")
-          (let [max-denominator (or (get @env :max-denominator) 4095)
-                improper  (get @env :improper)
-                [numerator denominator] (.toFraction val max-denominator)
-                delta (.minus (.dividedBy numerator denominator) val)]
-            (if (or (.isZero delta) (< (.-e delta) -16))
-              (if (> denominator 1)
-                (format-fraction numerator denominator improper)
-                (format-normal env numerator))
-              (format-normal env val)))
+        (let [max-denominator (or (get @env :max-denominator) 4095)
+              improper  (get @env :improper)
+              [numerator denominator] (.toFraction val max-denominator)
+              delta (.minus (.dividedBy numerator denominator) val)]
+          (if (or (.isZero delta) (< (.-e delta) -16))
+            (if (> denominator 1)
+              (format-fraction numerator denominator improper)
+              (format-normal env numerator))
+            (format-normal env val)))
 
 
         :else
         :else
-          (format-normal env val)))
+        (format-normal env val)))
     val))
     val))
 
 
 (defn eval-lines [s]
 (defn eval-lines [s]
   {:pre [(string? s)]}
   {:pre [(string? s)]}
   (let [env (new-env)]
   (let [env (new-env)]
     (mapv (fn [line]
     (mapv (fn [line]
-            (when-not (str/blank? line)
+            (when-not (string/blank? line)
               (format-val env (assign-last-value env (eval env (parse line))))))
               (format-val env (assign-last-value env (eval env (parse line))))))
-          (str/split-lines s))))
+          (string/split-lines s))))
 
 
 ;; ======================================================================
 ;; ======================================================================
 ;; UI
 ;; UI
@@ -225,7 +224,7 @@
        ;; if we stop click propagation on this element, we allow the user to
        ;; if we stop click propagation on this element, we allow the user to
        ;; copy and paste the calc results
        ;; copy and paste the calc results
        [:div.extensions__code-calc.pr-2 {:on-pointer-down (fn [e]
        [:div.extensions__code-calc.pr-2 {:on-pointer-down (fn [e]
-                                                          (.stopPropagation e))}
+                                                            (.stopPropagation e))}
         ;; TODO: add react keys
         ;; TODO: add react keys
         (for [[i line] (map-indexed vector output-lines)]
         (for [[i line] (map-indexed vector output-lines)]
           [:div.extensions__code-calc-output-line.CodeMirror-line {:key i}
           [:div.extensions__code-calc-output-line.CodeMirror-line {:key i}

+ 8 - 8
src/main/frontend/extensions/video/youtube.cljs

@@ -1,13 +1,13 @@
 (ns frontend.extensions.video.youtube
 (ns frontend.extensions.video.youtube
-  (:require [rum.core :as rum]
-            [cljs.core.async :refer [<! chan go] :as a]
+  (:require [cljs.core.async :refer [<! chan go] :as a]
+            [clojure.string :as string]
             [frontend.components.svg :as svg]
             [frontend.components.svg :as svg]
+            [frontend.handler.notification :as notification]
+            [frontend.mobile.util :as mobile-util]
             [frontend.state :as state]
             [frontend.state :as state]
             [frontend.util :as util]
             [frontend.util :as util]
             [goog.object :as gobj]
             [goog.object :as gobj]
-            [clojure.string :as str]
-            [frontend.mobile.util :as mobile-util]
-            [frontend.handler.notification :as notification]))
+            [rum.core :as rum]))
 
 
 (defn- load-yt-script []
 (defn- load-yt-script []
   (js/console.log "load yt script")
   (js/console.log "load yt script")
@@ -79,7 +79,7 @@
                          (when (or (> idx 0)
                          (when (or (> idx 0)
                                    (not= v "00"))
                                    (not= v "00"))
                            v)))
                            v)))
-         (str/join ":"))))
+         (string/join ":"))))
 
 
 (defn dom-after-video-node? [video-node target]
 (defn dom-after-video-node? [video-node target]
   (not (zero?
   (not (zero?
@@ -92,11 +92,11 @@
                          (filter
                          (filter
                           (fn [node]
                           (fn [node]
                             (let [src (gobj/get node "src" "")]
                             (let [src (gobj/get node "src" "")]
-                              (str/includes? src "youtube.com"))))
+                              (string/includes? src "youtube.com"))))
                          (filter #(dom-after-video-node? % target))
                          (filter #(dom-after-video-node? % target))
                          last)]
                          last)]
     (let [id (gobj/get iframe "id" "")
     (let [id (gobj/get iframe "id" "")
-          id (str/replace-first id #"youtube-player-" "")]
+          id (string/replace-first id #"youtube-player-" "")]
       (get (get @state/state :youtube/players) id))))
       (get (get @state/state :youtube/players) id))))
 
 
 (rum/defc timestamp
 (rum/defc timestamp

+ 103 - 103
src/main/frontend/extensions/zotero.cljs

@@ -1,7 +1,7 @@
 (ns frontend.extensions.zotero
 (ns frontend.extensions.zotero
   (:require [cljs.core.async :refer [<! >! chan go go-loop] :as a]
   (:require [cljs.core.async :refer [<! >! chan go go-loop] :as a]
             [clojure.edn :refer [read-string]]
             [clojure.edn :refer [read-string]]
-            [clojure.string :as str]
+            [clojure.string :as string]
             [frontend.components.svg :as svg]
             [frontend.components.svg :as svg]
             [frontend.extensions.pdf.assets :as pdf-assets]
             [frontend.extensions.pdf.assets :as pdf-assets]
             [frontend.extensions.zotero.api :as api]
             [frontend.extensions.zotero.api :as api]
@@ -29,7 +29,7 @@
      {:on-click (fn [] (go
      {:on-click (fn [] (go
                          (set-is-creating-page! true)
                          (set-is-creating-page! true)
                          (<!
                          (<!
-                           (zotero-handler/create-zotero-page item {:block-dom-id id}))
+                          (zotero-handler/create-zotero-page item {:block-dom-id id}))
                          (set-is-creating-page! false)))}
                          (set-is-creating-page! false)))}
      [[:div [[:span.font-medium.mb-1.mr-1.text-sm title]
      [[:div [[:span.font-medium.mb-1.mr-1.text-sm title]
              [:span.zotero-search-item-type.text-xs.p-1.rounded type]]]
              [:span.zotero-search-item-type.text-xs.p-1.rounded type]]]
@@ -51,7 +51,7 @@
 
 
         search-fn (fn [s-term start]
         search-fn (fn [s-term start]
                     (go
                     (go
-                      (when-not (str/blank? s-term)
+                      (when-not (string/blank? s-term)
                         (set-is-searching! true)
                         (set-is-searching! true)
 
 
                         (let [{:keys [success next prev result] :as response}
                         (let [{:keys [success next prev result] :as response}
@@ -68,16 +68,16 @@
                         (set-is-searching! false))))]
                         (set-is-searching! false))))]
 
 
     (rum/use-effect!
     (rum/use-effect!
-      (fn []
-        (let [d-chan (chan)]
-          (a/tap debounce-chan-mult d-chan)
-          (go-loop []
-                   (let [d-term (<! d-chan)]
-                     (<! (search-fn d-term "0")))
-                   (recur))
+     (fn []
+       (let [d-chan (chan)]
+         (a/tap debounce-chan-mult d-chan)
+         (go-loop []
+           (let [d-term (<! d-chan)]
+             (<! (search-fn d-term "0")))
+           (recur))
 
 
-          (fn [] (a/untap debounce-chan-mult d-chan))))
-      [])
+         (fn [] (a/untap debounce-chan-mult d-chan))))
+     [])
 
 
     (when-not (setting/valid?)
     (when-not (setting/valid?)
       (route-handler/redirect! {:to :zotero-setting})
       (route-handler/redirect! {:to :zotero-setting})
@@ -103,24 +103,24 @@
      (when (seq search-result)
      (when (seq search-result)
        [:div.p-2
        [:div.p-2
         (map
         (map
-          (fn [item] (rum/with-key (zotero-search-item item id) (:key item)))
-          search-result)
+         (fn [item] (rum/with-key (zotero-search-item item id) (:key item)))
+         search-result)
 
 
         ;; pagination
         ;; pagination
-        (when-not (str/blank? prev-page)
+        (when-not (string/blank? prev-page)
           (ui/button
           (ui/button
-            "prev"
-            :on-click
-            (fn []
-              (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
-              (search-fn prev-search-term prev-page))))
-        (when-not (str/blank? next-page)
+           "prev"
+           :on-click
+           (fn []
+             (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
+             (search-fn prev-search-term prev-page))))
+        (when-not (string/blank? next-page)
           (ui/button
           (ui/button
-            "next"
-            :on-click
-            (fn []
-              (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
-              (search-fn prev-search-term next-page))))])]))
+           "next"
+           :on-click
+           (fn []
+             (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
+             (search-fn prev-search-term next-page))))])]))
 
 
 (rum/defcs user-or-group-setting <
 (rum/defcs user-or-group-setting <
   (rum/local (setting/setting :type-id) ::type-id)
   (rum/local (setting/setting :type-id) ::type-id)
@@ -137,11 +137,11 @@
        {:value     (-> (setting/setting :type) name)
        {:value     (-> (setting/setting :type) name)
         :on-change (fn [e]
         :on-change (fn [e]
                      (let [type (-> (util/evalue e)
                      (let [type (-> (util/evalue e)
-                                    (str/lower-case)
+                                    (string/lower-case)
                                     keyword)]
                                     keyword)]
                        (setting/set-setting! :type type)))}
                        (setting/set-setting! :type type)))}
        (for [type (map name [:user :group])]
        (for [type (map name [:user :group])]
-         [:option {:key type :value type} (str/capitalize type)])]]]]
+         [:option {:key type :value type} (string/capitalize type)])]]]]
 
 
    [:div.row
    [:div.row
     [:label.title.w-72
     [:label.title.w-72
@@ -156,15 +156,15 @@
         :on-change     (fn [e] (reset! (::type-id state) (util/evalue e)))}]]]]
         :on-change     (fn [e] (reset! (::type-id state) (util/evalue e)))}]]]]
 
 
    (when
    (when
-     (and (not (str/blank? (str @(::type-id state))))
-          (not (re-matches #"^\d+$" (str @(::type-id state)))))
+    (and (not (string/blank? (str @(::type-id state))))
+         (not (re-matches #"^\d+$" (str @(::type-id state)))))
      (ui/admonition
      (ui/admonition
-       :warning
-       [:p.text-error
-        "User ID is different from username and can be found on the "
-        [:a {:href "https://www.zotero.org/settings/keys" :target "_blank"}
-         "https://www.zotero.org/settings/keys"]
-        " page, it's a number of digits"]))])
+      :warning
+      [:p.text-error
+       "User ID is different from username and can be found on the "
+       [:a {:href "https://www.zotero.org/settings/keys" :target "_blank"}
+        "https://www.zotero.org/settings/keys"]
+       " page, it's a number of digits"]))])
 
 
 (rum/defc overwrite-mode-setting <
 (rum/defc overwrite-mode-setting <
   rum/reactive
   rum/reactive
@@ -181,9 +181,9 @@
                  true)]]]
                  true)]]]
    (when (setting/setting :overwrite-mode?)
    (when (setting/setting :overwrite-mode?)
      (ui/admonition
      (ui/admonition
-       :warning
-       [:p.text-error
-        "Dangerous! This will delete and recreate Zotero existing page! Make sure to backup your notes first in case something goes wrong. Make sure you don't put any personal item in previous Zotero page and it's OK to overwrite the page!"]))])
+      :warning
+      [:p.text-error
+       "Dangerous! This will delete and recreate Zotero existing page! Make sure to backup your notes first in case something goes wrong. Make sure you don't put any personal item in previous Zotero page and it's OK to overwrite the page!"]))])
 
 
 (rum/defc attachment-setting <
 (rum/defc attachment-setting <
   rum/reactive
   rum/reactive
@@ -335,15 +335,15 @@
      [:div.mt-5.sm:mt-4.sm:flex.sm:flex-row-reverse
      [:div.mt-5.sm:mt-4.sm:flex.sm:flex-row-reverse
       [:span.flex.w-full.rounded-md.shadow-sm.sm:ml-3.sm:w-auto
       [:span.flex.w-full.rounded-md.shadow-sm.sm:ml-3.sm:w-auto
        (ui/button
        (ui/button
-         "Submit"
-         :class "ui__modal-enter"
-         :on-click (fn []
-                     (let [profile-name (str/trim @input)]
-                       (when-not (str/blank? profile-name)
-                         (p/let [_ (setting/add-profile profile-name)
-                                 _ (setting/set-profile profile-name)]
-                           (reset! profile* profile-name)))
-                       (shui/dialog-close!))))]
+        "Submit"
+        :class "ui__modal-enter"
+        :on-click (fn []
+                    (let [profile-name (string/trim @input)]
+                      (when-not (string/blank? profile-name)
+                        (p/let [_ (setting/add-profile profile-name)
+                                _ (setting/set-profile profile-name)]
+                          (reset! profile* profile-name)))
+                      (shui/dialog-close!))))]
       [:span.mt-3.flex.w-full.rounded-md.sm:mt-0.sm:w-auto
       [:span.mt-3.flex.w-full.rounded-md.sm:mt-0.sm:w-auto
        (ui/button "Cancel" {:variant :ghost :on-click close-fn :class "opacity-70 hover:opacity-100"})]]]))
        (ui/button "Cancel" {:variant :ghost :on-click close-fn :class "opacity-70 hover:opacity-100"})]]]))
 
 
@@ -366,25 +366,25 @@
                               :value x}
                               :value x}
                              x]) (setting/all-profiles))]
                              x]) (setting/all-profiles))]
     (ui/button
     (ui/button
-      "New profile"
-      :small? true
-      :class "ml-4"
-      :on-click
-      (fn []
-        (shui/dialog-open!
-          (fn [{:keys [close]}]
-            (profile-name-dialog-inner profile* close))
-          {:align :center
-           :auto-width? true})))
+     "New profile"
+     :small? true
+     :class "ml-4"
+     :on-click
+     (fn []
+       (shui/dialog-open!
+        (fn [{:keys [close]}]
+          (profile-name-dialog-inner profile* close))
+        {:align :center
+         :auto-width? true})))
     (ui/button
     (ui/button
-      "Delete profile!"
-      :small? true
-      :background "red"
-      :class "ml-4"
-      :on-click
-      (fn []
-        (p/let [_ (setting/remove-profile @profile*)]
-          (reset! profile* (setting/get-profile)))))]])
+     "Delete profile!"
+     :small? true
+     :background "red"
+     :class "ml-4"
+     :on-click
+     (fn []
+       (p/let [_ (setting/remove-profile @profile*)]
+         (reset! profile* (setting/get-profile)))))]])
 
 
 (rum/defcs add-all-items <
 (rum/defcs add-all-items <
   (rum/local nil ::progress)
   (rum/local nil ::progress)
@@ -399,24 +399,24 @@
      "Add all zotero items"]
      "Add all zotero items"]
     [:div.mt-1.sm:mt-0.sm:col-span-2
     [:div.mt-1.sm:mt-0.sm:col-span-2
      (ui/button
      (ui/button
-       @(::fetching-button state)
-       :on-click
-       (fn []
-         (go
-           (let [_ (reset! (::fetching-button state) "Fetching..")
-                 total (<! (api/all-top-items-count))
-                 _ (reset! (::fetching-button state) "Add all")]
-             (when (.confirm
-                     js/window
-                     (str "This will import all your zotero items and add total number of " total " pages. Do you wish to continue?"))
-
-               (reset! (::total state) total)
-               (<! (zotero-handler/add-all (::progress state)))
-               (reset! (::total state) false)
-               (notification/show! "Successfully added all items!" :success))))))]]
+      @(::fetching-button state)
+      :on-click
+      (fn []
+        (go
+          (let [_ (reset! (::fetching-button state) "Fetching..")
+                total (<! (api/all-top-items-count))
+                _ (reset! (::fetching-button state) "Add all")]
+            (when (.confirm
+                   js/window
+                   (str "This will import all your zotero items and add total number of " total " pages. Do you wish to continue?"))
+
+              (reset! (::total state) total)
+              (<! (zotero-handler/add-all (::progress state)))
+              (reset! (::total state) false)
+              (notification/show! "Successfully added all items!" :success))))))]]
    (ui/admonition
    (ui/admonition
-     :warning
-     "If you have a lot of items in Zotero, adding them all can slow down Logseq. You can type /zotero to import specific item on demand instead.")
+    :warning
+    "If you have a lot of items in Zotero, adding them all can slow down Logseq. You can type /zotero to import specific item on demand instead.")
 
 
    (when @(::total state)
    (when @(::total state)
      [:div.row
      [:div.row
@@ -464,43 +464,43 @@
    (add-all-items)])
    (add-all-items)])
 
 
 (defn open-button [full-path]
 (defn open-button [full-path]
-  (if (str/ends-with? (str/lower-case full-path) "pdf")
+  (if (string/ends-with? (string/lower-case full-path) "pdf")
     (ui/button
     (ui/button
-      "open"
-      :small? true
-      :on-click
-      (fn [e]
-        (when-let [current (pdf-assets/inflate-asset full-path)]
-          (util/stop e)
-          (state/set-state! :pdf/current current))))
+     "open"
+     :small? true
+     :on-click
+     (fn [e]
+       (when-let [current (pdf-assets/inflate-asset full-path)]
+         (util/stop e)
+         (state/set-state! :pdf/current current))))
     (ui/button
     (ui/button
-      "open"
-      :small? true
-      :target "_blank"
-      :href full-path)))
+     "open"
+     :small? true
+     :target "_blank"
+     :href full-path)))
 
 
 (rum/defc zotero-imported-file
 (rum/defc zotero-imported-file
   [item-key filename]
   [item-key filename]
-  (if (str/blank? (setting/setting :zotero-data-directory))
+  (if (string/blank? (setting/setting :zotero-data-directory))
     [:p.warning "This is a zotero imported file, setting Zotero data directory would allow you to open the file in Logseq"]
     [:p.warning "This is a zotero imported file, setting Zotero data directory would allow you to open the file in Logseq"]
     (let [filename (read-string filename)
     (let [filename (read-string filename)
           full-path
           full-path
           (str "file://"
           (str "file://"
                (util/node-path.join
                (util/node-path.join
-                 (setting/setting :zotero-data-directory)
-                 "storage"
-                 item-key
-                 filename))]
+                (setting/setting :zotero-data-directory)
+                "storage"
+                item-key
+                filename))]
       (open-button full-path))))
       (open-button full-path))))
 
 
 (rum/defc zotero-linked-file
 (rum/defc zotero-linked-file
   [path]
   [path]
-  (if (str/blank? (setting/setting :zotero-linked-attachment-base-directory))
+  (if (string/blank? (setting/setting :zotero-linked-attachment-base-directory))
     [:p.warning "This is a zotero linked file, setting Zotero linked attachment base directory would allow you to open the file in Logseq"]
     [:p.warning "This is a zotero linked file, setting Zotero linked attachment base directory would allow you to open the file in Logseq"]
     (let [path (read-string path)
     (let [path (read-string path)
           full-path
           full-path
           (str "file://"
           (str "file://"
                (util/node-path.join
                (util/node-path.join
-                 (setting/setting :zotero-linked-attachment-base-directory)
-                 (str/replace-first path "attachments:" "")))]
+                (setting/setting :zotero-linked-attachment-base-directory)
+                (string/replace-first path "attachments:" "")))]
       (open-button full-path))))
       (open-button full-path))))

+ 7 - 7
src/main/frontend/extensions/zotero/api.cljs

@@ -4,9 +4,9 @@
             [cljs-http.client :as http]
             [cljs-http.client :as http]
             [cljs.core.async :as async
             [cljs.core.async :as async
              :refer [<! >! alt! chan close! go go-loop]]
              :refer [<! >! alt! chan close! go go-loop]]
-            [clojure.string :as str]
-            [frontend.util :as util]
-            [frontend.extensions.zotero.setting :as setting]))
+            [clojure.string :as string]
+            [frontend.extensions.zotero.setting :as setting]
+            [frontend.util :as util]))
 
 
 (defn config []
 (defn config []
   {:api-version 3
   {:api-version 3
@@ -39,14 +39,14 @@
                        :next "rel=\"next\""
                        :next "rel=\"next\""
                        :prev "rel=\"prev\"")
                        :prev "rel=\"prev\"")
         links
         links
-        (str/split
+        (string/split
          (:link (cske/transform-keys csk/->kebab-case-keyword headers)) ",")
          (:link (cske/transform-keys csk/->kebab-case-keyword headers)) ",")
         next-link   (->> links
         next-link   (->> links
-                         (filter (fn [l] (str/includes? l include-text)))
+                         (filter (fn [l] (string/includes? l include-text)))
                          first)]
                          first)]
     (when next-link
     (when next-link
-      (let [start    (str/index-of next-link "<")
-            end      (str/last-index-of next-link ">;")
+      (let [start    (string/index-of next-link "<")
+            end      (string/last-index-of next-link ">;")
             next-url (subs next-link (inc start) end)]
             next-url (subs next-link (inc start) end)]
         (or
         (or
          (->
          (->

+ 8 - 8
src/main/frontend/extensions/zotero/handler.cljs

@@ -1,15 +1,15 @@
 (ns frontend.extensions.zotero.handler
 (ns frontend.extensions.zotero.handler
   (:require [cljs.core.async :refer [<! go]]
   (:require [cljs.core.async :refer [<! go]]
             [cljs.core.async.interop :refer [p->c]]
             [cljs.core.async.interop :refer [p->c]]
-            [clojure.string :as str]
+            [clojure.string :as string]
+            [frontend.db :as db]
             [frontend.extensions.zotero.api :as zotero-api]
             [frontend.extensions.zotero.api :as zotero-api]
             [frontend.extensions.zotero.extractor :as extractor]
             [frontend.extensions.zotero.extractor :as extractor]
             [frontend.extensions.zotero.setting :as setting]
             [frontend.extensions.zotero.setting :as setting]
-            [frontend.handler.notification :as notification]
-            [frontend.state :as state]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.editor :as editor-handler]
+            [frontend.handler.notification :as notification]
             [frontend.handler.page :as page-handler]
             [frontend.handler.page :as page-handler]
-            [frontend.db :as db]
+            [frontend.state :as state]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [promesa.core :as p]))
             [promesa.core :as p]))
 
 
@@ -31,7 +31,7 @@
         (let [items    (<! (api-fn key))
         (let [items    (<! (api-fn key))
               md-items (->> items
               md-items (->> items
                             (map extractor/extract)
                             (map extractor/extract)
-                            (remove str/blank?))]
+                            (remove string/blank?))]
           (when (not-empty md-items)
           (when (not-empty md-items)
             (p->c
             (p->c
              (p/let [result (editor-handler/api-insert-new-block! first-block {:page page-name})]
              (p/let [result (editor-handler/api-insert-new-block! first-block {:page page-name})]
@@ -52,7 +52,7 @@
 
 
 (defn- create-abstract-note!
 (defn- create-abstract-note!
   [page-name abstract-note]
   [page-name abstract-note]
-  (when-not (str/blank? abstract-note)
+  (when-not (string/blank? abstract-note)
     (p/let [block (editor-handler/api-insert-new-block!
     (p/let [block (editor-handler/api-insert-new-block!
                    "[[Abstract]]" {:page page-name})]
                    "[[Abstract]]" {:page page-name})]
       (editor-handler/api-insert-new-block!
       (editor-handler/api-insert-new-block!
@@ -76,8 +76,8 @@
      (let [{:keys [page-name properties abstract-note]} (extractor/extract item)]
      (let [{:keys [page-name properties abstract-note]} (extractor/extract item)]
        (p->c
        (p->c
         (p/do!
         (p/do!
-         (when-not (str/blank? page-name)
-           (if (db/page-exists? (str/lower-case page-name) "page")
+         (when-not (string/blank? page-name)
+           (if (db/page-exists? (string/lower-case page-name) "page")
              ;; FIXME: Overwrite if it has a zotero tag (which means created by Zotero)
              ;; FIXME: Overwrite if it has a zotero tag (which means created by Zotero)
              (if (setting/setting :overwrite-mode?)
              (if (setting/setting :overwrite-mode?)
                (page-handler/<delete!
                (page-handler/<delete!

+ 5 - 5
src/main/frontend/extensions/zotero/setting.cljs

@@ -1,9 +1,9 @@
 (ns frontend.extensions.zotero.setting
 (ns frontend.extensions.zotero.setting
-  (:require [clojure.string :as str]
-            [promesa.core :as p]
+  (:require [clojure.string :as string]
             [frontend.handler.config :as config-handler]
             [frontend.handler.config :as config-handler]
             [frontend.state :as state]
             [frontend.state :as state]
-            [frontend.storage :as storage]))
+            [frontend.storage :as storage]
+            [promesa.core :as p]))
 
 
 (def default-settings
 (def default-settings
   {:type                                    :user
   {:type                                    :user
@@ -71,5 +71,5 @@
 
 
 (defn valid? []
 (defn valid? []
   (and
   (and
-   (not (str/blank? (api-key)))
-   (not (str/blank? (setting :type-id)))))
+   (not (string/blank? (api-key)))
+   (not (string/blank? (setting :type-id)))))

+ 14 - 14
src/main/frontend/external/roam_export.cljs

@@ -1,6 +1,6 @@
 (ns ^:no-doc frontend.external.roam-export
 (ns ^:no-doc frontend.external.roam-export
   (:require [clojure.set :as s]
   (:require [clojure.set :as s]
-            [clojure.string :as str]
+            [clojure.string :as string]
             [clojure.walk :as walk]
             [clojure.walk :as walk]
             [frontend.db.async :as db-async]
             [frontend.db.async :as db-async]
             [frontend.state :as state]
             [frontend.state :as state]
@@ -18,7 +18,7 @@
 
 
 (defn nano-id []
 (defn nano-id []
   (->> (repeatedly 9 nano-id-char)
   (->> (repeatedly 9 nano-id-char)
-       (str/join)))
+       (string/join)))
 
 
 (defn <uuid->uid-map []
 (defn <uuid->uid-map []
   (let [repo (state/get-current-repo)]
   (let [repo (state/get-current-repo)]
@@ -36,13 +36,13 @@
 (defn update-content [content uuid->uid-map]
 (defn update-content [content uuid->uid-map]
   (when content                         ; page block doesn't have content
   (when content                         ; page block doesn't have content
     (let [uuids (keys uuid->uid-map)]
     (let [uuids (keys uuid->uid-map)]
-     (reduce
-      (fn [acc uuid]
-        (if (str/includes? acc (str uuid))
-          (str/replace acc (str uuid) (get uuid->uid-map uuid))
-          acc))
-      content
-      uuids))))
+      (reduce
+       (fn [acc uuid]
+         (if (string/includes? acc (str uuid))
+           (string/replace acc (str uuid) (get uuid->uid-map uuid))
+           acc))
+       content
+       uuids))))
 
 
 (defn update-uid [{:block/keys [uuid title] :as b}
 (defn update-uid [{:block/keys [uuid title] :as b}
                   uuid->uid-map]
                   uuid->uid-map]
@@ -50,7 +50,7 @@
     (contains? uuid->uid-map uuid)
     (contains? uuid->uid-map uuid)
     (assoc :block/uid (get uuid->uid-map uuid))
     (assoc :block/uid (get uuid->uid-map uuid))
 
 
-    (some (fn [id] (str/includes? (str title) (str id))) (keys uuid->uid-map))
+    (some (fn [id] (string/includes? (str title) (str id))) (keys uuid->uid-map))
     (update :block/title #(update-content % uuid->uid-map))))
     (update :block/title #(update-content % uuid->uid-map))))
 
 
 (defn update-todo [{:block/keys [title] :as block}]
 (defn update-todo [{:block/keys [title] :as block}]
@@ -58,10 +58,10 @@
     (update block :block/title
     (update block :block/title
             (fn [c]
             (fn [c]
               (-> c
               (-> c
-                  (str/replace todo-marker-regex "{{[[TODO]]}}")
-                  (str/replace done-marker-regex "{{[[DONE]]}}")
-                  (str/replace "{{embed " "{{embed: ")
-                  (str/trim))))
+                  (string/replace todo-marker-regex "{{[[TODO]]}}")
+                  (string/replace done-marker-regex "{{[[DONE]]}}")
+                  (string/replace "{{embed " "{{embed: ")
+                  (string/trim))))
     block))
     block))
 
 
 (defn traverse
 (defn traverse

+ 62 - 0
src/main/frontend/handler/profiler.cljs

@@ -0,0 +1,62 @@
+(ns frontend.handler.profiler
+  "Provides fns for profiling.
+  TODO: support both main thread and worker thread."
+  (:require [goog.object :as g]))
+
+(def ^:private *fn-symbol->key->call-count (volatile! {}))
+(def ^:private *fn-symbol->key->time-sum (volatile! {}))
+
+(def *fn-symbol->origin-fn (atom {}))
+
+(defn- get-profile-fn
+  [fn-sym original-fn custom-key-fn]
+  (fn profile-fn-inner [& args]
+    (let [start (system-time)
+          r (apply original-fn args)
+          elapsed-time (- (system-time) start)
+          k (when custom-key-fn (custom-key-fn r))]
+      (vswap! *fn-symbol->key->call-count update-in [fn-sym :total] inc)
+      (vswap! *fn-symbol->key->time-sum update-in [fn-sym :total] #(+ % elapsed-time))
+      (when k
+        (vswap! *fn-symbol->key->call-count update-in [fn-sym k] inc)
+        (vswap! *fn-symbol->key->time-sum update-in [fn-sym k] #(+ % elapsed-time)))
+      r)))
+
+(defn register-fn!
+  [fn-sym & {:keys [custom-key-fn] :as _opts}]
+  (assert (qualified-symbol? fn-sym))
+  (let [ns (namespace fn-sym)
+        s (munge (name fn-sym))]
+    (if-let [original-fn (find-ns-obj (str ns "." s))]
+      (let [profiled-fn (get-profile-fn fn-sym original-fn custom-key-fn)]
+        (swap! *fn-symbol->origin-fn assoc fn-sym original-fn)
+        (g/set (find-ns-obj ns) s profiled-fn))
+      (throw (ex-info (str "fn-sym not found: " fn-sym) {})))))
+
+(defn unregister-fn!
+  [fn-sym]
+  (let [ns (namespace fn-sym)
+        s (munge (name fn-sym))]
+    (vswap! *fn-symbol->key->call-count dissoc fn-sym)
+    (vswap! *fn-symbol->key->time-sum dissoc fn-sym)
+    (when-let [origin-fn (get @*fn-symbol->origin-fn fn-sym)]
+      (some-> (find-ns-obj ns) (g/set s origin-fn))
+      (swap! *fn-symbol->origin-fn dissoc fn-sym))))
+
+(defn reset-report!
+  []
+  (vreset! *fn-symbol->key->call-count {})
+  (vreset! *fn-symbol->key->time-sum {}))
+
+(defn profile-report
+  []
+  {:call-count @*fn-symbol->key->call-count
+   :time-sum @*fn-symbol->key->time-sum})
+
+(comment
+  (register-fn! 'datascript.core/entity)
+  (prn :profiling (keys @*fn-symbol->origin-fn))
+  (prn :report)
+  (pprint/pprint (profile-report))
+  (reset-report!)
+  (unregister-fn! 'datascript.core/entity))

+ 2 - 2
src/main/frontend/modules/shortcut/config.cljs

@@ -1,6 +1,6 @@
 (ns frontend.modules.shortcut.config
 (ns frontend.modules.shortcut.config
   (:require [clojure.data :as data]
   (:require [clojure.data :as data]
-            [clojure.string :as str]
+            [clojure.string :as string]
             [electron.ipc :as ipc]
             [electron.ipc :as ipc]
             [frontend.commands :as commands]
             [frontend.commands :as commands]
             [frontend.components.commit :as commit]
             [frontend.components.commit :as commit]
@@ -1026,7 +1026,7 @@
    (swap! *config assoc-in [handler-id id] shortcut-map)
    (swap! *config assoc-in [handler-id id] shortcut-map)
    (when-not config-only?
    (when-not config-only?
      (swap! *shortcut-cmds assoc id (:cmd shortcut-map))
      (swap! *shortcut-cmds assoc id (:cmd shortcut-map))
-     (let [plugin? (str/starts-with? (str id) ":plugin.")
+     (let [plugin? (string/starts-with? (str id) ":plugin.")
            category (or (:category shortcut-map)
            category (or (:category shortcut-map)
                         (if plugin?
                         (if plugin?
                           :shortcut.category/plugins
                           :shortcut.category/plugins

+ 34 - 34
src/main/frontend/modules/shortcut/core.cljs

@@ -1,11 +1,11 @@
 (ns frontend.modules.shortcut.core
 (ns frontend.modules.shortcut.core
-  (:require [clojure.string :as str]
+  (:require [clojure.string :as string]
             [frontend.handler.config :as config-handler]
             [frontend.handler.config :as config-handler]
             [frontend.handler.global-config :as global-config-handler]
             [frontend.handler.global-config :as global-config-handler]
-            [frontend.handler.plugin :as plugin-handler]
             [frontend.handler.notification :as notification]
             [frontend.handler.notification :as notification]
-            [frontend.modules.shortcut.data-helper :as dh]
+            [frontend.handler.plugin :as plugin-handler]
             [frontend.modules.shortcut.config :as shortcut-config]
             [frontend.modules.shortcut.config :as shortcut-config]
+            [frontend.modules.shortcut.data-helper :as dh]
             [frontend.modules.shortcut.utils :as shortcut-utils]
             [frontend.modules.shortcut.utils :as shortcut-utils]
             [frontend.state :as state]
             [frontend.state :as state]
             [frontend.util :as util]
             [frontend.util :as util]
@@ -20,10 +20,10 @@
 (defonce *pending-shortcuts (atom []))
 (defonce *pending-shortcuts (atom []))
 
 
 (def global-keys #js
 (def global-keys #js
-        [KeyCodes/TAB
-         KeyCodes/ENTER
-         KeyCodes/BACKSPACE KeyCodes/DELETE
-         KeyCodes/UP KeyCodes/LEFT KeyCodes/DOWN KeyCodes/RIGHT])
+                  [KeyCodes/TAB
+                   KeyCodes/ENTER
+                   KeyCodes/BACKSPACE KeyCodes/DELETE
+                   KeyCodes/UP KeyCodes/LEFT KeyCodes/DOWN KeyCodes/RIGHT])
 
 
 (def key-names (js->clj KeyNames))
 (def key-names (js->clj KeyNames))
 
 
@@ -82,7 +82,7 @@
                (log/error :shortcut/register-shortcut {:id      id
                (log/error :shortcut/register-shortcut {:id      id
                                                        :binding k
                                                        :binding k
                                                        :error   e})
                                                        :error   e})
-               (notification/show! (str/join " " [id k (.-message e)]) :error false)))))))))
+               (notification/show! (string/join " " [id k (.-message e)]) :error false)))))))))
 
 
 (defn unregister-shortcut!
 (defn unregister-shortcut!
   "Unregister a shortcut.
   "Unregister a shortcut.
@@ -114,9 +114,9 @@
 
 
   ;; force uninstall existed handler
   ;; force uninstall existed handler
   (some->>
   (some->>
-    (get-installed-ids-by-handler-id handler-id)
-    (map #(uninstall-shortcut-handler! % true))
-    (doall))
+   (get-installed-ids-by-handler-id handler-id)
+   (map #(uninstall-shortcut-handler! % true))
+   (doall))
 
 
   (let [shortcut-map (dh/shortcuts-map-by-handler-id handler-id state)
   (let [shortcut-map (dh/shortcuts-map-by-handler-id handler-id state)
         handler (new KeyboardShortcutHandler js/window)]
         handler (new KeyboardShortcutHandler js/window)]
@@ -167,25 +167,25 @@
   ([handler-id] (mixin handler-id true))
   ([handler-id] (mixin handler-id true))
   ([handler-id remount-reinstall?]
   ([handler-id remount-reinstall?]
    (cond->
    (cond->
-     {:did-mount
-      (fn [state]
-        (let [install-id (install-shortcut-handler! handler-id {:state state})]
-          (assoc state ::install-id install-id)))
+    {:did-mount
+     (fn [state]
+       (let [install-id (install-shortcut-handler! handler-id {:state state})]
+         (assoc state ::install-id install-id)))
 
 
-      :will-unmount
-      (fn [state]
-        (when-let [install-id (::install-id state)]
-          (uninstall-shortcut-handler! install-id))
-        state)}
+     :will-unmount
+     (fn [state]
+       (when-let [install-id (::install-id state)]
+         (uninstall-shortcut-handler! install-id))
+       state)}
 
 
      remount-reinstall?
      remount-reinstall?
      (assoc
      (assoc
-       :will-remount
-       (fn [old-state new-state]
-         (util/profile "[shortcuts] reinstalled:"
-                       (uninstall-shortcut-handler! (::install-id old-state))
-                       (when-let [install-id (install-shortcut-handler! handler-id {:state new-state})]
-                         (assoc new-state ::install-id install-id))))))))
+      :will-remount
+      (fn [old-state new-state]
+        (util/profile "[shortcuts] reinstalled:"
+                      (uninstall-shortcut-handler! (::install-id old-state))
+                      (when-let [install-id (install-shortcut-handler! handler-id {:state new-state})]
+                        (assoc new-state ::install-id install-id))))))))
 
 
 (defn mixin*
 (defn mixin*
   "This is an optimized version compared to (mixin).
   "This is an optimized version compared to (mixin).
@@ -197,7 +197,7 @@
      (let [*state (volatile! state)
      (let [*state (volatile! state)
            install-id (install-shortcut-handler! handler-id {:state *state})]
            install-id (install-shortcut-handler! handler-id {:state *state})]
        (assoc state ::install-id install-id
        (assoc state ::install-id install-id
-                    ::*state *state)))
+              ::*state *state)))
 
 
    :will-remount
    :will-remount
    (fn [old-state new-state]
    (fn [old-state new-state]
@@ -260,10 +260,10 @@
         shift (.-shiftKey e)
         shift (.-shiftKey e)
         keyname (get key-names (str (.-keyCode e)))]
         keyname (get key-names (str (.-keyCode e)))]
     (cond->> keyname
     (cond->> keyname
-             ctrl (str "ctrl+")
-             alt (str "alt+")
-             meta (str "meta+")
-             shift (str "shift+"))))
+      ctrl (str "ctrl+")
+      alt (str "alt+")
+      meta (str "meta+")
+      shift (str "shift+"))))
 
 
 (defn keyname [e]
 (defn keyname [e]
   (let [name (get key-names (str (.-keyCode e)))]
   (let [name (get key-names (str (.-keyCode e)))]
@@ -283,9 +283,9 @@
                 (dissoc id)
                 (dissoc id)
 
 
                 (and global?
                 (and global?
-                  (or (string? binding)
-                    (vector? binding)
-                    (boolean? binding)))
+                     (or (string? binding)
+                         (vector? binding)
+                         (boolean? binding)))
                 (assoc id binding)))]
                 (assoc id binding)))]
       ;; TODO: exclude current graph config shortcuts
       ;; TODO: exclude current graph config shortcuts
       (config-handler/set-config! :shortcuts (into-shortcuts graph-shortcuts))
       (config-handler/set-config! :shortcuts (into-shortcuts graph-shortcuts))

+ 53 - 53
src/main/frontend/modules/shortcut/data_helper.cljs

@@ -1,7 +1,7 @@
 (ns frontend.modules.shortcut.data-helper
 (ns frontend.modules.shortcut.data-helper
-  (:require [clojure.set :refer [rename-keys] :as set]
-            [clojure.string :as str]
-            [cljs-bean.core :as bean]
+  (:require [cljs-bean.core :as bean]
+            [clojure.set :refer [rename-keys] :as set]
+            [clojure.string :as string]
             [frontend.context.i18n :refer [t]]
             [frontend.context.i18n :refer [t]]
             [frontend.modules.shortcut.config :as shortcut-config]
             [frontend.modules.shortcut.config :as shortcut-config]
             [frontend.modules.shortcut.utils :as shortcut-utils]
             [frontend.modules.shortcut.utils :as shortcut-utils]
@@ -20,27 +20,27 @@
               {id (if binding-only?
               {id (if binding-only?
                     (get user-shortcuts id binding)
                     (get user-shortcuts id binding)
                     (assoc opts :user-binding (get user-shortcuts id)
                     (assoc opts :user-binding (get user-shortcuts id)
-                                :handler-id (get-group id)
-                                :id id))}))
+                           :handler-id (get-group id)
+                           :id id))}))
        (into {})))
        (into {})))
 
 
 (defn- flatten-bindings-by-key
 (defn- flatten-bindings-by-key
   [config user-shortcuts]
   [config user-shortcuts]
   (reduce-kv
   (reduce-kv
-    (fn [r handler-id vs]
-      (reduce-kv
-        (fn [r id {:keys [binding]}]
-          (if-let [ks (get user-shortcuts id binding)]
-            (let [ks (if (sequential? ks) ks [ks])]
-              (reduce (fn [a k]
-                        (let [k (shortcut-utils/undecorate-binding k)
-                              k' (shortcut-utils/safe-parse-string-binding k)
-                              k' (bean/->clj k')]
-                          (-> a
-                              (assoc-in [k' :key] k)
-                              (assoc-in [k' :refs id] handler-id)))) r ks))
-            r)) r vs))
-    {} config))
+   (fn [r handler-id vs]
+     (reduce-kv
+      (fn [r id {:keys [binding]}]
+        (if-let [ks (get user-shortcuts id binding)]
+          (let [ks (if (sequential? ks) ks [ks])]
+            (reduce (fn [a k]
+                      (let [k (shortcut-utils/undecorate-binding k)
+                            k' (shortcut-utils/safe-parse-string-binding k)
+                            k' (bean/->clj k')]
+                        (-> a
+                            (assoc-in [k' :key] k)
+                            (assoc-in [k' :refs id] handler-id)))) r ks))
+          r)) r vs))
+   {} config))
 
 
 (def m-flatten-bindings-by-id
 (def m-flatten-bindings-by-id
   (util/memoize-last flatten-bindings-by-id))
   (util/memoize-last flatten-bindings-by-id))
@@ -65,13 +65,13 @@
   (let [{:keys [id desc cmd]} binding-map
   (let [{:keys [id desc cmd]} binding-map
         desc (or desc (:desc cmd) (some-> id (shortcut-utils/decorate-namespace) (t)))]
         desc (or desc (:desc cmd) (some-> id (shortcut-utils/decorate-namespace) (t)))]
     (if (or (nil? desc)
     (if (or (nil? desc)
-            (and (string? desc) (str/starts-with? desc "{Missing")))
+            (and (string? desc) (string/starts-with? desc "{Missing")))
       (str id) desc)))
       (str id) desc)))
 
 
 (defn mod-key [shortcut]
 (defn mod-key [shortcut]
   (when (string? shortcut)
   (when (string? shortcut)
-    (str/replace shortcut #"(?i)mod"
-                 (if util/mac? "meta" "ctrl"))))
+    (string/replace shortcut #"(?i)mod"
+                    (if util/mac? "meta" "ctrl"))))
 
 
 (defn shortcut-binding
 (defn shortcut-binding
   "override by user custom binding"
   "override by user custom binding"
@@ -88,10 +88,10 @@
 
 
       :else
       :else
       (->>
       (->>
-        (if (string? shortcut)
-          [shortcut]
-          shortcut)
-        (mapv mod-key)))))
+       (if (string? shortcut)
+         [shortcut]
+         shortcut)
+       (mapv mod-key)))))
 
 
 (defn shortcut-item
 (defn shortcut-item
   [id]
   [id]
@@ -102,14 +102,14 @@
   (let [dict (get-bindings-ids-map)
   (let [dict (get-bindings-ids-map)
         plugin? (= name :shortcut.category/plugins)]
         plugin? (= name :shortcut.category/plugins)]
     (->> (if plugin?
     (->> (if plugin?
-           (->> (keys dict) (filter #(str/starts-with? (str %) ":plugin.")))
+           (->> (keys dict) (filter #(string/starts-with? (str %) ":plugin.")))
            (shortcut-config/get-category-shortcuts name))
            (shortcut-config/get-category-shortcuts name))
          (mapv (fn [k] [k (assoc (get dict k) :category name)])))))
          (mapv (fn [k] [k (assoc (get dict k) :category name)])))))
 
 
 (defn shortcuts-map-full
 (defn shortcuts-map-full
   []
   []
   (->> (vals @shortcut-config/*config)
   (->> (vals @shortcut-config/*config)
-    (into {})))
+       (into {})))
 
 
 (defn shortcuts-map-by-handler-id
 (defn shortcuts-map-by-handler-id
   ([handler-id]
   ([handler-id]
@@ -123,15 +123,15 @@
                         (into {}))
                         (into {}))
          before (-> raw meta :before)]
          before (-> raw meta :before)]
      (cond->> handler-m
      (cond->> handler-m
-              state (reduce-kv (fn [r k handle-fn]
-                                 (let [handle-fn' (if (volatile? state)
-                                                    (fn [*state & args] (apply handle-fn (cons @*state args)))
-                                                    handle-fn)]
-                                   (assoc r k (partial handle-fn' state))))
-                               {})
-              before (reduce-kv (fn [r k f]
-                                  (assoc r k (before f (get raw' k))))
-                                {})))))
+       state (reduce-kv (fn [r k handle-fn]
+                          (let [handle-fn' (if (volatile? state)
+                                             (fn [*state & args] (apply handle-fn (cons @*state args)))
+                                             handle-fn)]
+                            (assoc r k (partial handle-fn' state))))
+                        {})
+       before (reduce-kv (fn [r k f]
+                           (assoc r k (before f (get raw' k))))
+                         {})))))
 
 
 ;; if multiple bindings, gen seq for first binding only for now
 ;; if multiple bindings, gen seq for first binding only for now
 (defn gen-shortcut-seq [id]
 (defn gen-shortcut-seq [id]
@@ -139,8 +139,8 @@
     (if (false? bindings)
     (if (false? bindings)
       []
       []
       (-> bindings
       (-> bindings
-        last
-        (str/split #" |\+")))))
+          last
+          (string/split #" |\+")))))
 
 
 (defn binding-for-display [k binding]
 (defn binding-for-display [k binding]
   (let [tmp (cond
   (let [tmp (cond
@@ -158,11 +158,11 @@
               :else
               :else
               (->> binding
               (->> binding
                    (map shortcut-utils/decorate-binding)
                    (map shortcut-utils/decorate-binding)
-                   (str/join " | ")))]
+                   (string/join " | ")))]
 
 
     ;; Display "cmd" rather than "meta" to the user to describe the Mac
     ;; Display "cmd" rather than "meta" to the user to describe the Mac
     ;; mod key, because that's what the Mac keyboards actually say.
     ;; mod key, because that's what the Mac keyboards actually say.
-    (str/replace tmp "meta" "cmd")))
+    (string/replace tmp "meta" "cmd")))
 
 
 (defn get-group
 (defn get-group
   "Given shortcut key, return handler group
   "Given shortcut key, return handler group
@@ -208,10 +208,10 @@
                            (when-let [{:keys [key refs]} o]
                            (when-let [{:keys [key refs]} o]
                              [k [key (reduce-kv (fn [r id handler-id']
                              [k [key (reduce-kv (fn [r id handler-id']
                                                   (if (and
                                                   (if (and
-                                                        (not (contains? exclude-ids id))
-                                                        (or (= handler-ids #{handler-id'})
-                                                            (and (set? handler-ids) (contains? handler-ids handler-id'))
-                                                            (and global? (contains? global-handlers handler-id'))))
+                                                       (not (contains? exclude-ids id))
+                                                       (or (= handler-ids #{handler-id'})
+                                                           (and (set? handler-ids) (contains? handler-ids handler-id'))
+                                                           (and global? (contains? global-handlers handler-id'))))
                                                     (assoc r id handler-id')
                                                     (assoc r id handler-id')
                                                     r))
                                                     r))
                                                 {} refs)]]))]
                                                 {} refs)]]))]
@@ -233,19 +233,19 @@
     (when-let [target (some-> target (mod-key) (shortcut-utils/safe-parse-string-binding) (bean/->clj))]
     (when-let [target (some-> target (mod-key) (shortcut-utils/safe-parse-string-binding) (bean/->clj))]
       (->> from-binding
       (->> from-binding
            (filterv
            (filterv
-             #(when-let [from (some-> % (mod-key) (shortcut-utils/safe-parse-string-binding) (bean/->clj))]
-                (or (= from target)
-                    (and (or (= (count from) 1)
-                             (= (count target) 1))
-                         (= (first target) (first from))))))))))
+            #(when-let [from (some-> % (mod-key) (shortcut-utils/safe-parse-string-binding) (bean/->clj))]
+               (or (= from target)
+                   (and (or (= (count from) 1)
+                            (= (count target) 1))
+                        (= (first target) (first from))))))))))
 
 
 (defn shortcut-data-by-id [id]
 (defn shortcut-data-by-id [id]
   (let [binding (shortcut-binding id)
   (let [binding (shortcut-binding id)
         data (-> (shortcuts-map-full) id)]
         data (-> (shortcuts-map-full) id)]
     (assoc
     (assoc
-      data
-      :binding
-      (binding-for-display id binding))))
+     data
+     :binding
+     (binding-for-display id binding))))
 
 
 (defn shortcuts->commands [handler-id]
 (defn shortcuts->commands [handler-id]
   (let [m (get @shortcut-config/*config handler-id)]
   (let [m (get @shortcut-config/*config handler-id)]

+ 21 - 21
src/main/frontend/modules/shortcut/utils.cljs

@@ -1,5 +1,5 @@
 (ns frontend.modules.shortcut.utils
 (ns frontend.modules.shortcut.utils
-  (:require [clojure.string :as str]
+  (:require [clojure.string :as string]
             [frontend.util :as util])
             [frontend.util :as util])
   (:import [goog.ui KeyboardShortcutHandler]))
   (:import [goog.ui KeyboardShortcutHandler]))
 
 
@@ -11,8 +11,8 @@
       (js/console.warn "[shortcuts] parse key error: " e) binding)))
       (js/console.warn "[shortcuts] parse key error: " e) binding)))
 
 
 (defn mod-key [binding]
 (defn mod-key [binding]
-  (str/replace binding #"(?i)mod"
-               (if util/mac? "meta" "ctrl")))
+  (string/replace binding #"(?i)mod"
+                  (if util/mac? "meta" "ctrl")))
 
 
 (defn undecorate-binding
 (defn undecorate-binding
   [binding]
   [binding]
@@ -32,10 +32,10 @@
                     "↑"  "up"
                     "↑"  "up"
                     "↓"  "down"}]
                     "↓"  "down"}]
       (-> binding
       (-> binding
-          (str/replace #"[;=-\[\]'\(\)\~\→\←\⇧]" #(get keynames %))
-          (str/replace #"\s+" " ")
+          (string/replace #"[;=-\[\]'\(\)\~\→\←\⇧]" #(get keynames %))
+          (string/replace #"\s+" " ")
           (mod-key)
           (mod-key)
-          (str/lower-case)))))
+          (string/lower-case)))))
 
 
 (defn decorate-namespace [k]
 (defn decorate-namespace [k]
   (let [n (name k)
   (let [n (name k)
@@ -45,18 +45,18 @@
 (defn decorate-binding [binding]
 (defn decorate-binding [binding]
   (when (or (string? binding)
   (when (or (string? binding)
             (sequential? binding))
             (sequential? binding))
-    (-> (if (string? binding) binding (str/join "+" binding))
-        (str/replace "mod" (if util/mac? "⌘" "ctrl"))
-        (str/replace "meta" (if util/mac? "⌘" "⊞ win"))
-        (str/replace "alt" (if util/mac? "opt" "alt"))
-        (str/replace "shift+/" "?")
-        (str/replace "left" "←")
-        (str/replace "right" "→")
-        (str/replace "up" "↑")
-        (str/replace "down" "↓")
-        (str/replace "shift" "⇧")
-        (str/replace "open-square-bracket" "[")
-        (str/replace "close-square-bracket" "]")
-        (str/replace "equals" "=")
-        (str/replace "semicolon" ";")
-        (str/lower-case))))
+    (-> (if (string? binding) binding (string/join "+" binding))
+        (string/replace "mod" (if util/mac? "⌘" "ctrl"))
+        (string/replace "meta" (if util/mac? "⌘" "⊞ win"))
+        (string/replace "alt" (if util/mac? "opt" "alt"))
+        (string/replace "shift+/" "?")
+        (string/replace "left" "←")
+        (string/replace "right" "→")
+        (string/replace "up" "↑")
+        (string/replace "down" "↓")
+        (string/replace "shift" "⇧")
+        (string/replace "open-square-bracket" "[")
+        (string/replace "close-square-bracket" "]")
+        (string/replace "equals" "=")
+        (string/replace "semicolon" ";")
+        (string/lower-case))))

+ 38 - 38
src/main/frontend/rum.cljs

@@ -1,18 +1,18 @@
 (ns frontend.rum
 (ns frontend.rum
   "Utility fns for rum"
   "Utility fns for rum"
-  (:require [clojure.string :as s]
+  (:require [cljs-bean.core :as bean]
             [clojure.set :as set]
             [clojure.set :as set]
+            [clojure.string :as string]
             [clojure.walk :as w]
             [clojure.walk :as w]
-            [rum.core :refer [use-state use-effect!] :as rum]
             [daiquiri.interpreter :as interpreter]
             [daiquiri.interpreter :as interpreter]
-            [cljs-bean.core :as bean]))
+            [rum.core :refer [use-state use-effect!] :as rum]))
 
 
 ;; copy from https://github.com/priornix/antizer/blob/35ba264cf48b84e6597743e28b3570d8aa473e74/src/antizer/core.cljs
 ;; copy from https://github.com/priornix/antizer/blob/35ba264cf48b84e6597743e28b3570d8aa473e74/src/antizer/core.cljs
 
 
 (defn kebab-case->camel-case
 (defn kebab-case->camel-case
   "Converts from kebab case to camel case, eg: on-click to onClick"
   "Converts from kebab case to camel case, eg: on-click to onClick"
   [input]
   [input]
-  (s/replace input #"-([a-z])" (fn [[_ c]] (s/upper-case c))))
+  (string/replace input #"-([a-z])" (fn [[_ c]] (string/upper-case c))))
 
 
 (defn map-keys->camel-case
 (defn map-keys->camel-case
   "Stringifys all the keys of a cljs hashmap and converts them
   "Stringifys all the keys of a cljs hashmap and converts them
@@ -38,46 +38,46 @@
    (adapt-class react-class false))
    (adapt-class react-class false))
   ([react-class skip-opts-transform?]
   ([react-class skip-opts-transform?]
    (fn [& args]
    (fn [& args]
-    (let [[opts children] (if (map? (first args))
-                            [(first args) (rest args)]
-                            [{} args])
-          type# (first children)
+     (let [[opts children] (if (map? (first args))
+                             [(first args) (rest args)]
+                             [{} args])
+           type# (first children)
           ;; we have to make sure to check if the children is sequential
           ;; we have to make sure to check if the children is sequential
           ;; as a list can be returned, eg: from a (for)
           ;; as a list can be returned, eg: from a (for)
-          new-children (if (sequential? type#)
-                         (let [result (interpreter/interpret children)]
-                           (if (sequential? result)
-                             result
-                             [result]))
-                         children)
+           new-children (if (sequential? type#)
+                          (let [result (interpreter/interpret children)]
+                            (if (sequential? result)
+                              result
+                              [result]))
+                          children)
           ;; convert any options key value to a react element, if
           ;; convert any options key value to a react element, if
           ;; a valid html element tag is used, using sablono
           ;; a valid html element tag is used, using sablono
-          vector->react-elems (fn [[key val]]
-                                (if (sequential? val)
-                                  [key (interpreter/interpret val)]
-                                  [key val]))
-          new-options (into {}
-                            (if skip-opts-transform?
-                              opts
-                              (map vector->react-elems opts)))]
-      (apply js/React.createElement react-class
+           vector->react-elems (fn [[key val]]
+                                 (if (sequential? val)
+                                   [key (interpreter/interpret val)]
+                                   [key val]))
+           new-options (into {}
+                             (if skip-opts-transform?
+                               opts
+                               (map vector->react-elems opts)))]
+       (apply js/React.createElement react-class
         ;; sablono html-to-dom-attrs does not work for nested hashmaps
         ;; sablono html-to-dom-attrs does not work for nested hashmaps
-        (bean/->js (map-keys->camel-case new-options :html-props true))
-        new-children)))))
+              (bean/->js (map-keys->camel-case new-options :html-props true))
+              new-children)))))
 
 
 (defn use-atom-fn
 (defn use-atom-fn
   [a getter-fn setter-fn]
   [a getter-fn setter-fn]
   (let [[val set-val] (use-state (getter-fn @a))]
   (let [[val set-val] (use-state (getter-fn @a))]
     (use-effect!
     (use-effect!
-      (fn []
-        (let [id (str (random-uuid))]
-          (add-watch a id (fn [_ _ prev-state next-state]
-                            (let [prev-value (getter-fn prev-state)
-                                  next-value (getter-fn next-state)]
-                              (when-not (= prev-value next-value)
-                                (set-val next-value)))))
-          #(remove-watch a id)))
-      [])
+     (fn []
+       (let [id (str (random-uuid))]
+         (add-watch a id (fn [_ _ prev-state next-state]
+                           (let [prev-value (getter-fn prev-state)
+                                 next-value (getter-fn next-state)]
+                             (when-not (= prev-value next-value)
+                               (set-val next-value)))))
+         #(remove-watch a id)))
+     [])
     [val #(swap! a setter-fn %)]))
     [val #(swap! a setter-fn %)]))
 
 
 (defn use-atom
 (defn use-atom
@@ -94,10 +94,10 @@
   []
   []
   (let [*mounted (rum/use-ref false)]
   (let [*mounted (rum/use-ref false)]
     (use-effect!
     (use-effect!
-      (fn []
-         (rum/set-ref! *mounted true)
-         #(rum/set-ref! *mounted false))
-      [])
+     (fn []
+       (rum/set-ref! *mounted true)
+       #(rum/set-ref! *mounted false))
+     [])
     #(rum/deref *mounted)))
     #(rum/deref *mounted)))
 
 
 (defn use-bounding-client-rect
 (defn use-bounding-client-rect

+ 6 - 0
src/main/frontend/worker/db/migrate.cljs

@@ -596,6 +596,12 @@
                               (= (:db/ident data) :logseq.kv/schema-version)
                               (= (:db/ident data) :logseq.kv/schema-version)
                               nil
                               nil
 
 
+                              (:file/path data)
+                              (if-let [block (d/entity @conn [:file/path (:file/path data)])]
+                                (let [existing-data (assoc (into {} block) :db/id (:db/id block))]
+                                  (merge data existing-data))
+                                data)
+
                               (:block/uuid data)
                               (:block/uuid data)
                               (if-let [block (d/entity @conn [:block/uuid (:block/uuid data)])]
                               (if-let [block (d/entity @conn [:block/uuid (:block/uuid data)])]
                                 (do
                                 (do

+ 17 - 17
src/test/frontend/db/query_dsl_test.cljs

@@ -1,11 +1,11 @@
 (ns frontend.db.query-dsl-test
 (ns frontend.db.query-dsl-test
   (:require [cljs.test :refer [are deftest testing use-fixtures is]]
   (:require [cljs.test :refer [are deftest testing use-fixtures is]]
-            [clojure.string :as str]
-            [logseq.common.util.page-ref :as page-ref]
+            [clojure.string :as string]
             [frontend.db :as db]
             [frontend.db :as db]
-            [frontend.util :as util]
             [frontend.db.query-dsl :as query-dsl]
             [frontend.db.query-dsl :as query-dsl]
-            [frontend.test.helper :as test-helper :include-macros true :refer [load-test-files load-test-files-for-db-graph]]))
+            [frontend.test.helper :as test-helper :include-macros true :refer [load-test-files load-test-files-for-db-graph]]
+            [frontend.util :as util]
+            [logseq.common.util.page-ref :as page-ref]))
 
 
 ;; TODO: quickcheck
 ;; TODO: quickcheck
 ;; 1. generate query filters
 ;; 1. generate query filters
@@ -58,7 +58,7 @@
   [query]
   [query]
   (if js/process.env.DB_GRAPH
   (if js/process.env.DB_GRAPH
     (some-> query
     (some-> query
-            (str/replace "(page-tags" "(tags"))
+            (string/replace "(page-tags" "(tags"))
     query))
     query))
 
 
 (defn- dsl-query
 (defn- dsl-query
@@ -105,7 +105,7 @@
   [{:block/keys [title]}]
   [{:block/keys [title]}]
   (some->> title
   (some->> title
            (re-find #"[^\[]+")
            (re-find #"[^\[]+")
-           str/trim))
+           string/trim))
 
 
 (defn- block-property-queries-test
 (defn- block-property-queries-test
   []
   []
@@ -126,51 +126,51 @@ prop-d:: [[nada]]"}])
 
 
   (testing "Blocks have given property value"
   (testing "Blocks have given property value"
     (is (= #{"b1" "b2"}
     (is (= #{"b1" "b2"}
-           (set (map (comp first str/split-lines :block/title)
+           (set (map (comp first string/split-lines :block/title)
                      (dsl-query "(property prop-a val-a)")))))
                      (dsl-query "(property prop-a val-a)")))))
 
 
     (is (= ["b2"]
     (is (= ["b2"]
-           (map (comp first str/split-lines :block/title)
+           (map (comp first string/split-lines :block/title)
                 (dsl-query "(property prop-b val-b)")))))
                 (dsl-query "(property prop-b val-b)")))))
 
 
   (is (= ["b2"]
   (is (= ["b2"]
-         (map (comp first str/split-lines :block/title)
+         (map (comp first string/split-lines :block/title)
               (dsl-query "(and (property prop-b val-b))")))
               (dsl-query "(and (property prop-b val-b))")))
       "Blocks have property value with empty AND")
       "Blocks have property value with empty AND")
 
 
   (is (= ["b3"]
   (is (= ["b3"]
-         (map (comp first str/split-lines :block/title)
+         (map (comp first string/split-lines :block/title)
               (dsl-query "(and (property prop-c \"page c\"))")))
               (dsl-query "(and (property prop-c \"page c\"))")))
       "Blocks have property value from a set of values")
       "Blocks have property value from a set of values")
 
 
   (is (= ["b3"]
   (is (= ["b3"]
-         (map (comp first str/split-lines :block/title)
+         (map (comp first string/split-lines :block/title)
               (dsl-query "(and (property prop-c \"page c\") (property prop-c \"page b\"))")))
               (dsl-query "(and (property prop-c \"page c\") (property prop-c \"page b\"))")))
       "Blocks have ANDed property values")
       "Blocks have ANDed property values")
 
 
   (is (= #{"b2" "b3"}
   (is (= #{"b2" "b3"}
          (set
          (set
-          (map (comp first str/split-lines :block/title)
+          (map (comp first string/split-lines :block/title)
                (dsl-query "(or (property prop-c \"page c\") (property prop-b val-b))"))))
                (dsl-query "(or (property prop-c \"page c\") (property prop-b val-b))"))))
       "Blocks have ORed property values")
       "Blocks have ORed property values")
 
 
   (is (= ["b1"]
   (is (= ["b1"]
-         (map (comp first str/split-lines :block/title)
+         (map (comp first string/split-lines :block/title)
               (dsl-query "(property prop-num 2000)")))
               (dsl-query "(property prop-num 2000)")))
       "Blocks have integer property value")
       "Blocks have integer property value")
 
 
   (is (= ["b3"]
   (is (= ["b3"]
-         (map (comp first str/split-lines :block/title)
+         (map (comp first string/split-lines :block/title)
               (dsl-query "(property prop-linked-num 3000)")))
               (dsl-query "(property prop-linked-num 3000)")))
       "Blocks have property with integer page value")
       "Blocks have property with integer page value")
 
 
   (is (= ["b3"]
   (is (= ["b3"]
-         (map (comp first str/split-lines :block/title)
+         (map (comp first string/split-lines :block/title)
               (dsl-query "(property prop-d no-space-link)")))
               (dsl-query "(property prop-d no-space-link)")))
       "Blocks have property value with no space")
       "Blocks have property value with no space")
 
 
   (is (= #{"b3" "b4"}
   (is (= #{"b3" "b4"}
-         (set (map (comp first str/split-lines :block/title)
+         (set (map (comp first string/split-lines :block/title)
                    (dsl-query "(property prop-d)"))))
                    (dsl-query "(property prop-d)"))))
       "Blocks that have a property"))
       "Blocks that have a property"))
 
 
@@ -296,7 +296,7 @@ prop-d:: [[nada]]"}])
                                   {:file/path (str "pages/page" idx ".md")
                                   {:file/path (str "pages/page" idx ".md")
                                    :file/content (if (seq tags)
                                    :file/content (if (seq tags)
                                                    (str "page-prop:: b\n- block for page" idx
                                                    (str "page-prop:: b\n- block for page" idx
-                                                        "\ntagz:: " (str/join ", " (map page-ref/->page-ref tags)))
+                                                        "\ntagz:: " (string/join ", " (map page-ref/->page-ref tags)))
                                                    "")})))
                                                    "")})))
         _ (load-test-files pages)
         _ (load-test-files pages)
         {:keys [result time]}
         {:keys [result time]}

+ 15 - 15
src/test/frontend/extensions/calc_test.cljc

@@ -1,7 +1,7 @@
 (ns frontend.extensions.calc-test
 (ns frontend.extensions.calc-test
-  (:require [clojure.test :as test :refer [are deftest testing]]
-            [clojure.string :as str]
-            [clojure.edn :as edn]
+  (:require [clojure.edn :as edn]
+            [clojure.string :as string]
+            [clojure.test :as test :refer [are deftest testing]]
             [frontend.extensions.calc :as calc]))
             [frontend.extensions.calc :as calc]))
 
 
 (defn convert-bigNum [b]
 (defn convert-bigNum [b]
@@ -173,7 +173,7 @@
     (are [final-env exprs] (let [env (calc/new-env)]
     (are [final-env exprs] (let [env (calc/new-env)]
                              (doseq [expr exprs]
                              (doseq [expr exprs]
                                (calc/eval env (calc/parse expr)))
                                (calc/eval env (calc/parse expr)))
-                            (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
+                             (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
       {"a" 1 "b" 2}          ["a = 1" "b = a + 1"]
       {"a" 1 "b" 2}          ["a = 1" "b = a + 1"]
       {"a" 1 "b" 0}          ["a = 1" "b = -a + 1"]
       {"a" 1 "b" 0}          ["a = 1" "b = -a + 1"]
       {"a" 1 "b" 3}          ["a = 1" "b=a*2+1"]
       {"a" 1 "b" 3}          ["a = 1" "b=a*2+1"]
@@ -184,22 +184,22 @@
     (are [final-env exprs] (let [env (calc/new-env)]
     (are [final-env exprs] (let [env (calc/new-env)]
                              (doseq [expr exprs]
                              (doseq [expr exprs]
                                (calc/eval env (calc/parse expr)))
                                (calc/eval env (calc/parse expr)))
-                            (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
+                             (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
       {"a" 2}              ["a = 1" "a = 2"]
       {"a" 2}              ["a = 1" "a = 2"]
       {"a" 2 "b" 2}        ["a = 1" "b = a + 1" "a = b"]
       {"a" 2 "b" 2}        ["a = 1" "b = a + 1" "a = b"]
       {"variable" 1 "x" 0} ["variable = 1 + 0 * 2" "x = log(variable)" "x = variable - 1"])))
       {"variable" 1 "x" 0} ["variable = 1 + 0 * 2" "x = log(variable)" "x = variable - 1"])))
 
 
 (deftest last-value
 (deftest last-value
   (testing "last value is set"
   (testing "last value is set"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
       ["42" "126"]            ["6*7" "last*3"]
       ["42" "126"]            ["6*7" "last*3"]
       ["25" "5"]              ["3^2+4^2" "sqrt(last)"]
       ["25" "5"]              ["3^2+4^2" "sqrt(last)"]
       ["6" nil nil nil "12"]  ["2*3" "# a comment" "" "   " "last*2"])))
       ["6" nil nil nil "12"]  ["2*3" "# a comment" "" "   " "last*2"])))
 
 
 (deftest formatting
 (deftest formatting
   (testing "display normal"
   (testing "display normal"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
-      [nil "1000000"]     [":format norm" "1e6" ]
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
+      [nil "1000000"]     [":format norm" "1e6"]
       [nil "1000000"]     [":format norm 7" "1e6"]
       [nil "1000000"]     [":format norm 7" "1e6"]
       [nil "1e+6"]        [":format norm 6" "1e6"]
       [nil "1e+6"]        [":format norm 6" "1e6"]
       [nil "3.14"]        [":format norm 3" "PI"]
       [nil "3.14"]        [":format norm 3" "PI"]
@@ -209,7 +209,7 @@
       [nil "123400000"]   [":format normal 9" "1.234e8"]
       [nil "123400000"]   [":format normal 9" "1.234e8"]
       [nil "1.234e+8"]    [":format normal 8" "1.234e8"]))
       [nil "1.234e+8"]    [":format normal 8" "1.234e8"]))
   (testing "display fixed"
   (testing "display fixed"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
       [nil "0.123450"]    [":format fix 6" "0.12345"]
       [nil "0.123450"]    [":format fix 6" "0.12345"]
       [nil "0.1235"]      [":format fix 4" "0.12345"]
       [nil "0.1235"]      [":format fix 4" "0.12345"]
       [nil "2.7183"]      [":format fixed 4" "E"]
       [nil "2.7183"]      [":format fixed 4" "E"]
@@ -217,7 +217,7 @@
       [nil "4.000e-4"]    [":format fix 3" "0.0004"]
       [nil "4.000e-4"]    [":format fix 3" "0.0004"]
       [nil "1.00e+21"]    [":format fixed 2" "1e21+0.1"]))
       [nil "1.00e+21"]    [":format fixed 2" "1e21+0.1"]))
   (testing "display scientific"
   (testing "display scientific"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
       [nil "1e+6"]        [":format sci" "1e6"]
       [nil "1e+6"]        [":format sci" "1e6"]
       [nil "3.142e+0"]    [":format sci 3" "PI"]
       [nil "3.142e+0"]    [":format sci 3" "PI"]
       [nil "3.14e+2"]     [":format scientific" "3.14*10^2"])))
       [nil "3.14e+2"]     [":format scientific" "3.14*10^2"])))
@@ -234,7 +234,7 @@
       2.00101    "2 101/100000"
       2.00101    "2 101/100000"
       -99.2      "-99 8/40"))
       -99.2      "-99 8/40"))
   (testing "display fractions"
   (testing "display fractions"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
       [nil "4 3/8"]           [":format frac" "4.375"]
       [nil "4 3/8"]           [":format frac" "4.375"]
       [nil "-7 1/4"]          [":format fraction" "-7.25"]
       [nil "-7 1/4"]          [":format fraction" "-7.25"]
       [nil "2"]               [":format fractions" "19/20 + 1 1/20"]
       [nil "2"]               [":format fractions" "19/20 + 1 1/20"]
@@ -242,10 +242,10 @@
       [nil "3.14157"]         [":format frac" "3.14157"]
       [nil "3.14157"]         [":format frac" "3.14157"]
       [nil "3 14157/100000"]  [":format frac 100000" "3.14157"]))
       [nil "3 14157/100000"]  [":format frac 100000" "3.14157"]))
   (testing "display improper fractions"
   (testing "display improper fractions"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
       [nil "35/8"]            [":format improper" "4.375"]
       [nil "35/8"]            [":format improper" "4.375"]
       [nil "-29/4"]           [":format imp" "-7.25"]
       [nil "-29/4"]           [":format imp" "-7.25"]
-      [nil "3.14157"]         [":format improper" "3.14157" ]
+      [nil "3.14157"]         [":format improper" "3.14157"]
       [nil "314157/100000"]   [":format imp 100000" "3.14157"])))
       [nil "314157/100000"]   [":format imp 100000" "3.14157"])))
 
 
 (deftest base-conversion
 (deftest base-conversion
@@ -257,10 +257,10 @@
       324.0     "0x100 + 0o100 + 0b100"
       324.0     "0x100 + 0o100 + 0b100"
       32.0      "0b100 * 0b1000"))
       32.0      "0b100 * 0b1000"))
   (testing "mixed base output"
   (testing "mixed base output"
-    (are [values exprs] (= values (calc/eval-lines (str/join "\n" exprs)))
+    (are [values exprs] (= values (calc/eval-lines (string/join "\n" exprs)))
       ["12345" "0x3039"]          ["12345" ":hex"]
       ["12345" "0x3039"]          ["12345" ":hex"]
       ["12345" "0o30071"]         ["12345" ":oct"]
       ["12345" "0o30071"]         ["12345" ":oct"]
-      ["12345" "0b11000000111001"]["12345" ":bin"]
+      ["12345" "0b11000000111001"] ["12345" ":bin"]
       [nil "0b100000000"]         [":bin" "0b10000 * 0b10000"]
       [nil "0b100000000"]         [":bin" "0b10000 * 0b10000"]
       [nil "-0xff"]               [":hex" "-255"])))
       [nil "-0xff"]               [":hex" "-255"])))
 
 

+ 12 - 12
src/test/frontend/test/node_test_runner.cljs

@@ -6,13 +6,13 @@
   to call from the commandline. Once this test runner is stable enough we should
   to call from the commandline. Once this test runner is stable enough we should
   contribute it upstream"
   contribute it upstream"
   {:dev/always true} ;; necessary for test-data freshness
   {:dev/always true} ;; necessary for test-data freshness
-  (:require [shadow.test.env :as env]
-            [clojure.tools.cli :as cli]
-            [clojure.string :as str]
+  (:require [cljs.test :as ct]
             [clojure.set :as set]
             [clojure.set :as set]
+            [clojure.string :as string]
+            [clojure.tools.cli :as cli]
+            [goog.string :as gstring]
             [shadow.test :as st]
             [shadow.test :as st]
-            [cljs.test :as ct]
-            [goog.string :as gstring]))
+            [shadow.test.env :as env]))
 
 
 ;; Cljs.test customization
 ;; Cljs.test customization
 ;; Inherit behavior from default reporter
 ;; Inherit behavior from default reporter
@@ -58,8 +58,8 @@
   (let [{:keys [errors] :as parsed-input}
   (let [{:keys [errors] :as parsed-input}
         (apply cli/parse-opts args cli-opts parse-opts-options)]
         (apply cli/parse-opts args cli-opts parse-opts-options)]
     (if (seq errors)
     (if (seq errors)
-      (do (println (str/join "\n" (into ["Options failed to parse:"] errors)))
-        (js/process.exit 1))
+      (do (println (string/join "\n" (into ["Options failed to parse:"] errors)))
+          (js/process.exit 1))
       parsed-input)))
       parsed-input)))
 
 
 (defn- get-selected-tests
 (defn- get-selected-tests
@@ -80,11 +80,11 @@ returns selected tests and namespaces to run"
                                      #(seq (set/intersection exclude (set (keys (meta %)))))
                                      #(seq (set/intersection exclude (set (keys (meta %)))))
                                      test-vars)))
                                      test-vars)))
         test-syms (cond (some? focused-tests)
         test-syms (cond (some? focused-tests)
-                    focused-tests
-                    namespace
-                    [namespace]
-                    namespace-regex
-                    (filter #(re-find namespace-regex (str %)) test-namespaces))]
+                        focused-tests
+                        namespace
+                        [namespace]
+                        namespace-regex
+                        (filter #(re-find namespace-regex (str %)) test-namespaces))]
     test-syms))
     test-syms))
 
 
 ;; This is a patched version of https://github.com/thheller/shadow-cljs/blob/f271b3c40d3ccd4e587b0ffeaa2713d2f642114a/src/main/shadow/test/node.cljs#L44-L56
 ;; This is a patched version of https://github.com/thheller/shadow-cljs/blob/f271b3c40d3ccd4e587b0ffeaa2713d2f642114a/src/main/shadow/test/node.cljs#L44-L56