From 7eddfd25479a25c24f7c0879d3b004aada4ce27e Mon Sep 17 00:00:00 2001 From: hasecilu Date: Thu, 18 May 2023 21:10:39 -0600 Subject: [PATCH 01/36] Update Spanish translations with new format --- src/main/frontend/dicts/es.cljc | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/frontend/dicts/es.cljc b/src/main/frontend/dicts/es.cljc index 4ae0d72bf9..25dafebecc 100644 --- a/src/main/frontend/dicts/es.cljc +++ b/src/main/frontend/dicts/es.cljc @@ -497,4 +497,32 @@ :command.ui/install-plugins-from-file "Instalar extensiones de plugins.edn" :command.ui/select-theme-color "Seleccionar temas de colores disponibles" :command.ui/toggle-cards "Alternar tarjetas" - :command.ui/toggle-left-sidebar "Alternar barra lateral izquierda"}) \ No newline at end of file + :command.ui/toggle-left-sidebar "Alternar barra lateral izquierda" + :command.editor/toggle-number-list "Alternar lista de números" + :command.whiteboard/bring-forward "Avanzar" + :command.whiteboard/bring-to-front "Mover al frente" + :command.whiteboard/connector "Herramienta conector" + :command.whiteboard/ellipse "Herramienta elipse" + :command.whiteboard/eraser "Herramienta borrador" + :command.whiteboard/group "Agrupar selección" + :command.whiteboard/highlighter "Herramienta resaltar" + :command.whiteboard/lock "Bloquear selección" + :command.whiteboard/pan "Herramienta mover" + :command.whiteboard/pencil "Herramienta lápiz" + :command.whiteboard/portal "Herramienta portal" + :command.whiteboard/rectangle "Herramienta rectángulo" + :command.whiteboard/reset-zoom "Restablecer zoom" + :command.whiteboard/select "Seleccionar herramienta" + :command.whiteboard/send-backward "Retroceder" + :command.whiteboard/send-to-back "Mover hacia atrás" + :command.whiteboard/text "Herramienta texto" + :command.whiteboard/toggle-grid "Alternar la grilla del lienzo" + :command.whiteboard/ungroup "Desagrupar selección" + :command.whiteboard/unlock "Desbloquear selección" + :command.whiteboard/zoom-in "Acercar" + :command.whiteboard/zoom-out "Alejar" + :command.whiteboard/zoom-to-fit "Zoom al dibujo" + :command.whiteboard/zoom-to-selection "Zoom para ajustar a la selección" + :shortcut.category/whiteboard "Pizarra" + :context-menu/toggle-number-list "Alternar lista de números" + :file-sync/rsapi-cannot-upload-err "Incapaz de comenzar la sincronización, favor de checar si..."}) From 585efd1a64be17cbd2a6a4a80035e2aec4df79cb Mon Sep 17 00:00:00 2001 From: Michele Date: Fri, 19 May 2023 09:23:16 +0200 Subject: [PATCH 02/36] Update it.cljc --- src/main/frontend/dicts/it.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/dicts/it.cljc b/src/main/frontend/dicts/it.cljc index 468e9cf19b..bc6ce06879 100644 --- a/src/main/frontend/dicts/it.cljc +++ b/src/main/frontend/dicts/it.cljc @@ -218,7 +218,7 @@ :plugin/load-unpacked "Carica plugin non pacchettizzato" :plugin/restart "Riavvia app" :plugin/unpacked-tips "Seleziona la cartella del plugin" - :plugin/contribute "✨ Svilupppa e sottoponici un nuovo plugin" + :plugin/contribute "✨ Sviluppa e sottoponici un nuovo plugin" :plugin/up-to-date "È aggiornato" :plugin/custom-js-alert "Trovato il file custom.js, è consentito eseguirlo? (Se non si comprende il contenuto di questo file, si consiglia di non consentire l'esecuzione, che presenta alcuni rischi per la sicurezza.)" From 51a23934a40edd378c067e63136e50d1b7f17c2d Mon Sep 17 00:00:00 2001 From: Gabriel Horner Date: Fri, 19 May 2023 17:27:24 -0400 Subject: [PATCH 03/36] Fix parse-graph not ignoring correctly for relative dir parse-graph now returns absolute file paths --- deps/common/src/logseq/common/graph.cljs | 3 +- .../src/logseq/graph_parser/cli.cljs | 15 ++--- .../graph_parser/test/docs_graph_helper.cljs | 8 +-- .../test/logseq/graph_parser/cli_test.cljs | 58 +++++++++++++++++-- .../handler/repo_conversion_test.cljs | 10 ++-- src/test/frontend/handler/repo_test.cljs | 2 +- 6 files changed, 73 insertions(+), 23 deletions(-) diff --git a/deps/common/src/logseq/common/graph.cljs b/deps/common/src/logseq/common/graph.cljs index d6c012673c..abf64dfdda 100644 --- a/deps/common/src/logseq/common/graph.cljs +++ b/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)) diff --git a/deps/graph-parser/src/logseq/graph_parser/cli.cljs b/deps/graph-parser/src/logseq/graph_parser/cli.cljs index 33b6c2043f..e8c96d9a42 100644 --- a/deps/graph-parser/src/logseq/graph_parser/cli.cljs +++ b/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" diff --git a/deps/graph-parser/src/logseq/graph_parser/test/docs_graph_helper.cljs b/deps/graph-parser/src/logseq/graph_parser/test/docs_graph_helper.cljs index 0d6b6168a9..c63c2805d9 100644 --- a/deps/graph-parser/src/logseq/graph_parser/test/docs_graph_helper.cljs +++ b/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)) diff --git a/deps/graph-parser/test/logseq/graph_parser/cli_test.cljs b/deps/graph-parser/test/logseq/graph_parser/cli_test.cljs index 626cc58221..cc3094fb4f 100644 --- a/deps/graph-parser/test/logseq/graph_parser/cli_test.cljs +++ b/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"))) \ No newline at end of file diff --git a/src/test/frontend/handler/repo_conversion_test.cljs b/src/test/frontend/handler/repo_conversion_test.cljs index 20afee5c22..fc383fcce5 100644 --- a/src/test/frontend/handler/repo_conversion_test.cljs +++ b/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)))) diff --git a/src/test/frontend/handler/repo_test.cljs b/src/test/frontend/handler/repo_test.cljs index cb3662133a..6738f89160 100644 --- a/src/test/frontend/handler/repo_test.cljs +++ b/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" From c2f280cf4438fe94ba121047e8e2c341559dffcc Mon Sep 17 00:00:00 2001 From: Andelf Date: Fri, 19 May 2023 19:29:21 +0800 Subject: [PATCH 04/36] chore(mobile): drop support for ios 13 --- ios/App/App.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index b777c4ee75..2893ab95c3 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/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; From 8a0a41ccb87038dccbaa6e65bb0a1c07272649cd Mon Sep 17 00:00:00 2001 From: Giuseppe D'Andrea Date: Sun, 21 May 2023 13:14:57 +0200 Subject: [PATCH 05/36] enhance: calculator command on a non-blank line --- src/main/frontend/commands.cljs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index 5213ef7857..0559ed94d5 100644 --- a/src/main/frontend/commands.cljs +++ b/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) From ea019bcad5f5e1345317738485ced88f243f40da Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 14:35:35 +0800 Subject: [PATCH 06/36] fix: broken block ref when backspace/delete a block --- src/main/frontend/handler/editor.cljs | 57 +++++++++++++------ src/main/frontend/modules/file/core.cljs | 11 +++- src/main/frontend/modules/outliner/core.cljs | 5 ++ .../frontend/modules/outliner/datascript.cljc | 28 ++++++++- .../modules/outliner/transaction.cljc | 11 +++- 5 files changed, 88 insertions(+), 24 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 81670020db..f3afb0635d 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/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')) @@ -760,6 +768,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 @@ -788,9 +799,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))] @@ -808,9 +819,15 @@ (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)) + (delete-block-aux! block delete-children?))) (move-fn))))))))) (state/set-editor-op! nil))) @@ -1224,10 +1241,7 @@ (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] @@ -2611,11 +2625,22 @@ transact-opts {:outliner-op :delete-block :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)) + (delete-block-aux! next-block false) + (save-block! repo edit-block' new-content)) (state/set-edit-content! input-id new-content) (cursor/move-cursor-to input current-pos))))) diff --git a/src/main/frontend/modules/file/core.cljs b/src/main/frontend/modules/file/core.cljs index 4162c5e55c..f5ee06e582 100644 --- a/src/main/frontend/modules/file/core.cljs +++ b/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)) diff --git a/src/main/frontend/modules/outliner/core.cljs b/src/main/frontend/modules/outliner/core.cljs index 2fbb9d5fd9..ab66d8c069 100644 --- a/src/main/frontend/modules/outliner/core.cljs +++ b/src/main/frontend/modules/outliner/core.cljs @@ -859,6 +859,11 @@ see also `frontend.modules.outliner.transaction/transact!`" nil) +(def ^:private ^:dynamic *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)]} diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index 5a5928775a..212c5864a7 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -51,6 +51,28 @@ [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) + refs (:block/_refs from-e) + path-refs (:block/_path-refs from-e) + refs-txs (mapcat (fn [ref refs] + (let [id (:db/id ref)] + [[:db/retract id :block/refs from-id] + [:db/add id :block/refs to-id]])) refs) + path-refs-txs (mapcat (fn [ref refs] + (let [id (:db/id ref)] + [[:db/retract id :block/path-refs from-id] + [:db/add id :block/path-refs to-id]])) path-refs)] + (concat txs refs-txs path-refs-txs)) + txs))) + #?(:cljs (defn transact! [txs opts before-editor-cursor] @@ -58,8 +80,10 @@ 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 (update-block-refs txs opts)] (when (and (seq txs) (not (:skip-transact? opts)) (not (contains? (:file/unlinked-dirs @state/state) diff --git a/src/main/frontend/modules/outliner/transaction.cljc b/src/main/frontend/modules/outliner/transaction.cljc index 5f0ad51f7b..e3b39715eb 100644 --- a/src/main/frontend/modules/outliner/transaction.cljc +++ b/src/main/frontend/modules/outliner/transaction.cljc @@ -25,22 +25,27 @@ [opts & body] (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)] + (when transaction-opts# (conj! transaction-opts# opts#)) (if transact-data# (do ~@body) - (binding [frontend.modules.outliner.core/*transaction-data* (transient [])] + (binding [frontend.modules.outliner.core/*transaction-data* (transient []) + frontend.modules.outliner.core/*transaction-opts* (transient [])] ~@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 + (when-not (:nested-transaction? opts##) ; transact only for the whole transaction (let [result# (frontend.modules.outliner.datascript/transact! all-tx# opts## before-editor-cursor#)] {:tx-report result# :tx-data all-tx# From 95675269bc024184440e2ae712bae53e9dfbfe53 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 15:16:24 +0800 Subject: [PATCH 07/36] fix: transaction --- src/main/frontend/modules/outliner/datascript.cljc | 3 ++- src/main/frontend/modules/outliner/transaction.cljc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index 212c5864a7..08bd5fc9a1 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -83,7 +83,8 @@ :block/title :block/body :block/level :block/container :db/other-tx :block/additional-properties) m)) txs) - txs (update-block-refs txs opts)] + txs (-> (update-block-refs txs opts) + (distinct))] (when (and (seq txs) (not (:skip-transact? opts)) (not (contains? (:file/unlinked-dirs @state/state) diff --git a/src/main/frontend/modules/outliner/transaction.cljc b/src/main/frontend/modules/outliner/transaction.cljc index e3b39715eb..b2f7e3d393 100644 --- a/src/main/frontend/modules/outliner/transaction.cljc +++ b/src/main/frontend/modules/outliner/transaction.cljc @@ -45,7 +45,7 @@ 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 + (when-not (:nested-transaction? opts#) ; transact only for the whole transaction (let [result# (frontend.modules.outliner.datascript/transact! all-tx# opts## before-editor-cursor#)] {:tx-report result# :tx-data all-tx# From 9d6bda6b2ce4097b8676d08aa111798db2c78432 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 15:31:44 +0800 Subject: [PATCH 08/36] remove unnecessary save-current-block --- src/main/frontend/handler/editor.cljs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index f3afb0635d..16b8424559 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2448,7 +2448,6 @@ (profile "Insert block" (outliner-tx/transact! {:outliner-op :insert-blocks} - (save-current-block!) (insert-new-block! state))))))))) (defn- inside-of-single-block From f48235e9f58523642a67a09e749423a2fc0b44c6 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 17:45:13 +0800 Subject: [PATCH 09/36] fix: handle the case when both blocks are referenced --- src/main/frontend/handler/editor.cljs | 26 +++++------- .../frontend/handler/editor/property.cljs | 7 ++-- .../frontend/modules/outliner/datascript.cljc | 42 +++++++++++-------- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 16b8424559..4cfc6244e7 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -361,8 +361,8 @@ (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})))] + (assoc :uuid-changed {:kept (:block/uuid block) + :deleted original-uuid})))] (outliner-tx/transact! opts' (outliner-core/save-block! block')) @@ -390,17 +390,8 @@ block-id (when (map? properties) (get properties :id)) content (-> (property/remove-built-in-properties format content) (drawer/remove-logbook))] - (cond - (another-block-with-same-id-exists? uuid block-id) - (notification/show! - [:p.content - (util/format "Block with the id %s already exists!" block-id)] - :error) - - force? + (if force? (save-block-inner! block value opts) - - :else (let [content-changed? (not= (string/trim content) (string/trim value))] (when (and content-changed? page) (save-block-inner! block value opts))))))) @@ -778,10 +769,13 @@ (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 [] + (prn {:pos pos}) + (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 diff --git a/src/main/frontend/handler/editor/property.cljs b/src/main/frontend/handler/editor/property.cljs index dd5532f084..7afd6de4b9 100644 --- a/src/main/frontend/handler/editor/property.cljs +++ b/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]]))) \ No newline at end of file + (batch-set-block-property! [[block-id key value]]))) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index 08bd5fc9a1..084a98fd3f 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -10,7 +10,8 @@ [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]))) #?(:cljs (defn new-outliner-txs-state [] (atom []))) @@ -55,22 +56,27 @@ (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) - refs (:block/_refs from-e) - path-refs (:block/_path-refs from-e) - refs-txs (mapcat (fn [ref refs] - (let [id (:db/id ref)] - [[:db/retract id :block/refs from-id] - [:db/add id :block/refs to-id]])) refs) - path-refs-txs (mapcat (fn [ref refs] + (let [{:keys [kept deleted]} changed + kept-e (db/entity [:block/uuid kept]) + deleted-e (db/entity [:block/uuid deleted]) + kept-id (:db/id kept-e) + deleted-id (:db/id deleted-e) + kept-refs (:block/_refs kept-e) + kept-path-refs (:block/_path-refs kept-e) + deleted-refs (:block/_refs deleted-e) + kept-refs-txs (mapcat (fn [ref refs] (let [id (:db/id ref)] - [[:db/retract id :block/path-refs from-id] - [:db/add id :block/path-refs to-id]])) path-refs)] - (concat txs refs-txs path-refs-txs)) + [[:db/retract id :block/refs kept-id] + [:db/add id :block/refs deleted-id]])) kept-refs) + kept-path-refs-txs (mapcat (fn [ref refs] + (let [id (:db/id ref)] + [[:db/retract id :block/path-refs kept-id] + [:db/add id :block/path-refs deleted-id]])) kept-path-refs) + deleted-refs-txs (mapcat (fn [ref refs] + (let [id (:db/id ref)] + (let [new-content (string/replace (:block/content ref) (str deleted) (str kept))] + [[:db/add id :block/content new-content]]))) deleted-refs)] + (concat txs kept-refs-txs kept-path-refs-txs deleted-refs-txs)) txs))) #?(:cljs @@ -90,8 +96,8 @@ (not (contains? (:file/unlinked-dirs @state/state) (config/get-repo-dir (state/get-current-repo))))) - ;; (prn "[DEBUG] Outliner transact:") - ;; (frontend.util/pprint txs) + (prn "[DEBUG] Outliner transact:") + (frontend.util/pprint txs) (try (let [repo (get opts :repo (state/get-current-repo)) From 2313a6a9122ed6468abd289580ab9cb5c9392e77 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 18:44:54 +0800 Subject: [PATCH 10/36] fix: cursor not jump back when undo a DELETE at the end action It also remove built-in properties such as id from the editor content --- src/main/frontend/components/block.cljs | 3 ++- src/main/frontend/handler/editor.cljs | 5 ++--- src/main/frontend/handler/history.cljs | 2 +- src/main/frontend/modules/editor/undo_redo.cljs | 10 +++++++--- src/main/frontend/state.cljs | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index c48eb97664..b207a69d05 100644 --- a/src/main/frontend/components/block.cljs +++ b/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)) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 4cfc6244e7..d699543a6a 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2634,9 +2634,8 @@ (outliner-tx/transact! transact-opts (delete-block-aux! next-block false) (save-block! repo edit-block' new-content)) - - (state/set-edit-content! input-id new-content) - (cursor/move-cursor-to input current-pos))))) + (let [block (if next-block-has-refs? next-block edit-block)] + (edit-block! block current-pos (:block/uuid block))))))) (defn keydown-delete-handler [_e] diff --git a/src/main/frontend/handler/history.cljs b/src/main/frontend/handler/history.cljs index a9944c95d8..8988af5f6b 100644 --- a/src/main/frontend/handler/history.cljs +++ b/src/main/frontend/handler/history.cljs @@ -46,7 +46,7 @@ (let [{:keys [editor-cursor app-state]} (undo-redo/undo)] (restore-cursor! editor-cursor) (restore-app-state! app-state)) - (state/set-editor-op! nil)) + (js/setTimeout #(state/set-editor-op! nil) 100)) (defn redo! [e] diff --git a/src/main/frontend/modules/editor/undo_redo.cljs b/src/main/frontend/modules/editor/undo_redo.cljs index d0c4512e24..4dd3899f8c 100644 --- a/src/main/frontend/modules/editor/undo_redo.cljs +++ b/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)))))) + (let [content (:block/content (db/entity (:db/id block))) + 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] diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index ef05967334..f28d597700 100644 --- a/src/main/frontend/state.cljs +++ b/src/main/frontend/state.cljs @@ -261,7 +261,7 @@ ;; :file-sync/last-synced-at {}} :file-sync/graph-state {:current-graph-uuid nil} ;; graph-uuid -> ... - + :user/info {:UserGroups (storage/get :user-groups)} :encryption/graph-parsing? false From 35f7e2ead2162b855c2ecd95c66922b9011044b7 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 19:02:12 +0800 Subject: [PATCH 11/36] comment on setTimeout in undo --- src/main/frontend/handler/history.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/frontend/handler/history.cljs b/src/main/frontend/handler/history.cljs index 8988af5f6b..c20117856a 100644 --- a/src/main/frontend/handler/history.cljs +++ b/src/main/frontend/handler/history.cljs @@ -46,6 +46,7 @@ (let [{:keys [editor-cursor app-state]} (undo-redo/undo)] (restore-cursor! editor-cursor) (restore-app-state! app-state)) + ;; ugly timeout: avoid save block from frontend.handler.editor.lifecycle/will-unmount (js/setTimeout #(state/set-editor-op! nil) 100)) (defn redo! From a0b336c79011a694ad0c648dbd03ffbd263aec0c Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 20:19:23 +0800 Subject: [PATCH 12/36] fix: replace with source block's content when deleting refed blocks --- src/main/frontend/handler/editor.cljs | 4 +- .../frontend/modules/outliner/datascript.cljc | 45 +++++++++++++++---- .../modules/outliner/transaction.cljc | 10 +++-- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index d699543a6a..4cc0aba146 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -808,7 +808,7 @@ {: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)}))] @@ -2615,7 +2615,7 @@ :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}} next-block-has-refs? (some? (:block/_refs (db/entity (:db/id next-block)))) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index 084a98fd3f..a77a72de7a 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -11,7 +11,9 @@ [logseq.graph-parser.util :as gp-util] [lambdaisland.glogi :as log] [frontend.search :as search] - [clojure.string :as string]))) + [clojure.string :as string] + [frontend.util :as util] + [frontend.util.property :as property]))) #?(:cljs (defn new-outliner-txs-state [] (atom []))) @@ -64,21 +66,47 @@ kept-refs (:block/_refs kept-e) kept-path-refs (:block/_path-refs kept-e) deleted-refs (:block/_refs deleted-e) - kept-refs-txs (mapcat (fn [ref refs] + kept-refs-txs (mapcat (fn [ref] (let [id (:db/id ref)] [[:db/retract id :block/refs kept-id] [:db/add id :block/refs deleted-id]])) kept-refs) - kept-path-refs-txs (mapcat (fn [ref refs] + kept-path-refs-txs (mapcat (fn [ref] (let [id (:db/id ref)] [[:db/retract id :block/path-refs kept-id] [:db/add id :block/path-refs deleted-id]])) kept-path-refs) - deleted-refs-txs (mapcat (fn [ref refs] - (let [id (:db/id ref)] - (let [new-content (string/replace (:block/content ref) (str deleted) (str kept))] - [[:db/add id :block/content new-content]]))) deleted-refs)] + deleted-refs-txs (mapcat (fn [ref] + (let [id (:db/id ref) + new-content (string/replace (:block/content ref) (str deleted) (str kept))] + [[:db/add id :block/content new-content]])) deleted-refs)] (concat txs kept-refs-txs kept-path-refs-txs deleted-refs-txs)) txs))) +#?(:cljs + (defn replace-ref-with-content + [txs opts] + (if (and (= :delete-blocks (:outliner-op opts)) + (not (:uuid-changed opts))) + (let [retracted-blocks (->> (keep (fn [tx] + (when (and (vector? tx) + (= :db.fn/retractEntity (first tx))) + (second tx))) txs) + (map db/entity)) + retracted-tx (->> (for [block retracted-blocks] + (let [refs (:block/_refs block)] + (mapcat (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 "{{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block)))) + block-content) + (string/replace (util/format "((%s))" (str (:block/uuid block))) + block-content))] + [[:db/retract (:db/id ref) :block/refs (:db/id block)] + [:db/add id :block/content new-content]])) refs))) + (apply concat))] + (concat txs retracted-tx)) + txs))) + #?(:cljs (defn transact! [txs opts before-editor-cursor] @@ -90,6 +118,7 @@ :block/additional-properties) m)) txs) txs (-> (update-block-refs txs opts) + (replace-ref-with-content opts) (distinct))] (when (and (seq txs) (not (:skip-transact? opts)) @@ -97,7 +126,7 @@ (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)) diff --git a/src/main/frontend/modules/outliner/transaction.cljc b/src/main/frontend/modules/outliner/transaction.cljc index b2f7e3d393..7adf7bc5c8 100644 --- a/src/main/frontend/modules/outliner/transaction.cljc +++ b/src/main/frontend/modules/outliner/transaction.cljc @@ -23,18 +23,21 @@ (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)] - (when transaction-opts# (conj! transaction-opts# opts#)) (if transact-data# - (do ~@body) + (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#) @@ -44,6 +47,7 @@ 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#)] From 753d452b50411eba69a8ecc83bba636db4317201 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 21:30:57 +0800 Subject: [PATCH 13/36] fix: undo should bring refs back --- src/main/frontend/handler/editor.cljs | 20 +++++++-- .../frontend/modules/editor/undo_redo.cljs | 8 ++-- .../frontend/modules/outliner/datascript.cljc | 42 +++++++++++-------- src/main/frontend/state.cljs | 3 ++ 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 4cc0aba146..0b76dc7054 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -1968,6 +1968,15 @@ (let [ids (set (map :db/id blocks))] (some? (some #(ids (:db/id (:block/parent %))) blocks)))) +(defn- get-revert-cut-tx + [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 (and (= (set (map :block/uuid blocks)) recent-cut-block-ids) + (seq revert-tx)) + revert-tx))) + (defn paste-blocks "Given a vec of blocks, insert them into the target page. keep-uuid?: if true, keep the uuid provided in the block structure." @@ -1990,8 +1999,9 @@ 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?) + revert-cut-txs (get-revert-cut-tx blocks) + keep-uuid? (if (seq revert-cut-txs) true keep-uuid?) + 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,7 +2019,8 @@ false :else - true)] + true) +] (when has-unsaved-edits (outliner-tx/transact! @@ -2017,7 +2028,8 @@ (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] diff --git a/src/main/frontend/modules/editor/undo_redo.cljs b/src/main/frontend/modules/editor/undo_redo.cljs index 4dd3899f8c..ab133643f3 100644 --- a/src/main/frontend/modules/editor/undo_redo.cljs +++ b/src/main/frontend/modules/editor/undo_redo.cljs @@ -159,10 +159,10 @@ "Prevent block auto-save during undo/redo." [] (when-let [block (state/get-edit-block)] - (let [content (:block/content (db/entity (:db/id block))) - content' (-> (property/remove-built-in-properties (:block/format block) content) - (drawer/remove-logbook))] - (state/set-edit-content! (state/get-edit-input-id) content')))) + (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] diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index a77a72de7a..f979fb779e 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -86,25 +86,33 @@ [txs opts] (if (and (= :delete-blocks (:outliner-op opts)) (not (:uuid-changed opts))) - (let [retracted-blocks (->> (keep (fn [tx] - (when (and (vector? tx) - (= :db.fn/retractEntity (first tx))) - (second tx))) txs) - (map db/entity)) + (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)] - (mapcat (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 "{{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block)))) - block-content) - (string/replace (util/format "((%s))" (str (:block/uuid block))) - block-content))] - [[:db/retract (:db/id ref) :block/refs (:db/id block)] - [:db/add id :block/content new-content]])) refs))) - (apply concat))] - (concat txs retracted-tx)) + (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 "{{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block)))) + block-content) + (string/replace (util/format "((%s))" (str (:block/uuid block))) + block-content))] + {:tx [[:db/retract (:db/id ref) :block/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 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 diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index f28d597700..efb7f2d510 100644 --- a/src/main/frontend/state.cljs +++ b/src/main/frontend/state.cljs @@ -122,6 +122,9 @@ :editor/on-paste? false :editor/last-key-code nil + ;; delete refed blocks + :editor/last-replace-ref-content-tx nil + ;; for audio record :editor/record-status "NONE" From 0df201e7a899b6433365cdc42512d360f770dedf Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 21:46:15 +0800 Subject: [PATCH 14/36] fix: replace empty target when paste cut blocks --- src/main/frontend/handler/editor.cljs | 7 ++++--- src/main/frontend/modules/outliner/core.cljs | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 0b76dc7054..5fafc15c96 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2000,7 +2000,8 @@ paste-nested-blocks? (nested-blocks blocks) target-block-has-children? (db/has-children? (:block/uuid target-block)) revert-cut-txs (get-revert-cut-tx blocks) - keep-uuid? (if (seq revert-cut-txs) true keep-uuid?) + cut-paste? (seq revert-cut-txs) + keep-uuid? (if cut-paste? true keep-uuid?) replace-empty-target? (if (and paste-nested-blocks? empty-target? target-block-has-children?) false true) @@ -2019,8 +2020,7 @@ false :else - true) -] + true)] (when has-unsaved-edits (outliner-tx/transact! @@ -2036,6 +2036,7 @@ (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?})] diff --git a/src/main/frontend/modules/outliner/core.cljs b/src/main/frontend/modules/outliner/core.cljs index ab66d8c069..8066276f5c 100644 --- a/src/main/frontend/modules/outliner/core.cljs +++ b/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 From 03d6a8413893d9578fe1554150d4ae97ebfb11f1 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 21:53:18 +0800 Subject: [PATCH 15/36] fix: lint --- .carve/ignore | 1 + src/main/frontend/handler/editor.cljs | 14 ++------------ src/main/frontend/modules/outliner/core.cljs | 2 +- src/main/frontend/modules/outliner/datascript.cljc | 4 ++-- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/.carve/ignore b/.carve/ignore index 8cd677525c..acaa1900e9 100644 --- a/.carve/ignore +++ b/.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 diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 5fafc15c96..eddb198787 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -233,13 +233,6 @@ (doseq [block blocks] (gdom-classes/remove block "block-highlight")))) -;; id: block dom id, "ls-block-counter-uuid" -(defn- another-block-with-same-id-exists? - [current-id block-id] - (when-let [id (and (string? block-id) (parse-uuid block-id))] - (and (not= current-id id) - (db/entity [:block/uuid id])))) - (defn- remove-non-existed-refs! [refs] (remove (fn [x] (or @@ -383,11 +376,10 @@ ([block value {:keys [force?] :as opts}] - (let [{:block/keys [uuid page format repo content properties]} block + (let [{:block/keys [page format repo content]} block repo (or repo (state/get-current-repo)) format (or format (state/get-preferred-format)) page (db/entity repo (:db/id page)) - block-id (when (map? properties) (get properties :id)) content (-> (property/remove-built-in-properties format content) (drawer/remove-logbook))] (if force? @@ -770,7 +762,6 @@ 0) 0) f (fn [] - (prn {:pos pos}) (edit-block! (db/pull (:db/id block)) pos id @@ -2605,8 +2596,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)) diff --git a/src/main/frontend/modules/outliner/core.cljs b/src/main/frontend/modules/outliner/core.cljs index 8066276f5c..91d1cd2069 100644 --- a/src/main/frontend/modules/outliner/core.cljs +++ b/src/main/frontend/modules/outliner/core.cljs @@ -863,7 +863,7 @@ see also `frontend.modules.outliner.transaction/transact!`" nil) -(def ^:private ^:dynamic *transaction-opts* +(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) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index f979fb779e..0858b08892 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -133,8 +133,8 @@ (not (contains? (:file/unlinked-dirs @state/state) (config/get-repo-dir (state/get-current-repo))))) - (prn "[DEBUG] Outliner transact:") - (frontend.util/pprint {:txs txs :opts opts}) + ;; (prn "[DEBUG] Outliner transact:") + ;; (frontend.util/pprint {:txs txs :opts opts}) (try (let [repo (get opts :repo (state/get-current-repo)) From 27856812952271e72fe0d2e89d7fe781d0b90591 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 22:00:10 +0800 Subject: [PATCH 16/36] chore: uncomment code --- src/main/frontend/handler/editor.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index eddb198787..5a8c749ba2 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -1963,7 +1963,7 @@ [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) + (state/set-state! [:editor/last-replace-ref-content-tx (state/get-current-repo)] nil) (when (and (= (set (map :block/uuid blocks)) recent-cut-block-ids) (seq revert-tx)) revert-tx))) From dc14a6aee0fec20e8bc68b4db7c8b80d1b73db97 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 15 May 2023 23:53:24 +0800 Subject: [PATCH 17/36] add e2e tests --- e2e-tests/blockref.spec.ts | 74 ++++++++++++++++++++++++++++++++++++++ e2e-tests/utils.ts | 26 +++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 e2e-tests/blockref.spec.ts diff --git a/e2e-tests/blockref.spec.ts b/e2e-tests/blockref.spec.ts new file mode 100644 index 0000000000..b4416ee903 --- /dev/null +++ b/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); +}) diff --git a/e2e-tests/utils.ts b/e2e-tests/utils.ts index 503ea7d638..e61023a8aa 100644 --- a/e2e-tests/utils.ts +++ b/e2e-tests/utils.ts @@ -31,6 +31,26 @@ export async function lastBlock(page: Page): Promise { 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 { + 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 { + 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 { 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) } /** From d67d14f134008e84fd8b52848c3af239207c4855 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 18 May 2023 23:46:34 +0800 Subject: [PATCH 18/36] Changes suggested from Zhiyuan --- src/main/frontend/handler/editor.cljs | 4 +- .../frontend/modules/outliner/datascript.cljc | 60 +++++++++++-------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 5a8c749ba2..519bc80e7b 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -354,8 +354,8 @@ (assoc :block/uuid (:block/uuid block))) opts' (merge opts (cond-> {:outliner-op :save-block} uuid-changed? - (assoc :uuid-changed {:kept (:block/uuid block) - :deleted original-uuid})))] + (assoc :uuid-changed {:from (:block/uuid block) + :to original-uuid})))] (outliner-tx/transact! opts' (outliner-core/save-block! block')) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index 0858b08892..e87cd6fbe8 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -13,7 +13,8 @@ [frontend.search :as search] [clojure.string :as string] [frontend.util :as util] - [frontend.util.property :as property]))) + [frontend.util.property :as property] + [logseq.graph-parser.util.block-ref :as block-ref]))) #?(:cljs (defn new-outliner-txs-state [] (atom []))) @@ -58,34 +59,36 @@ (defn update-block-refs [txs opts] (if-let [changed (:uuid-changed opts)] - (let [{:keys [kept deleted]} changed - kept-e (db/entity [:block/uuid kept]) - deleted-e (db/entity [:block/uuid deleted]) - kept-id (:db/id kept-e) - deleted-id (:db/id deleted-e) - kept-refs (:block/_refs kept-e) - kept-path-refs (:block/_path-refs kept-e) - deleted-refs (:block/_refs deleted-e) - kept-refs-txs (mapcat (fn [ref] + (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 kept-id] - [:db/add id :block/refs deleted-id]])) kept-refs) - kept-path-refs-txs (mapcat (fn [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 kept-id] - [:db/add id :block/path-refs deleted-id]])) kept-path-refs) - deleted-refs-txs (mapcat (fn [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) (str deleted) (str kept))] - [[:db/add id :block/content new-content]])) deleted-refs)] - (concat txs kept-refs-txs kept-path-refs-txs deleted-refs-txs)) + 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)) - (not (:uuid-changed opts))) + (empty? (:uuid-changed opts))) (let [retracted-block-ids (->> (keep (fn [tx] (when (and (vector? tx) (= :db.fn/retractEntity (first tx))) @@ -97,13 +100,15 @@ (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 "{{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block)))) + (string/replace (re-pattern (util/format "(?i){{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block)))) block-content) (string/replace (util/format "((%s))" (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) @@ -125,9 +130,16 @@ :block/title :block/body :block/level :block/container :db/other-tx :block/additional-properties) m)) txs) - txs (-> (update-block-refs txs opts) - (replace-ref-with-content opts) - (distinct))] + 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) From 3b92fe638a33cd96e8225cd9115de653e6a9efb8 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 13:15:55 +0800 Subject: [PATCH 19/36] Update src/main/frontend/state.cljs Co-authored-by: Gabriel Horner <97210743+logseq-cldwalker@users.noreply.github.com> --- src/main/frontend/state.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index efb7f2d510..b5d6dc44ee 100644 --- a/src/main/frontend/state.cljs +++ b/src/main/frontend/state.cljs @@ -122,7 +122,7 @@ :editor/on-paste? false :editor/last-key-code nil - ;; delete refed blocks + ;; Stores deleted refed blocks, indexed by repo :editor/last-replace-ref-content-tx nil ;; for audio record From 3cc0e0ad6b059e33749f4735f7760dcc1752816c Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 13:16:13 +0800 Subject: [PATCH 20/36] Update src/main/frontend/modules/outliner/datascript.cljc Co-authored-by: Gabriel Horner <97210743+logseq-cldwalker@users.noreply.github.com> --- src/main/frontend/modules/outliner/datascript.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index e87cd6fbe8..1b90b5f602 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -102,7 +102,7 @@ new-content (-> (:block/content ref) (string/replace (re-pattern (util/format "(?i){{embed \\(\\(%s\\)\\)\\s?}}" (str (:block/uuid block)))) block-content) - (string/replace (util/format "((%s))" (str (:block/uuid block))) + (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)] From a2d1f67c5d6ff43fbfb1784c095a862a6b926b96 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 15:42:01 +0800 Subject: [PATCH 21/36] fix: parens --- src/main/frontend/modules/outliner/datascript.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/modules/outliner/datascript.cljc b/src/main/frontend/modules/outliner/datascript.cljc index 1b90b5f602..204618fefe 100644 --- a/src/main/frontend/modules/outliner/datascript.cljc +++ b/src/main/frontend/modules/outliner/datascript.cljc @@ -102,7 +102,7 @@ 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)))) + (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)] From 1be20c8f11264b4ad61ce1dbc4e5e021ee8fef13 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 16:00:17 +0800 Subject: [PATCH 22/36] Move cut-paste? logic to paste handler --- src/main/frontend/handler/editor.cljs | 16 +++------------- src/main/frontend/handler/paste.cljs | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 519bc80e7b..ca5499b180 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -1959,15 +1959,6 @@ (let [ids (set (map :db/id blocks))] (some? (some #(ids (:db/id (:block/parent %))) blocks)))) -(defn- get-revert-cut-tx - [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 (and (= (set (map :block/uuid blocks)) recent-cut-block-ids) - (seq revert-tx)) - revert-tx))) - (defn paste-blocks "Given a vec of blocks, insert them into the target page. keep-uuid?: if true, keep the uuid provided in the block structure." @@ -1975,7 +1966,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)]) @@ -1990,9 +1983,6 @@ 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)) - revert-cut-txs (get-revert-cut-tx blocks) - cut-paste? (seq revert-cut-txs) - keep-uuid? (if cut-paste? true keep-uuid?) replace-empty-target? (if (and paste-nested-blocks? empty-target? target-block-has-children?) false true) diff --git a/src/main/frontend/handler/paste.cljs b/src/main/frontend/handler/paste.cljs index 90cdef121c..da8e612821 100644 --- a/src/main/frontend/handler/paste.cljs +++ b/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 From 9cfc2f2d9e258b3ece470f34bb4fe9790f7cc241 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 16:19:08 +0800 Subject: [PATCH 23/36] fix: relax same block id check only when deleting a source block --- src/main/frontend/handler/editor.cljs | 41 +++++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index ca5499b180..2b6e0bc3f0 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -233,6 +233,13 @@ (doseq [block blocks] (gdom-classes/remove block "block-highlight")))) +;; id: block dom id, "ls-block-counter-uuid" +(defn- another-block-with-same-id-exists? + [current-id block-id] + (when-let [id (and (string? block-id) (parse-uuid block-id))] + (and (not= current-id id) + (db/entity [:block/uuid id])))) + (defn- remove-non-existed-refs! [refs] (remove (fn [x] (or @@ -376,14 +383,25 @@ ([block value {:keys [force?] :as opts}] - (let [{:block/keys [page format repo content]} block + (let [{:block/keys [uuid page format repo content properties]} block repo (or repo (state/get-current-repo)) format (or format (state/get-preferred-format)) page (db/entity repo (:db/id page)) + block-id (when (map? properties) (get properties :id)) content (-> (property/remove-built-in-properties format content) (drawer/remove-logbook))] - (if force? + (cond + (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)] + :error) + + force? (save-block-inner! block value opts) + + :else (let [content-changed? (not= (string/trim content) (string/trim value))] (when (and content-changed? page) (save-block-inner! block value opts))))))) @@ -811,7 +829,7 @@ :block/additional-properties (:block/properties block)) prev-block)] (delete-block-aux! block delete-children?) - (save-block! repo prev-block' new-content)) + (save-block! repo prev-block' new-content {:editor/op :delete})) (delete-block-aux! block delete-children?))) (move-fn))))))))) (state/set-editor-op! nil))) @@ -1231,20 +1249,19 @@ (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] @@ -2626,7 +2643,7 @@ edit-block)] (outliner-tx/transact! transact-opts (delete-block-aux! next-block false) - (save-block! repo edit-block' new-content)) + (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))))))) From 12f387169442d8fedf9151253b48bfac21a71800 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 16:51:31 +0800 Subject: [PATCH 24/36] fix: remove ugly timeout --- src/main/frontend/handler/editor/lifecycle.cljs | 6 ++++-- src/main/frontend/handler/history.cljs | 3 +-- src/main/frontend/state.cljs | 13 ++++++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/frontend/handler/editor/lifecycle.cljs b/src/main/frontend/handler/editor/lifecycle.cljs index ef57f3fdde..1014d062fa 100644 --- a/src/main/frontend/handler/editor/lifecycle.cljs +++ b/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) diff --git a/src/main/frontend/handler/history.cljs b/src/main/frontend/handler/history.cljs index c20117856a..a9944c95d8 100644 --- a/src/main/frontend/handler/history.cljs +++ b/src/main/frontend/handler/history.cljs @@ -46,8 +46,7 @@ (let [{:keys [editor-cursor app-state]} (undo-redo/undo)] (restore-cursor! editor-cursor) (restore-app-state! app-state)) - ;; ugly timeout: avoid save block from frontend.handler.editor.lifecycle/will-unmount - (js/setTimeout #(state/set-editor-op! nil) 100)) + (state/set-editor-op! nil)) (defn redo! [e] diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index b5d6dc44ee..d57bbcbc3f 100644 --- a/src/main/frontend/state.cljs +++ b/src/main/frontend/state.cljs @@ -104,6 +104,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 @@ -1694,13 +1696,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 [] From 812f8ac8ba2c737286201587417342303f854f2a Mon Sep 17 00:00:00 2001 From: Andelf Date: Mon, 15 May 2023 17:42:41 +0800 Subject: [PATCH 25/36] enhance(editor): restore scroll position new adding newline in a block --- src/main/frontend/handler/editor.cljs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 2b6e0bc3f0..92b6963783 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2224,10 +2224,16 @@ 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 + (let [scroll-pos (.-scrollTop (gdom/getElement "main-content-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 (gdom/getElement "main-content-container")) scroll-pos)))))) (defn- keydown-new-line + "Insert newline to current cursor position" [] (insert "\n")) From f0515f37f1fc6274a3172a4fe153111710e8b88b Mon Sep 17 00:00:00 2001 From: Andelf Date: Mon, 15 May 2023 17:53:04 +0800 Subject: [PATCH 26/36] enhance(editor): restore scroll position new paste in a long block --- src/main/frontend/commands.cljs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index 0559ed94d5..370375f9ed 100644 --- a/src/main/frontend/commands.cljs +++ b/src/main/frontend/commands.cljs @@ -403,17 +403,23 @@ 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-pos (.-scrollTop (gdom/getElement "main-content-container"))] + (state/set-block-content-and-last-pos! id new-value new-pos) + (cursor/move-cursor-to input new-pos) + (set! (.-scrollTop (gdom/getElement "main-content-container")) scroll-pos) + (when check-fn + (check-fn new-value (dec (count prefix)) new-pos))))) (defn simple-replace! [id value selected From f6211c77b7524004360b374d69f800ea1abfd52a Mon Sep 17 00:00:00 2001 From: Andelf Date: Tue, 16 May 2023 12:53:35 +0800 Subject: [PATCH 27/36] refactor(editor): add nearest-scrollable-container util fn --- src/main/frontend/commands.cljs | 5 +++-- src/main/frontend/handler/editor.cljs | 5 +++-- src/main/frontend/util.cljc | 7 +++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index 370375f9ed..9eeca2676f 100644 --- a/src/main/frontend/commands.cljs +++ b/src/main/frontend/commands.cljs @@ -414,10 +414,11 @@ (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-pos (.-scrollTop (gdom/getElement "main-content-container"))] + (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 (gdom/getElement "main-content-container")) scroll-pos) + (set! (.-scrollTop scroll-container) scroll-pos) (when check-fn (check-fn new-value (dec (count prefix)) new-pos))))) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 92b6963783..9f2ad2784b 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2226,11 +2226,12 @@ (state/set-edit-content! (state/get-edit-input-id) (str s1 insertion)) ;; HACK: save scroll-pos of current pos, then add trailing content - (let [scroll-pos (.-scrollTop (gdom/getElement "main-content-container"))] + (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 (gdom/getElement "main-content-container")) scroll-pos)))))) + (set! (.-scrollTop scroll-container) scroll-pos)))))) (defn- keydown-new-line "Insert newline to current cursor position" diff --git a/src/main/frontend/util.cljc b/src/main/frontend/util.cljc index 5751635dc8..eb49d51a95 100644 --- a/src/main/frontend/util.cljc +++ b/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 From 739f228b260a21915560672f2a17b1489caf5021 Mon Sep 17 00:00:00 2001 From: Andelf Date: Fri, 19 May 2023 15:19:03 +0800 Subject: [PATCH 28/36] fix(editor): auto complete parenthesis at line start --- src/main/frontend/handler/editor.cljs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 9f2ad2784b..c91b398e60 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -1555,7 +1555,7 @@ "$" "$" ":" ":")) -(defn autopair +(defn- autopair [input-id prefix _format _option] (let [value (get autopair-map prefix) selected (util/get-selected-text) @@ -1592,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] @@ -2226,6 +2226,7 @@ (state/set-edit-content! (state/get-edit-input-id) (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) @@ -2866,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) From c8312bc6df5373879f0ad0e088f6dd5ab4d16a0d Mon Sep 17 00:00:00 2001 From: Candide U <55474996+candideu@users.noreply.github.com> Date: Mon, 1 May 2023 23:51:58 -0400 Subject: [PATCH 29/36] Add custom.js script to html --- deps/publishing/src/logseq/publishing/html.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/deps/publishing/src/logseq/publishing/html.cljs b/deps/publishing/src/logseq/publishing/html.cljs index 344f2b0204..54126f086e 100644 --- a/deps/publishing/src/logseq/publishing/html.cljs +++ b/deps/publishing/src/logseq/publishing/html.cljs @@ -121,6 +121,7 @@ necessary db filtering" } }(window.location))"] ;; TODO: should make this configurable + [:script {:src "static/js/custom.js"}] [:script {:src "static/js/main.js"}] [:script {:src "static/js/interact.min.js"}] [:script {:src "static/js/highlight.min.js"}] From a2cf976161ef180027a81b591847b78c9bca538d Mon Sep 17 00:00:00 2001 From: Candide U <55474996+candideu@users.noreply.github.com> Date: Tue, 2 May 2023 00:13:27 -0400 Subject: [PATCH 30/36] Export custom.js --- deps/publishing/src/logseq/publishing/export.cljs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deps/publishing/src/logseq/publishing/export.cljs b/deps/publishing/src/logseq/publishing/export.cljs index e450a65e4c..2e857e5818 100644 --- a/deps/publishing/src/logseq/publishing/export.cljs +++ b/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 🎉")})) From fd8bb11c37fa438731a7c3c8aa811d6c1ddf89f4 Mon Sep 17 00:00:00 2001 From: Candide U <55474996+candideu@users.noreply.github.com> Date: Sun, 21 May 2023 22:26:36 -0400 Subject: [PATCH 31/36] Add test for custom.js to export_test.cljs --- .../publishing/test/logseq/publishing/export_test.cljs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/deps/publishing/test/logseq/publishing/export_test.cljs b/deps/publishing/test/logseq/publishing/export_test.cljs index 4ea36143b2..a7aa3aa40f 100644 --- a/deps/publishing/test/logseq/publishing/export_test.cljs +++ b/deps/publishing/test/logseq/publishing/export_test.cljs @@ -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") From 3b08b9a7e5dc9402800769f202befc80a4b90ff6 Mon Sep 17 00:00:00 2001 From: Candide U <55474996+candideu@users.noreply.github.com> Date: Sun, 21 May 2023 22:34:01 -0400 Subject: [PATCH 32/36] Add test for custom.js to export_test.cljs Fixed missing thing --- deps/publishing/test/logseq/publishing/export_test.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/publishing/test/logseq/publishing/export_test.cljs b/deps/publishing/test/logseq/publishing/export_test.cljs index a7aa3aa40f..988c5ac551 100644 --- a/deps/publishing/test/logseq/publishing/export_test.cljs +++ b/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 (= "
WOOT
" From 450fb9dae54762aa9dc6c4bd506f3b409f793576 Mon Sep 17 00:00:00 2001 From: Gabriel Horner Date: Mon, 22 May 2023 10:25:39 -0400 Subject: [PATCH 33/36] custom.js should load last in publishing app --- deps/publishing/src/logseq/publishing/html.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/publishing/src/logseq/publishing/html.cljs b/deps/publishing/src/logseq/publishing/html.cljs index 54126f086e..16568d9c8d 100644 --- a/deps/publishing/src/logseq/publishing/html.cljs +++ b/deps/publishing/src/logseq/publishing/html.cljs @@ -121,13 +121,13 @@ necessary db filtering" } }(window.location))"] ;; TODO: should make this configurable - [:script {:src "static/js/custom.js"}] [:script {:src "static/js/main.js"}] [:script {:src "static/js/interact.min.js"}] [: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 From 41e0596c93f074201d9609069344b9c657cece34 Mon Sep 17 00:00:00 2001 From: Bad3r Date: Mon, 15 May 2023 11:13:31 -0400 Subject: [PATCH 34/36] Update config.edn --- templates/config.edn | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/config.edn b/templates/config.edn index 9da61e259e..7bd1d58064 100644 --- a/templates/config.edn +++ b/templates/config.edn @@ -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 @@ -189,7 +189,7 @@ :ui/show-command-doc? true ;; Display empty bullet points. - ;; Default value: false + ;; Default value: true :ui/show-empty-bullets? false ;; Pre-defined :view function to use with advanced queries. @@ -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. From 86344d9701f263832bb62f306318d685f1b650bd Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 22 May 2023 22:57:27 +0800 Subject: [PATCH 35/36] Update comment --- templates/config.edn | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/config.edn b/templates/config.edn index 7bd1d58064..49bb34f951 100644 --- a/templates/config.edn +++ b/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 @@ -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. @@ -189,7 +189,7 @@ :ui/show-command-doc? true ;; Display empty bullet points. - ;; Default value: true + ;; Default value: false :ui/show-empty-bullets? false ;; Pre-defined :view function to use with advanced queries. @@ -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. From 746b6292c1ff7024e2742723752bffd7691e3aa0 Mon Sep 17 00:00:00 2001 From: Andelf Date: Tue, 23 May 2023 11:32:25 +0800 Subject: [PATCH 36/36] fix(ios): wrong link when sharing asset link (#9462) Fix #9454 --- src/main/frontend/components/block.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index b207a69d05..2a01b9b8b9 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -392,7 +392,9 @@ (util/stop event) (when (mobile-util/native-platform?) ;; File URL must be legal, so filename muse be URI-encoded + ;; incoming href format: "/assets/whatever.ext" (let [[rel-dir basename] (util/get-dir-and-basename href) + rel-dir (string/replace rel-dir #"^/+" "") asset-url (path/path-join repo-dir rel-dir basename)] (.share Share (clj->js {:url asset-url :title "Open file with your favorite app"})))))]