소스 검색

fix: remove inline page tags when saving or inserting blocks

Page tags here means db-class/page-classes.
Tienson Qin 4 달 전
부모
커밋
61b862d88a
3개의 변경된 파일115개의 추가작업 그리고 9개의 파일을 삭제
  1. 33 4
      deps/outliner/src/logseq/outliner/core.cljs
  2. 41 5
      src/main/frontend/worker/pipeline.cljs
  3. 41 0
      src/test/frontend/modules/outliner/core_test.cljs

+ 33 - 4
deps/outliner/src/logseq/outliner/core.cljs

@@ -10,6 +10,7 @@
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.uuid :as common-uuid]
             [logseq.db :as ldb]
+            [logseq.db.common.entity-plus :as entity-plus]
             [logseq.db.common.order :as db-order]
             [logseq.db.file-based.schema :as file-schema]
             [logseq.db.frontend.class :as db-class]
@@ -27,6 +28,8 @@
             [malli.core :as m]
             [malli.util :as mu]))
 
+;; TODO: remove `repo` usage, use db to check `entity-plus/db-based-graph?`
+
 (def ^:private block-map
   (mu/optional-keys
    [:map
@@ -234,14 +237,38 @@
           [:db/retract eid :block/tags :logseq.class/Page]])))
    tags))
 
+(defn- remove-inline-page-classes
+  [db {:block/keys [tags] :as block}]
+  (let [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)]
+    (-> block
+        (update :block/tags
+                (fn [tags] (->> (remove page-class? tags)
+                                (remove nil?))))
+        (update :block/refs
+                (fn [refs] (->> (remove page-class? 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))) "")
+                                      string/trim))
+                                title
+                                page-classes))))))
+
 (extend-type Entity
   otree/INode
   (-save [this *txs-state db repo _date-formatter {:keys [retract-attributes? retract-attributes outliner-op]
                                                    :or {retract-attributes? true}}]
     (assert (ds/outliner-txs-state? *txs-state)
             "db should be satisfied outliner-tx-state?")
-    (let [data this
-          db-based? (sqlite-util/db-based-graph? repo)
+    (let [db-based? (sqlite-util/db-based-graph? repo)
+          data (cond->> this
+                 db-based?
+                 (remove-inline-page-classes db))
           data' (cond->
                  (if (de/entity? data)
                    (assoc (.-kv ^js data) :db/id (:db/id data))
@@ -536,12 +563,14 @@
 
 (defn- build-insert-blocks-tx
   [db target-block blocks uuids get-new-id {:keys [sibling? outliner-op replace-empty-target? insert-template? keep-block-order?]}]
-  (let [block-ids (set (map :block/uuid blocks))
+  (let [db-based? (entity-plus/db-based-graph? db)
+        block-ids (set (map :block/uuid blocks))
         target-page (get-target-block-page target-block sibling?)
         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 [top-level? (= (:block/level block) 1)
+                     (let [block (if db-based? (remove-inline-page-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)
 
                            order (nth orders idx)

+ 41 - 5
src/main/frontend/worker/pipeline.cljs

@@ -152,7 +152,8 @@
                  (:added datom)
                  (= (:v datom) (:db/id tag)))
             (let [t (d/entity db-after (:e datom))]
-              (when (not (:db/ident t)) ; new tag without db/ident
+              (when (and (not (ldb/inline-tag? (:block/raw-title t) tag))
+                         (not (:db/ident t))) ; new tag without db/ident
                 (let [eid (:db/id t)]
                   [[:db/add eid :db/ident (db-class/create-user-class-ident-from-name db-after (:block/title t))]
                    [:db/add eid :logseq.property.class/extends :logseq.class/Root]
@@ -176,6 +177,39 @@
         tx-data)
        (apply concat)))))
 
+(defn- remove-inline-page-class-from-title
+  "Remove inline page tag from title"
+  [block page-tag]
+  (-> (string/replace (:block/raw-title block) (str "#" (page-ref/->page-ref (:block/uuid page-tag))) "")
+      string/trim))
+
+(defn- fix-inline-built-in-page-classes
+  [{:keys [db-after tx-data tx-meta]}]
+  (when-not (:rtc-op? tx-meta)
+    (let [classes (->> (remove #{:logseq.class/Page} db-class/page-classes)
+                       (map #(d/entity db-after %)))
+          class-ids (set (map :db/id classes))]
+      (->>
+       (keep
+        (fn [datom]
+          (when (and (= :block/tags (:a datom))
+                     (:added datom)
+                     (contains? class-ids (:v datom)))
+            (let [id (:e datom)
+                  entity (d/entity db-after id)
+                  title (or (:block/raw-title entity) (:block/title entity))
+                  page-tag (d/entity db-after (:v datom))]
+              (when (and title
+                         (string/includes? title "#[[")
+                         (ldb/inline-tag? title page-tag))
+                (let [title (remove-inline-page-class-from-title entity page-tag)]
+                  [{:db/id id
+                    :block/title title}
+                   [:db/retract id :block/tags (:v datom)]
+                   [:db/retract id :block/tags :logseq.class/Page]])))))
+        tx-data)
+       (apply concat)))))
+
 (defn- toggle-page-and-block
   [conn {:keys [db-before db-after tx-data tx-meta]}]
   (when-not (:rtc-op? tx-meta)
@@ -206,8 +240,7 @@
                    (let [block (d/entity db-after (:e datom))
                          block-parent (:block/parent block)
                          ;; remove inline #Page from title
-                         page-title (-> (string/replace (:block/raw-title block) (str "#" (page-ref/->page-ref (:block/uuid page-tag))) "")
-                                        string/trim)
+                         page-title (remove-inline-page-class-from-title block page-tag)
                          ->page-tx (concat
                                     [{:db/id id
                                       :block/name (common-util/page-name-sanity-lc page-title)
@@ -335,7 +368,9 @@
   [repo conn tx-report]
   (let [{:keys [db-before db-after tx-data tx-meta]} tx-report
         fix-page-tags-tx-data (fix-page-tags tx-report)
-        toggle-page-and-block-tx-data (toggle-page-and-block conn tx-report)
+        fix-inline-page-tx-data (fix-inline-built-in-page-classes tx-report)
+        toggle-page-and-block-tx-data (when (empty? fix-inline-page-tx-data)
+                                        (toggle-page-and-block conn tx-report))
         display-blocks-tx-data (add-missing-properties-to-typed-display-blocks db-after tx-data)
         commands-tx (when-not (or (:undo? tx-meta) (:redo? tx-meta) (:rtc-tx? tx-meta))
                       (commands/run-commands conn tx-report))
@@ -347,7 +382,8 @@
             commands-tx
             insert-templates-tx
             created-by-tx
-            fix-page-tags-tx-data)))
+            fix-page-tags-tx-data
+            fix-inline-page-tx-data)))
 
 (defn- undo-tx-data-if-disallowed!
   [conn {:keys [tx-data]}]

+ 41 - 0
src/test/frontend/modules/outliner/core_test.cljs

@@ -12,7 +12,9 @@
             [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]
@@ -537,6 +539,45 @@
     (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