Преглед на файлове

Merge branch 'master' into feat/integrated-title-bar

Konstantinos Kaloutas преди 2 години
родител
ревизия
f90eef2b1a
променени са 27 файла, в които са добавени 470 реда и са изтрити 124 реда
  1. 1 0
      .carve/ignore
  2. 2 1
      deps/common/src/logseq/common/graph.cljs
  3. 8 7
      deps/graph-parser/src/logseq/graph_parser/cli.cljs
  4. 4 4
      deps/graph-parser/src/logseq/graph_parser/test/docs_graph_helper.cljs
  5. 53 5
      deps/graph-parser/test/logseq/graph_parser/cli_test.cljs
  6. 3 0
      deps/publishing/src/logseq/publishing/export.cljs
  7. 2 1
      deps/publishing/src/logseq/publishing/html.cljs
  8. 11 1
      deps/publishing/test/logseq/publishing/export_test.cljs
  9. 74 0
      e2e-tests/blockref.spec.ts
  10. 25 1
      e2e-tests/utils.ts
  11. 2 2
      ios/App/App.xcodeproj/project.pbxproj
  12. 14 6
      src/main/frontend/commands.cljs
  13. 2 1
      src/main/frontend/components/block.cljs
  14. 89 54
      src/main/frontend/handler/editor.cljs
  15. 4 2
      src/main/frontend/handler/editor/lifecycle.cljs
  16. 3 4
      src/main/frontend/handler/editor/property.cljs
  17. 15 1
      src/main/frontend/handler/paste.cljs
  18. 7 3
      src/main/frontend/modules/editor/undo_redo.cljs
  19. 8 3
      src/main/frontend/modules/file/core.cljs
  20. 11 2
      src/main/frontend/modules/outliner/core.cljs
  21. 84 4
      src/main/frontend/modules/outliner/datascript.cljc
  22. 13 4
      src/main/frontend/modules/outliner/transaction.cljc
  23. 13 3
      src/main/frontend/state.cljs
  24. 7 0
      src/main/frontend/util.cljc
  25. 5 5
      src/test/frontend/handler/repo_conversion_test.cljs
  26. 1 1
      src/test/frontend/handler/repo_test.cljs
  27. 9 9
      templates/config.edn

+ 1 - 0
.carve/ignore

@@ -48,6 +48,7 @@ frontend.mixins/perf-measure-mixin
 frontend.mobile.util/get-idevice-statusbar-height
 ;; Used in macro
 frontend.modules.outliner.datascript/transact!
+frontend.modules.outliner.core/*transaction-opts*
 ;; Referenced in comment
 frontend.page/route-view
 ;; placeholder fn

+ 2 - 1
deps/common/src/logseq/common/graph.cljs

@@ -66,7 +66,8 @@
       keyword))
 
 (defn get-files
-  "Given a graph's root dir, returns a list of all files that it recognizes"
+  "Given a graph's root dir, returns a list of all files that it recognizes.
+   Graph dir must be an absolute path in order for ignoring to work correctly"
   [graph-dir]
   (->> (readdir graph-dir)
        (remove (partial ignored-path? graph-dir))

+ 8 - 7
deps/graph-parser/src/logseq/graph_parser/cli.cljs

@@ -24,14 +24,15 @@
     files))
 
 (defn- build-graph-files
-  "Given a graph directory, return allowed file paths and their contents in preparation
+  "Given a graph directory, return absolute, allowed file paths and their contents in preparation
    for parsing"
-  [dir config]
-  (->> (common-graph/get-files dir)
-       (map #(hash-map :file/path %))
-       graph-parser/filter-files
-       (remove-hidden-files dir config)
-       (mapv #(assoc % :file/content (slurp (:file/path %))))))
+  [dir* config]
+  (let [dir (path/resolve dir*)]
+    (->> (common-graph/get-files dir)
+        (map #(hash-map :file/path %))
+        graph-parser/filter-files
+        (remove-hidden-files dir config)
+        (mapv #(assoc % :file/content (slurp (:file/path %)))))))
 
 (defn- read-config
   "Reads repo-specific config from logseq/config.edn"

+ 4 - 4
deps/graph-parser/src/logseq/graph_parser/test/docs_graph_helper.cljs

@@ -69,11 +69,11 @@
        ffirst))
 
 (defn- query-assertions
-  [db files]
+  [db graph-dir files]
   (testing "Query based stats"
     (is (= (->> files
                 ;; logseq files aren't saved under :block/file
-                (remove #(string/includes? % (str "/" gp-config/app-name "/")))
+                (remove #(string/includes? % (str graph-dir "/" gp-config/app-name "/")))
                 ;; edn files being listed in docs by parse-graph aren't graph files
                 (remove #(and (not (gp-config/whiteboard? %)) (string/ends-with? % ".edn")))
                 set)
@@ -148,7 +148,7 @@
   logseq app. It is important to run these in both contexts to ensure that the
   functionality in frontend.handler.repo and logseq.graph-parser remain the
   same"
-  [db files]
+  [db graph-dir files]
   ;; Counts assertions help check for no major regressions. These counts should
   ;; only increase over time as the docs graph rarely has deletions
   (testing "Counts"
@@ -168,4 +168,4 @@
                  db)))
         "Advanced query count"))
 
-  (query-assertions db files))
+  (query-assertions db graph-dir files))

+ 53 - 5
deps/graph-parser/test/logseq/graph_parser/cli_test.cljs

@@ -1,16 +1,30 @@
-(ns logseq.graph-parser.cli-test
-  (:require [cljs.test :refer [deftest is testing]]
+(ns ^:node-only logseq.graph-parser.cli-test
+  (:require [cljs.test :refer [deftest is testing async use-fixtures]]
             [logseq.graph-parser.cli :as gp-cli]
             [logseq.graph-parser.test.docs-graph-helper :as docs-graph-helper]
-            [clojure.string :as string]))
+            [clojure.string :as string]
+            ["fs" :as fs]
+            ["process" :as process]
+            ["path" :as path]))
+
+(use-fixtures
+  :each
+  ;; Cleaning tmp/ before leaves last tmp/ after a test run for dev and debugging
+  {:before
+   #(async done
+           (if (fs/existsSync "tmp")
+             (fs/rm "tmp" #js {:recursive true} (fn [err]
+                                                  (when err (js/console.log err))
+                                                  (done)))
+             (done)))})
 
 ;; Integration test that test parsing a large graph like docs
 (deftest ^:integration parse-graph
   (let [graph-dir "test/docs-0.9.2"
         _ (docs-graph-helper/clone-docs-repo-if-not-exists graph-dir "v0.9.2")
-        {:keys [conn files asts]} (gp-cli/parse-graph graph-dir {:verbose false})] ;; legacy parsing
+        {:keys [conn files asts]} (gp-cli/parse-graph graph-dir {:verbose false})]
 
-    (docs-graph-helper/docs-graph-assertions @conn files)
+    (docs-graph-helper/docs-graph-assertions @conn graph-dir files)
 
     (testing "Asts"
       (is (seq asts) "Asts returned are non-zero")
@@ -25,3 +39,37 @@
                             (string/includes? (:file %) (str graph-dir "/logseq/")))
                           asts))
           "Parsed files shouldn't have empty asts"))))
+
+(defn- create-logseq-graph
+  "Creates a minimal mock graph"
+  [dir]
+  (fs/mkdirSync (path/join dir "logseq") #js {:recursive true})
+  (fs/mkdirSync (path/join dir "journals"))
+  (fs/mkdirSync (path/join dir "pages")))
+
+(deftest ^:focus build-graph-files
+  (create-logseq-graph "tmp/test-graph")
+  ;; Create files that are recognized
+  (fs/writeFileSync "tmp/test-graph/pages/foo.md" "")
+  (fs/writeFileSync "tmp/test-graph/journals/2023_05_09.md" "")
+  ;; Create file that are ignored and filtered out
+  (fs/writeFileSync "tmp/test-graph/pages/foo.json" "")
+  (fs/mkdirSync (path/join "tmp/test-graph" "logseq" "bak"))
+  (fs/writeFileSync "tmp/test-graph/logseq/bak/baz.md" "")
+
+  (testing "ignored files from common-graph"
+    (is (= (map #(path/join (process/cwd) "tmp/test-graph" %) ["journals/2023_05_09.md" "pages/foo.md"])
+           (map :file/path (#'gp-cli/build-graph-files (path/resolve "tmp/test-graph") {})))
+        "Correct paths returned for absolute dir")
+    (process/chdir "tmp/test-graph")
+    (is (= (map #(path/join (process/cwd) %) ["journals/2023_05_09.md" "pages/foo.md"])
+           (map :file/path (#'gp-cli/build-graph-files "." {})))
+        "Correct paths returned for relative current dir")
+    (process/chdir "../.."))
+
+  (testing ":hidden config"
+    (fs/mkdirSync (path/join "tmp/test-graph" "script"))
+    (fs/writeFileSync "tmp/test-graph/script/README.md" "")
+    (is (= (map #(path/join (process/cwd) "tmp/test-graph" %) ["journals/2023_05_09.md" "pages/foo.md"])
+           (map :file/path (#'gp-cli/build-graph-files "tmp/test-graph" {:hidden ["script"]})))
+        "Correct paths returned")))

+ 3 - 0
deps/publishing/src/logseq/publishing/export.cljs

@@ -78,6 +78,7 @@
                                          :as options}]
   (let [custom-css-path (node-path/join repo-path "logseq" "custom.css")
         export-css-path (node-path/join repo-path "logseq" "export.css")
+        custom-js-path (node-path/join repo-path "logseq" "custom.js")
         output-static-dir (node-path/join output-dir "static")
         index-html-path (node-path/join output-dir "index.html")]
     (-> (p/let [_ (fs/mkdirSync output-static-dir #js {:recursive true})
@@ -87,6 +88,8 @@
                 _ (fs/writeFileSync (node-path/join output-static-dir "css" "export.css")  export-css)
                 custom-css (if (fs/existsSync custom-css-path) (str (fs/readFileSync custom-css-path)) "")
                 _ (fs/writeFileSync (node-path/join output-static-dir "css" "custom.css") custom-css)
+                custom-js (if (fs/existsSync custom-js-path) (str (fs/readFileSync custom-js-path)) "")
+                _ (fs/writeFileSync (node-path/join output-static-dir "js" "custom.js") custom-js)
                 _ (cleanup-js-dir output-static-dir)]
                (notification-fn {:type "success"
                                  :payload (str "Export public pages and publish assets to " output-dir " successfully 🎉")}))

+ 2 - 1
deps/publishing/src/logseq/publishing/html.cljs

@@ -126,7 +126,8 @@ necessary db filtering"
             [:script {:src "static/js/highlight.min.js"}]
             [:script {:src "static/js/katex.min.js"}]
             [:script {:src "static/js/html2canvas.min.js"}]
-            [:script {:src "static/js/code-editor.js"}]])))))
+            [:script {:src "static/js/code-editor.js"}]
+            [:script {:src "static/js/custom.js"}]])))))
 
 (defn build-html
   "Given the graph's db, filters the db using the given options and returns the

+ 11 - 1
deps/publishing/test/logseq/publishing/export_test.cljs

@@ -73,7 +73,7 @@
          (let [original-paths (map path/basename (get-files-recursively "tmp/static"))
                copied-paths (map path/basename (get-files-recursively "tmp/published-graph"))
                new-files (set/difference (set copied-paths) (set original-paths))]
-           (is (= #{"index.html" "custom.css" "export.css"}
+           (is (= #{"index.html" "custom.css" "export.css" "custom.js"}
                   new-files)
                "A published graph has the correct new files")
            (is (= "<div>WOOT</div>"
@@ -97,6 +97,16 @@
                 (str (fs/readFileSync "tmp/published-graph/static/css/export.css")))
              "export.css is copied correctly")))
 
+(deftest-async create-export-with-js-files
+  (create-static-dir "tmp/static")
+  (create-logseq-graph "tmp/test-graph")
+  (fs/writeFileSync "tmp/test-graph/logseq/custom.js" "// foo")
+
+  (p/let [_ (create-export "tmp/static" "tmp/test-graph" "tmp/published-graph" {})]
+         (is (= "// foo"
+                (str (fs/readFileSync "tmp/published-graph/static/js/custom.js")))
+             "custom.js is copied correctly")))
+
 (deftest-async create-export-with-assets
   (create-static-dir "tmp/static")
   (create-logseq-graph "tmp/test-graph")

+ 74 - 0
e2e-tests/blockref.spec.ts

@@ -0,0 +1,74 @@
+import { expect } from '@playwright/test'
+import { test } from './fixtures'
+import { createRandomPage, enterNextBlock, modKey, editNthBlock, moveCursorToBeginning, moveCursorToEnd } from './utils'
+import { dispatch_kb_events } from './util/keyboard-events'
+
+// Create a random page with some pre-defined blocks
+// - a
+// - b
+//   id:: UUID
+// - ((id))
+async function setUpBlocks(page, block) {
+  await createRandomPage(page)
+
+  await block.mustFill('a')
+  await block.enterNext()
+  await block.mustFill('b')
+  await page.keyboard.press(modKey + '+c')
+  await page.waitForTimeout(100)
+  await block.enterNext()
+  await page.keyboard.press(modKey + '+v')
+  await page.waitForTimeout(100)
+}
+
+test('backspace at the beginning of a refed block #9406', async ({ page, block }) => {
+  await setUpBlocks(page, block)
+  await editNthBlock(page, 1)
+  await moveCursorToBeginning(page)
+  await page.keyboard.press('Backspace')
+  await expect(page.locator('textarea >> nth=0')).toHaveText("ab")
+  await expect(await block.selectionStart()).toEqual(1)
+  await expect(page.locator('.block-ref >> text="ab"')).toHaveCount(1);
+})
+
+test('delete at the end of a prev block before a refed block #9406', async ({ page, block }) => {
+  await setUpBlocks(page, block)
+  await editNthBlock(page, 0)
+  await moveCursorToEnd(page)
+  await page.keyboard.press('Delete')
+  await expect(page.locator('textarea >> nth=0')).toHaveText("ab")
+  await expect(await block.selectionStart()).toEqual(1)
+  await expect(page.locator('.block-ref >> text="ab"')).toHaveCount(1);
+})
+
+test('delete selected blocks, block ref should be replaced by content #9406', async ({ page, block }) => {
+  await setUpBlocks(page, block)
+  await editNthBlock(page, 0)
+  await page.waitForTimeout(100)
+  await page.keyboard.down('Shift')
+  await page.keyboard.press('ArrowDown')
+  await page.keyboard.press('ArrowDown')
+  await page.keyboard.up('Shift')
+  await block.waitForSelectedBlocks(2)
+  await page.keyboard.press('Backspace')
+  await expect(page.locator('.ls-block')).toHaveCount(1)
+  await editNthBlock(page, 0)
+  await expect(page.locator('textarea >> nth=0')).toHaveText("b")
+})
+
+test('delete and undo #9406', async ({ page, block }) => {
+  await setUpBlocks(page, block)
+  await editNthBlock(page, 0)
+  await page.waitForTimeout(100)
+  await page.keyboard.down('Shift')
+  await page.keyboard.press('ArrowDown')
+  await page.keyboard.press('ArrowDown')
+  await page.keyboard.up('Shift')
+  await block.waitForSelectedBlocks(2)
+  await page.keyboard.press('Backspace')
+  await expect(page.locator('.ls-block')).toHaveCount(1)
+  await page.keyboard.press(modKey + '+z')
+  await page.waitForTimeout(100)
+  await expect(page.locator('.ls-block')).toHaveCount(3)
+  await expect(page.locator('.block-ref >> text="b"')).toHaveCount(1);
+})

+ 25 - 1
e2e-tests/utils.ts

@@ -31,6 +31,26 @@ export async function lastBlock(page: Page): Promise<Locator> {
   return page.locator('textarea >> nth=0')
 }
 
+/**
+ * Move the cursor to the beginning of the current editor
+ * @param page The Playwright Page object.
+ */
+export async function moveCursorToBeginning(page: Page): Promise<Locator> {
+  await page.press('textarea >> nth=0', modKey + '+a') // select all
+  await page.press('textarea >> nth=0', 'ArrowLeft')
+  return page.locator('textarea >> nth=0')
+}
+
+/**
+ * Move the cursor to the end of the current editor
+ * @param page The Playwright Page object.
+ */
+export async function moveCursorToEnd(page: Page): Promise<Locator> {
+  await page.press('textarea >> nth=0', modKey + '+a') // select all
+  await page.press('textarea >> nth=0', 'ArrowRight')
+  return page.locator('textarea >> nth=0')
+}
+
 /**
  * Press Enter and create the next block.
  * @param page The Playwright Page object.
@@ -155,8 +175,12 @@ export async function loadLocalGraph(page: Page, path: string): Promise<void> {
   console.log('Graph loaded for ' + path)
 }
 
+export async function editNthBlock(page: Page, n) {
+  await page.click(`.ls-block .block-content >> nth=${n}`)
+}
+
 export async function editFirstBlock(page: Page) {
-  await page.click('.ls-block .block-content >> nth=0')
+  await editNthBlock(page, 0)
 }
 
 /**

+ 2 - 2
ios/App/App.xcodeproj/project.pbxproj

@@ -513,7 +513,7 @@
 				DEVELOPMENT_TEAM = K378MFWK59;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = App/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				MARKETING_VERSION = 0.9.6;
 				OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
@@ -540,7 +540,7 @@
 				DEVELOPMENT_TEAM = K378MFWK59;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = App/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				MARKETING_VERSION = 0.9.6;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;

+ 14 - 6
src/main/frontend/commands.cljs

@@ -278,7 +278,8 @@
                [:editor/exit]] query-doc]
      ["Zotero" (zotero-steps) "Import Zotero journal article"]
      ["Query table function" [[:editor/input "{{function }}" {:backward-pos 2}]] "Create a query table function"]
-     ["Calculator" [[:editor/input "```calc\n\n```" {:backward-pos 4}]
+     ["Calculator" [[:editor/input "```calc\n\n```" {:type "block"
+                                                     :backward-pos 4}]
                     [:codemirror/focus]] "Insert a calculator"]
      ["Draw" (fn []
                (let [file (draw/file-name)
@@ -402,17 +403,24 @@
         edit-content (gobj/get input "value")
         current-pos (cursor/pos input)
         prefix (subs edit-content 0 current-pos)
+        surfix (subs edit-content current-pos)
         new-value (str prefix
                        value
-                       (subs edit-content current-pos))
+                       surfix)
         new-pos (- (+ (count prefix)
                       (count value)
                       (or forward-pos 0))
                    (or backward-pos 0))]
-    (state/set-block-content-and-last-pos! id new-value new-pos)
-    (cursor/move-cursor-to input new-pos)
-    (when check-fn
-      (check-fn new-value (dec (count prefix)) new-pos))))
+    (state/set-edit-content! (state/get-edit-input-id)
+                             (str prefix value))
+    ;; HACK: save scroll-pos of current pos, then add trailing content
+    (let [scroll-container (util/nearest-scrollable-container input)
+          scroll-pos (.-scrollTop scroll-container)]
+      (state/set-block-content-and-last-pos! id new-value new-pos)
+      (cursor/move-cursor-to input new-pos)
+      (set! (.-scrollTop scroll-container) scroll-pos)
+      (when check-fn
+        (check-fn new-value (dec (count prefix)) new-pos)))))
 
 (defn simple-replace!
   [id value selected

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

@@ -2309,7 +2309,8 @@
 
 (rum/defc block-content < rum/reactive
   [config {:block/keys [uuid content children properties scheduled deadline format pre-block?] :as block} edit-input-id block-id slide?]
-  (let [{:block/keys [title body] :as block} (if (:block/title block) block
+  (let [content (property/remove-built-in-properties format content)
+        {:block/keys [title body] :as block} (if (:block/title block) block
                                                  (merge block (block/parse-title-and-body uuid format pre-block? content)))
         collapsed? (util/collapsed? block)
         plugin-slotted? (and config/lsp-enabled? (state/slot-hook-exist? uuid))

+ 89 - 54
src/main/frontend/handler/editor.cljs

@@ -353,8 +353,16 @@
         block (apply dissoc block db-schema/retract-attributes)]
     (profile
      "Save block: "
-     (let [block' (wrap-parse-block block)
-           opts' (merge opts {:outliner-op :save-block})]
+     (let [original-uuid (:block/uuid (db/entity (:db/id block)))
+           uuid-changed? (not= (:block/uuid block) original-uuid)
+           block' (-> (wrap-parse-block block)
+                      ;; :block/uuid might be changed when backspace/delete
+                      ;; a block that has been refed
+                      (assoc :block/uuid (:block/uuid block)))
+           opts' (merge opts (cond-> {:outliner-op :save-block}
+                               uuid-changed?
+                               (assoc :uuid-changed {:from (:block/uuid block)
+                                                     :to original-uuid})))]
        (outliner-tx/transact!
         opts'
         (outliner-core/save-block! block'))
@@ -383,7 +391,8 @@
          content (-> (property/remove-built-in-properties format content)
                      (drawer/remove-logbook))]
      (cond
-       (another-block-with-same-id-exists? uuid block-id)
+       (and (another-block-with-same-id-exists? uuid block-id)
+            (not (= :delete (:editor/op opts))))
        (notification/show!
         [:p.content
          (util/format "Block with the id %s already exists!" block-id)]
@@ -760,6 +769,9 @@
         (let [original-content (util/trim-safe (:block/content block))
               value' (-> (property/remove-built-in-properties format original-content)
                          (drawer/remove-logbook))
+              value (->> value
+                         (property/remove-properties format)
+                         (drawer/remove-logbook))
               new-value (str value' value)
               tail-len (count value)
               pos (max
@@ -767,10 +779,12 @@
                      (gobj/get (utf8/encode original-content) "length")
                      0)
                    0)
-              f (fn [] (edit-block! block pos id
-                                    {:custom-content new-value
-                                     :tail-len tail-len
-                                     :move-cursor? false}))]
+              f (fn []
+                  (edit-block! (db/pull (:db/id block))
+                               pos
+                               id
+                               {:custom-content new-value
+                                :tail-len tail-len}))]
           (when move? (f))
           {:prev-block block
            :new-content new-value
@@ -788,9 +802,9 @@
        (let [page-id (:db/id (:block/page (db/entity [:block/uuid block-id])))
              page-blocks-count (and page-id (db/get-page-blocks-count repo page-id))]
          (when (> page-blocks-count 1)
-           (let [block (db/entity [:block/uuid block-id])
-                 has-children? (seq (:block/_parent block))
-                 block (db/pull (:db/id block))
+           (let [block-e (db/entity [:block/uuid block-id])
+                 has-children? (seq (:block/_parent block-e))
+                 block (db/pull (:db/id block-e))
                  left (tree/-get-left (outliner-core/block block))
                  left-has-children? (and left
                                          (when-let [block-id (:block/uuid (:data left))]
@@ -803,14 +817,20 @@
                        {:keys [prev-block new-content move-fn]} (move-to-prev-block repo sibling-block format id value false)
                        concat-prev-block? (boolean (and prev-block new-content))
                        transact-opts (cond->
-                                       {:outliner-op :delete-block}
+                                       {:outliner-op :delete-blocks}
                                        concat-prev-block?
                                        (assoc :concat-data
                                               {:last-edit-block (:block/uuid block)}))]
                    (outliner-tx/transact! transact-opts
-                     (when concat-prev-block?
-                       (save-block! repo prev-block new-content))
-                     (delete-block-aux! block delete-children?))
+                     (if concat-prev-block?
+                       (let [prev-block' (if (seq (:block/_refs block-e))
+                                           (assoc prev-block
+                                                  :block/uuid (:block/uuid block)
+                                                  :block/additional-properties (:block/properties block))
+                                           prev-block)]
+                         (delete-block-aux! block delete-children?)
+                         (save-block! repo prev-block' new-content {:editor/op :delete}))
+                       (delete-block-aux! block delete-children?)))
                    (move-fn)))))))))
    (state/set-editor-op! nil)))
 
@@ -1224,28 +1244,24 @@
   (let [value (string/trim value)]
     ;; FIXME: somehow frontend.components.editor's will-unmount event will loop forever
     ;; maybe we shouldn't save the block/file in "will-unmount" event?
-    (save-block-if-changed! block value
-                            (merge
-                             {:init-properties (:block/properties block)}
-                             opts))))
+    (save-block-if-changed! block value opts)))
 
 (defn save-block!
   ([repo block-or-uuid content]
     (save-block! repo block-or-uuid content {}))
-  ([repo block-or-uuid content {:keys [properties] :or {}}]
+  ([repo block-or-uuid content {:keys [properties] :as opts}]
    (let [block (if (or (uuid? block-or-uuid)
                        (string? block-or-uuid))
                  (db-model/query-block-by-uuid block-or-uuid) block-or-uuid)]
      (save-block!
-       {:block block :repo repo}
-       (if (seq properties)
-          (property/insert-properties (:block/format block) content properties)
-        content)
-     )))
-  ([{:keys [block repo] :as _state} value]
+      {:block block :repo repo :opts (dissoc opts :properties)}
+      (if (seq properties)
+        (property/insert-properties (:block/format block) content properties)
+        content))))
+  ([{:keys [block repo opts] :as _state} value]
    (let [repo (or repo (state/get-current-repo))]
      (when (db/entity repo [:block/uuid (:block/uuid block)])
-       (save-block-aux! block value {})))))
+       (save-block-aux! block value opts)))))
 
 (defn save-blocks!
   [blocks]
@@ -1539,7 +1555,7 @@
          "$" "$"
          ":" ":"))
 
-(defn autopair
+(defn- autopair
   [input-id prefix _format _option]
   (let [value (get autopair-map prefix)
         selected (util/get-selected-text)
@@ -1576,11 +1592,11 @@
 (defn- autopair-left-paren?
   [input key]
   (and (= key "(")
-       (or
-         (surround-by? input :start "")
-         (surround-by? input " " "")
-         (surround-by? input "]" "")
-         (surround-by? input "(" ""))))
+       (or (surround-by? input :start "")
+           (surround-by? input "\n" "")
+           (surround-by? input " " "")
+           (surround-by? input "]" "")
+           (surround-by? input "(" ""))))
 
 (defn wrapped-by?
   [input before end]
@@ -1967,7 +1983,9 @@
                   exclude-properties
                   target-block
                   sibling?
-                  keep-uuid?]
+                  keep-uuid?
+                  cut-paste?
+                  revert-cut-txs]
            :or {exclude-properties []}}]
   (let [editing-block (when-let [editing-block (state/get-edit-block)]
                         (some-> (db/pull [:block/uuid (:block/uuid editing-block)])
@@ -1982,8 +2000,7 @@
         empty-target? (string/blank? (:block/content target-block))
         paste-nested-blocks? (nested-blocks blocks)
         target-block-has-children? (db/has-children? (:block/uuid target-block))
-        replace-empty-target? (if (and paste-nested-blocks? empty-target?
-                                       target-block-has-children?)
+        replace-empty-target? (if (and paste-nested-blocks? empty-target? target-block-has-children?)
                                 false
                                 true)
         target-block' (if replace-empty-target? target-block
@@ -2009,13 +2026,15 @@
         (outliner-core/save-block! editing-block)))
 
     (outliner-tx/transact!
-      {:outliner-op :insert-blocks}
+      {:outliner-op :insert-blocks
+       :additional-tx revert-cut-txs}
       (when target-block'
         (let [format (or (:block/format target-block') (state/get-preferred-format))
               blocks' (map (fn [block]
                              (paste-block-cleanup block page exclude-properties format content-update-fn keep-uuid?))
                         blocks)
               result (outliner-core/insert-blocks! blocks' target-block' {:sibling? sibling?
+                                                                          :cut-paste? cut-paste?
                                                                           :outliner-op :paste
                                                                           :replace-empty-target? replace-empty-target?
                                                                           :keep-uuid? keep-uuid?})]
@@ -2205,10 +2224,18 @@
            s1 (subs value 0 selected-start)
            s2 (subs value selected-end)]
        (state/set-edit-content! (state/get-edit-input-id)
-                                (str s1 insertion s2))
-       (cursor/move-cursor-to input (+ selected-start (count insertion)))))))
+                                (str s1 insertion))
+       ;; HACK: save scroll-pos of current pos, then add trailing content
+       ;; This logic is also in commands/simple-insert!
+       (let [scroll-container (util/nearest-scrollable-container input)
+             scroll-pos (.-scrollTop scroll-container)]
+         (state/set-edit-content! (state/get-edit-input-id)
+                                  (str s1 insertion s2))
+         (cursor/move-cursor-to input (+ selected-start (count insertion)))
+         (set! (.-scrollTop scroll-container) scroll-pos))))))
 
 (defn- keydown-new-line
+  "Insert newline to current cursor position"
   []
   (insert "\n"))
 
@@ -2434,7 +2461,6 @@
             (profile
              "Insert block"
              (outliner-tx/transact! {:outliner-op :insert-blocks}
-               (save-current-block!)
                (insert-new-block! state)))))))))
 
 (defn- inside-of-single-block
@@ -2585,8 +2611,7 @@
   (state/set-edit-content! (state/get-edit-input-id) (.-value input)))
 
 (defn- delete-concat [current-block]
-  (let [input-id (state/get-edit-input-id)
-        ^js input (state/get-input)
+  (let [^js input (state/get-input)
         current-pos (cursor/pos input)
         value (gobj/get input "value")
         right (outliner-core/get-right-sibling (:db/id current-block))
@@ -2608,17 +2633,27 @@
 
       :else
       (let [edit-block (state/get-edit-block)
-            transact-opts {:outliner-op :delete-block
+            transact-opts {:outliner-op :delete-blocks
                            :concat-data {:last-edit-block (:block/uuid edit-block)
                                          :end? true}}
-            new-content (str value "" (:block/content next-block))
-            repo (state/get-current-repo)]
+            next-block-has-refs? (some? (:block/_refs (db/entity (:db/id next-block))))
+            new-content (if next-block-has-refs?
+                          (str value ""
+                               (->> (:block/content next-block)
+                                    (property/remove-properties (:block/format next-block))
+                                    (drawer/remove-logbook)))
+                          (str value "" (:block/content next-block)))
+            repo (state/get-current-repo)
+            edit-block' (if next-block-has-refs?
+                          (assoc edit-block
+                                 :block/uuid (:block/uuid next-block)
+                                 :block/additional-properties (dissoc (:block/properties next-block) :block/uuid))
+                          edit-block)]
         (outliner-tx/transact! transact-opts
-          (save-block! repo edit-block new-content)
-          (delete-block-aux! next-block false))
-
-        (state/set-edit-content! input-id new-content)
-        (cursor/move-cursor-to input current-pos)))))
+          (delete-block-aux! next-block false)
+          (save-block! repo edit-block' new-content {:editor/op :delete}))
+        (let [block (if next-block-has-refs? next-block edit-block)]
+          (edit-block! block current-pos (:block/uuid block)))))))
 
 (defn keydown-delete-handler
   [_e]
@@ -2832,11 +2867,11 @@
             (contains? key)
             (or (autopair-left-paren? input key)))
         (let [curr (get-current-input-char input)
-                  prev (util/nth-safe value (dec pos))]
-            (util/stop e)
-            (if (and (= key "`") (= "`" curr) (not= "`" prev))
-              (cursor/move-cursor-forward input)
-              (autopair input-id key format nil)))
+              prev (util/nth-safe value (dec pos))]
+          (util/stop e)
+          (if (and (= key "`") (= "`" curr) (not= "`" prev))
+            (cursor/move-cursor-forward input)
+            (autopair input-id key format nil)))
 
         (let [sym "$"]
           (and (= key sym)

+ 4 - 2
src/main/frontend/handler/editor/lifecycle.cljs

@@ -36,8 +36,10 @@
   [state]
   (let [{:keys [value]} (get-state)]
     (editor-handler/clear-when-saved!)
-    ;; TODO: ugly
-    (when-not (contains? #{:insert :indent-outdent :auto-save :undo :redo :delete} (state/get-editor-op))
+    (when (and
+           (not (contains? #{:insert :indent-outdent :auto-save :undo :redo :delete} (state/get-editor-op)))
+           ;; Don't trigger auto-save if the latest op is undo or redo
+           (not (contains? #{:undo :redo} (state/get-editor-latest-op))))
       (editor-handler/save-block! (get-state) value)))
   state)
 

+ 3 - 4
src/main/frontend/handler/editor/property.cljs

@@ -38,9 +38,8 @@
 (defn edit-block!
   ([block pos id]
    (edit-block! block pos id nil))
-  ([block pos id {:keys [custom-content tail-len move-cursor? retry-times]
+  ([block pos id {:keys [custom-content tail-len retry-times]
                   :or {tail-len 0
-                       move-cursor? true
                        retry-times 0}
                   :as opts}]
    (when-not (> retry-times 2)
@@ -70,7 +69,7 @@
                            (drawer/remove-logbook))]
            (clear-selection!)
            (if edit-input-id
-             (state/set-editing! edit-input-id content block text-range move-cursor?)
+             (state/set-editing! edit-input-id content block text-range)
              ;; Block may not be rendered yet
              (js/setTimeout (fn [] (edit-block! block pos id (update opts :retry-times inc))) 10))))))))
 
@@ -138,4 +137,4 @@
 (defn set-block-property!
   [block-id key value]
   (let [key (keyword key)]
-    (batch-set-block-property! [[block-id key value]])))
+    (batch-set-block-property! [[block-id key value]])))

+ 15 - 1
src/main/frontend/handler/paste.cljs

@@ -105,6 +105,15 @@
   [text]
   (boolean (util/safe-re-find #"(?m)^\s*\*+\s+" text)))
 
+(defn- get-revert-cut-tx
+  "Get reverted previous cut tx when paste"
+  [blocks]
+  (let [{:keys [retracted-block-ids revert-tx]} (get-in @state/state [:editor/last-replace-ref-content-tx (state/get-current-repo)])
+        recent-cut-block-ids (->> retracted-block-ids (map second) (set))]
+    (state/set-state! [:editor/last-replace-ref-content-tx (state/get-current-repo)] nil)
+    (when (= (set (map :block/uuid blocks)) recent-cut-block-ids)
+      (seq revert-tx))))
+
 (defn- paste-copied-blocks-or-text
   ;; todo: logseq/whiteboard-shapes is now text/html
   [text e html]
@@ -120,7 +129,12 @@
                               (commands/simple-insert! input-id text nil)))
            internal-paste? (seq copied-blocks)]
        (if internal-paste?
-         (editor-handler/paste-blocks copied-blocks {})
+         (let [revert-cut-tx (get-revert-cut-tx copied-blocks)
+               cut-paste? (boolean (seq revert-cut-tx))
+               keep-uuid? cut-paste?]
+           (editor-handler/paste-blocks copied-blocks {:revert-cut-tx revert-cut-tx
+                                                       :cut-paste? cut-paste?
+                                                       :keep-uuid? keep-uuid?}))
          (let [shape-refs-text (when (and (not (string/blank? html))
                                           (get-whiteboard-tldr-from-text html))
                                  ;; text should always be prepared block-ref generated in tldr

+ 7 - 3
src/main/frontend/modules/editor/undo_redo.cljs

@@ -7,7 +7,9 @@
             [frontend.util.page :as page-util]
             [frontend.state :as state]
             [clojure.set :as set]
-            [medley.core :as medley]))
+            [medley.core :as medley]
+            [frontend.util.drawer :as drawer]
+            [frontend.util.property :as property]))
 
 ;;;; APIs
 
@@ -157,8 +159,10 @@
   "Prevent block auto-save during undo/redo."
   []
   (when-let [block (state/get-edit-block)]
-    (state/set-edit-content! (state/get-edit-input-id)
-                             (:block/content (db/entity (:db/id block))))))
+    (when-let [content (:block/content (db/entity (:db/id block)))]
+      (let [content' (-> (property/remove-built-in-properties (:block/format block) content)
+                         (drawer/remove-logbook))]
+        (state/set-edit-content! (state/get-edit-input-id) content')))))
 
 (defn- get-next-tx-editor-cursor
   [tx-id]

+ 8 - 3
src/main/frontend/modules/file/core.cljs

@@ -32,8 +32,10 @@
     content))
 
 (defn transform-content
-  [{:block/keys [collapsed? format pre-block? unordered content left page parent properties]} level {:keys [heading-to-list?]}]
-  (let [heading (:heading properties)
+  [{:block/keys [collapsed? format pre-block? unordered content left page parent properties] :as b} level {:keys [heading-to-list?]}]
+  (let [block-ref-not-saved? (and (seq (:block/_refs (db/entity (:db/id b))))
+                                  (not (string/includes? content (str (:block/uuid b)))))
+        heading (:heading properties)
         markdown? (= :markdown format)
         content (or content "")
         pre-block? (or pre-block?
@@ -80,7 +82,10 @@
                                     (string/blank? new-content))
                               ""
                               " ")]
-                    (str prefix sep new-content)))]
+                    (str prefix sep new-content)))
+        content (if block-ref-not-saved?
+                  (property/insert-property format content :id (str (:block/uuid b)))
+                  content)]
     content))
 
 

+ 11 - 2
src/main/frontend/modules/outliner/core.cljs

@@ -528,10 +528,11 @@
                     For example, if `blocks` are from internal copy, the uuids
                     need to be changed, but there's no need for drag & drop.
       `outliner-op`: what's the current outliner operation.
+      `cut-paste?`: whether it's pasted from cut blocks
       `replace-empty-target?`: If the `target-block` is an empty block, whether
                                to replace it, it defaults to be `false`.
     ``"
-  [blocks target-block {:keys [sibling? keep-uuid? outliner-op replace-empty-target?] :as opts}]
+  [blocks target-block {:keys [sibling? keep-uuid? outliner-op replace-empty-target? cut-paste?] :as opts}]
   {:pre [(seq blocks)
          (s/valid? ::block-map-or-entity target-block)]}
   (let [target-block' (get-target-block target-block)
@@ -587,7 +588,10 @@
                       (when-let [left (last (filter (fn [b] (= 1 (:block/level b))) tx))]
                         [{:block/uuid (tree/-get-id next)
                           :block/left (:db/id left)}]))
-            full-tx (util/concat-without-nil uuids-tx tx next-tx)]
+            cut-target-tx (when (and cut-paste? replace-empty-target?)
+                            [{:db/id (:db/id target-block')
+                              :block/uuid (:block/uuid (first blocks'))}])
+            full-tx (util/concat-without-nil uuids-tx tx next-tx cut-target-tx)]
         (when (and replace-empty-target? (state/editing?))
           (state/set-edit-content! (state/get-edit-input-id) (:block/content (first blocks))))
         {:tx-data full-tx
@@ -859,6 +863,11 @@
   see also `frontend.modules.outliner.transaction/transact!`"
   nil)
 
+(def ^:private ^:dynamic #_:clj-kondo/ignore *transaction-opts*
+  "Stores transaction opts that are generated by one or more write-operations,
+  see also `frontend.modules.outliner.transaction/transact!`"
+  nil)
+
 (defn- op-transact!
   [fn-var & args]
   {:pre [(var? fn-var)]}

+ 84 - 4
src/main/frontend/modules/outliner/datascript.cljc

@@ -10,7 +10,11 @@
                      [frontend.config :as config]
                      [logseq.graph-parser.util :as gp-util]
                      [lambdaisland.glogi :as log]
-                     [frontend.search :as search])))
+                     [frontend.search :as search]
+                     [clojure.string :as string]
+                     [frontend.util :as util]
+                     [frontend.util.property :as property]
+                     [logseq.graph-parser.util.block-ref :as block-ref])))
 
 #?(:cljs
    (defn new-outliner-txs-state [] (atom [])))
@@ -51,6 +55,71 @@
      [tx-report]
      (get-in tx-report [:tempids :db/current-tx])))
 
+#?(:cljs
+   (defn update-block-refs
+     [txs opts]
+     (if-let [changed (:uuid-changed opts)]
+       (let [{:keys [from to]} changed
+             from-e (db/entity [:block/uuid from])
+             to-e (db/entity [:block/uuid to])
+             from-id (:db/id from-e)
+             to-id (:db/id to-e)
+             from-refs (:block/_refs from-e)
+             from-path-refs (:block/_path-refs from-e)
+             to-refs (:block/_refs to-e)
+             from-refs-txs (mapcat (fn [ref]
+                                     (let [id (:db/id ref)]
+                                       [[:db/retract id :block/refs from-id]
+                                        [:db/add id :block/refs to-id]])) from-refs)
+             from-path-refs-txs (mapcat (fn [ref]
+                                          (let [id (:db/id ref)]
+                                            [[:db/retract id :block/path-refs from-id]
+                                             [:db/add id :block/path-refs to-id]])) from-path-refs)
+             to-refs-txs (mapcat (fn [ref]
+                                        (let [id (:db/id ref)
+                                              new-content (string/replace (:block/content ref)
+                                                                          (block-ref/->block-ref to)
+                                                                          (block-ref/->block-ref from))]
+                                          [[:db/add id :block/content new-content]])) to-refs)]
+         (concat txs from-refs-txs from-path-refs-txs to-refs-txs))
+       txs)))
+
+#?(:cljs
+   (defn replace-ref-with-content
+     [txs opts]
+     (if (and (= :delete-blocks (:outliner-op opts))
+              (empty? (:uuid-changed opts)))
+       (let [retracted-block-ids (->> (keep (fn [tx]
+                                              (when (and (vector? tx)
+                                                         (= :db.fn/retractEntity (first tx)))
+                                                (second tx))) txs))
+             retracted-blocks (map db/entity retracted-block-ids)
+             retracted-tx (->> (for [block retracted-blocks]
+                                 (let [refs (:block/_refs block)]
+                                   (map (fn [ref]
+                                          (let [id (:db/id ref)
+                                                block-content (property/remove-properties (:block/format block) (:block/content block))
+                                                new-content (-> (:block/content ref)
+                                                                (string/replace (re-pattern (util/format "(?i){{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block))))
+                                                                                block-content)
+                                                                (string/replace (block-ref/->block-ref (str (:block/uuid block)))
+                                                                                block-content))]
+                                            {:tx [[:db/retract (:db/id ref) :block/refs (:db/id block)]
+                                                  [:db/retract (:db/id ref) :block/path-refs (:db/id block)]
+                                                  [:db/add id :block/content new-content]]
+                                             :revert-tx [[:db/add (:db/id ref) :block/refs (:db/id block)]
+                                                         [:db/add (:db/id ref) :block/path-refs (:db/id block)]
+                                                         [:db/add id :block/content (:block/content ref)]]})) refs)))
+                               (apply concat))
+             retracted-tx' (mapcat :tx retracted-tx)
+             revert-tx (mapcat :revert-tx retracted-tx)]
+         (when (seq retracted-tx')
+           (state/set-state! [:editor/last-replace-ref-content-tx (state/get-current-repo)]
+                             {:retracted-block-ids retracted-block-ids
+                              :revert-tx revert-tx}))
+         (concat txs retracted-tx'))
+       txs)))
+
 #?(:cljs
    (defn transact!
      [txs opts before-editor-cursor]
@@ -58,15 +127,26 @@
            txs (map (fn [m] (if (map? m)
                               (dissoc m
                                       :block/children :block/meta :block/top? :block/bottom? :block/anchor
-                                      :block/title :block/body :block/level :block/container :db/other-tx)
-                              m)) txs)]
+                                      :block/title :block/body :block/level :block/container :db/other-tx
+                                      :block/additional-properties)
+                              m)) txs)
+           txs (cond-> txs
+                 (:uuid-changed opts)
+                 (update-block-refs opts)
+
+                 (and (= :delete-blocks (:outliner-op opts))
+                      (empty? (:uuid-changed opts)))
+                 (replace-ref-with-content opts)
+
+                 true
+                 (distinct))]
        (when (and (seq txs)
                   (not (:skip-transact? opts))
                   (not (contains? (:file/unlinked-dirs @state/state)
                                   (config/get-repo-dir (state/get-current-repo)))))
 
          ;; (prn "[DEBUG] Outliner transact:")
-         ;; (frontend.util/pprint txs)
+         ;; (frontend.util/pprint {:txs txs :opts opts})
 
          (try
            (let [repo (get opts :repo (state/get-current-repo))

+ 13 - 4
src/main/frontend/modules/outliner/transaction.cljc

@@ -23,22 +23,31 @@
     (move-blocks! ...)
     (delete-blocks! ...))"
   [opts & body]
-  (assert (or (map? opts) (symbol? opts)) (str "opts is not a map or symbol, type: " (type opts) ))
+  (assert (or (map? opts) (symbol? opts)) (str "opts is not a map or symbol, type: " (type opts)))
   `(let [transact-data# frontend.modules.outliner.core/*transaction-data*
+         transaction-opts# frontend.modules.outliner.core/*transaction-opts*
          opts# (if transact-data#
                  (assoc ~opts :nested-transaction? true)
                  ~opts)
          before-editor-cursor# (frontend.state/get-current-edit-block-and-position)]
      (if transact-data#
-       (do ~@body)
-       (binding [frontend.modules.outliner.core/*transaction-data* (transient [])]
+       (do
+         (when transaction-opts#
+           (conj! transaction-opts# opts#))
+         ~@body)
+       (binding [frontend.modules.outliner.core/*transaction-data* (transient [])
+                 frontend.modules.outliner.core/*transaction-opts* (transient [])]
+         (conj! frontend.modules.outliner.core/*transaction-opts* transaction-opts# opts#)
          ~@body
          (let [r# (persistent! frontend.modules.outliner.core/*transaction-data*)
                tx# (mapcat :tx-data r#)
                ;; FIXME: should we merge all the tx-meta?
                tx-meta# (first (map :tx-meta r#))
                all-tx# (concat tx# (:additional-tx opts#))
-               opts## (merge (dissoc opts# :additional-tx) tx-meta#)]
+               o# (persistent! frontend.modules.outliner.core/*transaction-opts*)
+               full-opts# (apply merge (reverse o#))
+               opts## (merge (dissoc full-opts# :additional-tx :current-block :nested-transaction?) tx-meta#)]
+
            (when (seq all-tx#) ;; If it's empty, do nothing
              (when-not (:nested-transaction? opts#) ; transact only for the whole transaction
                (let [result# (frontend.modules.outliner.datascript/transact! all-tx# opts## before-editor-cursor#)]

+ 13 - 3
src/main/frontend/state.cljs

@@ -105,6 +105,8 @@
 
      :config                                {}
      :block/component-editing-mode?         false
+     :editor/op                             nil
+     :editor/latest-op                      nil
      :editor/hidden-editors                 #{}             ;; page names
      :editor/draw-mode?                     false
      :editor/action                         nil
@@ -123,6 +125,9 @@
      :editor/on-paste?                      false
      :editor/last-key-code                  nil
 
+     ;; Stores deleted refed blocks, indexed by repo
+     :editor/last-replace-ref-content-tx    nil
+
      ;; for audio record
      :editor/record-status                  "NONE"
 
@@ -1694,13 +1699,18 @@ Similar to re-frame subscriptions"
 
 ;; TODO: Move those to the uni `state`
 
-(defonce editor-op (atom nil))
 (defn set-editor-op!
   [value]
-  (reset! editor-op value))
+  (set-state! :editor/op value)
+  (when value (set-state! :editor/latest-op value)))
+
 (defn get-editor-op
   []
-  @editor-op)
+  (:editor/op @state))
+
+(defn get-editor-latest-op
+  []
+  (:editor/latest-op @state))
 
 (defn get-events-chan
   []

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

@@ -398,6 +398,13 @@
    (defn stop-propagation [e]
      (when e (.stopPropagation e))))
 
+#?(:cljs
+   (defn nearest-scrollable-container [^js/HTMLElement element]
+     (some #(when-let [overflow-y (.-overflowY (js/window.getComputedStyle %))]
+              (when (contains? #{"auto" "scroll" "overlay"} overflow-y)
+                %))
+           (take-while (complement nil?) (iterate #(.-parentElement %) element)))))
+
 #?(:cljs
    (defn element-top [elem top]
      (when elem

+ 5 - 5
src/test/frontend/handler/repo_conversion_test.cljs

@@ -17,11 +17,11 @@
                      :after test-helper/destroy-test-db!})
 
 (defn- query-assertions-v067
-  [db files]
+  [db graph-dir files]
   (testing "Query based stats"
     (is (= (->> files
                 ;; logseq files aren't saved under :block/file
-                (remove #(string/includes? % (str "/" gp-config/app-name "/")))
+                (remove #(string/includes? % (str graph-dir "/" gp-config/app-name "/")))
                 set)
            (->> (d/q '[:find (pull ?b [* {:block/file [:file/path]}])
                        :where [?b :block/name] [?b :block/file]]
@@ -93,7 +93,7 @@
   logseq app. It is important to run these in both contexts to ensure that the
   functionality in frontend.handler.repo and logseq.graph-parser remain the
   same"
-  [db files]
+  [db graph-dir files]
   ;; Counts assertions help check for no major regressions. These counts should
   ;; only increase over time as the docs graph rarely has deletions
   (testing "Counts"
@@ -113,7 +113,7 @@
                  db)))
         "Advanced query count"))
 
-  (query-assertions-v067 db files))
+  (query-assertions-v067 db graph-dir files))
 
 (defn- convert-to-triple-lowbar
   [path]
@@ -144,4 +144,4 @@
         db (conn/get-db test-helper/test-db)]
 
     ;; Result under new naming rule after conversion should be the same as the old one
-    (docs-graph-assertions-v067 db (map :file/path files))))
+    (docs-graph-assertions-v067 db graph-dir (map :file/path files))))

+ 1 - 1
src/test/frontend/handler/repo_test.cljs

@@ -22,7 +22,7 @@
             (repo-handler/parse-files-and-load-to-db! test-helper/test-db files {:re-render? false :verbose false}))
         db (conn/get-db test-helper/test-db)]
 
-    (docs-graph-helper/docs-graph-assertions db (map :file/path files))))
+    (docs-graph-helper/docs-graph-assertions db graph-dir (map :file/path files))))
 
 (deftest parse-files-and-load-to-db-with-block-refs-on-reload
   (testing "Refs to blocks on a page are retained if that page is reloaded"

+ 9 - 9
templates/config.edn

@@ -13,7 +13,7 @@
  :preferred-workflow :now
 
  ;; Exclude directories/files.
- ;; Example usage: 
+ ;; Example usage:
  ;; :hidden ["/archived" "/test.md" "../assets/archived"]
  :hidden []
 
@@ -87,7 +87,7 @@
 
  ;; Specify the first day of the week.
  ;; Available options:
- ;;  - integer from 0 to 6 (Monday to Sunday) 
+ ;;  - integer from 0 to 6 (Monday to Sunday)
  ;; Default value: 6 (Sunday)
  :start-of-week 6
 
@@ -102,7 +102,7 @@
  ;; :custom-js-url "https://cdn.logseq.com/custom.js"
 
  ;; Set a custom Arweave gateway
- ;; Default value: https://arweave.net
+ ;; Default gateway: https://arweave.net
  ;; :arweave/gateway "https://arweave.net"
 
  ;; Set bullet indentation when exporting
@@ -154,7 +154,7 @@
  ;; Configure custom shortcuts.
  ;; Syntax:
  ;; 1. + indicates simultaneous key presses, e.g., `Ctrl+Shift+a`.
- ;; 2. A space between keys represents key chords, e.g., `t s` means 
+ ;; 2. A space between keys represents key chords, e.g., `t s` means
  ;;    pressing `t` followed by `s`.
  ;; 3. mod refers to `Ctrl` for Windows/Linux and `Command` for Mac.
  ;; 4. Use false to disable a specific shortcut.
@@ -280,7 +280,7 @@
  :ref/default-open-blocks-level 2
 
  ;; Configure the threshold for linked references before collapsing.
- ;; Default value: 50
+ ;; Default value: 100
  :ref/linked-references-collapsed-threshold 50
 
  ;; Graph view configuration.
@@ -325,7 +325,7 @@
  ;; Properties that are ignored when parsing property values for references
  ;; Example usage:
  ;; :ignored-page-references-keywords #{:author :website}
- 
+
  ;; logbook configuration.
  ;; :logbook/settings
  ;; {:with-second-support? false ;limit logbook to minutes, seconds will be eliminated
@@ -341,7 +341,7 @@
  ;; Mobile features options
  ;; Gestures
  ;; Example usage:
- ;; :mobile 
+ ;; :mobile
  ;; {:gestures/disabled-in-block-with-tags ["kanban"]}
 
  ;; Extra CodeMirror options
@@ -353,11 +353,11 @@
  ;;  :readOnly      false} ; Default value: false
 
  ;; Enable logical outdenting
- ;; Default value: false 
+ ;; Default value: false
  ;; :editor/logical-outdenting? false
 
  ;; Prefer pasting the file when text and a file are in the clipboard.
- ;; Default value: false 
+ ;; Default value: false
  ;; :editor/preferred-pasting-file? false
 
  ;; Quick capture templates for receiving content from other apps.