mirror of https://github.com/logseq/logseq
Merge branch 'feat/db' into perf/lazy-load-data
commit
c1a15c0708
|
@ -14,6 +14,7 @@
|
|||
:preferred-workflow :now
|
||||
|
||||
;; Exclude directories/files.
|
||||
;; This is _only_ for file graphs.
|
||||
;; Example usage:
|
||||
;; :hidden ["/archived" "/test.md" "../assets/archived"]
|
||||
:hidden []
|
||||
|
@ -144,6 +145,7 @@
|
|||
;; :whiteboards-directory "whiteboards"
|
||||
|
||||
;; Enabling this option converts
|
||||
;; This is _only_ for file graphs.
|
||||
;; [[Grant Ideas]] to [[file:./grant_ideas.org][Grant Ideas]] for org-mode.
|
||||
;; For more information, visit https://github.com/logseq/logseq/issues/672
|
||||
;; :org-mode/insert-file-link? false
|
||||
|
@ -289,6 +291,7 @@
|
|||
;; :journal? false} ; Default value: false
|
||||
|
||||
;; Favorites to list on the left sidebar
|
||||
;; This is _only_ for file graphs.
|
||||
:favorites []
|
||||
|
||||
;; Set flashcards interval.
|
||||
|
@ -307,19 +310,23 @@
|
|||
;; :block-hidden-properties #{:public :icon}
|
||||
|
||||
;; Create a page for all properties.
|
||||
;; This is _only_ for file graphs.
|
||||
;; Default value: true
|
||||
:property-pages/enabled? true
|
||||
|
||||
;; Properties to exclude from having property pages
|
||||
;; This is _only_ for file graphs.
|
||||
;; Example usage:
|
||||
;; :property-pages/excludelist #{:duration :author}
|
||||
|
||||
;; By default, property value separated by commas will not be treated as
|
||||
;; page references. You can add properties to enable it.
|
||||
;; This is _only_ for file graphs.
|
||||
;; Example usage:
|
||||
;; :property/separated-by-commas #{:alias :tags}
|
||||
|
||||
;; Properties that are ignored when parsing property values for references
|
||||
;; This is _only_ for file graphs.
|
||||
;; Example usage:
|
||||
;; :ignored-page-references-keywords #{:author :website}
|
||||
|
||||
|
@ -398,10 +405,10 @@
|
|||
;; :list? false} ;; Default value: false
|
||||
|
||||
;; Configure the escaping method for special characters in page titles.
|
||||
;; This is _only_ for file graphs.
|
||||
;; Warning:
|
||||
;; This is a dangerous operation. To modify the setting,
|
||||
;; access the 'Filename format' setting and follow the instructions.
|
||||
;; Otherwise, You may need to manually rename all affected files and
|
||||
;; you'll need to manually rename all affected files and
|
||||
;; re-index them on all clients after synchronization.
|
||||
;; Incorrect handling may result in messy page titles.
|
||||
;; Available options:
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
(log/error :decode-uri-component-failed uri)
|
||||
uri)))
|
||||
|
||||
(defn safe-url-decode
|
||||
[string]
|
||||
(if (string/includes? string "%")
|
||||
(some-> string str safe-decode-uri-component)
|
||||
string))
|
||||
|
||||
(defn path-normalize
|
||||
"Normalize file path (for reading paths from FS, not required by writing)
|
||||
Keep capitalization senstivity"
|
||||
|
@ -129,12 +123,7 @@
|
|||
result))
|
||||
(map string/trim))))
|
||||
|
||||
(defn decode-namespace-underlines
|
||||
"Decode namespace underlines to slashed;
|
||||
If continuous underlines, only decode at start;
|
||||
Having empty namespace is invalid."
|
||||
[string]
|
||||
(string/replace string "___" "/"))
|
||||
(def url-encoded-pattern #"(?i)%[0-9a-f]{2}") ;; (?i) for case-insensitive mode
|
||||
|
||||
(defn page-name-sanity
|
||||
"Sanitize the page-name. Unify different diacritics and other visual differences.
|
||||
|
@ -146,24 +135,6 @@
|
|||
(remove-boundary-slashes)
|
||||
(path-normalize)))
|
||||
|
||||
(defn make-valid-namespaces
|
||||
"Remove those empty namespaces from title to make it a valid page name."
|
||||
[title]
|
||||
(->> (string/split title "/")
|
||||
(remove empty?)
|
||||
(string/join "/")))
|
||||
|
||||
(def url-encoded-pattern #"(?i)%[0-9a-f]{2}") ;; (?i) for case-insensitive mode
|
||||
|
||||
(defn- tri-lb-title-parsing
|
||||
"Parsing file name under the new file name format
|
||||
Avoid calling directly"
|
||||
[file-name]
|
||||
(some-> file-name
|
||||
(decode-namespace-underlines)
|
||||
(string/replace url-encoded-pattern safe-url-decode)
|
||||
(make-valid-namespaces)))
|
||||
|
||||
(defn page-name-sanity-lc
|
||||
"Sanitize the query string for a page name (mandate for :block/name)"
|
||||
[s]
|
||||
|
@ -202,22 +173,6 @@
|
|||
;; default
|
||||
(keyword format)))
|
||||
|
||||
(defn path->file-name
|
||||
;; Only for internal paths, as they are converted to POXIS already
|
||||
;; https://github.com/logseq/logseq/blob/48b8e54e0fdd8fbd2c5d25b7f1912efef8814714/deps/graph-parser/src/logseq/graph_parser/extract.cljc#L32
|
||||
;; Should be converted to POXIS first for external paths
|
||||
[path]
|
||||
(if (string/includes? path "/")
|
||||
(last (split-last "/" path))
|
||||
path))
|
||||
|
||||
(defn path->file-body
|
||||
[path]
|
||||
(when-let [file-name (path->file-name path)]
|
||||
(if (string/includes? file-name ".")
|
||||
(first (split-last "." file-name))
|
||||
file-name)))
|
||||
|
||||
(defn path->file-ext
|
||||
[path-or-file-name]
|
||||
(second (re-find #"(?:\.)(\w+)[^.]*$" path-or-file-name)))
|
||||
|
@ -245,27 +200,6 @@
|
|||
(catch :default _
|
||||
false)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Keep for backward compatibility ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Rule of dir-ver 0
|
||||
;; Source: https://github.com/logseq/logseq/blob/e7110eea6790eda5861fdedb6b02c2a78b504cd9/deps/graph-parser/src/logseq/graph_parser/extract.cljc#L35
|
||||
(defn legacy-title-parsing
|
||||
[file-name-body]
|
||||
(let [title (string/replace file-name-body "." "/")]
|
||||
(or (safe-decode-uri-component title) title)))
|
||||
|
||||
;; Register sanitization / parsing fns in:
|
||||
;; logseq.common.util (parsing only)
|
||||
;; frontend.util.fs (sanitization only)
|
||||
(defn title-parsing
|
||||
"Convert file name in the given file name format to page title"
|
||||
[file-name-body filename-format]
|
||||
(case filename-format
|
||||
:triple-lowbar (tri-lb-title-parsing file-name-body)
|
||||
(legacy-title-parsing file-name-body)))
|
||||
|
||||
(defn safe-read-string
|
||||
([content]
|
||||
(safe-read-string {} content))
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
"C:\\Users\\foo\\Documents\\audio.mp3" "mp3"
|
||||
"/root/Documents/audio" nil
|
||||
"/root/Documents/audio." nil
|
||||
"special/characters/aäääöüß.7z" "7z"))
|
||||
"special/characters/aäääöüß.7z" "7z"
|
||||
"asldk lakls .lsad" "lsad"
|
||||
"中文asldk lakls .lsad" "lsad"))
|
||||
|
||||
(deftest url?
|
||||
(are [x y]
|
||||
|
|
|
@ -47,16 +47,6 @@
|
|||
(assoc :block/type #{"hidden"}
|
||||
:block/format :markdown))))
|
||||
|
||||
(defn new-property-tx
|
||||
"Provide attributes for a new built-in property given name, schema and uuid.
|
||||
TODO: Merge this with sqlite-util/build-new-property once common-util/page-name-sanity-lc
|
||||
is available to deps/db"
|
||||
[prop-name prop-schema prop-uuid]
|
||||
{:block/uuid prop-uuid
|
||||
:block/schema (merge {:type :default} prop-schema)
|
||||
:block/original-name (name prop-name)
|
||||
:block/name (common-util/page-name-sanity-lc (name prop-name))})
|
||||
|
||||
(defn build-closed-values
|
||||
"Builds all the tx needed for property with closed values including
|
||||
the hidden page and closed value blocks as needed"
|
||||
|
@ -76,8 +66,7 @@
|
|||
(:closed-values property)))
|
||||
property-schema (assoc (:block/schema property)
|
||||
:values (mapv :block/uuid closed-value-blocks-tx))
|
||||
property-tx (merge (sqlite-util/build-new-property
|
||||
(new-property-tx prop-name property-schema (:block/uuid property)))
|
||||
property-tx (merge (sqlite-util/build-new-property prop-name property-schema (:block/uuid property))
|
||||
property-attributes)]
|
||||
(into [property-tx page-tx]
|
||||
(when-not closed-value-page-uuids? closed-value-blocks-tx))))
|
||||
|
|
|
@ -22,10 +22,9 @@
|
|||
{:block/schema schema :block/uuid (d/squuid) :closed-values closed-values}
|
||||
{:icon-id (get default-property-uuids :icon)})
|
||||
[(sqlite-util/build-new-property
|
||||
{:block/schema schema
|
||||
:block/original-name (or original-name k-name)
|
||||
:block/name (common-util/page-name-sanity-lc k-name)
|
||||
:block/uuid (get default-property-uuids k-keyword (d/squuid))})])))
|
||||
(or original-name k-name)
|
||||
schema
|
||||
(get default-property-uuids k-keyword (d/squuid)))])))
|
||||
db-property/built-in-properties)))
|
||||
|
||||
(defn build-db-initial-data
|
||||
|
|
|
@ -35,12 +35,15 @@
|
|||
|
||||
(defn build-new-property
|
||||
"Build a standard new property so that it is is consistent across contexts"
|
||||
[block]
|
||||
[prop-name prop-schema prop-uuid]
|
||||
(block-with-timestamps
|
||||
(merge {:block/type "property"
|
||||
{:block/type "property"
|
||||
:block/journal? false
|
||||
:block/format :markdown}
|
||||
block)))
|
||||
:block/format :markdown
|
||||
:block/uuid prop-uuid
|
||||
:block/schema (merge {:type :default} prop-schema)
|
||||
:block/original-name (name prop-name)
|
||||
:block/name (common-util/page-name-sanity-lc (name prop-name))}))
|
||||
|
||||
|
||||
(defn build-new-class
|
||||
|
|
|
@ -27,6 +27,66 @@
|
|||
(common-util/safe-decode-uri-component (string/replace result "." "/"))
|
||||
result))))
|
||||
|
||||
(defn- path->file-name
|
||||
;; Only for internal paths, as they are converted to POXIS already
|
||||
;; https://github.com/logseq/logseq/blob/48b8e54e0fdd8fbd2c5d25b7f1912efef8814714/deps/graph-parser/src/logseq/graph_parser/extract.cljc#L32
|
||||
;; Should be converted to POXIS first for external paths
|
||||
[path]
|
||||
(if (string/includes? path "/")
|
||||
(last (common-util/split-last "/" path))
|
||||
path))
|
||||
|
||||
(defn- path->file-body
|
||||
[path]
|
||||
(when-let [file-name (path->file-name path)]
|
||||
(if (string/includes? file-name ".")
|
||||
(first (common-util/split-last "." file-name))
|
||||
file-name)))
|
||||
|
||||
(defn- safe-url-decode
|
||||
[string]
|
||||
(if (string/includes? string "%")
|
||||
(some-> string str common-util/safe-decode-uri-component)
|
||||
string))
|
||||
|
||||
(defn- decode-namespace-underlines
|
||||
"Decode namespace underlines to slashed;
|
||||
If continuous underlines, only decode at start;
|
||||
Having empty namespace is invalid."
|
||||
[string]
|
||||
(string/replace string "___" "/"))
|
||||
|
||||
(defn- make-valid-namespaces
|
||||
"Remove those empty namespaces from title to make it a valid page name."
|
||||
[title]
|
||||
(->> (string/split title "/")
|
||||
(remove empty?)
|
||||
(string/join "/")))
|
||||
|
||||
(defn- tri-lb-title-parsing
|
||||
"Parsing file name under the new file name format
|
||||
Avoid calling directly"
|
||||
[file-name]
|
||||
(some-> file-name
|
||||
(decode-namespace-underlines)
|
||||
(string/replace common-util/url-encoded-pattern safe-url-decode)
|
||||
(make-valid-namespaces)))
|
||||
|
||||
;; Keep for backward compatibility
|
||||
;; Rule of dir-ver 0
|
||||
;; Source: https://github.com/logseq/logseq/blob/e7110eea6790eda5861fdedb6b02c2a78b504cd9/deps/graph-parser/src/logseq/graph_parser/extract.cljc#L35
|
||||
(defn- legacy-title-parsing
|
||||
[file-name-body]
|
||||
(let [title (string/replace file-name-body "." "/")]
|
||||
(or (common-util/safe-decode-uri-component title) title)))
|
||||
|
||||
(defn title-parsing
|
||||
"Convert file name in the given file name format to page title"
|
||||
[file-name-body filename-format]
|
||||
(case filename-format
|
||||
:triple-lowbar (tri-lb-title-parsing file-name-body)
|
||||
(legacy-title-parsing file-name-body)))
|
||||
|
||||
(defn- get-page-name
|
||||
"Get page name with overridden order of
|
||||
`title::` property
|
||||
|
@ -54,9 +114,9 @@
|
|||
(and first-block
|
||||
(string? title)
|
||||
title))
|
||||
file-name (when-let [result (common-util/path->file-body file)]
|
||||
file-name (when-let [result (path->file-body file)]
|
||||
(if (common-config/mldoc-support? (common-util/get-file-ext file))
|
||||
(common-util/title-parsing result filename-format)
|
||||
(title-parsing result filename-format)
|
||||
result))]
|
||||
(or property-name
|
||||
file-name
|
||||
|
|
|
@ -3,6 +3,44 @@
|
|||
[logseq.graph-parser.extract :as extract]
|
||||
[clojure.pprint :as pprint]))
|
||||
|
||||
;; This is a copy of frontend.util.fs/multiplatform-reserved-chars for reserved chars testing
|
||||
(def multiplatform-reserved-chars ":\\*\\?\"<>|\\#\\\\")
|
||||
|
||||
;; Stuffs should be parsable (don't crash) when users dump some random files
|
||||
(deftest page-name-parsing-tests
|
||||
(is (string? (#'extract/tri-lb-title-parsing "___-_-_-_---___----")))
|
||||
(is (string? (#'extract/tri-lb-title-parsing "_____///____---___----")))
|
||||
(is (string? (#'extract/tri-lb-title-parsing "/_/////---/_----")))
|
||||
(is (string? (#'extract/tri-lb-title-parsing "/\\#*%lasdf\\//__--dsll_____----....-._0x2B")))
|
||||
(is (string? (#'extract/tri-lb-title-parsing "/\\#*%l;;&&;&\\//__--dsll_____----....-._0x2B")))
|
||||
(is (string? (#'extract/tri-lb-title-parsing multiplatform-reserved-chars)))
|
||||
(is (string? (#'extract/tri-lb-title-parsing "dsa&;l dsalfjk jkl"))))
|
||||
|
||||
(deftest uri-decoding-tests
|
||||
(is (= (#'extract/safe-url-decode "%*-sd%%%saf%=lks") "%*-sd%%%saf%=lks")) ;; Contains %, but invalid
|
||||
(is (= (#'extract/safe-url-decode "%2FDownloads%2FCNN%3AIs%5CAll%3AYou%20Need.pdf") "/Downloads/CNN:Is\\All:You Need.pdf"))
|
||||
(is (= (#'extract/safe-url-decode "asldkflksdaf啦放假啦睡觉啦啊啥的都撒娇浪费;dla") "asldkflksdaf啦放假啦睡觉啦啊啥的都撒娇浪费;dla")))
|
||||
|
||||
(deftest page-name-sanitization-backward-tests
|
||||
(is (= "abc.def.ghi.jkl" (#'extract/tri-lb-title-parsing "abc.def.ghi.jkl")))
|
||||
(is (= "abc/def/ghi/jkl" (#'extract/tri-lb-title-parsing "abc%2Fdef%2Fghi%2Fjkl")))
|
||||
(is (= "abc%/def/ghi/jkl" (#'extract/tri-lb-title-parsing "abc%25%2Fdef%2Fghi%2Fjkl")))
|
||||
(is (= "abc%2——ef/ghi/jkl" (#'extract/tri-lb-title-parsing "abc%2——ef%2Fghi%2Fjkl")))
|
||||
(is (= "abc&2Fghi/jkl" (#'extract/tri-lb-title-parsing "abc&2Fghi%2Fjkl")))
|
||||
(is (= "abc<2Fghi/jkl" (#'extract/tri-lb-title-parsing "abc<2Fghi%2Fjkl")))
|
||||
(is (= "abc%2Fghi/jkl" (#'extract/tri-lb-title-parsing "abc%2Fghi%2Fjkl")))
|
||||
(is (= "abc;&;2Fghi/jkl" (#'extract/tri-lb-title-parsing "abc;&;2Fghi%2Fjkl")))
|
||||
;; happens when importing some compatible files on *nix / macOS
|
||||
(is (= multiplatform-reserved-chars (#'extract/tri-lb-title-parsing multiplatform-reserved-chars))))
|
||||
|
||||
(deftest path-utils-tests
|
||||
(is (= "asldk lakls " (#'extract/path->file-body "/data/app/asldk lakls .lsad")))
|
||||
(is (= "asldk lakls " (#'extract/path->file-body "asldk lakls .lsad")))
|
||||
(is (= "asldk lakls" (#'extract/path->file-body "asldk lakls")))
|
||||
(is (= "asldk lakls" (#'extract/path->file-body "/data/app/asldk lakls")))
|
||||
(is (= "asldk lakls" (#'extract/path->file-body "file://data/app/asldk lakls.as")))
|
||||
(is (= "中文asldk lakls" (#'extract/path->file-body "file://中文data/app/中文asldk lakls.as"))))
|
||||
|
||||
(defn- extract
|
||||
[text]
|
||||
(let [{:keys [blocks]} (extract/extract "a.md" text {:block-pattern "-"})
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
(ns logseq.graph-parser.util.file-name-test
|
||||
(:require [logseq.common.util :as common-util]
|
||||
[cljs.test :refer [is deftest]]))
|
||||
|
||||
;; This is a copy of frontend.util.fs/multiplatform-reserved-chars for reserved chars testing
|
||||
(def multiplatform-reserved-chars ":\\*\\?\"<>|\\#\\\\")
|
||||
|
||||
;; Stuffs should be parsable (don't crash) when users dump some random files
|
||||
(deftest page-name-parsing-tests
|
||||
(is (string? (#'common-util/tri-lb-title-parsing "___-_-_-_---___----")))
|
||||
(is (string? (#'common-util/tri-lb-title-parsing "_____///____---___----")))
|
||||
(is (string? (#'common-util/tri-lb-title-parsing "/_/////---/_----")))
|
||||
(is (string? (#'common-util/tri-lb-title-parsing "/\\#*%lasdf\\//__--dsll_____----....-._0x2B")))
|
||||
(is (string? (#'common-util/tri-lb-title-parsing "/\\#*%l;;&&;&\\//__--dsll_____----....-._0x2B")))
|
||||
(is (string? (#'common-util/tri-lb-title-parsing multiplatform-reserved-chars)))
|
||||
(is (string? (#'common-util/tri-lb-title-parsing "dsa&;l dsalfjk jkl"))))
|
||||
|
||||
(deftest uri-decoding-tests
|
||||
(is (= (common-util/safe-url-decode "%*-sd%%%saf%=lks") "%*-sd%%%saf%=lks")) ;; Contains %, but invalid
|
||||
(is (= (common-util/safe-url-decode "%2FDownloads%2FCNN%3AIs%5CAll%3AYou%20Need.pdf") "/Downloads/CNN:Is\\All:You Need.pdf"))
|
||||
(is (= (common-util/safe-url-decode "asldkflksdaf啦放假啦睡觉啦啊啥的都撒娇浪费;dla") "asldkflksdaf啦放假啦睡觉啦啊啥的都撒娇浪费;dla")))
|
||||
|
||||
(deftest page-name-sanitization-backward-tests
|
||||
(is (= "abc.def.ghi.jkl" (#'common-util/tri-lb-title-parsing "abc.def.ghi.jkl")))
|
||||
(is (= "abc/def/ghi/jkl" (#'common-util/tri-lb-title-parsing "abc%2Fdef%2Fghi%2Fjkl")))
|
||||
(is (= "abc%/def/ghi/jkl" (#'common-util/tri-lb-title-parsing "abc%25%2Fdef%2Fghi%2Fjkl")))
|
||||
(is (= "abc%2——ef/ghi/jkl" (#'common-util/tri-lb-title-parsing "abc%2——ef%2Fghi%2Fjkl")))
|
||||
(is (= "abc&2Fghi/jkl" (#'common-util/tri-lb-title-parsing "abc&2Fghi%2Fjkl")))
|
||||
(is (= "abc<2Fghi/jkl" (#'common-util/tri-lb-title-parsing "abc<2Fghi%2Fjkl")))
|
||||
(is (= "abc%2Fghi/jkl" (#'common-util/tri-lb-title-parsing "abc%2Fghi%2Fjkl")))
|
||||
(is (= "abc;&;2Fghi/jkl" (#'common-util/tri-lb-title-parsing "abc;&;2Fghi%2Fjkl")))
|
||||
;; happens when importing some compatible files on *nix / macOS
|
||||
(is (= multiplatform-reserved-chars (#'common-util/tri-lb-title-parsing multiplatform-reserved-chars))))
|
||||
|
||||
(deftest path-utils-tests
|
||||
(is (= "asldk lakls " (common-util/path->file-body "/data/app/asldk lakls .lsad")))
|
||||
(is (= "asldk lakls " (common-util/path->file-body "asldk lakls .lsad")))
|
||||
(is (= "asldk lakls" (common-util/path->file-body "asldk lakls")))
|
||||
(is (= "asldk lakls" (common-util/path->file-body "/data/app/asldk lakls")))
|
||||
(is (= "asldk lakls" (common-util/path->file-body "file://data/app/asldk lakls.as")))
|
||||
(is (= "中文asldk lakls" (common-util/path->file-body "file://中文data/app/中文asldk lakls.as")))
|
||||
(is (= "lsad" (common-util/path->file-ext "asldk lakls .lsad")))
|
||||
(is (= "lsad" (common-util/path->file-ext "中文asldk lakls .lsad"))))
|
|
@ -100,7 +100,7 @@
|
|||
"@excalidraw/excalidraw": "0.16.1",
|
||||
"@highlightjs/cdn-assets": "10.4.1",
|
||||
"@isomorphic-git/lightning-fs": "^4.6.0",
|
||||
"@logseq/capacitor-file-sync": "5.0.1",
|
||||
"@logseq/capacitor-file-sync": "5.0.2",
|
||||
"@logseq/diff-merge": "0.2.2",
|
||||
"@logseq/react-tweet-embed": "1.3.1-1",
|
||||
"@logseq/sqlite-wasm": "=0.1.0",
|
||||
|
|
|
@ -176,13 +176,13 @@
|
|||
:property-attributes
|
||||
{:db/id (or (property-db-ids (name prop-name))
|
||||
(throw (ex-info "No :db/id for property" {:property prop-name})))}})
|
||||
[(sqlite-util/build-new-property
|
||||
(merge (db-property-util/new-property-tx prop-name (get-in properties [prop-name :block/schema]) uuid)
|
||||
[(merge
|
||||
(sqlite-util/build-new-property prop-name (get-in properties [prop-name :block/schema]) uuid)
|
||||
{:db/id (or (property-db-ids (name prop-name))
|
||||
(throw (ex-info "No :db/id for property" {:property prop-name})))}
|
||||
(when-let [props (not-empty (get-in properties [prop-name :properties]))]
|
||||
{:block/properties (->block-properties-tx props uuid-maps)
|
||||
:block/refs (build-property-refs props property-db-ids)})))]))
|
||||
:block/refs (build-property-refs props property-db-ids)}))]))
|
||||
property-uuids))
|
||||
pages-and-blocks-tx
|
||||
(vec
|
||||
|
|
|
@ -132,7 +132,8 @@
|
|||
|
||||
(rum/defc favorites < rum/reactive
|
||||
[t]
|
||||
(let [favorite-entities (page-handler/get-favorites)]
|
||||
(let [_favorites-updated? (state/sub :favorites/updated?)
|
||||
favorite-entities (page-handler/get-favorites)]
|
||||
(nav-content-item
|
||||
[:a.flex.items-center.text-sm.font-medium.rounded-md.wrap-th
|
||||
(ui/icon "star" {:size 16})
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[clojure.core.async :as async]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.string :as string]
|
||||
[datascript.core :as d]
|
||||
[frontend.components.onboarding.setups :as setups]
|
||||
[frontend.components.repo :as repo]
|
||||
[frontend.components.svg :as svg]
|
||||
|
@ -11,12 +12,14 @@
|
|||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.db :as db]
|
||||
[frontend.fs :as fs]
|
||||
[frontend.persist-db.browser :as db-browser]
|
||||
[frontend.handler.db-based.editor :as db-editor-handler]
|
||||
[frontend.handler.import :as import-handler]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.modules.outliner.ui :as ui-outliner-tx]
|
||||
[frontend.persist-db.browser :as db-browser]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
|
@ -24,13 +27,13 @@
|
|||
[goog.functions :refer [debounce]]
|
||||
[goog.object :as gobj]
|
||||
[logseq.common.path :as path]
|
||||
[logseq.common.util :as common-util]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.graph-parser :as graph-parser]
|
||||
[logseq.outliner.core :as outliner-core]
|
||||
[medley.core :as medley]
|
||||
[promesa.core :as p]
|
||||
[borkdude.rewrite-edn :as rewrite]
|
||||
[rum.core :as rum]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.common.config-edn :as config-edn-common-handler]))
|
||||
[rum.core :as rum]))
|
||||
|
||||
;; Can't name this component as `frontend.components.import` since shadow-cljs
|
||||
;; will complain about it.
|
||||
|
@ -214,14 +217,52 @@
|
|||
(-> (when config-file
|
||||
(.text config-file))
|
||||
(p/then (fn [content]
|
||||
(let [migrated-content (-> (reduce rewrite/dissoc
|
||||
(rewrite/parse-string (str content))
|
||||
(keys config-edn-common-handler/file-only-config))
|
||||
str)]
|
||||
(let [migrated-content (repo-handler/migrate-db-config content)]
|
||||
(p/do!
|
||||
(db-editor-handler/save-file! "logseq/config.edn" migrated-content))
|
||||
(edn/read-string migrated-content))))))
|
||||
|
||||
(defn- build-hidden-favorites-page-blocks
|
||||
[page-block-uuid-coll]
|
||||
(map
|
||||
(fn [uuid]
|
||||
{:block/link [:block/uuid uuid]
|
||||
:block/content ""
|
||||
:block/format :markdown})
|
||||
page-block-uuid-coll))
|
||||
|
||||
(def hidden-favorites-page-name "$$$favorites")
|
||||
(def hidden-favorites-page-tx
|
||||
{:block/uuid (d/squuid)
|
||||
:block/name hidden-favorites-page-name
|
||||
:block/original-name hidden-favorites-page-name
|
||||
:block/journal? false
|
||||
:block/type #{"hidden"}
|
||||
:block/format :markdown})
|
||||
|
||||
(defn- import-favorites-from-config-edn!
|
||||
[db-conn repo config-file]
|
||||
(let [now (inst-ms (js/Date.))]
|
||||
(p/do!
|
||||
(ldb/transact! repo [(assoc hidden-favorites-page-tx
|
||||
:block/created-at now
|
||||
:block/updated-at now)])
|
||||
(p/let [content (when config-file (.text config-file))]
|
||||
(when-let [content-edn (try (edn/read-string content)
|
||||
(catch :default _ nil))]
|
||||
(when-let [favorites (seq (:favorites content-edn))]
|
||||
(when-let [page-block-uuid-coll
|
||||
(seq
|
||||
(keep (fn [page-name]
|
||||
(some-> (d/entity @db-conn [:block/name (common-util/page-name-sanity-lc page-name)])
|
||||
:block/uuid))
|
||||
favorites))]
|
||||
(let [page-entity (d/entity @db-conn [:block/name hidden-favorites-page-name])]
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :insert-blocks}
|
||||
(outliner-core/insert-blocks! repo db-conn (build-hidden-favorites-page-blocks page-block-uuid-coll)
|
||||
page-entity {}))))))))))
|
||||
|
||||
|
||||
(rum/defc confirm-graph-name-dialog
|
||||
[initial-name on-graph-name-confirmed]
|
||||
|
@ -277,6 +318,7 @@
|
|||
(async/<! (p->c (import-config-file! config-file)))
|
||||
(async/<! (import-from-asset-files! asset-files))
|
||||
(async/<! (import-from-doc-files! db-conn repo doc-files))
|
||||
(async/<! (p->c (import-favorites-from-config-edn! db-conn repo config-file)))
|
||||
(state/set-state! :graph/importing nil)
|
||||
(finished-cb)))))]
|
||||
(state/set-modal!
|
||||
|
|
|
@ -209,3 +209,20 @@ a.control-link {
|
|||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.property-select {
|
||||
.menu-link:hover, a.menu-link.chosen {
|
||||
.iconTablerExtInProgress50,
|
||||
.iconTablerExtBacklog,
|
||||
.iconTablerExtTodo,
|
||||
.iconTablerExtDoing,
|
||||
.iconTablerExtInReview,
|
||||
.iconTablerExtDone {
|
||||
@apply text-accent-09;
|
||||
}
|
||||
|
||||
.iconTablerExtCancelled {
|
||||
@apply text-red-rx-09;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -357,7 +357,7 @@
|
|||
nil)
|
||||
(catch :default e
|
||||
(prn :debug :error)
|
||||
(js/console.error e)))))
|
||||
(js/console.error e tx-data)))))
|
||||
|
||||
(getInitialData
|
||||
[_this repo]
|
||||
|
|
|
@ -107,7 +107,9 @@ nested keys or positional errors e.g. tuples"
|
|||
:file/name-format
|
||||
"is not used in DB graphs"
|
||||
:feature/enable-block-timestamps?
|
||||
"is not used in DB graphs as it is always enabled"})
|
||||
"is not used in DB graphs as it is always enabled"
|
||||
:favorites
|
||||
"is not stored in config for DB graphs"})
|
||||
|
||||
(defn detect-deprecations
|
||||
"Detects config keys that will or have been deprecated"
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
(defn build-hidden-page-tx-data
|
||||
[page-name]
|
||||
(let [page-name* (str "$$$" page-name)]
|
||||
(assoc (block/page-name->map page-name* false false)
|
||||
(assoc (block/page-name->map page-name* true false)
|
||||
:block/type #{"hidden"}
|
||||
:block/format :markdown)))
|
||||
|
||||
|
@ -50,8 +50,7 @@
|
|||
(let [repo (state/get-current-repo)
|
||||
conn (db/get-db repo false)
|
||||
config (state/get-config repo)
|
||||
_ (worker-page/create! repo conn config title options)
|
||||
[_ page-name] (worker-page/get-title-and-pagename title)]
|
||||
[_ page-name] (worker-page/create! repo conn config title options)]
|
||||
(when redirect?
|
||||
(route-handler/redirect-to-page! page-name))
|
||||
(when-let [first-block (first (:block/_left (db/entity [:block/name page-name])))]
|
||||
|
@ -67,8 +66,8 @@
|
|||
(p/let [repo (state/get-current-repo)
|
||||
conn (db/get-db repo false)
|
||||
config (state/get-config repo)
|
||||
_ (worker-page/create! repo conn config title options)
|
||||
[_ page-name] (worker-page/get-title-and-pagename title)]
|
||||
[p page-name] (worker-page/create! repo conn config title options)
|
||||
_result p]
|
||||
(when redirect?
|
||||
(route-handler/redirect-to-page! page-name))
|
||||
(let [page (db/entity [:block/name page-name])]
|
||||
|
|
|
@ -105,12 +105,7 @@
|
|||
:block/uuid property-uuid
|
||||
:block/type "property"})]
|
||||
{:outliner-op :save-block})
|
||||
(db/transact! repo [(sqlite-util/build-new-property
|
||||
(cond-> {:block/original-name k-name
|
||||
:block/name (util/page-name-sanity-lc k-name)
|
||||
:block/uuid property-uuid}
|
||||
(seq schema)
|
||||
(assoc :block/schema schema)))]
|
||||
(db/transact! repo [(sqlite-util/build-new-property k-name schema property-uuid)]
|
||||
{:outliner-op :insert-blocks}))))
|
||||
|
||||
(defn validate-property-value
|
||||
|
|
|
@ -779,12 +779,7 @@
|
|||
"Check " [:a {:href "https://docs.logseq.com/#/page/logseq%20file%20and%20folder%20naming%20rules"
|
||||
:target "_blank"}
|
||||
"Logseq file and folder naming rules"]
|
||||
" for more details."]
|
||||
[:p
|
||||
(util/format "To solve this problem, we suggest you quit Logseq and update the filename format (on Settings > Advanced > Filename format > click EDIT button)%s to avoid more potential bugs."
|
||||
(if (and util/mac? (not (mobile-util/native-ios?)))
|
||||
""
|
||||
" in other devices"))]]]]
|
||||
" for more details."]]]]
|
||||
:warning
|
||||
false))
|
||||
|
||||
|
|
|
@ -49,21 +49,25 @@
|
|||
|
||||
(defn <unfavorite-page!
|
||||
[page-name]
|
||||
(p/do!
|
||||
(let [repo (state/get-current-repo)]
|
||||
(if (config/db-based-graph? repo)
|
||||
(let [db (conn/get-db)]
|
||||
(when-let [page-block-uuid (:block/uuid (d/entity db [:block/name (common-util/page-name-sanity-lc page-name)]))]
|
||||
(page-common-handler/<unfavorite-page!-v2 page-block-uuid)))
|
||||
(page-common-handler/unfavorite-page! page-name))))
|
||||
(page-common-handler/unfavorite-page! page-name)))
|
||||
(state/update-favorites-updated!)))
|
||||
|
||||
(defn <favorite-page!
|
||||
[page-name]
|
||||
(p/do!
|
||||
(let [repo (state/get-current-repo)]
|
||||
(if (config/db-based-graph? repo)
|
||||
(let [db (conn/get-db)]
|
||||
(when-let [page-block-uuid (:block/uuid (d/entity db [:block/name (common-util/page-name-sanity-lc page-name)]))]
|
||||
(page-common-handler/<favorite-page!-v2 page-block-uuid)))
|
||||
(page-common-handler/favorite-page! page-name))))
|
||||
(page-common-handler/favorite-page! page-name)))
|
||||
(state/update-favorites-updated!)))
|
||||
|
||||
(defn favorited?
|
||||
[page-name]
|
||||
|
@ -145,13 +149,14 @@
|
|||
favorites)
|
||||
current-blocks (ldb/sort-by-left (ldb/get-page-blocks @conn page-common-handler/favorites-page-name {})
|
||||
favorites-page-entity)]
|
||||
(prn :favorite-page-block-db-id-coll favorite-page-block-db-id-coll)
|
||||
(p/do!
|
||||
(ui-outliner-tx/transact!
|
||||
{}
|
||||
(doseq [[page-block-db-id block] (zipmap favorite-page-block-db-id-coll current-blocks)]
|
||||
(when (not= page-block-db-id (:db/id (:block/link block)))
|
||||
(outliner-core/save-block! repo conn (state/get-date-formatter)
|
||||
(assoc block :block/link page-block-db-id)))))))))
|
||||
(assoc block :block/link page-block-db-id)))))
|
||||
(state/update-favorites-updated!))))))
|
||||
|
||||
(defn has-more-journals?
|
||||
[]
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[frontend.fs.nfs :as nfs]
|
||||
[frontend.handler.file :as file-handler]
|
||||
[frontend.handler.repo-config :as repo-config-handler]
|
||||
[frontend.handler.common.config-edn :as config-edn-common-handler]
|
||||
[frontend.handler.common.file :as file-common-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
|
@ -35,7 +36,8 @@
|
|||
[clojure.core.async :as async]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[medley.core :as medley]
|
||||
[logseq.common.path :as path]))
|
||||
[logseq.common.path :as path]
|
||||
[borkdude.rewrite-edn :as rewrite]))
|
||||
|
||||
;; Project settings should be checked in two situations:
|
||||
;; 1. User changes the config.edn directly in logseq.com (fn: alter-file)
|
||||
|
@ -517,13 +519,20 @@
|
|||
(let [full-graph-name (string/lower-case (str config/db-version-prefix graph-name))]
|
||||
(some #(= (some-> (:url %) string/lower-case) full-graph-name) (state/get-repos))))
|
||||
|
||||
(defn migrate-db-config
|
||||
[content]
|
||||
(-> (reduce rewrite/dissoc
|
||||
(rewrite/parse-string (str content))
|
||||
(keys config-edn-common-handler/file-only-config))
|
||||
str))
|
||||
|
||||
(defn- create-db [full-graph-name {:keys [file-graph-import?]}]
|
||||
(->
|
||||
(p/let [_ (persist-db/<new full-graph-name)
|
||||
_ (start-repo-db-if-not-exists! full-graph-name)
|
||||
_ (state/add-repo! {:url full-graph-name})
|
||||
_ (when-not file-graph-import? (route-handler/redirect-to-home!))
|
||||
initial-data (sqlite-create-graph/build-db-initial-data config/config-default-content)
|
||||
initial-data (sqlite-create-graph/build-db-initial-data (migrate-db-config config/config-default-content))
|
||||
_ (db/transact! full-graph-name initial-data)
|
||||
_ (repo-config-handler/set-repo-config-state! full-graph-name config/config-default-content)
|
||||
;; TODO: handle global graph
|
||||
|
|
|
@ -13,11 +13,21 @@
|
|||
[goog.dom :as gdom]
|
||||
[rum.core :as rum]))
|
||||
|
||||
|
||||
(defn- blur-if-compositing
|
||||
"Call blur on the textarea if it is in composition mode, let the IME commit the composing text"
|
||||
[]
|
||||
(when-let [edit-input-id (and (state/editor-in-composition?)
|
||||
(state/get-edit-input-id))]
|
||||
(let [textarea-el (gdom/getElement edit-input-id)]
|
||||
(.blur textarea-el))))
|
||||
|
||||
(rum/defc indent-outdent [indent? icon]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(blur-if-compositing)
|
||||
(editor-handler/indent-outdent indent?))}
|
||||
(ui/icon icon {:size ui/icon-size})]])
|
||||
|
||||
|
@ -91,7 +101,13 @@
|
|||
(command #(if (state/sub :document/mode?)
|
||||
(editor-handler/insert-new-block! nil)
|
||||
(commands/simple-insert! parent-id "\n" {})) {:icon "arrow-back"})
|
||||
(command editor-handler/cycle-todo! {:icon "checkbox"} true)
|
||||
;; On mobile devies, some IME(keyboard) uses composing mode.
|
||||
;; The composing text can be committed by losing focus.
|
||||
;; 100ms is enough to commit the composing text to db.
|
||||
(command #(do
|
||||
(blur-if-compositing)
|
||||
(editor-handler/cycle-todo!))
|
||||
{:icon "checkbox"} true)
|
||||
(command #(mobile-camera/embed-photo parent-id) {:icon "camera"} true)
|
||||
(command history/undo! {:icon "rotate" :class "rotate-180"} true)
|
||||
(command history/redo! {:icon "rotate-clockwise" :class "rotate-180"} true)
|
||||
|
|
|
@ -311,6 +311,7 @@
|
|||
:system/info {}
|
||||
;; Whether block is selected
|
||||
:ui/select-query-cache (atom {})
|
||||
:favorites/updated? (atom 0)
|
||||
:db/async-queries (atom #{})})))
|
||||
|
||||
;; Block ast state
|
||||
|
@ -2366,3 +2367,7 @@ Similar to re-frame subscriptions"
|
|||
(when (and max-tx-id (nil? (:after (get @(:history/tx->editor-cursor @state) max-tx-id))))
|
||||
(update-state! :history/tx->editor-cursor
|
||||
(fn [m] (assoc-in m [max-tx-id :after] editor-cursor))))))
|
||||
|
||||
(defn update-favorites-updated!
|
||||
[]
|
||||
(update-state! :favorites/updated? inc))
|
||||
|
|
|
@ -81,8 +81,8 @@
|
|||
(date/valid-journal-title? date-formatter title)))
|
||||
|
||||
[title page-name] (get-title-and-pagename title)
|
||||
with-uuid? (if (uuid? uuid) uuid true)] ;; FIXME: prettier validation
|
||||
(when (ldb/page-empty? @conn page-name)
|
||||
with-uuid? (if (uuid? uuid) uuid true)
|
||||
result (when (ldb/page-empty? @conn page-name)
|
||||
(let [pages (if split-namespace?
|
||||
(common-util/split-namespace-pages title)
|
||||
[title])
|
||||
|
@ -130,7 +130,8 @@
|
|||
(ldb/transact! conn txs (cond-> {:persist-op? persist-op?}
|
||||
today-journal?
|
||||
(assoc :create-today-journal? true
|
||||
:today-journal-name page-name))))))))
|
||||
:today-journal-name page-name))))))] ;; FIXME: prettier validation
|
||||
[result page-name]))
|
||||
|
||||
(defn db-refs->page
|
||||
"Replace [[page name]] with page name"
|
||||
|
|
|
@ -302,7 +302,11 @@
|
|||
(d/pull-many @conn [:db/id])
|
||||
(filter :db/id)))
|
||||
(contains? key-set :properties) (assoc :block/properties
|
||||
(transit/read transit-r (:properties op-value))))]
|
||||
(transit/read transit-r (:properties op-value)))
|
||||
(contains? key-set :link) (assoc :block/link (some->> (:link op-value)
|
||||
(vector :block/uuid)
|
||||
(d/pull @conn [:db/id])
|
||||
:db/id)))]
|
||||
(transact-db! :save-block repo conn date-formatter new-block)))))))
|
||||
|
||||
(defn apply-remote-move-ops
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns frontend.db.name-sanity-test
|
||||
(:require [cljs.test :refer [deftest testing is]]
|
||||
[clojure.string :as string]
|
||||
[logseq.common.util :as common-util]
|
||||
[logseq.graph-parser.extract :as extract]
|
||||
[frontend.worker.handler.page.rename :as worker-page-rename]
|
||||
[frontend.util.fs :as fs-util]
|
||||
[frontend.worker.file.util :as wfu]))
|
||||
|
@ -11,7 +11,7 @@
|
|||
[page-name]
|
||||
(testing (str "Test sanitization page-name: " page-name)
|
||||
(let [file-name (#'wfu/tri-lb-file-name-sanity page-name)
|
||||
page-name' (#'common-util/tri-lb-title-parsing file-name)
|
||||
page-name' (#'extract/tri-lb-title-parsing file-name)
|
||||
url-single (js/encodeURIComponent file-name)
|
||||
url-double (js/encodeURIComponent url-single)
|
||||
file-name' (js/decodeURIComponent url-single)
|
||||
|
|
|
@ -537,10 +537,10 @@
|
|||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@logseq/capacitor-file-sync@5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/capacitor-file-sync/-/capacitor-file-sync-5.0.1.tgz#e154f715597785518ccd7d058f353acb67fbc2b8"
|
||||
integrity sha512-C1fLSS53orxsUWBsNb6LKwuOdlEU9ZhxkweMjNKG9VaSkLFTFqpjFG36OTso23WQ7hC5e45jjXq79aoWuqJaKA==
|
||||
"@logseq/capacitor-file-sync@5.0.2":
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@logseq/capacitor-file-sync/-/capacitor-file-sync-5.0.2.tgz#10c56e35b41b1a0afd293c9b045fbcfe150c3477"
|
||||
integrity sha512-FymsTeRtF66zG+oeO+ohZxWICMQMC8An4n9pdI0zz1WaGLer4oWC/lUghlC2DpztRLA32p0CH28tEzF5+2jARg==
|
||||
|
||||
"@logseq/diff-merge@0.2.2":
|
||||
version "0.2.2"
|
||||
|
|
Loading…
Reference in New Issue