mirror of https://github.com/logseq/logseq
enhance(plugin): support custom routes from the plugin sdk
parent
bd26d0db0e
commit
53125d6315
|
@ -12,7 +12,7 @@
|
|||
(def button base-core/button)
|
||||
(def link base-core/link)
|
||||
(def trigger-as base-core/trigger-as)
|
||||
(def tabler-icon icon-v2/root)
|
||||
(def ^:export tabler-icon icon-v2/root)
|
||||
|
||||
(def alert (util/lsui-wrap "Alert"))
|
||||
(def alert-title (util/lsui-wrap "AlertTitle"))
|
||||
|
|
|
@ -44,7 +44,7 @@ export class LSPluginExperiments {
|
|||
}
|
||||
|
||||
registerFencedCodeRenderer(
|
||||
type: string,
|
||||
lang: string,
|
||||
opts: {
|
||||
edit?: boolean
|
||||
before?: () => Promise<void>
|
||||
|
@ -54,7 +54,23 @@ export class LSPluginExperiments {
|
|||
) {
|
||||
return this.ensureHostScope().logseq.api.exper_register_fenced_code_renderer(
|
||||
this.ctx.baseInfo.id,
|
||||
type,
|
||||
lang,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
registerRouteRenderer(
|
||||
key: string,
|
||||
opts: {
|
||||
name?: string,
|
||||
path: string,
|
||||
render: (props: { content: string }) => any
|
||||
subs?: Array<string>
|
||||
}
|
||||
) {
|
||||
return this.ensureHostScope().logseq.api.exper_register_route_renderer(
|
||||
this.ctx.baseInfo.id,
|
||||
key,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
@ -83,7 +99,8 @@ export class LSPluginExperiments {
|
|||
|
||||
ensureHostScope(): any {
|
||||
if (window === top) {
|
||||
throw new Error('Can not access host scope!')
|
||||
console.error('Can not access host scope!')
|
||||
return {}
|
||||
}
|
||||
|
||||
return top
|
||||
|
|
|
@ -3536,7 +3536,7 @@
|
|||
(let [lang (util/safe-lower-case (:language options))]
|
||||
[:div.cp__fenced-code-block
|
||||
{:data-lang lang}
|
||||
(if-let [opts (plugin-handler/hook-fenced-code-by-type lang)]
|
||||
(if-let [opts (plugin-handler/hook-fenced-code-by-lang lang)]
|
||||
[:div.ui-fenced-code-wrap
|
||||
(src-cp config options html-export?)
|
||||
(plugins/hook-ui-fenced-code (:block config) (string/join "" (:lines options)) opts)]
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[frontend.ui :as ui]
|
||||
[frontend.config :as config]
|
||||
[frontend.state :as state]
|
||||
[frontend.handler.plugin :refer [hook-extensions-enhancer-by-type]]
|
||||
[frontend.handler.plugin :refer [hook-extensions-enhancer-by-key]]
|
||||
[promesa.core :as p]))
|
||||
|
||||
;; TODO: Why does shadow fail when code is required
|
||||
|
@ -23,7 +23,7 @@
|
|||
(if-not @loaded?
|
||||
(p/finally
|
||||
(p/all (when-let [enhancers (and config/lsp-enabled?
|
||||
(seq (hook-extensions-enhancer-by-type :codemirror)))]
|
||||
(seq (hook-extensions-enhancer-by-key :codemirror)))]
|
||||
(for [{f :enhancer} enhancers]
|
||||
(when (fn? f) (f (. js/window -CodeMirror))))))
|
||||
(fn []
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[frontend.search :as search]
|
||||
[frontend.util :as util]
|
||||
[frontend.mixins :as mixins]
|
||||
[frontend.config :as config]
|
||||
[logseq.shui.ui :as shui]
|
||||
[electron.ipc :as ipc]
|
||||
[promesa.core :as p]
|
||||
|
@ -1426,3 +1427,13 @@
|
|||
(focused-settings-content title)])
|
||||
{:label "plugin-settings-modal"
|
||||
:id "ls-focused-settings-modal"}))
|
||||
|
||||
(defn hook-custom-routes
|
||||
[routes]
|
||||
(cond-> routes
|
||||
config/lsp-enabled?
|
||||
(concat (some->> (plugin-handler/hook-routes-renderer)
|
||||
(mapv #(when-let [{:keys [name path render]} %]
|
||||
(when (not (string/blank? path))
|
||||
[path {:name name :view (fn [r] (render r %))}])))
|
||||
(remove nil?)))))
|
|
@ -5,6 +5,7 @@
|
|||
[frontend.handler :as handler]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.components.plugins :as plugins]
|
||||
[frontend.page :as page]
|
||||
[frontend.routes :as routes]
|
||||
[frontend.spec]
|
||||
|
@ -19,7 +20,7 @@
|
|||
(defn set-router!
|
||||
[]
|
||||
(rfe/start!
|
||||
(rf/router routes/routes nil)
|
||||
(rf/router (plugins/hook-custom-routes routes/routes) nil)
|
||||
(fn [route]
|
||||
(route-handler/set-route-match! route)
|
||||
(plugin-handler/hook-plugin-app
|
||||
|
@ -43,7 +44,7 @@
|
|||
\\/ /_____/ \\/ \\/ |__|
|
||||
"))
|
||||
|
||||
(defn start []
|
||||
(defn ^:export start []
|
||||
(when config/dev?
|
||||
(md/start!))
|
||||
(when-let [node (.getElementById js/document "root")]
|
||||
|
@ -62,10 +63,14 @@
|
|||
(plugin-handler/setup!
|
||||
#(handler/start! start)))
|
||||
|
||||
(defn stop []
|
||||
(defn ^:export stop []
|
||||
;; stop is called before any code is reloaded
|
||||
;; this is controlled by :before-load in the config
|
||||
(handler/stop!)
|
||||
(when config/dev?
|
||||
(sync/<sync-stop))
|
||||
(js/console.log "stop"))
|
||||
|
||||
(defn ^:export delay-remount
|
||||
[delay]
|
||||
(js/setTimeout #(start) delay))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[frontend.ui :as ui]
|
||||
[frontend.config :as config]
|
||||
[frontend.util :as util]
|
||||
[frontend.handler.plugin :refer [hook-extensions-enhancer-by-type] :as plugin-handler]
|
||||
[frontend.handler.plugin :refer [hook-extensions-enhancer-by-key] :as plugin-handler]
|
||||
[promesa.core :as p]
|
||||
[goog.dom :as gdom]))
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
|||
(config/asset-uri "/static/js/mhchem.min.js")
|
||||
(fn []
|
||||
(p/finally
|
||||
(p/all (when-let [enhancers (and config/lsp-enabled? (seq (hook-extensions-enhancer-by-type :katex)))]
|
||||
(p/all (when-let [enhancers (and config/lsp-enabled? (seq (hook-extensions-enhancer-by-key :katex)))]
|
||||
(for [{f :enhancer} enhancers]
|
||||
(when (fn? f) (f js/window.katex)))))
|
||||
(fn []
|
||||
|
|
|
@ -340,10 +340,11 @@
|
|||
(when-let [pid (keyword pid)]
|
||||
(when-let [type (and key (keyword type))]
|
||||
(let [path [:plugin/installed-resources pid type]]
|
||||
(when (contains? #{:error nil} (get-in @state/state (conj path key)))
|
||||
(swap! state/state update-in path
|
||||
(fnil assoc {}) key (merge opts {:pid pid}))
|
||||
true)))))
|
||||
;; TODO: conditions
|
||||
;; (when (contains? #{:error nil} (get-in @state/state (conj path key))))
|
||||
(swap! state/state update-in path
|
||||
(fnil assoc {}) key (merge opts {:pid pid}))
|
||||
true))))
|
||||
|
||||
(defn unregister-plugin-resources
|
||||
[pid]
|
||||
|
@ -380,39 +381,55 @@
|
|||
(when-let [hook (and uuid (str "hook:db:block_" (string/replace (str uuid) "-" "_")))]
|
||||
(boolean (seq (get (get-installed-hooks) hook)))))
|
||||
|
||||
(defn- create-local-renderer-register
|
||||
[type *providers]
|
||||
(fn [pid key {:keys [subs render] :as _opts}]
|
||||
(when-let [key (and key (keyword key))]
|
||||
(register-plugin-resources pid type
|
||||
(merge _opts {:key key :subs subs :render render}))
|
||||
(swap! *providers conj pid)
|
||||
#(swap! *providers disj pid))))
|
||||
|
||||
(defn- create-local-renderer-getter
|
||||
([type *providers] (create-local-renderer-getter type *providers false))
|
||||
([type *providers many?]
|
||||
(fn [key]
|
||||
(when-let [key (or many? (and (seq @*providers) key (keyword key)))]
|
||||
(when-let [rs (->> @*providers
|
||||
(map #(if many?
|
||||
(some-> (state/get-plugin-resources-with-type % type)
|
||||
(vals))
|
||||
(state/get-plugin-resource % type key)))
|
||||
(remove nil?)
|
||||
(flatten)
|
||||
(seq))]
|
||||
(if many? rs (first rs)))))))
|
||||
|
||||
(defonce *fenced-code-providers (atom #{}))
|
||||
|
||||
(defn register-fenced-code-renderer
|
||||
[pid type {:keys [before subs render edit] :as _opts}]
|
||||
(when-let [key (and type (keyword type))]
|
||||
(register-plugin-resources pid :fenced-code-renderers
|
||||
{:key key :edit edit :before before :subs subs :render render})
|
||||
(swap! *fenced-code-providers conj pid)
|
||||
#(swap! *fenced-code-providers disj pid)))
|
||||
|
||||
(defn hook-fenced-code-by-type
|
||||
[type]
|
||||
(when-let [key (and (seq @*fenced-code-providers) type (keyword type))]
|
||||
(->> @*fenced-code-providers
|
||||
(map #(state/get-plugin-resource % :fenced-code-renderers key))
|
||||
(remove nil?)
|
||||
(first))))
|
||||
(def register-fenced-code-renderer
|
||||
;; [pid key payload]
|
||||
(create-local-renderer-register
|
||||
:fenced-code-renderers *fenced-code-providers))
|
||||
(def hook-fenced-code-by-lang
|
||||
;; [key]
|
||||
(create-local-renderer-getter
|
||||
:fenced-code-renderers *fenced-code-providers))
|
||||
|
||||
(def *extensions-enhancer-providers (atom #{}))
|
||||
(def register-extensions-enhancer
|
||||
(create-local-renderer-register
|
||||
:extensions-enhancers *extensions-enhancer-providers))
|
||||
(def hook-extensions-enhancer-by-key
|
||||
(create-local-renderer-getter
|
||||
:extensions-enhancers *extensions-enhancer-providers))
|
||||
|
||||
(defn register-extensions-enhancer
|
||||
[pid type {:keys [enhancer] :as _opts}]
|
||||
(when-let [key (and type (keyword type))]
|
||||
(register-plugin-resources pid :extensions-enhancers
|
||||
{:key key :enhancer enhancer})
|
||||
(swap! *extensions-enhancer-providers conj pid)
|
||||
#(swap! *extensions-enhancer-providers disj pid)))
|
||||
|
||||
(defn hook-extensions-enhancer-by-type
|
||||
[type]
|
||||
(when-let [key (and type (keyword type))]
|
||||
(map #(state/get-plugin-resource % :extensions-enhancers key)
|
||||
@*extensions-enhancer-providers)))
|
||||
(def *route-renderer-providers (atom #{}))
|
||||
(def register-route-renderer
|
||||
(create-local-renderer-register
|
||||
:route-renderers *route-renderer-providers))
|
||||
(def hook-routes-renderer
|
||||
(create-local-renderer-getter
|
||||
:route-renderers *route-renderer-providers true))
|
||||
|
||||
(defn select-a-plugin-theme
|
||||
[pid]
|
||||
|
@ -788,7 +805,8 @@
|
|||
(p/then
|
||||
(fn []
|
||||
(state/set-state! :plugin/indicator-text "END")
|
||||
(callback)))
|
||||
;; wait for the plugin register async messages
|
||||
(js/setTimeout #(callback) 64)))
|
||||
(p/catch
|
||||
(fn [^js e]
|
||||
(log/error :setup-plugin-system-error e)
|
||||
|
|
|
@ -69,7 +69,12 @@
|
|||
#?(:cljs (def string-join-path common-util/string-join-path))
|
||||
|
||||
#?(:cljs
|
||||
(def safe-re-find common-util/safe-re-find))
|
||||
(do
|
||||
(def safe-re-find common-util/safe-re-find)
|
||||
(defn safe-keyword
|
||||
[s]
|
||||
(when (string? s)
|
||||
(keyword (string/replace s " " "_"))))))
|
||||
|
||||
#?(:cljs
|
||||
(do
|
||||
|
|
|
@ -982,12 +982,25 @@
|
|||
(keyword pid) type (reduce #(assoc %1 %2 (aget opts (name %2))) {}
|
||||
[:edit :before :subs :render]))))
|
||||
|
||||
(defn ^:export exper_register_route_renderer
|
||||
[pid key ^js opts]
|
||||
(when-let [^js _pl (plugin-handler/get-plugin-inst pid)]
|
||||
(let [key (util/safe-keyword key)]
|
||||
(plugin-handler/register-route-renderer
|
||||
(keyword pid) key
|
||||
(reduce (fn [r k]
|
||||
(assoc r k (cond-> (aget opts (name k))
|
||||
(= :name k)
|
||||
(#(if % (util/safe-keyword %) key)))))
|
||||
{} [:v :name :path :subs :render])))))
|
||||
|
||||
(defn ^:export exper_register_extensions_enhancer
|
||||
[pid type enhancer]
|
||||
(when-let [^js _pl (and (fn? enhancer) (plugin-handler/get-plugin-inst pid))]
|
||||
(plugin-handler/register-extensions-enhancer
|
||||
(keyword pid) type {:enhancer enhancer})))
|
||||
|
||||
;; http request
|
||||
(defonce *request-k (volatile! 0))
|
||||
|
||||
(defn ^:export exper_request
|
||||
|
@ -1060,4 +1073,4 @@
|
|||
[]
|
||||
true)
|
||||
|
||||
(def ^:export set_blocks_id #(editor-handler/set-blocks-id! (map uuid %)))
|
||||
(def ^:export set_blocks_id #(editor-handler/set-blocks-id! (map uuid %)))
|
|
@ -1,7 +1,8 @@
|
|||
(ns logseq.sdk.utils
|
||||
(:require [clojure.walk :as walk]
|
||||
[camel-snake-kebab.core :as csk]
|
||||
[frontend.util :as util]))
|
||||
[frontend.util :as util]
|
||||
[cljs-bean.core :as bean]))
|
||||
|
||||
(defn normalize-keyword-for-json
|
||||
([input] (normalize-keyword-for-json input true))
|
||||
|
@ -28,4 +29,8 @@
|
|||
(uuid s)
|
||||
|
||||
:else
|
||||
(throw (js/Error. (str s " is not a valid UUID string.")))))
|
||||
(throw (js/Error. (str s " is not a valid UUID string.")))))
|
||||
|
||||
(def ^:export to-clj bean/->clj)
|
||||
(def ^:export to-keyword keyword)
|
||||
(def ^:export to-symbol symbol)
|
Loading…
Reference in New Issue