config.cljs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. (ns frontend.config
  2. "App config and fns built on top of configuration"
  3. (:require [clojure.set :as set]
  4. [clojure.string :as string]
  5. [frontend.mobile.util :as mobile-util]
  6. [frontend.state :as state]
  7. [frontend.util :as util]
  8. [logseq.graph-parser.config :as gp-config]
  9. [logseq.graph-parser.util :as gp-util]
  10. [shadow.resource :as rc]))
  11. (goog-define DEV-RELEASE false)
  12. (defonce dev-release? DEV-RELEASE)
  13. (defonce dev? ^boolean (or dev-release? goog.DEBUG))
  14. (goog-define PUBLISHING false)
  15. (defonce publishing? PUBLISHING)
  16. (reset! state/publishing? publishing?)
  17. (def test? false)
  18. (goog-define ENABLE-FILE-SYNC-PRODUCTION false)
  19. (if ENABLE-FILE-SYNC-PRODUCTION
  20. (do (def FILE-SYNC-PROD? true)
  21. (def LOGIN-URL
  22. "https://logseq-prod.auth.us-east-1.amazoncognito.com/login?client_id=3c7np6bjtb4r1k1bi9i049ops5&response_type=code&scope=email+openid+phone&redirect_uri=logseq%3A%2F%2Fauth-callback")
  23. (def API-DOMAIN "api.logseq.com")
  24. (def WS-URL "wss://ws.logseq.com/file-sync?graphuuid=%s"))
  25. (do (def FILE-SYNC-PROD? false)
  26. (def LOGIN-URL
  27. "https://logseq-test2.auth.us-east-2.amazoncognito.com/login?client_id=3ji1a0059hspovjq5fhed3uil8&response_type=code&scope=email+openid+phone&redirect_uri=logseq%3A%2F%2Fauth-callback")
  28. (def API-DOMAIN "api-dev.logseq.com")
  29. (def WS-URL "wss://ws-dev.logseq.com/file-sync?graphuuid=%s")))
  30. ;; Feature flags
  31. ;; =============
  32. (goog-define ENABLE-PLUGINS true)
  33. (defonce feature-plugin-system-on? ENABLE-PLUGINS)
  34. ;; Desktop only as other platforms requires better understanding of their
  35. ;; multi-graph workflows and optimal place for a "global" dir
  36. (def global-config-enabled? util/electron?)
  37. ;; User level configuration for whether plugins are enabled
  38. (defonce lsp-enabled?
  39. (and (util/electron?)
  40. (not (false? feature-plugin-system-on?))
  41. (state/lsp-enabled?-or-theme)))
  42. (defn plugin-config-enabled?
  43. []
  44. (and lsp-enabled? (global-config-enabled?)))
  45. ;; :TODO: How to do this?
  46. ;; (defonce desktop? ^boolean goog.DESKTOP)
  47. ;; ============
  48. (def app-name "logseq")
  49. (def website
  50. (if dev?
  51. "http://localhost:3000"
  52. (util/format "https://%s.com" app-name)))
  53. (def asset-domain (util/format "https://asset.%s.com"
  54. app-name))
  55. ;; TODO: Remove this, switch to lazy loader
  56. (defn asset-uri
  57. [path]
  58. (cond
  59. publishing?
  60. path
  61. (util/file-protocol?)
  62. (string/replace path "/static/" "./")
  63. :else
  64. (if dev? path
  65. (str asset-domain path))))
  66. (def markup-formats
  67. #{:org :md :markdown :asciidoc :adoc :rst})
  68. (def doc-formats
  69. #{:doc :docx :xls :xlsx :ppt :pptx :one :pdf :epub})
  70. (def image-formats
  71. #{:png :jpg :jpeg :bmp :gif :webp :svg})
  72. (def audio-formats
  73. #{:mp3 :ogg :mpeg :wav :m4a :flac :wma :aac})
  74. (def video-formats
  75. #{:mp4 :webm :mov})
  76. (def media-formats (set/union (gp-config/img-formats) audio-formats))
  77. (def html-render-formats
  78. #{:adoc :asciidoc})
  79. (defn extname-of-supported?
  80. ([input] (extname-of-supported?
  81. input
  82. [image-formats doc-formats audio-formats
  83. video-formats markup-formats html-render-formats
  84. (gp-config/text-formats)]))
  85. ([input formats]
  86. (when-let [input (some->
  87. (cond-> input
  88. (and (string? input)
  89. (not (string/blank? input)))
  90. (string/replace-first "." ""))
  91. (util/safe-lower-case)
  92. (keyword))]
  93. (some
  94. (fn [s]
  95. (contains? s input))
  96. formats))))
  97. (def mobile?
  98. "Triggering condition: Mobile phones
  99. *** Warning!!! ***
  100. For UX logic only! Don't use for FS logic
  101. iPad / Android Pad doesn't trigger!
  102. Same as config/mobile?"
  103. (when-not util/node-test?
  104. (util/safe-re-find #"Mobi" js/navigator.userAgent)))
  105. ;; TODO: protocol design for future formats support
  106. (defn get-block-pattern
  107. [format]
  108. (gp-config/get-block-pattern (or format (state/get-preferred-format))))
  109. (defn get-hr
  110. [format]
  111. (let [format (or format (keyword (state/get-preferred-format)))]
  112. (case format
  113. :org
  114. "-----"
  115. :markdown
  116. "---"
  117. "")))
  118. (defn get-bold
  119. [format]
  120. (let [format (or format (keyword (state/get-preferred-format)))]
  121. (case format
  122. :org
  123. "*"
  124. :markdown
  125. "**"
  126. "")))
  127. (defn get-italic
  128. [format]
  129. (let [format (or format (keyword (state/get-preferred-format)))]
  130. (case format
  131. :org
  132. "/"
  133. :markdown
  134. "*"
  135. "")))
  136. (defn get-underline
  137. [format]
  138. (let [format (or format (keyword (state/get-preferred-format)))]
  139. (case format
  140. :org
  141. "_"
  142. :markdown ;; no underline for markdown
  143. ""
  144. "")))
  145. (defn get-strike-through
  146. [format]
  147. (let [format (or format (keyword (state/get-preferred-format)))]
  148. (case format
  149. :org
  150. "+"
  151. :markdown
  152. "~~"
  153. "")))
  154. (defn get-highlight
  155. [format]
  156. (case format
  157. :org
  158. "^^"
  159. :markdown
  160. "=="
  161. ""))
  162. (defn get-code
  163. [format]
  164. (let [format (or format (keyword (state/get-preferred-format)))]
  165. (case format
  166. :org
  167. "~"
  168. :markdown
  169. "`"
  170. "")))
  171. (defn get-empty-link-and-forward-pos
  172. [format]
  173. (case format
  174. :org
  175. ["[[][]]" 2]
  176. :markdown
  177. ["[]()" 1]
  178. ["" 0]))
  179. (defn link-format
  180. [format label link]
  181. (if label
  182. (case format
  183. :org
  184. (util/format "[[%s][%s]]" link label)
  185. :markdown
  186. (util/format "[%s](%s)" label link))
  187. link))
  188. (defn with-default-link
  189. [format link]
  190. (case format
  191. :org
  192. [(util/format "[[%s][]]" link)
  193. (+ 4 (count link))]
  194. :markdown
  195. [(util/format "[](%s)" link)
  196. 1]
  197. ["" 0]))
  198. (defn with-label-link
  199. [format label link]
  200. (case format
  201. :org
  202. [(util/format "[[%s][%s]]" link label)
  203. (+ 4 (count link) (count label))]
  204. :markdown
  205. [(util/format "[%s](%s)" label link)
  206. (+ 4 (count link) (count label))]
  207. ["" 0]))
  208. (defn with-default-label
  209. [format label]
  210. (case format
  211. :org
  212. [(util/format "[[][%s]]" label)
  213. 2]
  214. :markdown
  215. [(util/format "[%s]()" label)
  216. (+ 3 (count label))]
  217. ["" 0]))
  218. (defn properties-wrapper-pattern
  219. [format]
  220. (case format
  221. :markdown
  222. "---\n%s\n---"
  223. "%s"))
  224. (defn get-file-extension
  225. [format]
  226. (case (keyword format)
  227. :markdown
  228. "md"
  229. (name format)))
  230. (defonce default-journals-directory "journals")
  231. (defonce default-pages-directory "pages")
  232. (defonce default-whiteboards-directory "whiteboards")
  233. (defn get-pages-directory
  234. []
  235. (or (state/get-pages-directory) default-pages-directory))
  236. (defn get-journals-directory
  237. []
  238. (or (state/get-journals-directory) default-journals-directory))
  239. (defn get-whiteboards-directory
  240. []
  241. (or (state/get-whiteboards-directory) default-whiteboards-directory))
  242. (defonce local-repo "local")
  243. (defn demo-graph?
  244. "Demo graph or nil graph?"
  245. ([]
  246. (demo-graph? (state/get-current-repo)))
  247. ([graph]
  248. (or (nil? graph) (= graph local-repo))))
  249. (defonce recycle-dir ".recycle")
  250. (def config-file "config.edn")
  251. (def custom-css-file "custom.css")
  252. (def export-css-file "export.css")
  253. (def custom-js-file "custom.js")
  254. (def config-default-content (rc/inline "config.edn"))
  255. (defonce idb-db-prefix "logseq-db/")
  256. (defonce local-db-prefix "logseq_local_")
  257. (defonce local-handle "handle")
  258. (defonce local-handle-prefix (str local-handle "/" local-db-prefix))
  259. (defn local-db?
  260. [s]
  261. (and (string? s)
  262. (string/starts-with? s local-db-prefix)))
  263. (defn get-local-asset-absolute-path
  264. [s]
  265. (str "/" (string/replace s #"^[./]*" "")))
  266. (defn get-local-dir
  267. [s]
  268. (string/replace s local-db-prefix ""))
  269. (defn get-local-repo
  270. [dir]
  271. (str local-db-prefix dir))
  272. (defn get-repo-dir
  273. [repo-url]
  274. (cond
  275. (and (util/electron?) (local-db? repo-url))
  276. (get-local-dir repo-url)
  277. (and (mobile-util/native-platform?) (local-db? repo-url))
  278. (let [dir (get-local-dir repo-url)]
  279. (if (string/starts-with? dir "file:")
  280. dir
  281. (str "file:///" (string/replace dir #"^/+" ""))))
  282. :else
  283. (str "/"
  284. (->> (take-last 2 (string/split repo-url #"/"))
  285. (string/join "_")))))
  286. (defn get-string-repo-dir
  287. [repo-dir]
  288. (if (mobile-util/native-ios?)
  289. (str (if (mobile-util/iCloud-container-path? repo-dir)
  290. "iCloud"
  291. (cond (mobile-util/native-iphone?)
  292. "On My iPhone"
  293. (mobile-util/native-ipad?)
  294. "On My iPad"
  295. :else
  296. "Local"))
  297. (->> (string/split repo-dir "Documents/")
  298. last
  299. gp-util/safe-decode-uri-component
  300. (str "/" (string/capitalize app-name) "/")))
  301. (get-repo-dir repo-dir)))
  302. (defn get-repo-path
  303. [repo-url path]
  304. (if (and (or (util/electron?) (mobile-util/native-platform?))
  305. (local-db? repo-url))
  306. path
  307. (util/node-path.join (get-repo-dir repo-url) path)))
  308. ;; FIXME: There is another normalize-file-protocol-path at src/main/frontend/fs/capacitor_fs.cljs
  309. (defn get-file-path
  310. "Normalization happens here"
  311. [repo-url relative-path]
  312. (when (and repo-url relative-path)
  313. (let [path (cond
  314. (demo-graph?)
  315. nil
  316. (and (util/electron?) (local-db? repo-url))
  317. (let [dir (get-repo-dir repo-url)]
  318. (if (string/starts-with? relative-path dir)
  319. relative-path
  320. (str dir "/"
  321. (string/replace relative-path #"^/" ""))))
  322. (and (mobile-util/native-ios?) (local-db? repo-url))
  323. (let [dir (get-repo-dir repo-url)]
  324. (util/safe-path-join dir relative-path))
  325. (and (mobile-util/native-android?) (local-db? repo-url))
  326. (let [dir (get-repo-dir repo-url)
  327. dir (if (or (string/starts-with? dir "file:")
  328. (string/starts-with? dir "content:"))
  329. dir
  330. (str "file:///" (string/replace dir #"^/+" "")))]
  331. (util/safe-path-join dir relative-path))
  332. (= "/" (first relative-path))
  333. (subs relative-path 1)
  334. :else
  335. relative-path)]
  336. (and (not-empty path) (gp-util/path-normalize path)))))
  337. ;; NOTE: js/encodeURIComponent cannot be used here
  338. (defn get-page-file-path
  339. "Get the path to the page file for the given page. This is used when creating new files."
  340. [repo-url sub-dir page-name ext]
  341. (let [page-basename (if (mobile-util/native-platform?)
  342. (js/encodeURI page-name)
  343. page-name)]
  344. (get-file-path repo-url (str sub-dir "/" page-basename "." ext))))
  345. (defn get-repo-config-path
  346. ([]
  347. (get-repo-config-path (state/get-current-repo)))
  348. ([repo]
  349. (when repo
  350. (get-file-path repo (str app-name "/" config-file)))))
  351. (defn get-custom-css-path
  352. ([]
  353. (get-custom-css-path (state/get-current-repo)))
  354. ([repo]
  355. (when repo
  356. (get-file-path repo
  357. (str app-name "/" custom-css-file)))))
  358. (defn get-export-css-path
  359. ([]
  360. (get-export-css-path (state/get-current-repo)))
  361. ([repo]
  362. (when repo
  363. (get-file-path repo
  364. (str app-name "/" export-css-file)))))
  365. (defn expand-relative-assets-path
  366. ;; ../assets/xxx -> {assets|file}://{current-graph-root-path}/xxx
  367. [source]
  368. (when-let [protocol (and (string? source)
  369. (not (string/blank? source))
  370. (if (util/electron?) "assets" "file"))]
  371. (string/replace
  372. source "../assets" (util/format "%s://%s/assets" protocol (get-repo-dir (state/get-current-repo))))))
  373. (defn get-current-repo-assets-root
  374. []
  375. (when-let [repo-root (and (local-db? (state/get-current-repo))
  376. (get-repo-dir (state/get-current-repo)))]
  377. (util/node-path.join repo-root "assets")))
  378. (defn get-custom-js-path
  379. ([]
  380. (get-custom-js-path (state/get-current-repo)))
  381. ([repo]
  382. (when repo
  383. (get-file-path repo
  384. (str app-name "/" custom-js-file)))))
  385. (defn get-block-hidden-properties
  386. []
  387. (:block-hidden-properties (state/get-config)))