Просмотр исходного кода

fix: some built-in tags shouldn't be recognized as inline tags

related to https://github.com/logseq/db-test/issues/555
Tienson Qin 3 месяцев назад
Родитель
Сommit
a4ec889a5d

+ 2 - 1
deps/db/src/logseq/db.cljs

@@ -129,7 +129,8 @@
               ;; notify ui
               (when-let [f @*transact-invalid-callback]
                 (f tx-report errors))
-              (throw (ex-info "DB write failed with invalid data" {:tx-data tx-data}))))
+              (throw (ex-info "DB write failed with invalid data" {:tx-data tx-data
+                                                                   :pipeline-tx-data (:tx-data tx-report)}))))
           tx-report)
         (d/transact! conn tx-data tx-meta)))
     (catch :default e

+ 14 - 4
deps/db/src/logseq/db/frontend/class.cljs

@@ -117,14 +117,24 @@
              #{:logseq.class/Journal :logseq.class/Whiteboard
                :logseq.class/Pdf-annotation}))
 
+(def block-kind-tags
+  #{:logseq.class/Cards :logseq.class/Code-block
+    :logseq.class/Math-block :logseq.class/Quote-block
+    :logseq.class/Query :logseq.class/Pdf-annotation
+    :logseq.class/Template})
+
+(def disallowed-inline-tags
+  "Classes that should be removed from inline tags"
+  (set/union page-classes
+             private-tags
+             block-kind-tags))
+
 (def extends-hidden-tags
   "Built-in classes that are hidden when choosing extends"
   (set/union
    private-tags
-   #{:logseq.class/Cards :logseq.class/Code-block
-     :logseq.class/Math-block :logseq.class/Pdf-annotation
-     :logseq.class/Query :logseq.class/Quote-block
-     :logseq.class/Template}))
+   block-kind-tags))
+
 (def hidden-tags
   "Built-in classes that are hidden in a few contexts like property values"
   #{:logseq.class/Page :logseq.class/Root :logseq.class/Asset})

+ 31 - 16
deps/outliner/src/logseq/outliner/core.cljs

@@ -237,9 +237,26 @@
           [:db/retract eid :block/tags :logseq.class/Page]])))
    tags))
 
-(defn- remove-inline-page-classes
+(defn- inline-tag-disallowed?
+  [db t]
+  ;; both disallowed tags and built-in pages shouldn't be used as inline tags
+  (let [disallowed-idents (into db-class/disallowed-inline-tags
+                                #{:logseq.property/query :logseq.property/asset})]
+    (and (map? t)
+         (or
+          (contains?
+           disallowed-idents
+           (or (:db/ident t)
+               (when-let [id (:block/uuid t)]
+                 (:db/ident (d/entity db [:block/uuid id])))))
+          (contains?
+           sqlite-create-graph/built-in-pages-names
+           (or (:block/title t)
+               (when-let [id (:block/uuid t)]
+                 (:block/title (d/entity db [:block/uuid id])))))))))
+
+(defn- remove-disallowed-inline-classes
   [db {:block/keys [tags] :as block}]
-  ;; Notice: should check `page?` for block from the current db
   (if (or (ldb/page? (d/entity db (:db/id block))) (:block/name block))
     block
     (let [tags' (cond
@@ -253,28 +270,26 @@
                   :else
                   tags)
           block (assoc block :block/tags tags')
-          page-class? (fn [t]
-                        (and (map? t) (contains? db-class/page-classes
-                                                 (or (:db/ident t)
-                                                     (when-let [id (:block/uuid t)]
-                                                       (:db/ident (d/entity db [:block/uuid id])))))))
-          page-classes (filter page-class? tags')]
-      (if (seq page-classes)
+          disallowed-tag? (fn [tag] (inline-tag-disallowed? db tag))
+          disallowed-tags (filter disallowed-tag? tags')]
+      (if (seq disallowed-tags)
         (-> block
             (update :block/tags
                     (fn [tags]
-                      (->> (remove page-class? tags)
+                      (->> (remove disallowed-tag? tags)
                            (remove nil?))))
             (update :block/refs
-                    (fn [refs] (->> (remove page-class? refs)
+                    (fn [refs] (->> (remove disallowed-tag? refs)
                                     (remove nil?))))
             (update :block/title (fn [title]
                                    (reduce
-                                    (fn [title page-class]
-                                      (-> (string/replace title (str "#" (page-ref/->page-ref (:block/uuid page-class))) "")
+                                    (fn [title tag]
+                                      (-> (string/replace title
+                                                          (str "#" (page-ref/->page-ref (:block/uuid tag)))
+                                                          (str "#" (:block/title tag)))
                                           string/trim))
                                     title
-                                    page-classes))))
+                                    disallowed-tags))))
         block))))
 
 (extend-type Entity
@@ -289,7 +304,7 @@
                  this)
           data' (if db-based?
                   (->> (dissoc data :block/properties)
-                       (remove-inline-page-classes db))
+                       (remove-disallowed-inline-classes db))
                   data)
           collapse-or-expand? (= outliner-op :collapse-expand-blocks)
           m* (cond->
@@ -586,7 +601,7 @@
         orders (get-block-orders blocks target-block sibling? keep-block-order?)]
     (map-indexed (fn [idx {:block/keys [parent] :as block}]
                    (when-let [uuid' (get uuids (:block/uuid block))]
-                     (let [block (if db-based? (remove-inline-page-classes db block) block)
+                     (let [block (if db-based? (remove-disallowed-inline-classes db block) block)
                            top-level? (= (:block/level block) 1)
                            parent (compute-block-parent block parent target-block top-level? sibling? get-new-id outliner-op replace-empty-target? idx)
 

+ 5 - 1
src/main/frontend/components/block.cljs

@@ -2012,7 +2012,11 @@
     ["Tag" _]
     (when-let [s (gp-block/get-tag item)]
       (let [s (text/page-ref-un-brackets! s)]
-        (page-cp (assoc config :tag? true) {:block/name s})))
+        (if (config/db-based-graph?)
+          (if (common-util/uuid-string? s)
+            (page-cp (assoc config :tag? true) {:block/name s})
+            [:span (str "#" s)])
+          (page-cp (assoc config :tag? true) {:block/name s}))))
 
     ["Emphasis" [[kind] data]]
     (emphasis-cp config kind data)

+ 1 - 1
src/main/frontend/handler/db_based/editor.cljs

@@ -64,7 +64,7 @@
                             (-> refs
                                 remove-non-existed-refs!
                                 (use-cached-refs! block))))))
-        title' (db-content/title-ref->id-ref (:block/title block) (:block/refs block))
+        title' (db-content/title-ref->id-ref (or (get block :block/title) title) (:block/refs block))
         result (-> block
                    (merge (if level {:block/level level} {}))
                    (assoc :block/title title'))]

+ 1 - 0
src/main/frontend/handler/editor.cljs

@@ -1483,6 +1483,7 @@
                           (string/trim value)))
                (save-block-aux! db-block value opts))))
          (catch :default error
+           (js/console.error error)
            (log/error :save-block-failed error)))))))
 
 (defn- clean-content!

+ 19 - 19
src/main/frontend/worker/db_worker.cljs

@@ -492,18 +492,18 @@
 (def-thread-api :thread-api/block-refs-check
   [repo id {:keys [unlinked?]}]
   (m/sp
-   (when-let [conn (worker-state/get-datascript-conn repo)]
-     (let [db @conn
-           block (d/entity db id)]
-       (if unlinked?
-         (let [title (string/lower-case (:block/title block))
-               result (m/? (search-blocks repo title {:limit 100}))]
-           (boolean (some (fn [b]
-                            (let [block (d/entity db (:db/id b))]
-                              (and (not= id (:db/id block))
-                                   (not ((set (map :db/id (:block/refs block))) id))
-                                   (string/includes? (string/lower-case (:block/title block)) title)))) result)))
-         (some? (first (common-initial-data/get-block-refs db (:db/id block)))))))))
+    (when-let [conn (worker-state/get-datascript-conn repo)]
+      (let [db @conn
+            block (d/entity db id)]
+        (if unlinked?
+          (let [title (string/lower-case (:block/title block))
+                result (m/? (search-blocks repo title {:limit 100}))]
+            (boolean (some (fn [b]
+                             (let [block (d/entity db (:db/id b))]
+                               (and (not= id (:db/id block))
+                                    (not ((set (map :db/id (:block/refs block))) id))
+                                    (string/includes? (string/lower-case (:block/title block)) title)))) result)))
+          (some? (first (common-initial-data/get-block-refs db (:db/id block)))))))))
 
 (def-thread-api :thread-api/get-block-parents
   [repo id depth]
@@ -642,7 +642,7 @@
             :notification
             (do
               (log/error ::apply-outliner-ops-failed e)
-              (shared-service/broadcast-to-clients! :notification [(:message payload) (:type payload)]))
+              (shared-service/broadcast-to-clients! :notification [(:message payload) (:type payload) (:clear? payload) (:uid payload) (:timeout payload)]))
             (throw e)))))))
 
 (def-thread-api :thread-api/file-writes-finished?
@@ -881,14 +881,14 @@
   [repo start-opts]
   (js/Promise.
    (m/sp
-    (c.m/<? (init-sqlite-module!))
-    (when-not (:import-type start-opts)
-      (c.m/<? (start-db! repo start-opts))
-      (assert (some? (worker-state/get-datascript-conn repo))))
+     (c.m/<? (init-sqlite-module!))
+     (when-not (:import-type start-opts)
+       (c.m/<? (start-db! repo start-opts))
+       (assert (some? (worker-state/get-datascript-conn repo))))
      ;; Don't wait for rtc started because the app will be slow to be ready
      ;; for users.
-    (when @worker-state/*rtc-ws-url
-      (rtc.core/new-task--rtc-start true)))))
+     (when @worker-state/*rtc-ws-url
+       (rtc.core/new-task--rtc-start true)))))
 
 (def broadcast-data-types
   (set (map

+ 1 - 59
src/test/frontend/modules/outliner/core_test.cljs

@@ -1,5 +1,5 @@
 (ns frontend.modules.outliner.core-test
-  (:require [cljs.test :refer [deftest is use-fixtures testing] :as test]
+  (:require [cljs.test :refer [deftest is testing use-fixtures] :as test]
             [clojure.set :as set]
             [clojure.test.check.generators :as gen]
             [clojure.walk :as walk]
@@ -12,10 +12,7 @@
             [frontend.test.fixtures :as fixtures]
             [frontend.test.helper :as test-helper :refer [load-test-files]]
             [frontend.worker.db-listener :as worker-db-listener]
-            [logseq.common.util :as common-util]
             [logseq.db :as ldb]
-            [logseq.db.frontend.class :as db-class]
-            [logseq.db.test.helper :as db-test]
             [logseq.graph-parser.block :as gp-block]
             [logseq.outliner.core :as outliner-core]
             [logseq.outliner.transaction :as outliner-tx]))
@@ -523,61 +520,6 @@
                                                     (state/get-date-formatter)
                                                     block)))
 
-(deftest save-inline-tag
-  (let [conn (db-test/create-conn-with-blocks
-              [{:page {:block/title "page1"} :blocks [{:block/title "test"}]}])
-        block (db-test/find-block-by-content @conn "test")
-        _ (outliner-core/save-block! "logseq_db_test" conn
-                                     "MMM do, yyyy"
-                                     {:block/uuid (:block/uuid block)
-                                      :block/refs '({:block/name "audio", :block/title "audio", :block/uuid #uuid "6852be3e-6e80-4245-b72c-0d586f1fd007", :block/created-at 1750253118663, :block/updated-at 1750253118663, :block/tags [:logseq.class/Page]}),
-                                      :block/tags '({:block/name "audio", :block/title "audio", :block/uuid #uuid "6852be3e-6e80-4245-b72c-0d586f1fd007", :block/created-at 1750253118663, :block/updated-at 1750253118663, :block/tags [:logseq.class/Tag]}),
-                                      :block/title "test #[[6852be3e-6e80-4245-b72c-0d586f1fd007]]",
-                                      :db/id (:db/id block)})
-        audio-tag (ldb/get-page @conn "audio")]
-    (is (some? (:db/ident audio-tag)) "#audio doesn't have db/ident")
-    (is (= [:logseq.class/Tag] (map :db/ident (:block/tags audio-tag)))
-        "#audio has wrong tags")))
-
-(deftest do-not-save-inline-page-tag-when-save-block
-  (testing "Inline page class shouldn't be saved when save block"
-    (let [conn (db-test/create-conn-with-blocks
-                [{:page {:block/title "page1"} :blocks [{:block/title "test"}]}])
-          block (db-test/find-block-by-content @conn "test")
-          block' (d/entity @conn (:db/id block))]
-      (doseq [class-ident db-class/page-classes]
-        (let [class (d/entity @conn class-ident)]
-          (outliner-core/save-block! "logseq_db_test" conn
-                                     "MMM do, yyyy"
-                                     {:block/uuid (:block/uuid block)
-                                      :block/tags [(select-keys class [:block/name :block/title :block/uuid :db/ident])],
-                                      :block/title (common-util/format "test #[[%s]]" (str (:block/uuid class))),
-                                      :db/id (:db/id block)})
-          (is (= "test" (:block/title block')))
-          (is (empty? (:block/tags block'))))))))
-
-(deftest do-not-save-inline-page-tag-when-insert-blocks
-  (testing "Inline page class shouldn't be saved when insert blocks"
-    (let [conn (db-test/create-conn-with-blocks
-                [{:page {:block/title "page1"} :blocks [{:block/title "test"}]}])
-          block (db-test/find-block-by-content @conn "test")]
-      (doseq [class-ident db-class/page-classes]
-        (let [class (d/entity @conn class-ident)
-              new-block-id (random-uuid)
-              _ (outliner-tx/transact!
-                 (transact-opts)
-                 (outliner-core/insert-blocks! "logseq_db_test" conn
-                                               [{:block/uuid new-block-id
-                                                 :block/tags [(select-keys class [:block/name :block/title :block/uuid :db/ident])],
-                                                 :block/title (common-util/format "test #[[%s]]" (str (:block/uuid class))),
-                                                 :block/page (:db/id (:block/page block))}]
-                                               block
-                                               {:sibling? false
-                                                :keep-uuid? true}))
-              block' (d/entity @conn [:block/uuid new-block-id])]
-          (is (= "test" (:block/title block')))
-          (is (empty? (:block/tags block'))))))))
-
 (deftest save-test
   (load-test-files [{:file/path "pages/page1.md"
                      :file/content "alias:: foo, bar

+ 64 - 0
src/test/frontend/modules/outliner/inline_tag_test.cljs

@@ -0,0 +1,64 @@
+(ns frontend.modules.outliner.inline-tag-test
+  (:require [cljs.test :refer [use-fixtures deftest is testing] :as test]
+            [datascript.core :as d]
+            [frontend.test.helper :as test-helper]
+            [logseq.common.util :as common-util]
+            [logseq.db :as ldb]
+            [logseq.db.frontend.class :as db-class]
+            [logseq.db.test.helper :as db-test]
+            [logseq.outliner.core :as outliner-core]))
+
+(use-fixtures :each test-helper/db-based-start-and-destroy-db)
+
+(deftest save-inline-tag
+  (let [conn (db-test/create-conn-with-blocks
+              [{:page {:block/title "page1"} :blocks [{:block/title "test"}]}])
+        block (db-test/find-block-by-content @conn "test")
+        _ (outliner-core/save-block! "logseq_db_test" conn
+                                     "MMM do, yyyy"
+                                     {:block/uuid (:block/uuid block)
+                                      :block/refs '({:block/name "audio", :block/title "audio", :block/uuid #uuid "6852be3e-6e80-4245-b72c-0d586f1fd007", :block/created-at 1750253118663, :block/updated-at 1750253118663, :block/tags [:logseq.class/Page]}),
+                                      :block/tags '({:block/name "audio", :block/title "audio", :block/uuid #uuid "6852be3e-6e80-4245-b72c-0d586f1fd007", :block/created-at 1750253118663, :block/updated-at 1750253118663, :block/tags [:logseq.class/Tag]}),
+                                      :block/title "test #[[6852be3e-6e80-4245-b72c-0d586f1fd007]]",
+                                      :db/id (:db/id block)})
+        audio-tag (ldb/get-page @conn "audio")]
+    (is (some? (:db/ident audio-tag)) "#audio doesn't have db/ident")
+    (is (= [:logseq.class/Tag] (map :db/ident (:block/tags audio-tag)))
+        "#audio has wrong tags")))
+
+(deftest disallowed-inline-tags-when-save-block
+  (testing "Disallowed inline tags shouldn't be recognized when save block"
+    (let [conn (db-test/create-conn-with-blocks
+                [{:page {:block/title "page1"} :blocks [{:block/title "test"}]}])
+          block (db-test/find-block-by-content @conn "test")]
+      (doseq [class-ident db-class/page-classes]
+        (let [class (d/entity @conn class-ident)]
+          (outliner-core/save-block! "logseq_db_test" conn
+                                     "MMM do, yyyy"
+                                     {:block/uuid (:block/uuid block)
+                                      :block/tags [(select-keys class [:block/name :block/title :block/uuid :db/ident])],
+                                      :block/title (common-util/format "test #[[%s]]" (str (:block/uuid class))),
+                                      :db/id (:db/id block)})
+          (let [block' (d/entity @conn (:db/id block))]
+            (is (= (str "test #" (:block/title class)) (:block/title block')))
+            (is (empty? (:block/tags block')))))))))
+
+(deftest disallowed-inline-tags-when-insert-blocks
+  (testing "Disallowed inline tags shouldn't be recognized when insert blocks"
+    (let [conn (db-test/create-conn-with-blocks
+                [{:page {:block/title "page1"} :blocks [{:block/title "test"}]}])
+          block (db-test/find-block-by-content @conn "test")]
+      (doseq [class-ident db-class/page-classes]
+        (let [class (d/entity @conn class-ident)
+              new-block-id (random-uuid)
+              _ (outliner-core/insert-blocks! "logseq_db_test" conn
+                                              [{:block/uuid new-block-id
+                                                :block/tags [(select-keys class [:block/name :block/title :block/uuid :db/ident])],
+                                                :block/title (common-util/format "test #[[%s]]" (str (:block/uuid class))),
+                                                :block/page (:db/id (:block/page block))}]
+                                              block
+                                              {:sibling? false
+                                               :keep-uuid? true})
+              block' (d/entity @conn [:block/uuid new-block-id])]
+          (is (= (str "test #" (:block/title class)) (:block/title block')))
+          (is (empty? (:block/tags block'))))))))