Browse Source

fix conflicts

charlie 4 years ago
parent
commit
f5fade2d5d
35 changed files with 757 additions and 344 deletions
  1. 1 1
      libs/package.json
  2. 10 5
      libs/src/LSPlugin.ts
  3. 17 11
      libs/src/LSPlugin.user.ts
  4. 3 2
      package.json
  5. 0 4
      resources/css/common.css
  6. 7 6
      resources/js/lsplugin.core.js
  7. 1 1
      resources/package.json
  8. 4 0
      shadow-cljs.edn
  9. 2 1
      src/main/frontend/commands.cljs
  10. 52 51
      src/main/frontend/components/block.cljs
  11. 8 0
      src/main/frontend/components/block.css
  12. 16 13
      src/main/frontend/components/editor.cljs
  13. 1 1
      src/main/frontend/components/header.cljs
  14. 5 0
      src/main/frontend/components/header.css
  15. 3 3
      src/main/frontend/components/page.cljs
  16. 130 0
      src/main/frontend/components/query_table.cljs
  17. 1 1
      src/main/frontend/components/repo.cljs
  18. 149 162
      src/main/frontend/components/sidebar.cljs
  19. 6 0
      src/main/frontend/date.cljs
  20. 12 11
      src/main/frontend/extensions/calc.cljc
  21. 2 1
      src/main/frontend/extensions/code.cljs
  22. 9 1
      src/main/frontend/extensions/sci.cljs
  23. 35 18
      src/main/frontend/handler/editor.cljs
  24. 52 9
      src/main/frontend/handler/events.cljs
  25. 8 8
      src/main/frontend/handler/plugin.cljs
  26. 46 0
      src/main/frontend/handler/query.cljs
  27. 4 1
      src/main/frontend/modules/instrumentation/sentry.cljs
  28. 1 1
      src/main/frontend/search/db.cljs
  29. 1 1
      src/main/frontend/ui.cljs
  30. 1 1
      src/main/frontend/util/property.cljs
  31. 1 1
      src/main/frontend/version.cljs
  32. 9 7
      src/main/grammar/calc.bnf
  33. 8 4
      src/main/logseq/api.cljs
  34. 20 2
      src/test/frontend/extensions/calc_test.cljc
  35. 132 16
      yarn.lock

+ 1 - 1
libs/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@logseq/libs",
-  "version": "0.0.1-alpha.25",
+  "version": "0.0.1-alpha.26",
   "description": "Logseq SDK libraries",
   "main": "dist/lsplugin.user.js",
   "typings": "index.d.ts",

+ 10 - 5
libs/src/LSPlugin.ts

@@ -177,8 +177,8 @@ export interface IAppProxy {
   getCurrentGraph: () => Promise<AppGraphInfo | null>
 
   // router
-  pushState: (k: string, params?: {}) => void
-  replaceState: (k: string, params?: {}) => void
+  pushState: (k: string, params?: Record<string, any>, query?: Record<string, any>) => void
+  replaceState: (k: string, params?: Record<string, any>, query?: Record<string, any>) => void
 
   // ui
   showMsg: (content: string, status?: 'success' | 'warning' | string) => void
@@ -187,12 +187,12 @@ export interface IAppProxy {
   registerUIItem: (
     type: 'toolbar' | 'pagebar',
     opts: { key: string, template: string }
-  ) => boolean
+  ) => void
 
   registerPageMenuItem: (
     tag: string,
     action: (e: IHookEvent & { page: string }) => void
-  ) => unknown
+  ) => void
 
   // events
   onCurrentGraphChanged: IUserHook
@@ -231,7 +231,7 @@ export interface IEditorProxy extends Record<string, any> {
   registerSlashCommand: (
     tag: string,
     action: BlockCommandCallback | Array<SlashCommandAction>
-  ) => boolean
+  ) => unknown
 
   /**
    * register a custom command in the block context menu (triggered by right clicking the block dot)
@@ -339,6 +339,11 @@ export interface IEditorProxy extends Record<string, any> {
   getBlockProperty: (block: BlockIdentity, key: string) => Promise<any>
 
   getBlockProperties: (block: BlockIdentity) => Promise<any>
+
+  scrollToBlockInPage: (
+    pageName: BlockPageName,
+    blockId: BlockIdentity
+  ) => void
 }
 
 /**

+ 17 - 11
libs/src/LSPlugin.user.ts

@@ -10,7 +10,7 @@ import {
   BlockCommandCallback,
   StyleString,
   ThemeOptions,
-  UIOptions, IHookEvent
+  UIOptions, IHookEvent, BlockIdentity, BlockPageName
 } from './LSPlugin'
 import Debug from 'debug'
 import * as CSS from 'csstype'
@@ -24,6 +24,7 @@ declare global {
   }
 }
 
+const PROXY_CONTINUE = Symbol.for('proxy-continue')
 const debug = Debug('LSPlugin:user')
 
 /**
@@ -67,15 +68,13 @@ const app: Partial<IAppProxy> = {
       method: 'register-plugin-ui-item',
       args: [pid, type, opts]
     })
-
-    return false
   },
 
   registerPageMenuItem (
     this: LSPluginUser,
     tag: string,
     action: (e: IHookEvent & { page: string }) => void
-  ): unknown {
+  ) {
     if (typeof action !== 'function') {
       return false
     }
@@ -88,8 +87,6 @@ const app: Partial<IAppProxy> = {
       type, {
         key, label
       }, action)
-
-    return false
   }
 }
 
@@ -142,15 +139,13 @@ const editor: Partial<IEditorProxy> = {
       method: 'register-plugin-slash-command',
       args: [this.baseInfo.id, [tag, actions]]
     })
-
-    return false
   },
 
   registerBlockContextMenuItem (
     this: LSPluginUser,
     tag: string,
     action: BlockCommandCallback
-  ): unknown {
+  ) {
     if (typeof action !== 'function') {
       return false
     }
@@ -163,8 +158,19 @@ const editor: Partial<IEditorProxy> = {
       type, {
         key, label
       }, action)
+  },
 
-    return false
+  scrollToBlockInPage (
+    this: LSPluginUser,
+    pageName: BlockPageName,
+    blockId: BlockIdentity
+  ) {
+    const anchor = `block-content-` + blockId
+    this.App.pushState(
+      'page',
+      { name: pageName },
+      { anchor }
+    )
   }
 }
 
@@ -363,7 +369,7 @@ export class LSPluginUser extends EventEmitter<LSPluginUserEvents> implements IL
         return function (this: any, ...args: any) {
           if (origMethod) {
             const ret = origMethod.apply(that, args)
-            if (ret === false) return
+            if (ret !== PROXY_CONTINUE) return
           }
 
           // Handle hook

+ 3 - 2
package.json

@@ -43,7 +43,7 @@
         "gulp:watch": "gulp watch",
         "gulp:build": "cross-env NODE_ENV=production gulp build",
         "css:build": "postcss tailwind.all.css -o static/css/style.css --verbose --env production",
-        "css:watch": "postcss tailwind.all.css -o static/css/style.css --verbose --watch",
+        "css:watch": "TAILWIND_MODE=watch postcss tailwind.all.css -o static/css/style.css --verbose --watch",
         "cljs:watch": "clojure -M:cljs watch app electron",
         "cljs:electron-watch": "clojure -M:cljs watch app electron",
         "cljs:release": "clojure -M:cljs release app publishing electron",
@@ -62,6 +62,7 @@
         "@excalidraw/excalidraw": "^0.4.2",
         "@kanru/rage-wasm": "^0.2.1",
         "@sentry/browser": "^6.4.1",
+        "@sentry/electron": "^2.5.1",
         "@tippyjs/react": "^4.2.5",
         "chokidar": "^3.5.1",
         "chrono-node": "^2.2.4",
@@ -81,7 +82,7 @@
         "ignore": "^5.1.8",
         "is-svg": "4.2.2",
         "jszip": "^3.5.0",
-        "mldoc": "0.8.8",
+        "mldoc": "0.8.9",
         "path": "^0.12.7",
         "pixi-graph-fork": "^0.1.3",
         "posthog-js": "^1.10.2",

+ 0 - 4
resources/css/common.css

@@ -1147,7 +1147,3 @@ html[data-theme='dark'] .keyboard-shortcut > code {
 .overflow-y-scroll {
     overflow-y: scroll;
 }
-
-.whitespace-no-wrap {
-    white-space: nowrap;
-}

File diff suppressed because it is too large
+ 7 - 6
resources/js/lsplugin.core.js


+ 1 - 1
resources/package.json

@@ -1,6 +1,6 @@
 {
   "name": "Logseq",
-  "version": "0.2.5",
+  "version": "0.2.6",
   "main": "electron.js",
   "author": "Logseq",
   "description": "A privacy-first, open-source platform for knowledge management and collaboration.",

+ 4 - 0
shadow-cljs.edn

@@ -28,6 +28,8 @@
    :compiler-options {:infer-externs :auto
                       :output-feature-set :es-next-in
                       :source-map true
+                      :source-map-include-sources-content true
+                      :source-map-detail-level :all
                       :externs ["datascript/externs.js"
                                 "externs.js"]
                       :warnings {:fn-deprecated false}}
@@ -54,6 +56,8 @@
              :compiler-options
              {:infer-externs :auto
               :source-map true
+              :source-map-include-sources-content true
+              :source-map-detail-level :all
               :externs ["datascript/externs.js"
                         "externs.js"]
               :warnings {:fn-deprecated false}}}

+ 2 - 1
src/main/frontend/commands.cljs

@@ -244,6 +244,7 @@
     ;; advanced
 
     [["Query" [[:editor/input "{{query }}" {:backward-pos 2}]] "Create a DataScript query"]
+     ["Query table function" [[:editor/input "{{function }}" {:backward-pos 2}]] "Create a query table function"]
      ["Calculator" [[:editor/input "```calc\n\n```" {:backward-pos 4}]
                     [:codemirror/focus]] "Insert a calculator"]
      ["Draw" (fn []
@@ -562,4 +563,4 @@
   [pid {:keys [key label block-id] :as cmd} action]
   (let [format (and block-id (:block/format (db-util/pull [:block/uuid block-id])))
         inputs (vector (conj action (assoc cmd :pid pid)))]
-    (handle-steps inputs format)))
+    (handle-steps inputs format)))

+ 52 - 51
src/main/frontend/components/block.cljs

@@ -30,6 +30,8 @@
             [frontend.handler.repeated :as repeated]
             [frontend.handler.route :as route-handler]
             [frontend.handler.ui :as ui-handler]
+            [frontend.handler.query :as query-handler]
+            [frontend.handler.common :as common-handler]
             [frontend.modules.outliner.tree :as tree]
             [frontend.search :as search]
             [frontend.security :as security]
@@ -46,7 +48,8 @@
             [promesa.core :as p]
             [reitit.frontend.easy :as rfe]
             [rum.core :as rum]
-            [shadow.loader :as loader]))
+            [shadow.loader :as loader]
+            [frontend.components.query-table :as query-table]))
 
 ;; TODO: remove rum/with-context because it'll make reactive queries not working
 
@@ -989,9 +992,26 @@
         [:div.dsl-query
          (let [query (string/join ", " arguments)]
            (custom-query (assoc config :dsl-query? true)
-                         {:title [:span.font-medium.p-1 (str "Query: " query)]
+                         {:title [:span.font-medium.p-1.query-title
+                                  (str "Query: " query)]
                           :query query}))]
 
+        (= name "function")
+        (or
+         (when (:query-result config)
+           (when-let [query-result (rum/react (:query-result config))]
+             (let [fn-string (-> (util/format "(fn [result] %s)" (first arguments))
+                                 (common-handler/safe-read-string "failed to parse function")
+                                 (query-handler/normalize-query-function query-result)
+                                 (str))
+                   f (sci/eval-string fn-string)]
+               (when (fn? f)
+                 (try (f query-result)
+                      (catch js/Error e
+                        (js/console.error e)))))))
+         [:span.warning
+          (util/format "{{function %s}}" (first arguments))])
+
         (= name "youtube")
         (when-let [url (first arguments)]
           (let [YouTube-regex #"^((?:https?:)?//)?((?:www|m).)?((?:youtube.com|youtu.be))(/(?:[\w-]+\?v=|embed/|v/)?)([\w-]+)(\S+)?$"]
@@ -1639,6 +1659,7 @@
        (when (and (seq properties)
                   (let [hidden? (property/properties-built-in? properties)]
                     (not hidden?))
+                  (not block-ref?)
                   (not (:slide? config)))
          (properties-cp config block))
 
@@ -1864,6 +1885,11 @@
   [state config {:block/keys [uuid title body meta content page format repo children pre-block? top? properties refs path-refs heading-level level type] :as block}]
   (let [blocks-container-id (:blocks-container-id config)
         config (update config :block merge block)
+
+        ;; Each block might have multiple queries, but we store only the first query's result
+        config (if (nil? (:query-result config))
+                 (assoc config :query-result (atom nil))
+                 config)
         heading? (and (= type :heading) heading-level (<= heading-level 6))
         *control-show? (get state ::control-show?)
         *ref-collapsed? (get state ::ref-collapsed?)
@@ -2088,43 +2114,6 @@
                      result-atom)]
     (assoc state :query-atom query-atom)))
 
-(rum/defc query-result-table < rum/reactive
-  [config result {:keys [select-keys page?]}]
-  (let [editor-box (get config :editor-box)
-        all-keys (distinct (mapcat keys (map :block/properties result)))
-        keys (if (seq select-keys) select-keys all-keys)
-        keys (if page? (cons :page keys) keys)]
-    [:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
-                           :style {:width "100%"}}
-     [:table.table-auto
-      (for [key keys]
-        [:th.whitespace-no-wrap (name key)])
-      (for [item result]
-        [:tr {:on-click (fn [e]
-                          (when (gobj/get e "shiftKey")
-                            (state/sidebar-add-block!
-                             (state/get-current-repo)
-                             (:db/id item)
-                             :block-ref
-                             {:block item})))}
-         (let [format (:block/format item)]
-           (for [key keys]
-             (let [value (if (= key :page)
-                           (or (:block/original-name item)
-                               (:block/name item))
-                           (get-in item [:block/properties key]))]
-               [:td.whitespace-no-wrap
-                (when value
-                  (if (coll? value)
-                    (let [vals (for [item value]
-                                 (page-cp {} {:block/name item}))]
-                      (interpose [:span ", "] vals))
-                    (if (not (string? value))
-                      value
-                      (if-let [page (db/entity [:block/name (string/lower-case value)])]
-                        (page-cp {} page)
-                        (inline-text format value)))))])))])]]))
-
 (rum/defcs custom-query < rum/reactive
   {:will-mount trigger-custom-query!
    :did-mount (fn [state]
@@ -2157,6 +2146,9 @@
                                     (and (string? query) (string/includes? query "(by-page false)")))
            result (when query-result
                     (db/custom-query-result-transform query-result remove-blocks q not-grouped-by-page?))
+           _ (when-let [query-result (:query-result config)]
+               (let [result (remove (fn [b] (some? (get-in b [:block/properties :template]))) result)]
+                     (reset! query-result result)))
            view-f (and view (sci/eval-string (pr-str view)))
            only-blocks? (:block/uuid (first result))
            blocks-grouped-by-page? (and (seq result)
@@ -2173,17 +2165,26 @@
           (ui/foldable
            [:div.custom-query-title
             title
-            (when (and current-block (not page-list?))
+            (when current-block
               [:div.flex.flex-row.align-items.mt-2 {:on-mouse-down (fn [e] (util/stop e))}
-               [:span.mr-2.ml-2.text-sm "Table view"]
-               [:div {:style {:margin-top 3}}
-                (ui/toggle table?
-                           (fn []
-                             (editor-handler/set-block-property! current-block-uuid
-                                                                 "query-table"
-                                                                 (not table?)))
-                           true)]
-               [:span.ml-4.text-sm "Tip: Shift + Click a row to open its block in the right sidebar."]])]
+               (when-not page-list?
+                 [:div.flex.flex-row
+                  [:div.mx-2 [:span.text-sm "Table view"]]
+                  [:div {:style {:margin-top 5}}
+                   (ui/toggle table?
+                              (fn []
+                                (editor-handler/set-block-property! current-block-uuid
+                                                                    "query-table"
+                                                                    (not table?)))
+                              true)]])
+
+               [:a.mx-2.opacity-60.hover:opacity-100.block
+                {:on-click (fn []
+                             (let [all-keys (query-table/get-keys result page-list?)]
+                               (state/pub-event! [:modal/set-query-properties current-block all-keys])))}
+                [:span.table-query-properties
+                 [:span.text-sm.mr-1 "Set properties"]
+                 svg/settings-sm]]])]
            (cond
              (and (seq result) view-f)
              (let [result (try
@@ -2196,10 +2197,10 @@
                (util/hiccup-keywordize result))
 
              page-list?
-             (query-result-table config result {:page? true})
+             (query-table/result-table config current-block result {:page? true} map-inline page-cp ->elem inline-text)
 
              table?
-             (query-result-table config result {:page? false})
+             (query-table/result-table config current-block result {:page? false} map-inline page-cp ->elem inline-text)
 
              (and (seq result) (or only-blocks? blocks-grouped-by-page?))
              (->hiccup result (cond-> (assoc config

+ 8 - 0
src/main/frontend/components/block.css

@@ -427,3 +427,11 @@ a:hover > .bullet-container .bullet {
 a.filter svg {
   transform: scale(0.9);
 }
+
+.table-query-properties svg {
+    display: inline;
+}
+
+.query-title {
+    background: var(--ls-page-properties-background-color);
+}

+ 16 - 13
src/main/frontend/components/editor.cljs

@@ -386,24 +386,27 @@
 (def starts-with? clojure.string/starts-with?)
 
 (defn get-editor-heading-class [content]
-  (cond
-    (string/includes? content "\n") "multiline-block"
-    (starts-with? content "# ") "h1"
-    (starts-with? content "## ") "h2"
-    (starts-with? content "### ") "h3"
-    (starts-with? content "#### ") "h4"
-    (starts-with? content "##### ") "h5"
-    (starts-with? content "###### ") "h6"
-    (starts-with? content "TODO ") "todo-block"
-    (starts-with? content "DOING ") "doing-block"
-    (starts-with? content "DONE ") "done-block"
-    :else "normal-block"))
+  (let [content (if content (str content) "")]
+    (cond
+     (string/includes? content "\n") "multiline-block"
+     (starts-with? content "# ") "h1"
+     (starts-with? content "## ") "h2"
+     (starts-with? content "### ") "h3"
+     (starts-with? content "#### ") "h4"
+     (starts-with? content "##### ") "h5"
+     (starts-with? content "###### ") "h6"
+     (starts-with? content "TODO ") "todo-block"
+     (starts-with? content "DOING ") "doing-block"
+     (starts-with? content "DONE ") "done-block"
+     :else "normal-block")))
 
 (rum/defc mock-textarea
   < rum/reactive
   {:did-update
    (fn [state]
-     (editor-handler/handle-last-input)
+     (try (editor-handler/handle-last-input)
+          (catch js/Error _e
+            nil))
      state)}
   []
   [:div#mock-text

+ 1 - 1
src/main/frontend/components/header.cljs

@@ -217,7 +217,7 @@
          [:a.text-sm.font-medium.button
           {:on-click (fn []
                        (page-handler/ls-dir-files!))}
-          [:div.flex.flex-row.text-center.open-button__inner
+          [:div.flex.flex-row.text-center.open-button__inner.items-center
            [:span.inline-block.open-button__icon-wrapper svg/folder-add]
            (when-not config/mobile?
              [:span.ml-1 {:style {:margin-top (if electron-mac? 0 2)}}

+ 5 - 0
src/main/frontend/components/header.css

@@ -27,6 +27,11 @@
       min-width: 14rem;
     }
   }
+
+  a.button {
+    padding: 0.25rem;
+    margin: 0 4px;
+  }
 }
 
 .is-electron.is-mac .cp__header {

+ 3 - 3
src/main/frontend/components/page.cljs

@@ -396,7 +396,7 @@
                         (svg/vertical-dots nil)])
                      links
                      {:modal-class (util/hiccup->class
-                                    "origin-top-right.absolute.right-0.top-10.mt-2.rounded-md.shadow-lg.whitespace-no-wrap.dropdown-overflow-auto.page-drop-options")
+                                    "origin-top-right.absolute.right-0.top-10.mt-2.rounded-md.shadow-lg.whitespace-nowrap.dropdown-overflow-auto.page-drop-options")
                       :z-index     1})]))])
 
             ;; related assets upload
@@ -739,8 +739,8 @@
                       (block/page-cp {} page)]]
                 [:td [:span.text-gray-500.text-sm backlinks]]
                 [:td [:span.text-gray-500.text-sm (if created-at
-                                                    (date/int->local-time created-at)
+                                                    (date/int->local-time-2 created-at)
                                                     "Unknown")]]
                 [:td [:span.text-gray-500.text-sm (if updated-at
-                                                    (date/int->local-time updated-at)
+                                                    (date/int->local-time-2 updated-at)
                                                     "Unknown")]]])]]))])))

+ 130 - 0
src/main/frontend/components/query_table.cljs

@@ -0,0 +1,130 @@
+(ns frontend.components.query-table
+  (:require [frontend.ui :as ui]
+            [frontend.util :as util]
+            [rum.core :as rum]
+            [frontend.util.property :as property]
+            [frontend.db :as db]
+            [frontend.date :as date]
+            [frontend.state :as state]
+            [clojure.string :as string]
+            [frontend.components.svg :as svg]
+            [frontend.handler.common :as common-handler]))
+
+;; TODO: extract to table utils
+(defn- sort-result-by
+  [by-item desc? result]
+  (def result result)
+  (def by-item by-item)
+  (def desc? desc?)
+  (let [comp (if desc? > <)]
+    (sort-by by-item comp result)))
+
+(rum/defc sortable-title
+  [title key by-item desc?]
+  [:th.whitespace-nowrap
+   [:a {:on-click (fn []
+                    (reset! by-item key)
+                    (swap! desc? not))}
+    [:div.flex.items-center
+     [:span.mr-1 title]
+     (when (= @by-item key)
+       [:span
+        (if @desc? (svg/caret-down) (svg/caret-up))])]]])
+
+(defn get-keys
+  [result page?]
+  (let [keys (->> (distinct (mapcat keys (map :block/properties result)))
+                  (remove property/built-in-properties)
+                  (remove #{:template}))
+        keys (if page? (cons :page keys) (cons :block keys))
+        keys (concat keys [:created-at :updated-at])]
+    keys))
+
+(rum/defcs result-table < rum/reactive
+  (rum/local :updated-at ::sort-by-item)
+  (rum/local true ::desc?)
+  (rum/local false ::select?)
+  [state config current-block result {:keys [page?]} map-inline page-cp ->elem inline-text]
+  (when current-block
+    (let [select? (get state ::select?)
+          *sort-by-item (get state ::sort-by-item)
+          *desc? (get state ::desc?)
+          editor-box (get config :editor-box)
+          ;; remove templates
+          result (remove (fn [b] (some? (get-in b [:block/properties :template]))) result)
+          query-properties (some-> (get-in current-block [:block/properties :query-properties] "")
+                                   (common-handler/safe-read-string "Parsing query properties failed"))
+          keys (if (seq query-properties)
+                 query-properties
+                 (get-keys result page?))
+          keys (if (some #{:created-at :updated-at} keys)
+                 (concat
+                  (remove #{:created-at :updated-at} keys)
+                  (filter #{:created-at :updated-at} keys))
+                 keys)
+          sort-by-fn (fn [item]
+                       (let [key @*sort-by-item]
+                         (case key
+                           :created-at
+                           (:block/created-at item)
+                           :updated-at
+                           (:block/updated-at item)
+                           :block
+                           (:block/content item)
+                           :page
+                           (:block/name item)
+                           (get-in item [:block/properties key]))))
+          result (sort-result-by sort-by-fn @*desc? result)]
+      [:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
+                             :style {:width "100%"}}
+       [:table.table-auto
+        (for [key keys]
+          (sortable-title (name key) key *sort-by-item *desc?))
+        (for [item result]
+          (let [format (:block/format item)
+                edit-input-id (str "edit-block-" (:id config) "-" (:block/uuid item))
+                heading-level (:block/heading-level item)]
+            [:tr.cursor
+             (for [key keys]
+               (let [value (case key
+                             :page
+                             [:string (or (:block/original-name item)
+                                          (:block/name item))]
+
+                             :block       ; block title
+                             (let [title (:block/title item)]
+                               (if (seq title)
+                                 [:element (->elem :div (map-inline config title))]
+                                 [:string (:block/content item)]))
+
+                             :created-at
+                             [:string (when-let [created-at (:block/created-at item)]
+                                        (date/int->local-time-2 created-at))]
+
+                             :updated-at
+                             [:string (when-let [updated-at (:block/updated-at item)]
+                                        (date/int->local-time-2 updated-at))]
+
+                             [:string (get-in item [:block/properties key])])]
+                 [:td.whitespace-nowrap {:on-mouse-down (fn [] (reset! select? false))
+                                         :on-mouse-move (fn [] (reset! select? true))
+                                         :on-mouse-up (fn []
+                                                        (when-not @select?
+                                                          (state/sidebar-add-block!
+                                                           (state/get-current-repo)
+                                                           (:db/id item)
+                                                           :block-ref
+                                                           {:block item})))}
+                  (when value
+                    (if (= :element (first value))
+                      (second value)
+                      (let [value (second value)]
+                        (if (coll? value)
+                          (let [vals (for [item value]
+                                       (page-cp {} {:block/name item}))]
+                            (interpose [:span ", "] vals))
+                          (if (not (string? value))
+                            value
+                            (if-let [page (db/entity [:block/name (string/lower-case value)])]
+                              (page-cp {} page)
+                              (inline-text format value)))))))]))]))]])))

+ 1 - 1
src/main/frontend/components/repo.cljs

@@ -202,7 +202,7 @@
         (when (seq repos)
           (ui/dropdown-with-links
            (fn [{:keys [toggle-fn]}]
-             [:a#repo-switch.fade-link.block.pr-2 {:on-click toggle-fn}
+             [:a#repo-switch.fade-link.block.pr-2.whitespace-nowrap {:on-click toggle-fn}
               [:span
                [:span.repo-plus svg/plus]
                (let [repo-name (get-repo-name current-repo)

+ 149 - 162
src/main/frontend/components/sidebar.cljs

@@ -100,54 +100,43 @@
   {:did-mount (fn [state]
                 (when-let [element (gdom/getElement "main-content")]
                   (dnd/subscribe!
-                   element
-                   :upload-files
-                   {:drop (fn [e files]
-                            (when-let [id (state/get-edit-input-id)]
-                              (let [format (:block/format (state/get-edit-block))]
-                                (editor-handler/upload-asset id files format editor-handler/*asset-uploading? true))))}))
+                    element
+                    :upload-files
+                    {:drop (fn [e files]
+                             (when-let [id (state/get-edit-input-id)]
+                               (let [format (:block/format (state/get-edit-block))]
+                                 (editor-handler/upload-asset id files format editor-handler/*asset-uploading? true))))}))
                 state)}
   [{:keys [route-match global-graph-pages? logged? home? route-name indexeddb-support? white? db-restoring? main-content]}]
-  (ui/catch-error
-   [:div#main-content-container.w-full.flex.justify-center
-    [:div.mt-8
-     [:span.error "⚠️ Oops, Something Went Wrong, please back up your data first!"]
-     [:div.my-2 "Usually, a re-index could fix it. If it doesn't, you can join our "
-      [:a.inline {:href "https://discord.gg/KpN4eHY"
-                  :target "_blank"}
-       "discord group"]
-      " to ask for help."]
-     (ui/button "Re-index current graph"
-       :on-click #(repo-handler/re-index! nfs-handler/rebuild-index!))]]
-   (rum/with-context [[t] i18n/*tongue-context*]
-     [:div#main-content.cp__sidebar-main-layout.flex-1.flex
-      [:div#sidebar-nav-wrapper.flex-col.pt-4.hidden.sm:block
-       {:style {:flex (if (state/get-left-sidebar-open?)
-                        "0 1 20%"
-                        "0 0 0px")
-                :border-right (str "1px solid "
-                                   (if white? "#f0f8ff" "#073642"))}}
-       (when (state/sub :ui/left-sidebar-open?)
-         (sidebar-nav route-match nil))]
-      [:div#main-content-container.w-full.flex.justify-center
-       {:style {:margin-top (if global-graph-pages? 0 "2rem")}}
-       [:div.cp__sidebar-main-content
-        {:data-is-global-graph-pages global-graph-pages?
-         :data-is-full-width (or global-graph-pages?
-                                 (contains? #{:all-files :all-pages :my-publishing :home} route-name))}
-        (cond
-          (not indexeddb-support?)
-          nil
+  (rum/with-context [[t] i18n/*tongue-context*]
+                    [:div#main-content.cp__sidebar-main-layout.flex-1.flex
+                     [:div#sidebar-nav-wrapper.flex-col.pt-4.hidden.sm:block
+                      {:style {:flex (if (state/get-left-sidebar-open?)
+                                       "0 1 20%"
+                                       "0 0 0px")
+                               :border-right (str "1px solid "
+                                                  (if white? "#f0f8ff" "#073642"))}}
+                      (when (state/sub :ui/left-sidebar-open?)
+                        (sidebar-nav route-match nil))]
+                     [:div#main-content-container.w-full.flex.justify-center
+                      {:style {:margin-top (if global-graph-pages? 0 "2rem")}}
+                      [:div.cp__sidebar-main-content
+                       {:data-is-global-graph-pages global-graph-pages?
+                        :data-is-full-width (or global-graph-pages?
+                                                (contains? #{:all-files :all-pages :my-publishing} route-name))}
+                       (cond
+                         (not indexeddb-support?)
+                         nil
 
-          db-restoring?
-          [:div.mt-20
-           [:div.ls-center
-            (ui/loading (t :loading))]]
+                         db-restoring?
+                         [:div.mt-20
+                          [:div.ls-center
+                           (ui/loading (t :loading))]]
 
-          :else
-          [:div.pb-24 {:class (if global-graph-pages? "" (util/hiccup->class "max-w-7xl.mx-auto"))
-                       :style {:margin-bottom (if global-graph-pages? 0 120)}}
-           main-content])]]])))
+                         :else
+                         [:div.pb-24 {:class (if global-graph-pages? "" (util/hiccup->class "max-w-7xl.mx-auto"))
+                                      :style {:margin-bottom (if global-graph-pages? 0 120)}}
+                          main-content])]]]))
 
 (rum/defc footer
   []
@@ -167,23 +156,23 @@
 ;; TODO: simplify logic
 
 (rum/defc main-content < rum/reactive db-mixins/query
-  {:init (fn [state]
-           (when-not @sidebar-inited?
-             (let [current-repo (state/sub :git/current-repo)
-                   default-home (get-default-home-if-valid)
-                   sidebar (:sidebar default-home)
-                   sidebar (if (string? sidebar) [sidebar] sidebar)]
-               (when-let [pages (->> (seq sidebar)
-                                     (remove nil?))]
-                 (let [blocks (remove nil? pages)]
-                   (doseq [page pages]
-                     (let [page (string/lower-case page)
-                           [db-id block-type] (if (= page "contents")
-                                                ["contents" :contents]
-                                                [page :page])]
-                       (state/sidebar-add-block! current-repo db-id block-type nil))))
-                 (reset! sidebar-inited? true))))
-           state)}
+                         {:init (fn [state]
+                                  (when-not @sidebar-inited?
+                                    (let [current-repo (state/sub :git/current-repo)
+                                          default-home (get-default-home-if-valid)
+                                          sidebar (:sidebar default-home)
+                                          sidebar (if (string? sidebar) [sidebar] sidebar)]
+                                      (when-let [pages (->> (seq sidebar)
+                                                            (remove nil?))]
+                                        (let [blocks (remove nil? pages)]
+                                          (doseq [page pages]
+                                            (let [page (string/lower-case page)
+                                                  [db-id block-type] (if (= page "contents")
+                                                                       ["contents" :contents]
+                                                                       [page :page])]
+                                              (state/sidebar-add-block! current-repo db-id block-type nil))))
+                                        (reset! sidebar-inited? true))))
+                                  state)}
   []
   (let [today (state/sub :today)
         cloning? (state/sub :repo/cloning?)
@@ -197,60 +186,60 @@
         preferred-format (state/sub [:me :preferred_format])
         logged? (:name me)]
     (rum/with-context [[t] i18n/*tongue-context*]
-      [:div
-       (cond
-         (and default-home
-              (= :home (state/get-current-route))
-              (not (state/route-has-p?))
-              (:page default-home))
-         (route-handler/redirect! {:to :page
-                                   :path-params {:name (:page default-home)}})
+                      [:div
+                       (cond
+                         (and default-home
+                              (= :home (state/get-current-route))
+                              (not (state/route-has-p?))
+                              (:page default-home))
+                         (route-handler/redirect! {:to :page
+                                                   :path-params {:name (:page default-home)}})
 
-         (and config/publishing?
-              (not default-home)
-              (empty? latest-journals))
-         (route-handler/redirect! {:to :all-pages})
+                         (and config/publishing?
+                              (not default-home)
+                              (empty? latest-journals))
+                         (route-handler/redirect! {:to :all-pages})
 
-         importing-to-db?
-         (ui/loading (t :parsing-files))
+                         importing-to-db?
+                         (ui/loading (t :parsing-files))
 
-         loading-files?
-         (ui/loading (t :loading-files))
+                         loading-files?
+                         (ui/loading (t :loading-files))
 
-         (and (not logged?) (seq latest-journals))
-         (journal/journals latest-journals)
+                         (and (not logged?) (seq latest-journals))
+                         (journal/journals latest-journals)
 
-         (and logged? (not preferred-format))
-         (widgets/choose-preferred-format)
+                         (and logged? (not preferred-format))
+                         (widgets/choose-preferred-format)
 
-         ;; TODO: delay this
-         (and logged? (nil? (:email me)))
-         (settings/set-email)
+                         ;; TODO: delay this
+                         (and logged? (nil? (:email me)))
+                         (settings/set-email)
 
-         cloning?
-         (ui/loading (t :cloning))
+                         cloning?
+                         (ui/loading (t :cloning))
 
-         (seq latest-journals)
-         (journal/journals latest-journals)
+                         (seq latest-journals)
+                         (journal/journals latest-journals)
 
-         (and logged? (empty? (:repos me)))
-         (widgets/add-graph)
+                         (and logged? (empty? (:repos me)))
+                         (widgets/add-graph)
 
-         ;; FIXME: why will this happen?
-         :else
-         [:div])])))
+                         ;; FIXME: why will this happen?
+                         :else
+                         [:div])])))
 
 (rum/defc custom-context-menu < rum/reactive
   []
   (when (state/sub :custom-context-menu/show?)
     (when-let [links (state/sub :custom-context-menu/links)]
       (ui/css-transition
-       {:class-names "fade"
-        :timeout {:enter 500
-                  :exit 300}}
-       links
-       ;; (custom-context-menu-content)
-       ))))
+        {:class-names "fade"
+         :timeout {:enter 500
+                   :exit 300}}
+        links
+        ;; (custom-context-menu-content)
+        ))))
 
 (rum/defc new-block-mode < rum/reactive
   []
@@ -274,11 +263,11 @@
   (when-not (state/sub :ui/sidebar-open?)
     ;; TODO: remove with-context usage
     (rum/with-context [[t] i18n/*tongue-context*]
-      [:div.cp__sidebar-help-btn
-       {:title (t :help-shortcut-title)
-        :on-click (fn []
-                    (state/sidebar-add-block! (state/get-current-repo) "help" :help nil))}
-       "?"])))
+                      [:div.cp__sidebar-help-btn
+                       {:title (t :help-shortcut-title)
+                        :on-click (fn []
+                                    (state/sidebar-add-block! (state/get-current-repo) "help" :help nil))}
+                       "?"])))
 
 (rum/defc settings-modal < rum/reactive
   []
@@ -286,7 +275,7 @@
     (if settings-open?
       (do
         (state/set-modal!
-         (fn [] [:div.settings-modal (settings/settings)]))
+          (fn [] [:div.settings-modal (settings/settings)]))
         (util/lock-global-scroll settings-open?))
       (state/set-modal! nil))
     nil))
@@ -295,12 +284,12 @@
   (mixins/modal :modal/show?)
   rum/reactive
   (mixins/event-mixin
-   (fn [state]
-     (mixins/listen state js/window "click"
-                    (fn [e]
-                      ;; hide context menu
-                      (state/hide-custom-context-menu!)
-                      (editor-handler/clear-selection! e)))))
+    (fn [state]
+      (mixins/listen state js/window "click"
+                     (fn [e]
+                       ;; hide context menu
+                       (state/hide-custom-context-menu!)
+                       (editor-handler/clear-selection! e)))))
   [state route-match main-content]
   (let [{:keys [open? close-fn open-fn]} state
         close-fn (fn []
@@ -322,58 +311,56 @@
         home? (= :home route-name)
         default-home (get-default-home-if-valid)]
     (rum/with-context [[t] i18n/*tongue-context*]
-      (theme/container
-       {:theme         theme
-        :route         route-match
-        :current-repo  current-repo
-        :nfs-granted?  granted?
-        :db-restoring? db-restoring?
-        :sidebar-open? sidebar-open?
-        :system-theme? system-theme?
-        :on-click      #(do
-                          (editor-handler/unhighlight-blocks!)
-                          (util/fix-open-external-with-shift! %))}
+                      (theme/container
+                        {:theme         theme
+                         :route         route-match
+                         :current-repo  current-repo
+                         :nfs-granted?  granted?
+                         :db-restoring? db-restoring?
+                         :sidebar-open? sidebar-open?
+                         :system-theme? system-theme?
+                         :on-click      #(do
+                                           (editor-handler/unhighlight-blocks!)
+                                           (util/fix-open-external-with-shift! %))}
 
-       [:div.theme-inner
-        (sidebar-mobile-sidebar
-         {:open?       open?
-          :close-fn    close-fn
-          :route-match route-match})
-        [:div.#app-container.h-screen.flex
-         [:div.flex-1.h-full.flex.flex-col#left-container.relative
-          {:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
-          (header/header {:open-fn        open-fn
-                          :white?         white?
-                          :current-repo   current-repo
-                          :logged?        logged?
-                          :page?          page?
-                          :route-match    route-match
-                          :me             me
-                          :default-home   default-home
-                          :new-block-mode new-block-mode})
+                        [:div.theme-inner
+                         (sidebar-mobile-sidebar
+                           {:open?       open?
+                            :close-fn    close-fn
+                            :route-match route-match})
+                         [:div.#app-container.h-screen.flex
+                          [:div.flex-1.h-full.flex.flex-col#left-container.relative
+                           {:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
+                           (header/header {:open-fn        open-fn
+                                           :white?         white?
+                                           :current-repo   current-repo
+                                           :logged?        logged?
+                                           :page?          page?
+                                           :route-match    route-match
+                                           :me             me
+                                           :default-home   default-home
+                                           :new-block-mode new-block-mode})
 
-          [:div#main-container.scrollbar-spacing
-           (main {:route-match         route-match
-                  :global-graph-pages? global-graph-pages?
-                  :logged?             logged?
-                  :home?               home?
-                  :route-name          route-name
-                  :indexeddb-support?  indexeddb-support?
-                  :white?              white?
-                  :db-restoring?       db-restoring?
-                  :main-content        main-content})]
+                           [:div#main-container.scrollbar-spacing
+                            (main {:route-match         route-match
+                                   :global-graph-pages? global-graph-pages?
+                                   :logged?             logged?
+                                   :home?               home?
+                                   :route-name          route-name
+                                   :indexeddb-support?  indexeddb-support?
+                                   :white?              white?
+                                   :db-restoring?       db-restoring?
+                                   :main-content        main-content})]
 
-          (footer)]
-         (right-sidebar/sidebar)
+                           (footer)]
+                          (right-sidebar/sidebar)]
 
-         [:div#app-single-container]]
-
-        (ui/notification)
-        (ui/modal)
-        (settings-modal)
-        (custom-context-menu)
-        [:a#download.hidden]
-        (when
-         (and (not config/mobile?)
-              (not config/publishing?))
-          (help-button))]))))
+                         (ui/notification)
+                         (ui/modal)
+                         (settings-modal)
+                         (custom-context-menu)
+                         [:a#download.hidden]
+                         (when
+                           (and (not config/mobile?)
+                                (not config/publishing?))
+                           (help-button))]))))

+ 6 - 0
src/main/frontend/date.cljs

@@ -218,6 +218,12 @@
   [n]
   (get-date-time-string (t/to-default-time-zone (tc/from-long n))))
 
+(defn int->local-time-2
+  [n]
+  (tf/unparse
+   (tf/formatter "yyyy-MM-dd HH:mm")
+   (t/to-default-time-zone (tc/from-long n))))
+
 (comment
   (def default-formatter (tf/formatter "MMM do, yyyy"))
   (def zh-formatter (tf/formatter "YYYY年MM月dd日"))

+ 12 - 11
src/main/frontend/extensions/calc.cljc

@@ -29,34 +29,35 @@
   (insta/transform
    {:number     (comp edn/read-string #(str/replace % "," ""))
     :scientific edn/read-string
+    :negterm    (fn neg [a] (- a))
     :expr       identity
     :add        +
     :sub        -
     :mul        *
     :div        /
-    :pow        (fn [a b]
+    :pow        (fn pow [a b]
                   #?(:clj (java.lang.Math/pow a b) :cljs (js/Math.pow a b)))
-    :log        (fn [a]
+    :log        (fn log [a]
                   #?(:clj (java.lang.Math/log10 a) :cljs (js/Math.log10 a)))
-    :ln         (fn [a]
+    :ln         (fn ln [a]
                   #?(:clj (java.lang.Math/log a) :cljs (js/Math.log a)))
-    :sin        (fn [a]
+    :sin        (fn sin [a]
                   #?(:clj (java.lang.Math/sin a) :cljs (js/Math.sin a)))
-    :cos        (fn [a]
+    :cos        (fn cos [a]
                   #?(:clj (java.lang.Math/cos a) :cljs (js/Math.cos a)))
-    :tan        (fn [a]
+    :tan        (fn tan [a]
                   #?(:clj (java.lang.Math/tan a) :cljs (js/Math.tan a)))
-    :atan       (fn [a]
+    :atan       (fn atan [a]
                   #?(:clj (java.lang.Math/atan a) :cljs (js/Math.atan a)))
-    :asin       (fn [a]
+    :asin       (fn asin [a]
                   #?(:clj (java.lang.Math/asin a) :cljs (js/Math.asin a)))
-    :acos       (fn [a]
+    :acos       (fn acos [a]
                   #?(:clj (java.lang.Math/acos a) :cljs (js/Math.acos a)))
-    :assignment (fn [var val]
+    :assignment (fn assign! [var val]
                   (swap! env assoc var val)
                   val)
     :toassign   str/trim
-    :variable   (fn [var]
+    :variable   (fn resolve [var]
                   (let [var (str/trim var)]
                     (or (get @env var)
                         (throw

+ 2 - 1
src/main/frontend/extensions/code.cljs

@@ -12,6 +12,7 @@
             [clojure.string :as string]
             [dommy.core :as dom]
             [frontend.utf8 :as utf8]
+            [frontend.util.property :as property]
             ["codemirror" :as cm]
             ["codemirror/addon/edit/matchbrackets"]
             ["codemirror/addon/edit/closebrackets"]
@@ -63,7 +64,7 @@
         (:block/uuid config)
         (let [block (db/pull [:block/uuid (:block/uuid config)])
               format (:block/format block)
-              content (:block/content block)
+              content (property/remove-properties format (:block/content block))
               full-content (:full_content (last (:rum/args state)))]
           (when (and full-content (string/includes? content full-content))
             (let [lines (string/split-lines full-content)

+ 9 - 1
src/main/frontend/extensions/sci.cljs

@@ -1,10 +1,18 @@
 (ns frontend.extensions.sci
   (:require [sci.core :as sci]))
 
+;; Some helpers
+(def sum (partial apply +))
+
+(defn average [coll]
+  (def coll coll)
+  (/ (reduce + coll) (count coll)))
+
 (defn eval-string
   [s]
   (try
-    (sci/eval-string s)
+    (sci/eval-string s {:bindings {'sum sum
+                                   'average average}})
     (catch js/Error e
       (println "Query: sci eval failed:")
       (js/console.error e))))

+ 35 - 18
src/main/frontend/handler/editor.cljs

@@ -819,24 +819,25 @@
                                            (let [block (db/entity [:block/uuid block-id])]
                                              (seq (:block/_parent block)))))]
              (when-not (and has-children? left-has-children?)
-               (let [block-parent (gdom/getElement block-parent-id)
-                     sibling-block (util/get-prev-block-non-collapsed block-parent)]
-                 (delete-block-aux! block delete-children?)
-                 (when (and repo sibling-block)
-                   (when-let [sibling-block-id (dom/attr sibling-block "blockid")]
-                     (when-let [block (db/pull repo '[*] [:block/uuid (uuid sibling-block-id)])]
-                       (let [original-content (util/trim-safe (:block/content block))
-                             new-value (str original-content " " (string/triml value))
-                             tail-len (count (string/triml value))
-                             pos (max
-                                  (if original-content
-                                    (utf8/length (utf8/encode original-content))
-                                    0)
-                                  0)]
-                         (edit-block! block pos format id
-                                      {:custom-content new-value
-                                       :tail-len tail-len
-                                       :move-cursor? false}))))))))))))
+               (when block-parent-id
+                 (let [block-parent (gdom/getElement block-parent-id)
+                       sibling-block (util/get-prev-block-non-collapsed block-parent)]
+                   (delete-block-aux! block delete-children?)
+                   (when (and repo sibling-block)
+                     (when-let [sibling-block-id (dom/attr sibling-block "blockid")]
+                       (when-let [block (db/pull repo '[*] [:block/uuid (uuid sibling-block-id)])]
+                         (let [original-content (util/trim-safe (:block/content block))
+                               new-value (str original-content " " (string/triml value))
+                               tail-len (count (string/triml value))
+                               pos (max
+                                    (if original-content
+                                      (utf8/length (utf8/encode original-content))
+                                      0)
+                                    0)]
+                           (edit-block! block pos format id
+                                        {:custom-content new-value
+                                         :tail-len tail-len
+                                         :move-cursor? false})))))))))))))
    (state/set-editor-op! nil)))
 
 (defn- get-end-block-parent
@@ -922,6 +923,22 @@
   (let [key (keyword key)]
     (block-property-aux! block-id key value)))
 
+(defn set-block-query-properties!
+  [block-id all-properties key add?]
+  (when-let [block (db/entity [:block/uuid block-id])]
+    (let [query-properties (-> (get-in block [:block/properties :query-properties] "")
+                               (common-handler/safe-read-string "Failed to parse query properties"))
+          query-properties (if (seq query-properties)
+                             query-properties
+                             all-properties)
+          query-properties (if add?
+                             (distinct (conj query-properties key))
+                             (remove #{key} query-properties))
+          query-properties (vec query-properties)]
+      (if (seq query-properties)
+        (set-block-property! block-id :query-properties (str query-properties))
+        (remove-block-property! block-id :query-properties)))))
+
 (defn set-block-timestamp!
   [block-id key value]
   (let [key (string/lower-case key)

+ 52 - 9
src/main/frontend/handler/events.cljs

@@ -7,6 +7,8 @@
             [frontend.util :as util :refer [profile]]
             [frontend.config :as config]
             [frontend.handler.notification :as notification]
+            [frontend.handler.common :as common-handler]
+            [frontend.handler.editor :as editor-handler]
             [frontend.components.encryption :as encryption]
             [frontend.fs.nfs :as nfs]
             [frontend.db.conn :as conn]
@@ -14,7 +16,9 @@
             [frontend.db-schema :as db-schema]
             [frontend.db :as db]
             [datascript.core :as d]
-            ["semver" :as semver]))
+            ["semver" :as semver]
+            [clojure.set :as set]
+            [rum.core :as rum]))
 
 ;; TODO: should we move all events here?
 
@@ -30,8 +34,8 @@
       "Please make sure that you've installed the logseq app for the repo %s on GitHub. "
       repo-url)
      (ui/button
-      "Install Logseq on GitHub"
-      :href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
+       "Install Logseq on GitHub"
+       :href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
    :error
    false))
 
@@ -86,17 +90,56 @@
         "Grant native filesystem permission for directory: "
         [:b (config/get-local-dir repo)]]
        (ui/button
-        "Grant"
-        :class "ui__modal-enter"
-        :on-click (fn []
-                    (nfs/check-directory-permission! repo)
-                    (close-fn)))])))
+         "Grant"
+         :class "ui__modal-enter"
+         :on-click (fn []
+                     (nfs/check-directory-permission! repo)
+                     (close-fn)))])))
 
 (defmethod handle :modal/nfs-ask-permission []
   (when-let [repo (get-local-repo)]
     (state/set-modal! (ask-permission repo))))
 
-
+(defonce *query-properties (atom {}))
+(rum/defc query-properties-settings-inner < rum/reactive
+  {:will-unmount (fn [state]
+                   (reset! *query-properties {})
+                   state)}
+  [block shown-properties all-properties close-fn]
+  (let [query-properties (rum/react *query-properties)]
+    [:div.p-4
+     [:div.font-bold "Properties settings for this query:"]
+     (for [property all-properties]
+       (let [property-value (get query-properties property)
+             shown? (if (nil? property-value)
+                      (contains? shown-properties property)
+                      property-value)]
+         [:div.flex.flex-row.m-2.justify-between.align-items
+          [:div (name property)]
+          [:div.mt-1 (ui/toggle shown?
+                                (fn []
+                                  (let [value (not shown?)]
+                                    (swap! *query-properties assoc property value)
+                                    (editor-handler/set-block-query-properties!
+                                     (:block/uuid block)
+                                     all-properties
+                                     property
+                                     value)))
+                                true)]]))]))
+
+(defn query-properties-settings
+  [block shown-properties all-properties]
+  (fn [close-fn]
+    (query-properties-settings-inner block shown-properties all-properties close-fn)))
+
+(defmethod handle :modal/set-query-properties [[_ block all-properties]]
+  (let [block-properties (some-> (get-in block [:block/properties :query-properties])
+                                 (common-handler/safe-read-string "Parsing query properties failed"))
+        shown-properties (if (seq block-properties)
+                           (set block-properties)
+                           (set all-properties))
+        shown-properties (set/intersection (set all-properties) shown-properties)]
+    (state/set-modal! (query-properties-settings block shown-properties all-properties))))
 
 (defmethod handle :after-db-restore [[_ repos]]
   (mapv (fn [{url :url} repo]

+ 8 - 8
src/main/frontend/handler/plugin.cljs

@@ -40,11 +40,11 @@
 
 (defn register-plugin-slash-command
   [pid [cmd actions]]
-  (prn (if-let [pid (keyword pid)]
-         (when (contains? (:plugin/installed-plugins @state/state) pid)
-           (do (swap! state/state update-in [:plugin/installed-commands pid]
-                      (fnil merge {}) (hash-map cmd (mapv #(conj % {:pid pid}) actions)))
-               true)))))
+  (when-let [pid (keyword pid)]
+    (when (contains? (:plugin/installed-plugins @state/state) pid)
+      (do (swap! state/state update-in [:plugin/installed-commands pid]
+                 (fnil merge {}) (hash-map cmd (mapv #(conj % {:pid pid}) actions)))
+          true))))
 
 (defn unregister-plugin-slash-command
   [pid]
@@ -52,8 +52,8 @@
 
 (defn register-plugin-simple-command
   ;; action => [:action-key :event-key]
-  [pid {:keys [key label type] :as cmd}  action]
-  (if-let [pid (keyword pid)]
+  [pid {:keys [key label type] :as cmd} action]
+  (when-let [pid (keyword pid)]
     (when (contains? (:plugin/installed-plugins @state/state) pid)
       (do (swap! state/state update-in [:plugin/simple-commands pid]
                  (fnil conj []) [type cmd action pid])
@@ -66,7 +66,7 @@
 (defn register-plugin-ui-item
   [pid {:keys [key type template] :as opts}]
   (when-let [pid (keyword pid)]
-    (when (or true (contains? (:plugin/installed-plugins @state/state) pid))
+    (when (contains? (:plugin/installed-plugins @state/state) pid)
       (do (swap! state/state update-in [:plugin/installed-ui-items pid]
                  (fnil conj []) [type opts pid])
           true))))

+ 46 - 0
src/main/frontend/handler/query.cljs

@@ -0,0 +1,46 @@
+(ns frontend.handler.query
+  (:require [clojure.walk :as walk]))
+
+(defn normalize-query-function
+  [ast result]
+  (let [ast (walk/prewalk
+             (fn [f]
+               (if (and (list? f)
+                        (keyword? (second f))
+                        (contains? #{'sum 'average 'count 'min 'max} (first f)))
+                 (if (contains? #{'min 'max} (first f))
+                   (list
+                    'apply
+                    (first f)
+                    (list 'map (second f) 'result))
+                   (list
+                    (first f)
+                    (list 'map (second f) 'result)))
+                 f))
+             ast)]
+    (walk/postwalk
+     (fn [f]
+       (cond
+         (keyword? f)
+         (case f
+           :block
+           :block/content
+
+           :page
+           :block/name
+
+           :created-at
+           :block/created-at
+
+           :updated-at
+           :block/updated-at
+
+           (let [vals (map #(get-in % [:block/properties f]) result)
+                 int? (some integer? vals)]
+             `(~'fn [~'b]
+               (~'let [~'result (~'get-in ~'b [:block/properties ~f])]
+                (~'or ~'result (~'when ~int? 0))))))
+
+         :else
+         f))
+     ast)))

+ 4 - 1
src/main/frontend/modules/instrumentation/sentry.cljs

@@ -3,6 +3,7 @@
             [frontend.util :as util]
             [frontend.config :as cfg]
             ["@sentry/browser" :as Sentry]
+            ["@sentry/electron" :as Sentry-electron]
             ["posthog-js" :as posthog]))
 
 (def config
@@ -14,4 +15,6 @@
    :tracesSampleRate 1.0})
 
 (defn init []
-  (Sentry/init (clj->js config)))
+  (let [config (clj->js config)
+        init-fn (if (util/electron?) Sentry-electron/init Sentry/init)]
+    (Sentry/init config)))

+ 1 - 1
src/main/frontend/search/db.cljs

@@ -17,7 +17,7 @@
 (defn block->index
   [{:block/keys [uuid content format page] :as block}]
   (when-let [result (->> (text/remove-level-spaces content format)
-                         (property/remove-id-property format))]
+                         (property/remove-built-in-properties format))]
     {:id (:db/id block)
      :uuid (str uuid)
      :page page

+ 1 - 1
src/main/frontend/ui.cljs

@@ -446,7 +446,7 @@
              "exiting" "ease-in duration-200 opacity-100 translate-y-0 sm:scale-100"
              "exited" "ease-in duration-200 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95")}
    [:div.absolute.top-0.right-0.pt-2.pr-2
-    [:button.ui__modal-close
+    [:a.ui__modal-close.opacity-60.hover:opacity-100
      {:aria-label "Close"
       :type       "button"
       :on-click   close-fn}

+ 1 - 1
src/main/frontend/util/property.cljs

@@ -14,7 +14,7 @@
 
 (def built-in-properties
   (set/union
-   #{:id :custom-id :background-color :heading :collapsed :created-at :updated-at :last-modified-at :created_at :last_modified_at :query-table}
+   #{:id :custom-id :background-color :heading :collapsed :created-at :updated-at :last-modified-at :created_at :last_modified_at :query-table :query-properties}
    (set (map keyword config/markers))))
 
 (defn properties-built-in?

+ 1 - 1
src/main/frontend/version.cljs

@@ -1,3 +1,3 @@
 (ns frontend.version)
 
-(defonce version "0.2.5")
+(defonce version "0.2.6")

+ 9 - 7
src/main/grammar/calc.bnf

@@ -1,14 +1,14 @@
 <start> = assignment | expr
 expr = add-sub
-<add-sub> = pow-log | mul-div | add | sub |  variable
+<add-sub> = pow-term | mul-div | add | sub |  variable
 add = add-sub <'+'> mul-div
 sub = add-sub <'-'> mul-div
-<mul-div> = pow-log | mul | div
-mul = mul-div <'*'> pow-log
-div = mul-div <'/'> pow-log
+<mul-div> = pow-term | mul | div
+mul = mul-div <'*'> pow-term
+div = mul-div <'/'> pow-term
+<pow-term> = pow | term
+pow = pow-term <'^'> term
 <trig> = sin | cos | tan | acos | asin | atan
-<pow-log> = term | pow | log | ln | trig
-pow = pow-log <'^'> term
 log = <#'\s*'> <'log('> expr <')'> <#'\s*'>
 ln = <#'\s*'> <'ln('> expr <')'> <#'\s*'>
 sin = <#'\s*'> <'sin('> expr <')'> <#'\s*'>
@@ -17,7 +17,9 @@ tan = <#'\s*'> <'tan('> expr <')'> <#'\s*'>
 atan = <#'\s*'> <'atan('> expr <')'> <#'\s*'>
 acos = <#'\s*'> <'acos('> expr <')'> <#'\s*'>
 asin = <#'\s*'> <'asin('> expr <')'> <#'\s*'>
-<term> = scientific | number | variable | <#'\s*'> <'('> expr <')'> <#'\s*'>
+<posterm> = log | ln | trig | scientific | number | variable | <#'\s*'> <'('> expr <')'> <#'\s*'>
+negterm = <#'\s*'> <'-'> posterm
+<term> = negterm | posterm
 scientific = #'\s*[0-9]+\.?[0-9]*(e|E)-?[0-9]+()\s*'
 number = #'\s*\d+(,\d+)*(\.\d*)?\s*'
 variable = #'\s*[a-zA-Z]+(\_+[a-zA-Z]+)*\s*'

+ 8 - 4
src/main/logseq/api.cljs

@@ -242,14 +242,18 @@
       (js/apis.openExternal url))))
 
 (def ^:export push_state
-  (fn [^js k ^js params]
+  (fn [^js k ^js params ^js query]
     (rfe/push-state
-     (keyword k) (bean/->clj params))))
+     (keyword k)
+     (bean/->clj params)
+     (bean/->clj query))))
 
 (def ^:export replace_state
-  (fn [^js k ^js params]
+  (fn [^js k ^js params ^js query]
     (rfe/replace-state
-     (keyword k) (bean/->clj params))))
+     (keyword k)
+     (bean/->clj params)
+     (bean/->clj query))))
 
 ;; editor
 (def ^:export check_editing

+ 20 - 2
src/test/frontend/extensions/calc_test.cljc

@@ -22,7 +22,12 @@
         98123      "9,8,123"
         1123.0     " 112,3.0 "
         22.1124131 "2,2.1124131"
-        100.01231  " 1,00.01231 ")))
+        100.01231  " 1,00.01231 "))
+    (testing "even when they are negative"
+      (are [value expr] (= value (run expr))
+        -98123      "-98123"
+        -1123.0     " -112,3.0 "
+        -22.1124131 "-2,2.1124131")))
   (testing "basic operations work"
     (are [value expr] (= value (run expr))
       1             "1 + 0"
@@ -32,11 +37,15 @@
       1             "(2-1 ) "
       211           "100  + 111"
       2111          "1,000  + 11,11"
+      -111          "1,000  + -11,11"
       0             "1 + 2 + 3 + 4 + 5 -1-2-3-4-5"
       1             "1 * 1"
+      -1            "1 * -1"
       2             "1*2"
+      -2            "-1*2"
       9             " 3 *3"
       1             " 2 * 3 / 3 / 2"
+      -1            " 2 * 3 / 3 / -2"
       #?(:clj 1/2
          :cljs 0.5) " 1 / 2"
       0.5           " 1/ 2.0"))
@@ -45,6 +54,7 @@
       1.0   "1 ^ 0"
       4.0   "2^2 "
       27.0  " 3^ 3"
+      0.125 " 2^ -3"
       16.0  "2 ^ 2 ^ 2"
       256.0 "4.000 ^ 4.0"))
   (testing "operator precedence"
@@ -54,6 +64,8 @@
       4     "8 / 4 + 2 * 1 - 25 * 0 / 1"
       14.0  "3 *2 ^ 2 + 1 * 2"
       74.0  "((3*2) ^ 2 + 1) * 2"
+      -74.0 "((3*2) ^ 2 + 1) * -2"
+      74.0  "-((3*2) ^ 2 + 1) * -2"
       432.0 "(3*2) ^ (2 + 1) * 2"
       97.0  "(2 * 3) * 2 ^ (2 * 2) + 1"
       4.0   "2 * 3 / 2 ^ 2 * 2 + 1"))
@@ -62,6 +74,7 @@
       1.0e1    "1.0e01"
       1.23e-10 "123.0e-12"
       12.3     "123.0e-1"
+      -12.3    "-123.0e-1"
       12.3     "123.0E-1"
       2.0      "1e0 + 1e0"))
   (testing "scientific functions"
@@ -70,8 +83,10 @@
       0.0  "sin( 1 -1 )"
       0.0  "atan(tan(0))"
       1.0  "sin(asin(0)) + 1"
+      1.0  "-sin(asin(0)) + 1"
       0.0  "acos(cos(0))"
       5.0  "2 * log(10) + 3"
+      1.0  "-2 * log(10) + 3"
       10.0 "ln(1) + 10")))
 
 (deftest variables
@@ -80,9 +95,11 @@
                             (calc/eval env (calc/parse expr))
                             (= final-env @env))
       {"a" 1}        "a = 1"
+      {"a" -1}        "a = -1"
       {"variable" 1} "variable = 1 + 0 * 2"
       {"x" 1}        "x= 2 * 1 - 1 "
       {"y" 4}        "y =8 / 4 + 2 * 1 - 25 * 0 / 1"
+      {"y" 4}        "y =8 / 4 + 2 * 1 - 25 * 0 / 1"
       {"zzz" 14.0}   "zzz=3 *2 ^ 2 + 1 * 2"
       {"foo" 74.0}   "foo = (((3*2) ^ 2 + 1) * 2)"))
   (testing "variables can have underscores"
@@ -91,13 +108,14 @@
                             (= final-env @env))
       {"a_a" 1}         "a_a = 1"
       {"x_yy_zzz" 1}    "x_yy_zzz= 1"
-      {"foo_bar_baz" 1} "foo_bar_baz = 1 + 0 * 2"))
+      {"foo_bar_baz" 1} "foo_bar_baz = 1 + -0 * 2"))
   (testing "variables can be reused"
     (are [final-env exprs] (let [env (calc/new-env)]
                              (doseq [expr exprs]
                                (calc/eval env (calc/parse expr)))
                              (= final-env @env))
       {"a" 1 "b" 2}          ["a = 1" "b = a + 1"]
+      {"a" 1 "b" 0}          ["a = 1" "b = -a + 1"]
       {"a" 1 "b" 3}          ["a = 1" "b=a*2+1"]
       {"a_a" 1 "b_b" 2}      ["a_a = 1" "b_b = a_a + 1"]
       {"variable" 1 "x" 0.0} ["variable = 1 + 0 * 2" "x = log(variable)"]

+ 132 - 16
yarn.lock

@@ -1202,6 +1202,16 @@
   resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
   integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
 
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.7.1.tgz#e01144a08984a486ecc91d7922cc457e9c9bd6b7"
+  integrity sha512-R5PYx4TTvifcU790XkK6JVGwavKaXwycDU0MaAwfc4Vf7BLm5KCNJCsDySu1RPAap/017MVYf54p6dWvKiRviA==
+  dependencies:
+    "@sentry/core" "6.7.1"
+    "@sentry/types" "6.7.1"
+    "@sentry/utils" "6.7.1"
+    tslib "^1.9.3"
+
 "@sentry/browser@^6.4.1":
   version "6.4.1"
   resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.4.1.tgz#b6c62736caaade7fdf6638513d9aad138abde2ac"
@@ -1223,6 +1233,30 @@
     "@sentry/utils" "6.4.1"
     tslib "^1.9.3"
 
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.7.1.tgz#c3aaa6415d06bec65ac446b13b84f073805633e3"
+  integrity sha512-VAv8OR/7INn2JfiLcuop4hfDcyC7mfL9fdPndQEhlacjmw8gRrgXjR7qyhnCTgzFLkHI7V5bcdIzA83TRPYQpA==
+  dependencies:
+    "@sentry/hub" "6.7.1"
+    "@sentry/minimal" "6.7.1"
+    "@sentry/types" "6.7.1"
+    "@sentry/utils" "6.7.1"
+    tslib "^1.9.3"
+
+"@sentry/electron@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.1.tgz#6d1d42117e074c4b9f2f200def8ffb602c0221b6"
+  integrity sha512-1rVE1IgGZTAy2qlLQxDsuhv7/0sT88oHYyD4f6ZTDzge3lsReeMu4xA32M4ldo4yRlRQM5gpdSS/D7Q/4huH0A==
+  dependencies:
+    "@sentry/browser" "6.7.1"
+    "@sentry/core" "6.7.1"
+    "@sentry/minimal" "6.7.1"
+    "@sentry/node" "6.7.1"
+    "@sentry/types" "6.7.1"
+    "@sentry/utils" "6.7.1"
+    tslib "^2.2.0"
+
 "@sentry/[email protected]":
   version "6.4.1"
   resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.4.1.tgz#fa9c05ca32674e2e8477120b71084a1c91a5e023"
@@ -1232,6 +1266,15 @@
     "@sentry/utils" "6.4.1"
     tslib "^1.9.3"
 
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.7.1.tgz#d46d24deec67f0731a808ca16796e6765b371bc1"
+  integrity sha512-eVCTWvvcp6xa0A5GGNHMQEWslmKPlisE5rGmsV/kjvSUv3zSrI0eIDfb51ikdnCiBjHpK2NBWP8Vy8cZOEJegg==
+  dependencies:
+    "@sentry/types" "6.7.1"
+    "@sentry/utils" "6.7.1"
+    tslib "^1.9.3"
+
 "@sentry/[email protected]":
   version "6.4.1"
   resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.4.1.tgz#d3f968c060c3d3cc997071756659e24047b5dd97"
@@ -1241,11 +1284,51 @@
     "@sentry/types" "6.4.1"
     tslib "^1.9.3"
 
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.7.1.tgz#babf85ee2f167e9dcf150d750d7a0b250c98449c"
+  integrity sha512-HDDPEnQRD6hC0qaHdqqKDStcdE1KhkFh0RCtJNMCDn0zpav8Dj9AteF70x6kLSlliAJ/JFwi6AmQrLz+FxPexw==
+  dependencies:
+    "@sentry/hub" "6.7.1"
+    "@sentry/types" "6.7.1"
+    tslib "^1.9.3"
+
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.7.1.tgz#b09e2eca8e187168feba7bd865a23935bf0f5cc0"
+  integrity sha512-rtZo1O8ROv4lZwuljQz3iFZW89oXSlgXCG2VqkxQyRspPWu89abROpxLjYzsWwQ8djnur1XjFv51kOLDUTS6Qw==
+  dependencies:
+    "@sentry/core" "6.7.1"
+    "@sentry/hub" "6.7.1"
+    "@sentry/tracing" "6.7.1"
+    "@sentry/types" "6.7.1"
+    "@sentry/utils" "6.7.1"
+    cookie "^0.4.1"
+    https-proxy-agent "^5.0.0"
+    lru_map "^0.3.3"
+    tslib "^1.9.3"
+
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.7.1.tgz#b11f0c17a6c5dc14ef44733e5436afb686683268"
+  integrity sha512-wyS3nWNl5mzaC1qZ2AIp1hjXnfO9EERjMIJjCihs2LWBz1r3efxrHxJHs8wXlNWvrT3KLhq/7vvF5CdU82uPeQ==
+  dependencies:
+    "@sentry/hub" "6.7.1"
+    "@sentry/minimal" "6.7.1"
+    "@sentry/types" "6.7.1"
+    "@sentry/utils" "6.7.1"
+    tslib "^1.9.3"
+
 "@sentry/[email protected]":
   version "6.4.1"
   resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.4.1.tgz#7c0a4355a1d04321b901197723a8f55c263226e9"
   integrity sha512-sTu/GaLsLYk1AkAqpkMT4+4q665LtZjhV0hkgiTD4N3zPl5uSf1pCIzxPRYjOpe7NEANmWv8U4PaGKGtc2eMfA==
 
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b"
+  integrity sha512-9AO7HKoip2MBMNQJEd6+AKtjj2+q9Ze4ooWUdEvdOVSt5drg7BGpK221/p9JEOyJAZwEPEXdcMd3VAIMiOb4MA==
+
 "@sentry/[email protected]":
   version "6.4.1"
   resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.4.1.tgz#55fa7da58898773cbd538e4895fc2e4ec695ecab"
@@ -1254,6 +1337,14 @@
     "@sentry/types" "6.4.1"
     tslib "^1.9.3"
 
+"@sentry/[email protected]":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.7.1.tgz#909184ad580f0f6375e1e4d4a6ffd33dfe64a4d1"
+  integrity sha512-Tq2otdbWlHAkctD+EWTYKkEx6BL1Qn3Z/imkO06/PvzpWvVhJWQ5qHAzz5XnwwqNHyV03KVzYB6znq1Bea9HuA==
+  dependencies:
+    "@sentry/types" "6.7.1"
+    tslib "^1.9.3"
+
 "@sindresorhus/is@^0.14.0":
   version "0.14.0"
   resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz"
@@ -1469,6 +1560,13 @@ acorn@^7.0.0:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz"
   integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
 
+agent-base@6:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+  integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+  dependencies:
+    debug "4"
+
 aggregate-error@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz"
@@ -2833,6 +2931,11 @@ convert-source-map@~1.1.0:
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
   integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=
 
+cookie@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
+  integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
+
 copy-descriptor@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz"
@@ -3236,6 +3339,13 @@ dayjs@^1.10.4:
   resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.5.tgz#5600df4548fc2453b3f163ebb2abbe965ccfb986"
   integrity sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==
 
+debug@4, [email protected]:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
+  integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
+  dependencies:
+    ms "2.1.2"
+
 [email protected]:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
@@ -3243,13 +3353,6 @@ [email protected]:
   dependencies:
     ms "^2.1.1"
 
[email protected]:
-  version "4.3.2"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
-  integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
-  dependencies:
-    ms "2.1.2"
-
 debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz"
@@ -4785,6 +4888,14 @@ https-browserify@^1.0.0:
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz"
   integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
 
+https-proxy-agent@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
+  integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
+  dependencies:
+    agent-base "6"
+    debug "4"
+
 human-signals@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
@@ -5771,6 +5882,11 @@ lru-cache@^6.0.0:
   dependencies:
     yallist "^4.0.0"
 
+lru_map@^0.3.3:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
+  integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=
+
 make-iterator@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz"
@@ -6049,10 +6165,10 @@ mkdirp@^0.5.0, mkdirp@^0.5.4, mkdirp@~0.5.1:
   dependencies:
     minimist "^1.2.5"
 
[email protected].8:
-  version "0.8.8"
-  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-0.8.8.tgz#4076f00712108caba3fbf4e5df4e2945b407d2c7"
-  integrity sha512-bulOsjdZS6jFVsgK2lwqZMNd5+liHlwFb2xwrovMdxnTFQ5F150k+RZF32RRZx6z62Y43RJUb+2vLGpXJK0qZQ==
[email protected].9:
+  version "0.8.9"
+  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-0.8.9.tgz#801092f7fabfaa5a4173b05da3876d311e634dda"
+  integrity sha512-WIZMqQYPFAxQi1O8lkPcx1cxSCyzLSCr1x6ZvdTwhY3YnEUjywe2pD5poMg0meSkfEme7H6yX+/jKZLHPgNRUw==
   dependencies:
     yargs "^12.0.2"
 
@@ -7482,11 +7598,6 @@ react-grid-layout@^0.16.6:
     react-draggable "3.x"
     react-resizable "1.x"
 
[email protected]:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/react-icon-base/-/react-icon-base-2.1.0.tgz#a196e33fdf1e7aaa1fda3aefbb68bdad9e82a79d"
-  integrity sha1-oZbjP98eeqof2jrvu2i9rZ6Cp50=
-
 react-icons@^2.2.7:
   version "2.2.7"
   resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-2.2.7.tgz#d7860826b258557510dac10680abea5ca23cf650"
@@ -8985,6 +9096,11 @@ tslib@^1.9.0, tslib@^1.9.3:
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 
+tslib@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
+  integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
+
 [email protected]:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz"

Some files were not shown because too many files changed in this diff