mirror of
https://github.com/logseq/logseq.git
synced 2026-05-23 20:24:15 +00:00
Merge branch 'master' into feat/pdf-shape
This commit is contained in:
@@ -213,6 +213,7 @@
|
||||
(second (re-find #"(?:\.)(\w+)[^.]*$" path-or-file-name)))
|
||||
|
||||
(defn get-format
|
||||
"File path to format keyword, :org, :markdown, etc."
|
||||
[file]
|
||||
(when file
|
||||
(normalize-format (keyword (some-> (path->file-ext file) string/lower-case)))))
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
(fs/mkdirSync (path/join dir "journals"))
|
||||
(fs/mkdirSync (path/join dir "pages")))
|
||||
|
||||
(deftest ^:focus build-graph-files
|
||||
(deftest build-graph-files
|
||||
(create-logseq-graph "tmp/test-graph")
|
||||
;; Create files that are recognized
|
||||
(fs/writeFileSync "tmp/test-graph/pages/foo.md" "")
|
||||
|
||||
@@ -519,7 +519,7 @@
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 0.9.9;
|
||||
MARKETING_VERSION = 0.9.10;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -546,7 +546,7 @@
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 0.9.9;
|
||||
MARKETING_VERSION = 0.9.10;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
||||
@@ -571,7 +571,7 @@
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 0.9.9;
|
||||
MARKETING_VERSION = 0.9.10;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
|
||||
@@ -598,7 +598,7 @@
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 0.9.9;
|
||||
MARKETING_VERSION = 0.9.10;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -90,8 +90,8 @@
|
||||
"@capawesome/capacitor-background-task": "^2.0.0",
|
||||
"@excalidraw/excalidraw": "0.12.0",
|
||||
"@hugotomazi/capacitor-navigation-bar": "^2.0.0",
|
||||
"@logseq/capacitor-file-sync": "0.0.24",
|
||||
"@logseq/diff-merge": "^0.0.2",
|
||||
"@logseq/capacitor-file-sync": "0.0.30",
|
||||
"@logseq/diff-merge": "0.1.0",
|
||||
"@logseq/react-tweet-embed": "1.3.1-1",
|
||||
"@radix-ui/colors": "^0.1.8",
|
||||
"@sentry/react": "^6.18.2",
|
||||
@@ -117,7 +117,7 @@
|
||||
"highlight.js": "10.4.1",
|
||||
"ignore": "5.1.8",
|
||||
"jszip": "3.8.0",
|
||||
"mldoc": "^1.5.5",
|
||||
"mldoc": "1.5.7",
|
||||
"path": "0.12.7",
|
||||
"path-complete-extname": "1.0.0",
|
||||
"pixi-graph-fork": "0.2.0",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"@sentry/electron": "2.5.1",
|
||||
"posthog-js": "1.10.2",
|
||||
"@logseq/rsapi": "0.0.70",
|
||||
"@logseq/rsapi": "0.0.73",
|
||||
"electron-deeplink": "1.0.10",
|
||||
"abort-controller": "3.0.0",
|
||||
"fastify": "latest",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
frontend.modules.instrumentation.sentry/SENTRY-DSN #shadow/env "LOGSEQ_SENTRY_DSN"
|
||||
frontend.modules.instrumentation.posthog/POSTHOG-TOKEN #shadow/env "LOGSEQ_POSTHOG_TOKEN"
|
||||
frontend.config/ENABLE-PLUGINS #shadow/env ["ENABLE_PLUGINS" :as :bool :default true]
|
||||
;; Set to switch file sync server to dev, set this to false in `yarn watch`
|
||||
frontend.config/ENABLE-FILE-SYNC-PRODUCTION #shadow/env ["ENABLE_FILE_SYNC_PRODUCTION" :as :bool :default true]
|
||||
frontend.config/TEST #shadow/env ["LOGSEQ_CI" :as :bool :default false]
|
||||
frontend.config/REVISION #shadow/env ["LOGSEQ_REVISION" :default "dev"]} ;; set by git-revision-hook
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
(defn delete-local-files [graph-uuid base-path file-paths]
|
||||
(rsapi/deleteLocalFiles graph-uuid base-path (clj->js file-paths)))
|
||||
|
||||
(defn fetch-remote-files [graph-uuid base-path file-paths token]
|
||||
(rsapi/fetchRemoteFiles graph-uuid base-path (clj->js file-paths) token))
|
||||
|
||||
(defn update-local-files [graph-uuid base-path file-paths token]
|
||||
(rsapi/updateLocalFiles graph-uuid base-path (clj->js file-paths) token))
|
||||
|
||||
|
||||
@@ -96,6 +96,10 @@
|
||||
(catch :default _e
|
||||
false)))
|
||||
|
||||
(defmethod handle :copyFile [_window [_ _repo from-path to-path]]
|
||||
(logger/info ::copy-file from-path to-path)
|
||||
(fs-extra/copy from-path to-path))
|
||||
|
||||
(defmethod handle :writeFile [window [_ repo path content]]
|
||||
(let [^js Buf (.-Buffer buffer)
|
||||
^js content (if (instance? js/ArrayBuffer content)
|
||||
@@ -636,6 +640,9 @@
|
||||
(defmethod handle :delete-local-files [_ args]
|
||||
(apply rsapi/delete-local-files (rest args)))
|
||||
|
||||
(defmethod handle :fetch-remote-files [_ args]
|
||||
(apply rsapi/fetch-remote-files (rest args)))
|
||||
|
||||
(defmethod handle :update-local-files [_ args]
|
||||
(apply rsapi/update-local-files (rest args)))
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
(if favorited?
|
||||
(page-handler/unfavorite-page! page-original-name)
|
||||
(page-handler/favorite-page! page-original-name)))}})
|
||||
|
||||
|
||||
(when (or (util/electron?) file-sync-graph-uuid)
|
||||
{:title (t :page/version-history)
|
||||
:options {:on-click
|
||||
@@ -117,12 +117,12 @@
|
||||
|
||||
(when (and (not (mobile-util/native-platform?))
|
||||
(state/get-current-page))
|
||||
{:title (t :page/presentation-mode)
|
||||
{:title (t :page/slide-view)
|
||||
:options {:on-click (fn []
|
||||
(state/sidebar-add-block!
|
||||
repo
|
||||
(:db/id page)
|
||||
:page-presentation))}})
|
||||
:page-slide-view))}})
|
||||
|
||||
;; TODO: In the future, we'd like to extract file-related actions
|
||||
;; (such as open-in-finder & open-with-default-app) into a sub-menu of
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[frontend.util :as util]
|
||||
[frontend.config :as config]
|
||||
[frontend.modules.editor.undo-redo :as undo-redo]
|
||||
[goog.object :as gobj]
|
||||
@@ -159,7 +159,7 @@
|
||||
[:div.ml-2
|
||||
(page-cp repo page-name)]])
|
||||
|
||||
:page-presentation
|
||||
:page-slide-view
|
||||
(let [page-name (:block/name (db/entity db-id))]
|
||||
[[:a.page-title {:href (rfe/href :page {:name page-name})}
|
||||
(db-model/get-page-original-name page-name)]
|
||||
|
||||
@@ -137,6 +137,22 @@
|
||||
new-fpath (path/path-join repo-dir new-path)]
|
||||
(protocol/rename! (get-fs old-fpath) repo old-fpath new-fpath)))))
|
||||
|
||||
(defn stat
|
||||
([fpath]
|
||||
(protocol/stat (get-fs fpath) fpath))
|
||||
([dir path]
|
||||
(let [fpath (path/path-join dir path)]
|
||||
(protocol/stat (get-fs dir) fpath))))
|
||||
|
||||
(defn mkdir-if-not-exists
|
||||
[dir]
|
||||
(when dir
|
||||
(util/p-handle
|
||||
(stat dir)
|
||||
(fn [_stat])
|
||||
(fn [_error]
|
||||
(mkdir-recur! dir)))))
|
||||
|
||||
(defn copy!
|
||||
"Only used by Logseq Sync"
|
||||
[repo old-path new-path]
|
||||
@@ -149,15 +165,13 @@
|
||||
(map #(if (or (util/electron?) (mobile-util/native-platform?))
|
||||
%
|
||||
(str (config/get-repo-dir repo) "/" %))
|
||||
[old-path new-path])]
|
||||
(protocol/copy! (get-fs old-path) repo old-path new-path))))
|
||||
[old-path new-path])
|
||||
new-dir (path/dirname new-path)]
|
||||
(p/do!
|
||||
(mkdir-if-not-exists new-dir)
|
||||
(protocol/copy! (get-fs old-path) repo old-path new-path)))))
|
||||
|
||||
|
||||
(defn stat
|
||||
([fpath]
|
||||
(protocol/stat (get-fs fpath) fpath))
|
||||
([dir path]
|
||||
(let [fpath (path/path-join dir path)]
|
||||
(protocol/stat (get-fs dir) fpath))))
|
||||
|
||||
(defn open-dir
|
||||
[dir]
|
||||
@@ -192,15 +206,6 @@
|
||||
[dir]
|
||||
(protocol/unwatch-dir! (get-fs dir) dir))
|
||||
|
||||
(defn mkdir-if-not-exists
|
||||
[dir]
|
||||
(when dir
|
||||
(util/p-handle
|
||||
(stat dir)
|
||||
(fn [_stat])
|
||||
(fn [_error]
|
||||
(mkdir! dir)))))
|
||||
|
||||
;; FIXME: counterintuitive return value
|
||||
(defn create-if-not-exists
|
||||
"Create a file if it doesn't exist. return false on written, true on already exists"
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
(ns frontend.fs.diff-merge
|
||||
"Implementation of text (file) based content diff & merge for conflict resolution"
|
||||
(:require ["@logseq/diff-merge" :refer [Differ attach_uuids]]
|
||||
(:require ["@logseq/diff-merge" :refer [attach_uuids Differ Merger]]
|
||||
[cljs-bean.core :as bean]
|
||||
[frontend.db.model :as db-model]
|
||||
[frontend.db.utils :as db-utils]
|
||||
[logseq.graph-parser.block :as gp-block]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[logseq.graph-parser.property :as gp-property]
|
||||
[logseq.graph-parser.utf8 :as utf8]
|
||||
[cljs-bean.core :as bean]
|
||||
[frontend.db.utils :as db-utils]
|
||||
[frontend.db.model :as db-model]))
|
||||
[clojure.string :as string]))
|
||||
|
||||
;; (defn diff-merge
|
||||
;; "N-ways diff & merge
|
||||
;; Accept: blocks
|
||||
;; https://github.com/logseq/diff-merge/blob/44546f2427f20bd417b898c8ba7b7d10a9254774/lib/mldoc.ts#L17-L22
|
||||
;; https://github.com/logseq/diff-merge/blob/85ca7e9bf7740d3880ed97d535a4f782a963395d/lib/merge.ts#L40"
|
||||
;; [base & branches]
|
||||
;; ()
|
||||
;; (let [merger (Merger.)]
|
||||
;; (.mergeBlocks merger (bean/->js base) (bean/->js branches))))
|
||||
|
||||
(defn diff
|
||||
(defn diff
|
||||
"2-ways diff
|
||||
Accept: blocks in the struct with the required info
|
||||
Please refer to the `Block` struct in the link below
|
||||
@@ -46,6 +39,7 @@
|
||||
blocks levels)]
|
||||
blocks))
|
||||
|
||||
;; TODO: Switch to ast->diff-blocks-alt
|
||||
;; Diverged from gp-block/extract-blocks for decoupling
|
||||
;; The process of doing 2 way diff is like:
|
||||
;; 1. Given a base ver. of page (AST in DB), and a branch ver. of page (externally modified file content)
|
||||
@@ -71,7 +65,7 @@
|
||||
pos-meta (assoc pos-meta :end_pos end-pos)]
|
||||
(cond
|
||||
(gp-block/heading-block? block)
|
||||
(let [content (gp-block/get-block-content encoded-content block format pos-meta block-pattern)]
|
||||
(let [content (gp-block/get-block-content encoded-content (second block) format pos-meta block-pattern)]
|
||||
(recur (conj headings {:body content
|
||||
:level (:level (second block))
|
||||
:uuid (:id properties)})
|
||||
@@ -87,6 +81,7 @@
|
||||
(recur headings (rest blocks) properties (:end_pos pos-meta))))
|
||||
(if (empty? properties)
|
||||
(reverse headings)
|
||||
;; Add pre-blocks
|
||||
(let [[block _] (first blocks)
|
||||
pos-meta {:start_pos 0 :end_pos end-pos}
|
||||
content (gp-block/get-block-content encoded-content block format pos-meta block-pattern)
|
||||
@@ -95,3 +90,107 @@
|
||||
:level 1
|
||||
:uuid uuid}
|
||||
(reverse headings))))))))
|
||||
|
||||
|
||||
(defn- get-sub-content-from-pos-meta
|
||||
"Replace gp-block/get-block-content, return bare content, without any trim"
|
||||
[raw-content pos-meta]
|
||||
(let [{:keys [start_pos end_pos]} pos-meta]
|
||||
(utf8/substring raw-content start_pos end_pos)))
|
||||
|
||||
;; Diverged from ast->diff-blocks
|
||||
;; Add :meta :raw-body to the block
|
||||
(defn- ast->diff-blocks-alt
|
||||
"Prepare the blocks for diff-merge
|
||||
blocks: ast of blocks
|
||||
content: corresponding raw content"
|
||||
[blocks content format {:keys [user-config block-pattern]}]
|
||||
{:pre [(string? content) (contains? #{:markdown :org} format)]}
|
||||
(let [utf8-encoded-content (utf8/encode content)]
|
||||
(loop [headings []
|
||||
blocks (reverse blocks)
|
||||
properties {}
|
||||
end-pos (.-length utf8-encoded-content)]
|
||||
(cond
|
||||
(seq blocks)
|
||||
(let [[block pos-meta] (first blocks)
|
||||
;; fix start_pos for properties
|
||||
fixed-pos-meta (assoc pos-meta :end_pos end-pos)]
|
||||
(cond
|
||||
(gp-block/heading-block? block)
|
||||
(let [content (gp-block/get-block-content utf8-encoded-content (second block) format fixed-pos-meta block-pattern)
|
||||
content-raw (get-sub-content-from-pos-meta utf8-encoded-content fixed-pos-meta)]
|
||||
(recur (conj headings {:body content
|
||||
:meta {:raw-body (string/trimr content-raw)}
|
||||
:level (:level (second block))
|
||||
:uuid (:id properties)})
|
||||
(rest blocks)
|
||||
{}
|
||||
(:start_pos fixed-pos-meta))) ;; The current block's start pos is the next block's end pos
|
||||
|
||||
(gp-property/properties-ast? block)
|
||||
(let [new-props (:properties (gp-block/extract-properties (second block) (assoc user-config :format format)))]
|
||||
;; sending the current end pos to next, as it's not finished yet
|
||||
;; supports multiple properties sub-block possible in future
|
||||
(recur headings (rest blocks) (merge properties new-props) (:end_pos fixed-pos-meta)))
|
||||
|
||||
:else
|
||||
(recur headings (rest blocks) properties (:end_pos fixed-pos-meta))))
|
||||
|
||||
(empty? properties)
|
||||
(reverse headings)
|
||||
|
||||
;; Add pre-blocks
|
||||
:else ;; ??? unreachable
|
||||
(let [[block _] (first blocks)
|
||||
pos-meta {:start_pos 0 :end_pos end-pos}
|
||||
content (gp-block/get-block-content utf8-encoded-content block format pos-meta block-pattern)
|
||||
content-raw (get-sub-content-from-pos-meta utf8-encoded-content pos-meta)
|
||||
uuid (:id properties)]
|
||||
(cons {:body content
|
||||
:meta {:raw-body (string/trimr content-raw)}
|
||||
:level 1
|
||||
:uuid uuid}
|
||||
(reverse headings)))))))
|
||||
|
||||
(defn- rebuild-content
|
||||
"translate [[[op block]]] to merged content"
|
||||
[_base-diffblocks diffs _format]
|
||||
;; [[[0 {:body "attrib:: xxx", :level 1, :uuid nil}] ...] ...]
|
||||
(let [ops-fn (fn [ops]
|
||||
(map (fn [[op {:keys [meta]}]]
|
||||
(when (or (= op 0) (= op 1)) ;; equal or insert
|
||||
(:raw-body meta)))
|
||||
ops))]
|
||||
(->> diffs
|
||||
(mapcat ops-fn)
|
||||
(filter seq)
|
||||
(string/join "\n"))))
|
||||
|
||||
(defn three-way-merge
|
||||
[base income current format]
|
||||
(let [->ast (fn [text] (if (= format :org)
|
||||
(gp-mldoc/->edn text (gp-mldoc/default-config :org))
|
||||
(gp-mldoc/->edn text (gp-mldoc/default-config :markdown))))
|
||||
options (if (= format :org)
|
||||
{:block-pattern "*"}
|
||||
{:block-pattern "-"})
|
||||
merger (Merger.)
|
||||
base-ast (->ast base)
|
||||
base-diffblocks (ast->diff-blocks-alt base-ast base format options)
|
||||
income-ast (->ast income)
|
||||
income-diffblocks (ast->diff-blocks-alt income-ast income format options)
|
||||
current-ast (->ast current)
|
||||
current-diffblocks (ast->diff-blocks-alt current-ast current format options)
|
||||
branch-diffblocks [income-diffblocks current-diffblocks]
|
||||
merged (.mergeBlocks merger (bean/->js base-diffblocks) (bean/->js branch-diffblocks))
|
||||
;; For extracting diff-merge test cases
|
||||
;; _ (prn "input:")
|
||||
;; _ (prn (js/JSON.stringify (bean/->js base-diffblocks)))
|
||||
;; _ (prn (js/JSON.stringify (bean/->js branch-diffblocks)))
|
||||
;; _ (prn "logseq diff merge version: " version)
|
||||
;; _ (prn "output:")
|
||||
;; _ (prn (js/JSON.stringify merged))
|
||||
merged-diff (bean/->clj merged)
|
||||
merged-content (rebuild-content base-diffblocks merged-diff format)]
|
||||
merged-content))
|
||||
|
||||
@@ -118,7 +118,9 @@
|
||||
|
||||
(rename! [_this _repo old-path new-path]
|
||||
(ipc/ipc "rename" old-path new-path))
|
||||
|
||||
;; copy with overwrite, without confirmation
|
||||
(copy! [_this repo old-path new-path]
|
||||
(ipc/ipc "copyFile" repo old-path new-path))
|
||||
(stat [_this fpath]
|
||||
(-> (ipc/ipc "stat" fpath)
|
||||
(p/then bean/->clj)))
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
(ns frontend.fs.sync
|
||||
"Main ns for providing file sync functionality"
|
||||
(:require [cljs-http.client :as http]
|
||||
(:require ["@capawesome/capacitor-background-task" :refer [BackgroundTask]]
|
||||
["path" :as node-path]
|
||||
[cljs-http.client :as http]
|
||||
[cljs-time.coerce :as tc]
|
||||
[cljs-time.core :as t]
|
||||
[cljs-time.format :as tf]
|
||||
[cljs-time.coerce :as tc]
|
||||
[cljs.core.async :as async :refer [go timeout go-loop offer! poll! chan <! >!]]
|
||||
[cljs.core.async :as async :refer [<! >! chan go go-loop offer!
|
||||
poll! timeout]]
|
||||
[cljs.core.async.impl.channels]
|
||||
[cljs.core.async.interop :refer [p->c]]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.pprint :as pp]
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[clojure.pprint :as pp]
|
||||
[electron.ipc :as ipc]
|
||||
[goog.string :as gstring]
|
||||
[frontend.config :as config]
|
||||
[frontend.debug :as debug]
|
||||
[frontend.handler.user :as user]
|
||||
[frontend.state :as state]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.persist-var :as persist-var]
|
||||
[frontend.util.fs :as fs-util]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.diff :as diff]
|
||||
[frontend.db :as db]
|
||||
[frontend.fs :as fs]
|
||||
[frontend.debug :as debug]
|
||||
[frontend.diff :as diff]
|
||||
[frontend.encrypt :as encrypt]
|
||||
[frontend.fs :as fs]
|
||||
[frontend.fs.capacitor-fs :as capacitor-fs]
|
||||
[frontend.fs.diff-merge :as diff-merge]
|
||||
[frontend.handler.file :as file-handler]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.user :as user]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.pubsub :as pubsub]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.fs :as fs-util]
|
||||
[frontend.util.persist-var :as persist-var]
|
||||
[goog.string :as gstring]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.common.path :as path]
|
||||
[logseq.graph-parser.util :as gp-util]
|
||||
[medley.core :refer [dedupe-by]]
|
||||
[rum.core :as rum]
|
||||
[promesa.core :as p]
|
||||
[lambdaisland.glogi :as log]
|
||||
[frontend.fs.capacitor-fs :as capacitor-fs]
|
||||
["@capawesome/capacitor-background-task" :refer [BackgroundTask]]
|
||||
["path" :as node-path]))
|
||||
[rum.core :as rum]))
|
||||
|
||||
;;; ### Commentary
|
||||
;; file-sync related local files/dirs:
|
||||
@@ -606,7 +610,7 @@
|
||||
(defn diff-file-metadata-sets
|
||||
"Find the `FileMetadata`s that exists in s1 and does not exist in s2,
|
||||
compare by path+checksum+last-modified,
|
||||
if s1.path = s2.path & s1.checksum <> s2.checksum & s1.last-modified > s2.last-modified
|
||||
if s1.path = s2.path & s1.checksum <> s2.checksum
|
||||
(except some default created files),
|
||||
keep this `FileMetadata` in result"
|
||||
[s1 s2]
|
||||
@@ -632,7 +636,11 @@
|
||||
(and (contains? ignore-default-value-files path)
|
||||
(#{config/config-default-content-md5 empty-custom-css-md5} (:etag %)))
|
||||
false
|
||||
(< last-modified (:last-modified %))
|
||||
;; special handling for css & edn files
|
||||
(and
|
||||
(or (string/ends-with? lower-case-path ".css")
|
||||
(string/ends-with? lower-case-path ".edn"))
|
||||
(< last-modified (:last-modified %)))
|
||||
true)
|
||||
s2)
|
||||
result
|
||||
@@ -719,6 +727,7 @@
|
||||
(<get-local-all-files-meta [this graph-uuid base-path] "get all local files' metadata")
|
||||
(<rename-local-file [this graph-uuid base-path from to])
|
||||
(<update-local-files [this graph-uuid base-path filepaths] "remote -> local")
|
||||
(<fetch-remote-files [this graph-uuid base-path filepaths] "remote -> local version-db")
|
||||
(<download-version-files [this graph-uuid base-path filepaths])
|
||||
(<delete-local-files [this graph-uuid base-path filepaths])
|
||||
(<update-remote-files [this graph-uuid base-path filepaths local-txid] "local -> remote, return err or txid")
|
||||
@@ -850,6 +859,12 @@
|
||||
(<! (<rsapi-cancel-all-requests))
|
||||
(let [token (<! (<get-token this))]
|
||||
(<! (p->c (ipc/ipc "update-local-files" graph-uuid base-path filepaths token))))))
|
||||
(<fetch-remote-files [this graph-uuid base-path filepaths]
|
||||
(go
|
||||
(<! (<rsapi-cancel-all-requests))
|
||||
(let [token (<! (<get-token this))]
|
||||
(<! (p->c (ipc/ipc "fetch-remote-files" graph-uuid base-path filepaths token))))))
|
||||
|
||||
(<download-version-files [this graph-uuid base-path filepaths]
|
||||
(go
|
||||
(let [token (<! (<get-token this))
|
||||
@@ -944,7 +959,16 @@
|
||||
:basePath base-path
|
||||
:filePaths filepaths'
|
||||
:token token})))))))
|
||||
|
||||
(<fetch-remote-files [this graph-uuid base-path filepaths]
|
||||
(go
|
||||
(let [token (<! (<get-token this))
|
||||
r (<! (<retry-rsapi
|
||||
#(p->c (.fetchRemoteFiles mobile-util/file-sync
|
||||
(clj->js {:graphUUID graph-uuid
|
||||
:basePath base-path
|
||||
:filePaths filepaths
|
||||
:token token})))))]
|
||||
(js->clj (.-value r)))))
|
||||
(<download-version-files [this graph-uuid base-path filepaths]
|
||||
(go
|
||||
(let [token (<! (<get-token this))
|
||||
@@ -980,12 +1004,13 @@
|
||||
r
|
||||
(get (js->clj r) "txid"))))))
|
||||
|
||||
(<delete-remote-files [this graph-uuid _base-path filepaths local-txid]
|
||||
(<delete-remote-files [this graph-uuid base-path filepaths local-txid]
|
||||
(let [normalized-filepaths (mapv path-normalize filepaths)]
|
||||
(go
|
||||
(let [token (<! (<get-token this))
|
||||
r (<! (p->c (.deleteRemoteFiles mobile-util/file-sync
|
||||
(clj->js {:graphUUID graph-uuid
|
||||
:basePath base-path
|
||||
:filePaths normalized-filepaths
|
||||
:txid local-txid
|
||||
:token token}))))]
|
||||
@@ -1461,7 +1486,10 @@
|
||||
(let [rpath (relative-path filetxn)
|
||||
repo (state/get-current-repo)
|
||||
repo-dir (config/get-repo-dir repo)
|
||||
content (<! (p->c (fs/read-file repo-dir rpath)))]
|
||||
content (<! (p->c (-> (fs/file-exists? repo-dir rpath)
|
||||
(p/then (fn [exists?]
|
||||
(when exists?
|
||||
(fs/read-file repo-dir rpath)))))))]
|
||||
(and (seq origin-db-content)
|
||||
(or (nil? content)
|
||||
(some :removed (diff/diff origin-db-content content))))))))
|
||||
@@ -1539,6 +1567,117 @@
|
||||
delete-filetxns)]
|
||||
(set (concat update-file-items rename-file-items delete-file-items))))
|
||||
|
||||
(defn- <apply-remote-deletion
|
||||
"Apply remote deletion, if the file is not deleted locally, delete it locally.
|
||||
if the file is changed locally, leave the changed part.
|
||||
|
||||
To replace <delete-local-files"
|
||||
[graph-uuid base-path relative-paths]
|
||||
(go
|
||||
(p->c (p/all (->> relative-paths
|
||||
(map (fn [rpath]
|
||||
(p/let [base-file (path/path-join "logseq/version-files/base" rpath)
|
||||
current-change-file rpath
|
||||
format (gp-util/get-format current-change-file)
|
||||
repo (state/get-current-repo)
|
||||
repo-dir (config/get-repo-dir repo)
|
||||
base-exists? (fs/file-exists? repo-dir base-file)]
|
||||
(if base-exists?
|
||||
(p/let [base-content (fs/read-file repo-dir base-file)
|
||||
current-content (-> (fs/read-file repo-dir current-change-file)
|
||||
(p/catch (fn [_] nil)))]
|
||||
(if (= base-content current-content)
|
||||
;; base-content == current-content, delete current-change-file
|
||||
(p/do!
|
||||
(<delete-local-files rsapi graph-uuid base-path [rpath])
|
||||
(fs/unlink! repo (path/path-join repo-dir base-file) {}))
|
||||
;; base-content != current-content, merge, do not delete
|
||||
(p/let [merged-content (diff-merge/three-way-merge base-content "" current-content format)]
|
||||
(fs/write-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
|
||||
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
|
||||
:from-disk? true
|
||||
:fs/event :fs/remote-file-change}))))
|
||||
|
||||
;; no base-version, use legacy approach, delete it
|
||||
(<delete-local-files rsapi graph-uuid base-path [rpath]))))))))))
|
||||
|
||||
(defn- <fetch-remote-and-update-local-files
|
||||
[graph-uuid base-path relative-paths]
|
||||
(go
|
||||
(let [fetched-file-rpaths-or-ex (<! (<fetch-remote-files rsapi graph-uuid base-path relative-paths))]
|
||||
(if (instance? ExceptionInfo fetched-file-rpaths-or-ex)
|
||||
fetched-file-rpaths-or-ex
|
||||
(<!
|
||||
(p->c (p/all (->> fetched-file-rpaths-or-ex
|
||||
(map (fn [rpath]
|
||||
(p/let [incoming-file (path/path-join "logseq/version-files/incoming" rpath)
|
||||
base-file (path/path-join "logseq/version-files/base" rpath)
|
||||
current-change-file rpath
|
||||
format (gp-util/get-format current-change-file)
|
||||
repo (state/get-current-repo)
|
||||
repo-dir (config/get-repo-dir repo)
|
||||
base-exists? (fs/file-exists? repo-dir base-file)]
|
||||
(cond
|
||||
base-exists?
|
||||
(p/let [base-content (fs/read-file repo-dir base-file)
|
||||
current-content (-> (fs/read-file repo-dir current-change-file)
|
||||
(p/catch (fn [_] nil)))
|
||||
incoming-content (fs/read-file repo-dir incoming-file)]
|
||||
(if (= base-content current-content)
|
||||
(do
|
||||
(prn "[diff-merge]base=current, write directly")
|
||||
(p/do!
|
||||
(fs/copy! repo
|
||||
(path/path-join repo-dir incoming-file)
|
||||
(path/path-join repo-dir current-change-file))
|
||||
(fs/copy! repo
|
||||
(path/path-join repo-dir incoming-file)
|
||||
(path/path-join repo-dir base-file))
|
||||
(file-handler/alter-file repo current-change-file incoming-content {:re-render-root? true
|
||||
:from-disk? true
|
||||
:fs/event :fs/remote-file-change})))
|
||||
(do
|
||||
(prn "[diff-merge]base!=current, 3-way merge")
|
||||
(p/let [current-content (or current-content "")
|
||||
incoming-content (fs/read-file repo-dir incoming-file)
|
||||
merged-content (diff-merge/three-way-merge base-content incoming-content current-content format)]
|
||||
(when (seq merged-content)
|
||||
(p/do!
|
||||
(fs/write-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
|
||||
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
|
||||
:from-disk? true
|
||||
:fs/event :fs/remote-file-change})))))))
|
||||
|
||||
:else
|
||||
(do
|
||||
(prn "[diff-merge]no base found, use empty content as base, avoid loosing data")
|
||||
(p/let [current-content (-> (fs/read-file repo-dir current-change-file)
|
||||
(p/catch (fn [_] nil)))
|
||||
current-content (or current-content "")
|
||||
incoming-content (fs/read-file repo-dir incoming-file)
|
||||
merged-content (diff-merge/three-way-merge "" current-content incoming-content format)]
|
||||
(if (= incoming-content merged-content)
|
||||
(p/do!
|
||||
(fs/copy! repo
|
||||
(path/path-join repo-dir incoming-file)
|
||||
(path/path-join repo-dir current-change-file))
|
||||
(fs/copy! repo
|
||||
(path/path-join repo-dir incoming-file)
|
||||
(path/path-join repo-dir base-file))
|
||||
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
|
||||
:from-disk? true
|
||||
:fs/event :fs/remote-file-change}))
|
||||
|
||||
;; else
|
||||
(p/do!
|
||||
(fs/write-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
|
||||
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
|
||||
:from-disk? true
|
||||
:fs/event :fs/remote-file-change})
|
||||
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
|
||||
:from-disk? true
|
||||
:fs/event :fs/remote-file-change})))))))))))))))))
|
||||
|
||||
(defn- apply-filetxns
|
||||
[*sync-state graph-uuid base-path filetxns *paused]
|
||||
(go
|
||||
@@ -1574,7 +1713,7 @@
|
||||
(swap! *sync-state sync-state--remove-recent-remote->local-files
|
||||
[recent-remote->local-file-item])))))
|
||||
|
||||
(let [update-local-files-ch (<update-local-files rsapi graph-uuid base-path (map relative-path filetxns))
|
||||
(let [update-local-files-ch (<fetch-remote-and-update-local-files graph-uuid base-path (map relative-path filetxns))
|
||||
r (<! (<with-pause update-local-files-ch *paused))]
|
||||
(doseq [[filetxn origin-db-content] txn->db-content-vec]
|
||||
(when (<! (need-add-version-file? filetxn origin-db-content))
|
||||
@@ -1592,7 +1731,7 @@
|
||||
(if (<! (<local-file-not-exist? graph-uuid rsapi base-path (relative-path filetxn)))
|
||||
;; not exist, ignore
|
||||
true
|
||||
(let [r (<! (<delete-local-files rsapi graph-uuid base-path [(relative-path filetxn)]))]
|
||||
(let [r (<! (<apply-remote-deletion graph-uuid base-path [(relative-path filetxn)]))]
|
||||
(if (and (instance? ExceptionInfo r)
|
||||
(string/index-of (str (ex-cause r)) "No such file or directory"))
|
||||
true
|
||||
@@ -2714,20 +2853,20 @@
|
||||
;;; ### put all stuff together
|
||||
|
||||
(defrecord ^:large-vars/cleanup-todo
|
||||
SyncManager [user-uuid graph-uuid base-path *sync-state
|
||||
^Local->RemoteSyncer local->remote-syncer ^Remote->LocalSyncer remote->local-syncer remoteapi
|
||||
^:mutable ratelimit-local-changes-chan
|
||||
*txid *txid-for-get-deletion-log
|
||||
^:mutable state ^:mutable remote-change-chan ^:mutable *ws *stopped? *paused?
|
||||
^:mutable ops-chan ^:mutable app-awake-from-sleep-chan
|
||||
SyncManager [user-uuid graph-uuid base-path *sync-state
|
||||
^Local->RemoteSyncer local->remote-syncer ^Remote->LocalSyncer remote->local-syncer remoteapi
|
||||
^:mutable ratelimit-local-changes-chan
|
||||
*txid *txid-for-get-deletion-log
|
||||
^:mutable state ^:mutable remote-change-chan ^:mutable *ws *stopped? *paused?
|
||||
^:mutable ops-chan ^:mutable app-awake-from-sleep-chan
|
||||
;; control chans
|
||||
private-full-sync-chan private-remote->local-sync-chan
|
||||
private-remote->local-full-sync-chan private-pause-resume-chan]
|
||||
private-full-sync-chan private-remote->local-sync-chan
|
||||
private-remote->local-full-sync-chan private-pause-resume-chan]
|
||||
Object
|
||||
(schedule [this next-state args reason]
|
||||
{:pre [(s/valid? ::state next-state)]}
|
||||
(println (str "[SyncManager " graph-uuid "]")
|
||||
(and state (name state)) "->" (and next-state (name next-state)) :reason reason :local-txid @*txid :now (tc/to-string (t/now)))
|
||||
(and state (name state)) "->" (and next-state (name next-state)) :reason reason :local-txid @*txid :args args :now (tc/to-string (t/now)))
|
||||
(set! state next-state)
|
||||
(swap! *sync-state sync-state--update-state next-state)
|
||||
(go
|
||||
@@ -2925,7 +3064,7 @@
|
||||
:epoch (tc/to-epoch (t/now))}})
|
||||
(.schedule this ::idle nil nil))))))
|
||||
|
||||
(remote->local-full-sync [this _]
|
||||
(remote->local-full-sync [this {:keys [retry-count]}]
|
||||
(go
|
||||
(let [{:keys [succ unknown stop pause]}
|
||||
(<! (<sync-remote->local-all-files! remote->local-syncer))]
|
||||
@@ -2952,12 +3091,19 @@
|
||||
:data {:graph-uuid graph-uuid
|
||||
:exp unknown
|
||||
:epoch (tc/to-epoch (t/now))}})
|
||||
(let [next-state (if (string/includes? (str (ex-cause unknown)) "404 Not Found")
|
||||
;; TODO: this should never happen
|
||||
::stop
|
||||
;; if any other exception occurred, re-exec remote->local-full-sync
|
||||
::remote->local-full-sync)]
|
||||
(.schedule this next-state nil nil)))))))
|
||||
(let [next-state
|
||||
(cond
|
||||
(string/includes? (str (ex-cause unknown)) "404 Not Found")
|
||||
;; TODO: this should never happen
|
||||
::stop
|
||||
(> retry-count 3)
|
||||
::stop
|
||||
|
||||
:else ;; if any other exception occurred, re-exec remote->local-full-sync
|
||||
::remote->local-full-sync)]
|
||||
(.schedule this next-state
|
||||
(when (= ::remote->local-full-sync next-state) {:retry-count (inc retry-count)})
|
||||
nil)))))))
|
||||
|
||||
(remote->local [this _next-state {remote-val :remote}]
|
||||
(go
|
||||
@@ -3002,7 +3148,7 @@
|
||||
(let [distincted-local-changes (distinct-file-change-events local-changes)
|
||||
_ (swap! *sync-state #(sync-state-reset-full-local->remote-files % distincted-local-changes))
|
||||
change-events-partitions
|
||||
(sequence (partition-file-change-events upload-batch-size) distincted-local-changes)
|
||||
(sequence (partition-file-change-events upload-batch-size) distincted-local-changes)
|
||||
_ (put-sync-event! {:event :start
|
||||
:data {:type :local->remote
|
||||
:graph-uuid graph-uuid
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
Decide how to treat the parsed file based on the file's triggering event
|
||||
options -
|
||||
:fs/reset-event - the event that triggered the file update
|
||||
:fs/local-file-change - file changed on local disk
|
||||
:fs/remote-file-change - file changed on remote"
|
||||
:fs/local-file-change - file changed on local disk
|
||||
:fs/remote-file-change - file changed on remote"
|
||||
[repo-url file-path content {:fs/keys [event] :as options}]
|
||||
(let [db-conn (db/get-db repo-url false)]
|
||||
(case event
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
:right-side-bar/switch-theme "Skakel oor na die {1} tema"
|
||||
:right-side-bar/contents "Inhoud"
|
||||
:right-side-bar/block-ref "Blok verwysing"
|
||||
:page/presentation-mode "Aanbiedings modus"
|
||||
:page/delete-confirmation "Is jy seker jy wil die bladsy uitvee?"
|
||||
:page/show-journals "Wys joernale"
|
||||
:file/name "Lêer naam"
|
||||
@@ -60,7 +59,7 @@
|
||||
:language "Taal"
|
||||
|
||||
:file-sync/other-user-graph "Huidige plaaslike grafiek is gebonde aan ander gebruiker se afgeleë grafiek. So kan nie begin om te sinkroniseer nie."
|
||||
:file-sync/graph-deleted "Huidige afstandgrafiek is geskrap"
|
||||
:file-sync/graph-deleted "Huidige afstandgrafiek is geskrap"
|
||||
|
||||
:shortcut.category/formatting "Formatering"
|
||||
:command.editor/indent "Ingekeepte blok oortjie"
|
||||
@@ -84,4 +83,4 @@
|
||||
:command.ui/toggle-document-mode "Wissel dokument modus"
|
||||
:command.go/journals "Spring na joernale"
|
||||
:command.ui/toggle-theme "Wissel tussen donker/lig temas"
|
||||
:command.ui/toggle-right-sidebar "Wissel regter sybalk"}
|
||||
:command.ui/toggle-right-sidebar "Wissel regter sybalk"}
|
||||
|
||||
@@ -193,7 +193,6 @@
|
||||
:page/open-backup-directory "Verzeichnis für Seiten-Backups öffnen"
|
||||
:page/open-in-finder "Im Verzeichnis öffnen"
|
||||
:page/open-with-default-app "Mit Standard-Anwendung öffnen"
|
||||
:page/presentation-mode "Präsentationsmodus"
|
||||
:page/show-journals "Journal anzeigen"
|
||||
:page/show-whiteboards "Whiteboards anzeigen"
|
||||
:page/unfavorite "Seite aus Favoriten entfernen"
|
||||
@@ -498,4 +497,4 @@
|
||||
:shortcut.category/formatting "Formatierung"
|
||||
:shortcut.category/navigating "Navigation"
|
||||
:shortcut.category/others "Sonstiges"
|
||||
:shortcut.category/toggle "Umschalten"}
|
||||
:shortcut.category/toggle "Umschalten"}
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
:page/logseq-is-having-a-problem "Logseq is having a problem. To try to get it back to a working state, please try the following safe steps in order:"
|
||||
:page/step "Step {1}"
|
||||
:page/try "Try"
|
||||
:page/presentation-mode "Presentation"
|
||||
:page/slide-view "View as slides"
|
||||
:page/delete-confirmation "Are you sure you want to delete this page and its file?"
|
||||
:page/open-in-finder "Open in directory"
|
||||
:page/open-with-default-app "Open with default app"
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
:left-side-bar/new-page "Nueva página"
|
||||
:left-side-bar/nav-favorites "Favoritos"
|
||||
:left-side-bar/nav-recent-pages "Recientes"
|
||||
:page/presentation-mode "Modo presentación"
|
||||
:page/delete-confirmation "¿Está seguro que desea eliminar esta página y su archivo?"
|
||||
:page/open-in-finder "Abrir ubicación del archivo"
|
||||
:page/open-with-default-app "Abrir con la aplicación predeterminada"
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
:right-side-bar/flashcards "Cartes-mémoire"
|
||||
:right-side-bar/new-page "Nouvelle page"
|
||||
:left-side-bar/journals "Journaux"
|
||||
:page/presentation-mode "Mode présentation"
|
||||
:page/delete-confirmation "Etes-vous sûr de vouloir supprimer la page ?"
|
||||
:page/make-public "Rendre la page publique"
|
||||
:page/make-private "Rendre la page privée"
|
||||
@@ -437,4 +436,4 @@
|
||||
:shortcut.category/others "Autres"
|
||||
:shortcut.category/toggle "Basculer"
|
||||
:command.editor/select-parent "Sélectionnez le bloc parent"
|
||||
:command.sidebar/close-top "Ferme l'élément supérieur dans la barre latérale droite"}
|
||||
:command.sidebar/close-top "Ferme l'élément supérieur dans la barre latérale droite"}
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
:left-side-bar/new-page "Nuova pagina"
|
||||
:left-side-bar/nav-favorites "Preferiti"
|
||||
:left-side-bar/nav-recent-pages "Recenti"
|
||||
:page/presentation-mode "Presentazione"
|
||||
:page/delete-confirmation "Sei sicuro di voler eliminare questa pagina e i suoi dati?"
|
||||
:page/open-in-finder "Apri nella cartella"
|
||||
:page/open-with-default-app "Apri con l'app predefinita"
|
||||
@@ -343,4 +342,4 @@
|
||||
:shortcut.category/others "Altri"
|
||||
:command.editor/copy-embed "Copia un incorporamento di blocco che punta al blocco corrente"
|
||||
:command.editor/copy-text "Copia le selezioni come testo"
|
||||
:command.pdf/close "Chiudi anteprima PDF"}
|
||||
:command.pdf/close "Chiudi anteprima PDF"}
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
:left-side-bar/new-page "新規ページ"
|
||||
:left-side-bar/nav-favorites "お気に入り"
|
||||
:left-side-bar/nav-recent-pages "最新"
|
||||
:page/presentation-mode "プレゼンテーション"
|
||||
:page/delete-confirmation "このページとページのファイルを削除してもよいですか?"
|
||||
:page/open-in-finder "ディレクトリで開く"
|
||||
:page/open-with-default-app "デフォルトのアプリで開く"
|
||||
@@ -362,4 +361,4 @@
|
||||
:command.editor/strike-through "打ち消し線"
|
||||
:command.misc/copy "コピー"
|
||||
:command.ui/goto-plugins "プラグインへ"
|
||||
:command.ui/select-theme-color "利用可能なテーマ色を選択"}
|
||||
:command.ui/select-theme-color "利用可能なテーマ色を選択"}
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
:left-side-bar/new-page "새 페이지"
|
||||
:left-side-bar/nav-favorites "즐겨찾기"
|
||||
:left-side-bar/nav-recent-pages "최근 페이지"
|
||||
:page/presentation-mode "프레젠테이션 모드"
|
||||
:page/delete-confirmation "이 페이지와 페이지의 파일들을 삭제하시겠습니까?"
|
||||
:page/open-in-finder "디렉토리에서 열기"
|
||||
:page/open-with-default-app "기본 앱으로 열기"
|
||||
@@ -455,4 +454,4 @@
|
||||
:command.pdf/find "PDF: 현재 PDF 문서에서 검색"
|
||||
:command.sidebar/close-top "우축 사이드바의 최상단 항목 닫기"
|
||||
:command.ui/clear-all-notifications "모든 알람 제거"
|
||||
:command.ui/install-plugins-from-file "plugins.edn에서 플러그인 설치"}
|
||||
:command.ui/install-plugins-from-file "plugins.edn에서 플러그인 설치"}
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
:left-side-bar/new-page "Ny side"
|
||||
:left-side-bar/nav-favorites "Favoritter"
|
||||
:left-side-bar/nav-recent-pages "Nylig"
|
||||
:page/presentation-mode "Presentasjonsmodus"
|
||||
:page/delete-confirmation "Er du sikker på at du vil slette denne siden og filen dens?"
|
||||
:page/open-in-finder "Åpne i mappe"
|
||||
:page/open-with-default-app "Åpne med forhåndsvalgt app"
|
||||
@@ -504,7 +503,7 @@
|
||||
:command.whiteboard/zoom-out "Zoom ut"
|
||||
:command.whiteboard/zoom-to-fit "Zoom til tegning"
|
||||
:command.whiteboard/zoom-to-selection "Zoom for å passe seleksjonen"
|
||||
|
||||
|
||||
:home "Hjem"
|
||||
:importing "Importerer"
|
||||
:port "Port"
|
||||
@@ -634,4 +633,4 @@
|
||||
:window/exit-fullscreen "Gå ut av fullskjerm"
|
||||
:window/maximize "Maksimer"
|
||||
:window/minimize "Minimer"
|
||||
:window/restore "Gjenopprett"}
|
||||
:window/restore "Gjenopprett"}
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
:page/open-backup-directory "Open backups map pagina"
|
||||
:page/open-in-finder "Open in map"
|
||||
:page/open-with-default-app "Open met standaard app"
|
||||
:page/presentation-mode "Presentatiemodus"
|
||||
:page/show-journals "Toon Journaals"
|
||||
:page/unfavorite "Pagina uit favorieten verwijderen"
|
||||
:page/updated-at "Bijgewerkt op"
|
||||
@@ -341,4 +340,4 @@
|
||||
:shortcut.category/block-selection "Blokselectie (druk op Esc om selectie te beëindigen)"
|
||||
:shortcut.category/formatting "Formatteren"
|
||||
:shortcut.category/navigating "Navigatie"
|
||||
:shortcut.category/others "Anderen"}
|
||||
:shortcut.category/others "Anderen"}
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
:left-side-bar/new-page "Nowa strona"
|
||||
:left-side-bar/nav-favorites "Ulubione"
|
||||
:left-side-bar/nav-recent-pages "Ostatnio odwiedzane"
|
||||
:page/presentation-mode "Tryb prezentacji"
|
||||
:page/delete-confirmation "Czy jesteś pewien że chcesz usunąć tę stronę i jej plik?"
|
||||
:page/open-in-finder "Otwórz w przeglądarce plików"
|
||||
:page/open-with-default-app "Otwórz w domyślnej aplikacji"
|
||||
@@ -343,4 +342,4 @@
|
||||
:command.ui/toggle-wide-mode "Włącz / wyłącz tryb szeroki"
|
||||
:command.ui/goto-plugins "Przejdź do dashboardu pluginów"
|
||||
:command.ui/toggle-cards "Pokaż / Ukryj karty"
|
||||
:command.git/commit "Wykonaj GIT COMMIT z wiadomością"}
|
||||
:command.git/commit "Wykonaj GIT COMMIT z wiadomością"}
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
:right-side-bar/block-ref "Referência de bloco"
|
||||
:right-side-bar/new-page "Nova página"
|
||||
:left-side-bar/journals "Diários"
|
||||
:page/presentation-mode "Modo de apresentação"
|
||||
:page/delete-confirmation "Tem certeza que quer apagar esta página e o arquivo associado?"
|
||||
:page/open-in-finder "Abrir em pasta"
|
||||
:page/open-with-default-app "Abrir com a aplicação por omissão"
|
||||
@@ -451,7 +450,7 @@
|
||||
:command.pdf/find "PDF: Pesquisar no documento PDF atual"
|
||||
:command.sidebar/close-top "Fechar item superior na barra lateral direita"
|
||||
:command.ui/install-plugins-from-file "Instalar plugins de plugins.edn"
|
||||
|
||||
|
||||
:home "Início"
|
||||
:toggle-theme "Trocar tema"
|
||||
:whiteboard "Quadro Branco"
|
||||
@@ -650,7 +649,7 @@
|
||||
:plugins "Plugins"
|
||||
:right-side-bar/flashcards "Flashcards"
|
||||
:settings-page/enable-flashcards "Flashcards"
|
||||
:page/backlinks "Backlinks"
|
||||
:page/backlinks "Backlinks"
|
||||
:host "Host"
|
||||
:settings-page/tab-editor "Editor"
|
||||
:shortcut.category/plugins "Plugins"
|
||||
|
||||
@@ -72,7 +72,6 @@
|
||||
:page/logseq-is-having-a-problem "Logseq está tendo um problema. Para tentar colocá-lo de volta em um estado de funcionamento, por favor tente os seguintes passos seguros em ordem:"
|
||||
:page/step "Passo {1}"
|
||||
:page/try "Tentar"
|
||||
:page/presentation-mode "Modo de apresentação"
|
||||
:page/delete-confirmation "Tem a certeza de que quer apagar esta página e o respetivo ficheiro?"
|
||||
:page/open-in-finder "Abrir em pasta"
|
||||
:page/open-with-default-app "Abrir com a aplicação predefinida"
|
||||
@@ -455,4 +454,4 @@
|
||||
:command.graph/export-as-html "Exportar páginas de gráficos públicos como html"
|
||||
:command.pdf/find "PDF: Pesquisar no documento PDF atual"
|
||||
:command.sidebar/close-top "Fechar item superior na barra lateral direita"
|
||||
:command.ui/install-plugins-from-file "Instalar plugins de plugins.edn"}
|
||||
:command.ui/install-plugins-from-file "Instalar plugins de plugins.edn"}
|
||||
|
||||
@@ -86,7 +86,6 @@
|
||||
:page/logseq-is-having-a-problem "У Logseq возникла проблема. Чтобы попытаться вернуть его в рабочее состояние, пожалуйста, попробуйте выполнить следующие безопасные шаги по порядку:"
|
||||
:page/step "Шаг {1}"
|
||||
:page/try "Попробовать"
|
||||
:page/presentation-mode "Презентация"
|
||||
:page/delete-confirmation "Вы уверены, что хотите удалить эту страницу и её файл(ы)?"
|
||||
:page/open-in-finder "Открыть в каталоге"
|
||||
:page/open-with-default-app "Открыть в приложении по умолчанию"
|
||||
@@ -267,7 +266,7 @@
|
||||
:sync-from-local-files "Обновить"
|
||||
:sync-from-local-files-detail "Импортировать изменения из локальных файлов"
|
||||
:sync-from-local-changes-detected "При обновлении будут найдены и обработаны файлы, изменённые на диске и отличающиеся от текущего содержимого страниц Logseq. Продолжить?"
|
||||
|
||||
|
||||
:search/publishing "Искать"
|
||||
:search "Искать или создать страницу"
|
||||
:whiteboard/link-whiteboard-or-block "Ссылка на доску/страницу/блок"
|
||||
@@ -339,7 +338,7 @@
|
||||
:whiteboard/circle "Круг"
|
||||
:whiteboard/triangle "Треугольник"
|
||||
:whiteboard/shape "Фигура"
|
||||
:whiteboard/open-page "Открыть страницу"
|
||||
:whiteboard/open-page "Открыть страницу"
|
||||
:whiteboard/open-page-in-sidebar "Открыть страницу на боковой панели"
|
||||
:whiteboard/remove-link "Удалить ссылку"
|
||||
:whiteboard/link "Ссылка"
|
||||
@@ -487,9 +486,9 @@
|
||||
:file-sync/other-user-graph "Текущий локальный граф привязан к удаленному графу другого пользователя. Поэтому синхронизацию начать нельзя."
|
||||
:file-sync/graph-deleted "Текущий удаленный граф был удален"
|
||||
:file-sync/rsapi-cannot-upload-err "Не удалось начать синхронизацию, пожалуйста, проверьте, правильно ли установлено локальное время."
|
||||
|
||||
|
||||
:notification/clear-all "Очистить всё"
|
||||
|
||||
|
||||
:shortcut.category/basics "Базовые"
|
||||
:shortcut.category/formatting "Форматирование"
|
||||
:shortcut.category/navigating "Навигация"
|
||||
@@ -663,4 +662,4 @@
|
||||
:command.dev/show-block-data "(Dev) Показать данные блока"
|
||||
:command.dev/show-block-ast "(Dev) Показать AST блока"
|
||||
:command.dev/show-page-data "(Dev) Показать данные страницы"
|
||||
:command.dev/show-page-ast "(Dev) Показать AST страницы"}
|
||||
:command.dev/show-page-ast "(Dev) Показать AST страницы"}
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
:left-side-bar/new-whiteboard "Nová tabuľa"
|
||||
:left-side-bar/nav-favorites "Obľúbené"
|
||||
:left-side-bar/nav-recent-pages "Posledné"
|
||||
:page/presentation-mode "Prezentácia"
|
||||
:page/delete-confirmation "Naozaj chcete odstrániť túto stránku a jej súbor?"
|
||||
:page/open-in-finder "Otvoriť v adresári"
|
||||
:page/open-with-default-app "Otvoriť pomocou predvolenej aplikácie"
|
||||
@@ -443,4 +442,4 @@
|
||||
:command.ui/install-plugins-from-file "Inštalovať doplnky z plugins.edn"
|
||||
:command.editor/toggle-open-blocks "Prepnúť otvorené bloky (zbaliť alebo rozbaliť všetky bloky)"
|
||||
:command.ui/toggle-cards "Zobraziť/Skryť karty"
|
||||
:command.git/commit "Spusiť príkaz git commit so správou"}
|
||||
:command.git/commit "Spusiť príkaz git commit so správou"}
|
||||
|
||||
@@ -152,7 +152,6 @@
|
||||
:page/logseq-is-having-a-problem "Logseq'te bir sorun var. Tekrar çalışır duruma getirmek için lütfen aşağıdaki güvenli adımları sırayla deneyin:"
|
||||
:page/step "{1}. Adım"
|
||||
:page/try "Deneyin"
|
||||
:page/presentation-mode "Sunu"
|
||||
:page/delete-confirmation "Bu sayfayı ve dosyasını silmek istediğinizden emin misiniz?"
|
||||
:page/open-in-finder "Dizini aç"
|
||||
:page/open-with-default-app "Varsayılan uygulamayla aç"
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
:page/logseq-is-having-a-problem "У Logseq виникла проблема. Щоб спробувати повернути його до робочого стану, виконайте такі безпечні кроки по порядку:"
|
||||
:page/step "Крок {1}"
|
||||
:page/try "Спробувати"
|
||||
:page/presentation-mode "Презентація"
|
||||
:page/delete-confirmation "Ви впевнені, що хочете видалити цю сторінку та її файл?"
|
||||
:page/open-in-finder "Відкрити у директорії"
|
||||
:page/open-with-default-app "Відкрити за допомогою програми за умовчанням"
|
||||
@@ -520,4 +519,4 @@
|
||||
:command.dev/show-block-ast "(Dev) Показати блок AST"
|
||||
:command.dev/show-block-data "(Dev) Показати дані блоку"
|
||||
:command.dev/show-page-ast "(Dev) Показати сторінку AST"
|
||||
:command.dev/show-page-data "(Dev) Показати дані сторінки"}
|
||||
:command.dev/show-page-data "(Dev) Показати дані сторінки"}
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
:left-side-bar/nav-recent-pages "最近使用"
|
||||
:left-side-bar/new-whiteboard "新建白板"
|
||||
:left-side-bar/create "新建"
|
||||
:page/presentation-mode "打开幻灯片"
|
||||
:page/delete-confirmation "您确定要删除此页面和文件吗?"
|
||||
:page/open-in-finder "打开文件对应目录"
|
||||
:page/open-with-default-app "用默认应用打开文件"
|
||||
@@ -462,4 +461,4 @@
|
||||
:command.editor/backward-kill-word "向前删除一个单词"
|
||||
:command.editor/open-edit "编辑选中块"
|
||||
:command.editor/delete-selection "删除选中块"
|
||||
:command.editor/toggle-open-blocks "切换折叠/展开所有块(非编辑状态)"}
|
||||
:command.editor/toggle-open-blocks "切换折叠/展开所有块(非编辑状态)"}
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
:page/logseq-is-having-a-problem "Logseq 出了些問題。請按照以下安全步驟將其恢復到正常狀態:"
|
||||
:page/step "步驟 {1}"
|
||||
:page/try "嘗試"
|
||||
:page/presentation-mode "簡報模式"
|
||||
:page/delete-confirmation "你確定想刪除此頁面檔案嗎?"
|
||||
:page/open-in-finder "開啟資料夾"
|
||||
:page/open-with-default-app "使用預設應用程式開啟"
|
||||
@@ -345,4 +344,4 @@
|
||||
:command.ui/toggle-document-mode "切換文檔模式"
|
||||
:command.ui/toggle-theme "“在暗色/亮色主題之間切換”"
|
||||
:command.ui/toggle-right-sidebar "啟用/關閉右側欄"
|
||||
:command.go/journals "跳轉到日記"}
|
||||
:command.go/journals "跳轉到日記"}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
(ns frontend.fs.diff-merge-test
|
||||
(:require [cljs.test :refer [deftest are is]]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.graph-parser :as graph-parser]
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[cljs.test :refer [are deftest is]]
|
||||
[frontend.db.conn :as conn]
|
||||
[frontend.fs.diff-merge :as fs-diff]
|
||||
[frontend.handler.common.file :as file-common-handler]
|
||||
[frontend.db.conn :as conn]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.graph-parser :as graph-parser]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[cljs-bean.core :as bean]))
|
||||
[logseq.graph-parser.text :as text]))
|
||||
|
||||
(defn test-db->diff-blocks
|
||||
"A hijacked version of db->diff-blocks for testing.
|
||||
@@ -28,18 +29,18 @@
|
||||
:ID: 72289d9a-eb2f-427b-ad97-b605a4b8c59b
|
||||
:END:
|
||||
#+tItLe: Well parsed!"
|
||||
[{:body ":PROPERTIES:\n:ID: 72289d9a-eb2f-427b-ad97-b605a4b8c59b\n:END:\n#+tItLe: Well parsed!"
|
||||
:uuid "72289d9a-eb2f-427b-ad97-b605a4b8c59b"
|
||||
[{:body ":PROPERTIES:\n:ID: 72289d9a-eb2f-427b-ad97-b605a4b8c59b\n:END:\n#+tItLe: Well parsed!"
|
||||
:uuid "72289d9a-eb2f-427b-ad97-b605a4b8c59b"
|
||||
:level 1}]
|
||||
|
||||
|
||||
"#+title: Howdy"
|
||||
[{:body "#+title: Howdy" :uuid nil :level 1}]
|
||||
|
||||
|
||||
":PROPERTIES:
|
||||
:fiction: [[aldsjfklsda]]
|
||||
:END:\n#+title: Howdy"
|
||||
[{:body ":PROPERTIES:\n:fiction: [[aldsjfklsda]]\n:END:\n#+title: Howdy"
|
||||
:uuid nil
|
||||
[{:body ":PROPERTIES:\n:fiction: [[aldsjfklsda]]\n:END:\n#+title: Howdy"
|
||||
:uuid nil
|
||||
:level 1}]))
|
||||
|
||||
(deftest db<->ast-diff-blocks-test
|
||||
@@ -68,13 +69,23 @@
|
||||
{:body "b" :uuid nil :level 2}
|
||||
{:body "c" :uuid nil :level 3}]
|
||||
|
||||
"- a
|
||||
\t- b
|
||||
\t\t- c
|
||||
\t\t multiline
|
||||
- d"
|
||||
[{:body "a" :uuid nil :level 1}
|
||||
{:body "b" :uuid nil :level 2}
|
||||
{:body "c\nmultiline" :uuid nil :level 3}
|
||||
{:body "d" :uuid nil :level 1}]
|
||||
|
||||
"## hello
|
||||
\t- world
|
||||
\t\t- nice
|
||||
\t\t\t- nice
|
||||
\t\t\t- bingo
|
||||
\t\t\t- world"
|
||||
[{:body "## hello" :uuid nil :level 2}
|
||||
[{:body "## hello" :uuid nil :level 1}
|
||||
{:body "world" :uuid nil :level 2}
|
||||
{:body "nice" :uuid nil :level 3}
|
||||
{:body "nice" :uuid nil :level 4}
|
||||
@@ -92,23 +103,97 @@
|
||||
\t- i
|
||||
- j"
|
||||
[{:body "# a" :uuid nil :level 1}
|
||||
{:body "## b" :uuid nil :level 2}
|
||||
{:body "### c" :uuid nil :level 3}
|
||||
{:body "#### d" :uuid nil :level 4}
|
||||
{:body "### e" :uuid nil :level 3}
|
||||
{:body "## b" :uuid nil :level 1}
|
||||
{:body "### c" :uuid nil :level 1}
|
||||
{:body "#### d" :uuid nil :level 1}
|
||||
{:body "### e" :uuid nil :level 1}
|
||||
{:body "f" :uuid nil :level 1}
|
||||
{:body "g" :uuid nil :level 2}
|
||||
{:body "h" :uuid nil :level 3}
|
||||
{:body "i" :uuid nil :level 2}
|
||||
{:body "j" :uuid nil :level 1}]
|
||||
|
||||
|
||||
"- a\n id:: 63e25526-3612-4fb1-8cf9-f66db1254a58
|
||||
\t- b
|
||||
\t\t- c"
|
||||
[{:body "a\n id:: 63e25526-3612-4fb1-8cf9-f66db1254a58"
|
||||
[{:body "a\nid:: 63e25526-3612-4fb1-8cf9-f66db1254a58"
|
||||
:uuid "63e25526-3612-4fb1-8cf9-f66db1254a58" :level 1}
|
||||
{:body "b" :uuid nil :level 2}
|
||||
{:body "c" :uuid nil :level 3}]))
|
||||
{:body "c" :uuid nil :level 3}]
|
||||
|
||||
"alias:: ⭐️\nicon:: ⭐️"
|
||||
[{:body "alias:: ⭐️\nicon:: ⭐️", :level 1, :uuid nil}]))
|
||||
|
||||
(defn text->diffblocks-alt
|
||||
[text]
|
||||
(-> (gp-mldoc/->edn text (gp-mldoc/default-config :markdown))
|
||||
(#'fs-diff/ast->diff-blocks-alt text :markdown {:block-pattern "-"})))
|
||||
|
||||
(deftest md->ast->diff-blocks-alt-test
|
||||
(are [text diff-blocks]
|
||||
(= (text->diffblocks-alt text)
|
||||
diff-blocks)
|
||||
"- a
|
||||
\t- b
|
||||
\t\t- c"
|
||||
[{:body "a" :uuid nil :level 1 :meta {:raw-body "- a"}}
|
||||
{:body "b" :uuid nil :level 2 :meta {:raw-body "\t- b"}}
|
||||
{:body "c" :uuid nil :level 3 :meta {:raw-body "\t\t- c"}}]
|
||||
|
||||
"- a
|
||||
\t- b
|
||||
\t\t- c
|
||||
\t\t multiline
|
||||
- d"
|
||||
[{:body "a" :uuid nil :level 1 :meta {:raw-body "- a"}}
|
||||
{:body "b" :uuid nil :level 2 :meta {:raw-body "\t- b"}}
|
||||
{:body "c\nmultiline" :uuid nil :level 3 :meta {:raw-body "\t\t- c\n\t\t multiline"}}
|
||||
{:body "d" :uuid nil :level 1 :meta {:raw-body "- d"}}]
|
||||
|
||||
"## hello
|
||||
\t- world
|
||||
\t\t- nice
|
||||
\t\t\t- nice
|
||||
\t\t\t- bingo
|
||||
\t\t\t- world"
|
||||
[{:body "## hello" :uuid nil :level 1 :meta {:raw-body "## hello"}}
|
||||
{:body "world" :uuid nil :level 2 :meta {:raw-body "\t- world"}}
|
||||
{:body "nice" :uuid nil :level 3 :meta {:raw-body "\t\t- nice"}}
|
||||
{:body "nice" :uuid nil :level 4 :meta {:raw-body "\t\t\t- nice"}}
|
||||
{:body "bingo" :uuid nil :level 4 :meta {:raw-body "\t\t\t- bingo"}}
|
||||
{:body "world" :uuid nil :level 4 :meta {:raw-body "\t\t\t- world"}}]
|
||||
|
||||
"# a
|
||||
## b
|
||||
### c
|
||||
#### d
|
||||
### e
|
||||
- f
|
||||
\t- g
|
||||
\t\t- h
|
||||
\t- i
|
||||
- j"
|
||||
[{:body "# a" :uuid nil :level 1 :meta {:raw-body "# a"}}
|
||||
{:body "## b" :uuid nil :level 1 :meta {:raw-body "## b"}}
|
||||
{:body "### c" :uuid nil :level 1 :meta {:raw-body "### c"}}
|
||||
{:body "#### d" :uuid nil :level 1 :meta {:raw-body "#### d"}}
|
||||
{:body "### e" :uuid nil :level 1 :meta {:raw-body "### e"}}
|
||||
{:body "f" :uuid nil :level 1 :meta {:raw-body "- f"}}
|
||||
{:body "g" :uuid nil :level 2 :meta {:raw-body "\t- g"}}
|
||||
{:body "h" :uuid nil :level 3 :meta {:raw-body "\t\t- h"}}
|
||||
{:body "i" :uuid nil :level 2 :meta {:raw-body "\t- i"}}
|
||||
{:body "j" :uuid nil :level 1 :meta {:raw-body "- j"}}]
|
||||
|
||||
"- a\n id:: 63e25526-3612-4fb1-8cf9-f66db1254a58
|
||||
\t- b
|
||||
\t\t- c"
|
||||
[{:body "a\nid:: 63e25526-3612-4fb1-8cf9-f66db1254a58"
|
||||
:uuid "63e25526-3612-4fb1-8cf9-f66db1254a58" :level 1 :meta {:raw-body "- a\n id:: 63e25526-3612-4fb1-8cf9-f66db1254a58"}}
|
||||
{:body "b" :uuid nil :level 2 :meta {:raw-body "\t- b"}}
|
||||
{:body "c" :uuid nil :level 3 :meta {:raw-body "\t\t- c"}}]
|
||||
|
||||
"alias:: ⭐️\nicon:: ⭐️"
|
||||
[{:body "alias:: ⭐️\nicon:: ⭐️", :meta {:raw-body "alias:: ⭐️\nicon:: ⭐️"}, :level 1, :uuid nil}]))
|
||||
|
||||
(deftest diff-test
|
||||
(are [text1 text2 diffs]
|
||||
@@ -127,11 +212,14 @@
|
||||
\t\t\t- nice
|
||||
\t\t\t- bingo
|
||||
\t\t\t- world"
|
||||
[[[-1 {:body "## hello"
|
||||
:level 2
|
||||
;; Empty op, because no insertion op before the first base block required
|
||||
;; See https://github.com/logseq/diff-merge#usage
|
||||
[[]
|
||||
[[-1 {:body "## hello"
|
||||
:level 1
|
||||
:uuid nil}]
|
||||
[1 {:body "## Halooooo"
|
||||
:level 2
|
||||
:level 1
|
||||
:uuid nil}]]
|
||||
[[0 {:body "world"
|
||||
:level 2
|
||||
@@ -148,7 +236,7 @@
|
||||
[[0 {:body "world"
|
||||
:level 4
|
||||
:uuid nil}]]]
|
||||
|
||||
|
||||
"## hello
|
||||
\t- world
|
||||
\t id:: 63e25526-3612-4fb1-8cf9-abcd12354abc
|
||||
@@ -162,16 +250,19 @@
|
||||
\t\t\t- nice
|
||||
\t\t\t- bingo
|
||||
\t\t\t- world"
|
||||
[[[-1 {:body "## hello"
|
||||
:level 2
|
||||
;; Empty op, because no insertion op before the first base block required
|
||||
;; See https://github.com/logseq/diff-merge#usage
|
||||
[[]
|
||||
[[-1 {:body "## hello"
|
||||
:level 1
|
||||
:uuid nil}]
|
||||
[1 {:body "## Halooooo"
|
||||
:level 2
|
||||
:level 1
|
||||
:uuid nil}]
|
||||
[1 {:body "world"
|
||||
:level 2
|
||||
:uuid nil}]]
|
||||
[[-1 {:body "world\n id:: 63e25526-3612-4fb1-8cf9-abcd12354abc"
|
||||
[[-1 {:body "world\nid:: 63e25526-3612-4fb1-8cf9-abcd12354abc"
|
||||
:level 2
|
||||
:uuid "63e25526-3612-4fb1-8cf9-abcd12354abc"}]]
|
||||
[[0 {:body "nice"
|
||||
@@ -217,7 +308,7 @@
|
||||
|
||||
"bar"
|
||||
[{:body "ghi\nid:: 11451411-1111-1111-1111-111111111111" :uuid "11451411-1111-1111-1111-111111111111" :level 1}
|
||||
{:body "jkl\nid:: 63241234-1234-1234-1234-123412341234" :uuid "63241234-1234-1234-1234-123412341234" :level 2}])
|
||||
{:body "jkl\nid:: 63241234-1234-1234-1234-123412341234" :uuid "63241234-1234-1234-1234-123412341234" :level 2}])
|
||||
|
||||
(are [page-name text new-uuids] (= (let [old-blks (test-db->diff-blocks conn page-name)
|
||||
new-blks (text->diffblocks text)
|
||||
@@ -254,7 +345,7 @@
|
||||
[[["Properties" [["TiTlE" "Howdy" []]]] nil]]
|
||||
"#+title: Howdy"
|
||||
[{:body "#+title: Howdy", :level 1, :uuid nil}])
|
||||
|
||||
|
||||
(are [ast text diff-blocks]
|
||||
(= (fs-diff/ast->diff-blocks ast text :org {:block-pattern "-" :user-config {:property-pages/enabled? true}})
|
||||
diff-blocks)
|
||||
@@ -332,7 +423,7 @@
|
||||
foo-new-content
|
||||
"foo-persist"
|
||||
(fn [db-uuids] (conj db-uuids nil))
|
||||
|
||||
|
||||
;; Prepend a new line to bar
|
||||
(gp-mldoc/->edn new-bar-content (gp-mldoc/default-config :markdown))
|
||||
new-bar-content
|
||||
@@ -358,3 +449,25 @@
|
||||
(gp-mldoc/->edn foo-new-content (gp-mldoc/default-config :markdown))
|
||||
foo-new-content
|
||||
"foo-error-cap")))
|
||||
|
||||
(deftest test-remove-indentation-spaces
|
||||
(is (= "" (gp-mldoc/remove-indentation-spaces "" 0 false)))
|
||||
(is (= "" (gp-mldoc/remove-indentation-spaces "" 3 true)))
|
||||
|
||||
(is (= "- nice\n happy" (gp-mldoc/remove-indentation-spaces "\t\t\t- nice\n\t\t\t happy" 3 true)))
|
||||
(is (= "\t\t\t- nice\n happy" (gp-mldoc/remove-indentation-spaces "\t\t\t- nice\n\t\t\t happy" 3 false)))
|
||||
(is (= "\t\t\t- nice\n\t\t\t happy" (gp-mldoc/remove-indentation-spaces "\t\t\t- nice\n\t\t\t happy" 0 true))))
|
||||
|
||||
(deftest test-remove-level-spaces
|
||||
;; Test when `format` is nil
|
||||
(is (= "nice\n\t\t\t good" (text/remove-level-spaces "\t\t\t- nice\n\t\t\t good" :markdown "-")))
|
||||
(is (= "- nice" (text/remove-level-spaces "\t\t\t- nice" :markdown "")))
|
||||
(is (= "nice" (text/remove-level-spaces "\t\t\t- nice" :markdown "-"))))
|
||||
|
||||
(deftest test-three-way-merge
|
||||
(is (= (fs-diff/three-way-merge
|
||||
"- a\n id:: 648ab5e6-5e03-4c61-95d4-dd904a0a007f\n- b"
|
||||
"- a\n id:: 648ab5e6-5e03-4c61-95d4-dd904a0a007f\n aaa:: 111\n- b"
|
||||
"- c"
|
||||
:markdown)
|
||||
"- a\n id:: 648ab5e6-5e03-4c61-95d4-dd904a0a007f\n aaa:: 111\n- c")))
|
||||
|
||||
@@ -27,17 +27,19 @@
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
|
||||
#{}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 22 "3" 4 6 nil nil nil)}
|
||||
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 22 "3" 4 4 nil nil nil) (sync/->FileMetadata 1 22 "3" 44 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 22 "3" 4 4 nil nil nil)
|
||||
(sync/->FileMetadata 1 22 "3" 44 5 nil nil nil)}
|
||||
|
||||
#{}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 5 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 4 nil nil nil) (sync/->FileMetadata 1 2 "3" 4 6 nil nil nil)}
|
||||
#{(sync/->FileMetadata 1 2 "3" 4 4 nil nil nil)
|
||||
(sync/->FileMetadata 1 2 "3" 4 6 nil nil nil)}
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
@@ -400,47 +400,47 @@
|
||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
||||
|
||||
"@logseq/rsapi-darwin-arm64@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-arm64/-/rsapi-darwin-arm64-0.0.70.tgz#9f0214d0d61081d287dee2d75c33b272270c82f1"
|
||||
integrity sha512-N3wNhAwyoZuXu8O83y69vTzDxolciPpeoMJAmkokXq0+3L8+74lRm9+d/Rn2xzRoXwdPyogvRvG75HpG+vC2Ww==
|
||||
"@logseq/rsapi-darwin-arm64@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-arm64/-/rsapi-darwin-arm64-0.0.73.tgz#4753f05e2dc70f37a31dfb7440e9b2601acb7696"
|
||||
integrity sha512-TvFwh3/fnwRAZwourk1UUgptcNN7FqmOcL07F373M2rWhTIOba/u1eBwjW9wNMRcXtgLWacaXzBmC4ENvAKDpg==
|
||||
|
||||
"@logseq/rsapi-darwin-x64@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-x64/-/rsapi-darwin-x64-0.0.70.tgz#270940af25f168a463d0e4eee68613aabe84a837"
|
||||
integrity sha512-ZsvZymdUDMrRM4QYKG8yOBJn8CDpZhWu6CrwHX8FfXyCJfglZT9V4KPt97ortAyyTlnKpr8/flYTd9mOs+eUcg==
|
||||
"@logseq/rsapi-darwin-x64@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-x64/-/rsapi-darwin-x64-0.0.73.tgz#44180532e3ccf62a7fe597e385ee85a700b14bea"
|
||||
integrity sha512-tnOSgQ1qgerwDTnR5v1TMbHnVXVabzZf9i3bxon0y9ItwlIY7j7OW80+1AfNoHu9Fbo/e+3bFg5Muq3/Gm7Yrw==
|
||||
|
||||
"@logseq/rsapi-freebsd-x64@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-freebsd-x64/-/rsapi-freebsd-x64-0.0.70.tgz#8785dc753068074d16e7de17115d5c004a1ded4c"
|
||||
integrity sha512-jkUXBlm+Z4VTJUtqenwTV4THFww2lNnHkfXDyFS4Zghnby2Cg/jDe/eUwVvgUIY9fPDTivkwWwx37SLtgMCIsA==
|
||||
"@logseq/rsapi-freebsd-x64@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-freebsd-x64/-/rsapi-freebsd-x64-0.0.73.tgz#3ff4f720eb05d9ffd32a5391ddf33034a05f42e0"
|
||||
integrity sha512-YAjggQHzVCZYhXDybR/37Y5czTQbYDE5A5piwsg09Xt4/m5REFSVKqdeQpnOb2LX7wBGbnPxMhsg6QUV/y/eHA==
|
||||
|
||||
"@logseq/rsapi-linux-arm64-gnu@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-arm64-gnu/-/rsapi-linux-arm64-gnu-0.0.70.tgz#5a25ef4cdd758a04a625a7d265674681314d5c7c"
|
||||
integrity sha512-OXDwjfpT/oKrLEucnVxeIu1hIdAO4B371uA/33qCH8pNVCPNZffSITGfgPKY0dXJ3zT2i5s5+Z06AJMcsjiReg==
|
||||
"@logseq/rsapi-linux-arm64-gnu@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-arm64-gnu/-/rsapi-linux-arm64-gnu-0.0.73.tgz#1f423e296ca69e6e92a06afbb25f9f2f0e452b69"
|
||||
integrity sha512-t5W9SBraKYU2iGPzBgUhSzVPtH98RwuE1tLW2MpAJh0QNb2DI4/axbc9nrC1IVc1dqAmTkuL8GGGN80VONisUA==
|
||||
|
||||
"@logseq/rsapi-linux-x64-gnu@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-x64-gnu/-/rsapi-linux-x64-gnu-0.0.70.tgz#e453448bfadfd195df02f0c3b148b815010b61ea"
|
||||
integrity sha512-rvCjREn2uHLESR3+UAgoKfkST7ysge9L4m4pol5eABczPB4BNiEGy0xpB3ML3/M/8t9Iaw9LcLdq2en80FM3fA==
|
||||
"@logseq/rsapi-linux-x64-gnu@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-x64-gnu/-/rsapi-linux-x64-gnu-0.0.73.tgz#d33e621d7ea24089a9b863809e6dfbe4362443d5"
|
||||
integrity sha512-WidDZv4mnG6Ys90KYLzJl0fwMWj/kEItGHjfR3FoDAVKkvu3mezNDWCsd+I2kMrh1dlIpPqcP+BJ9evI4Gbwkw==
|
||||
|
||||
"@logseq/rsapi-win32-x64-msvc@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-win32-x64-msvc/-/rsapi-win32-x64-msvc-0.0.70.tgz#c855a9e0aed512ae8c465c55ec698855f888deed"
|
||||
integrity sha512-wRNBJblaZjX8G1cl7Nvn8b8uMuItqaHkrblyfGzsoEOzALyJIZB95zrJvC2tk8Kc47sriK/KzH16+bW/OBxbOA==
|
||||
"@logseq/rsapi-win32-x64-msvc@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi-win32-x64-msvc/-/rsapi-win32-x64-msvc-0.0.73.tgz#7734187c1b56da6373c947680a65b21551134bec"
|
||||
integrity sha512-YQTE4ZMtlrbuDVfD/6DWtnsiC2uUZpNDqcy6LIN6Ui98yeZ88ktOsEV/lQJF4+4cAflrzW7Xr8ejl2SWSdX6EQ==
|
||||
|
||||
"@logseq/rsapi@0.0.70":
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi/-/rsapi-0.0.70.tgz#4eca5606318b2ab8c92611dc301cbb722281878c"
|
||||
integrity sha512-w6eSfCLrewZ/8qE+b/GF8YIdvm+4vDurz/haHAR2qmscsXsZr7XoYOcT2eC2FcHyYYforzAppBvxpK9t7FO2ZA==
|
||||
"@logseq/rsapi@0.0.73":
|
||||
version "0.0.73"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/rsapi/-/rsapi-0.0.73.tgz#b02fc017bb12df3afa0fce60ba13e1b01bbf4342"
|
||||
integrity sha512-ppQCCzc1pAgqlxkYg2CprcU5RTz01fWqba9lhEVg2FpeF9l8IVVCXhbBIUnWPEFTqkoySiwXpMU8kbkTgvEPIg==
|
||||
optionalDependencies:
|
||||
"@logseq/rsapi-darwin-arm64" "0.0.70"
|
||||
"@logseq/rsapi-darwin-x64" "0.0.70"
|
||||
"@logseq/rsapi-freebsd-x64" "0.0.70"
|
||||
"@logseq/rsapi-linux-arm64-gnu" "0.0.70"
|
||||
"@logseq/rsapi-linux-x64-gnu" "0.0.70"
|
||||
"@logseq/rsapi-win32-x64-msvc" "0.0.70"
|
||||
"@logseq/rsapi-darwin-arm64" "0.0.73"
|
||||
"@logseq/rsapi-darwin-x64" "0.0.73"
|
||||
"@logseq/rsapi-freebsd-x64" "0.0.73"
|
||||
"@logseq/rsapi-linux-arm64-gnu" "0.0.73"
|
||||
"@logseq/rsapi-linux-x64-gnu" "0.0.73"
|
||||
"@logseq/rsapi-win32-x64-msvc" "0.0.73"
|
||||
|
||||
"@malept/cross-spawn-promise@^1.0.0", "@malept/cross-spawn-promise@^1.1.0":
|
||||
version "1.1.1"
|
||||
|
||||
24
yarn.lock
24
yarn.lock
@@ -487,15 +487,15 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@logseq/capacitor-file-sync@0.0.24":
|
||||
version "0.0.24"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/capacitor-file-sync/-/capacitor-file-sync-0.0.24.tgz#be7b69492b92df9c4e899502c632deebe179746b"
|
||||
integrity sha512-CBIXEPYVp1ddjyYN+Z2dTQ9gwF0KYwZwlvwnl+zmR0Q3ODXxg75BExh5vAU8khXkSNZjZXgZT/J61/kn9xN11w==
|
||||
"@logseq/capacitor-file-sync@0.0.30":
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/capacitor-file-sync/-/capacitor-file-sync-0.0.30.tgz#9441ad5689f6139acbc7444530b11e0648a586b3"
|
||||
integrity sha512-rrk4CdSyS8y1M3WgqkFtdtoP3YWRhuaaQOPtO18roOTztbwdu/w7/+uEt7RDVcV92rwCjhCeg4yaTxbmgWwFYw==
|
||||
|
||||
"@logseq/diff-merge@^0.0.2":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/diff-merge/-/diff-merge-0.0.2.tgz#0bf29a550921311f63754db65ea83b82c54b16c8"
|
||||
integrity sha512-c6V7rTg/pEoqhByJxRv7yyZ7q3LylKmkiKxoU99R7Fr7Cf5j9dn7GUQW/RlOs68IqYv76BkTHR6EhrLf6cKtZg==
|
||||
"@logseq/diff-merge@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/diff-merge/-/diff-merge-0.1.0.tgz#fca282e3ff7c256a1f447d0463d78fb23ebee1d9"
|
||||
integrity sha512-VNAJI7Mo/xHEw2LN6rpoWf/BbVfsC1wRpyyLbvm1jQbRxcwRgqYwWkSIVS0t1wswquDS64ZolJkCIFXeNXQbTA==
|
||||
|
||||
"@logseq/react-tweet-embed@1.3.1-1":
|
||||
version "1.3.1-1"
|
||||
@@ -4667,10 +4667,10 @@ mkdirp@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
mldoc@^1.5.5:
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.5.tgz#2f18439740cbcf474bf7d59266d4d98bbbc89412"
|
||||
integrity sha512-hBVLgzlh/648l0b0Y2rkQ9KK65EBf4T+IINNFGERpn2MccXwIAiXTCZXuMIe4xfhWQ2C8KHb+k4Wb2Nw5O1TKQ==
|
||||
mldoc@1.5.7:
|
||||
version "1.5.7"
|
||||
resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.7.tgz#9b316f633a3032ce217a339621b98e70bb229235"
|
||||
integrity sha512-Ph9y8t195UWtkn0hK/VVNvi/wjZUJCLXAaUGVE80KmaE9Rwp9wWBMSEg4wPgjCac3edMjaONucD52fHOFTU9UA==
|
||||
dependencies:
|
||||
yargs "^12.0.2"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user