gadget-inspector

所属分类:其他
开发工具:Clojure
文件大小:0KB
下载次数:0
上传日期:2023-04-12 10:16:17
上 传 者sh-1993
说明:  ClojureScript数据浏览器-从Chrome扩展或通过任何浏览器中的服务器使用,
(ClojureScript data browser - use from a Chrome extension or over a server in any browser,)

文件列表:
.dir-locals.el (149, 2023-04-12)
LICENSE (11218, 2023-04-12)
Makefile (2630, 2023-04-12)
demo/ (0, 2023-04-12)
demo/deps.edn (357, 2023-04-12)
demo/dev.cljs.edn (269, 2023-04-12)
demo/prod.cljs.edn (111, 2023-04-12)
demo/resources/ (0, 2023-04-12)
demo/resources/public/ (0, 2023-04-12)
demo/resources/public/gadget-demo.js (957, 2023-04-12)
demo/resources/public/index.html (486, 2023-04-12)
demo/src/ (0, 2023-04-12)
demo/src/gadget_demo/ (0, 2023-04-12)
demo/src/gadget_demo/core.cljs (11700, 2023-04-12)
extension/ (0, 2023-04-12)
extension/background.js (929, 2023-04-12)
extension/cljs.png (64806, 2023-04-12)
extension/content-script.js (1432, 2023-04-12)
extension/devtools.html (36, 2023-04-12)
extension/devtools.js (1926, 2023-04-12)
extension/firefox-manifest.json (135, 2023-04-12)
extension/icon-128.png (16721, 2023-04-12)
extension/icon-24.png (1220, 2023-04-12)
extension/icon-256.png (41607, 2023-04-12)
extension/icon-36.png (1780, 2023-04-12)
extension/icon-48.png (4233, 2023-04-12)
extension/manifest.json (903, 2023-04-12)
extension/panel.html (241, 2023-04-12)
icon.xcf (2167449, 2023-04-12)
inspector/ (0, 2023-04-12)
inspector/cljs.edn (57, 2023-04-12)
inspector/deps.edn (868, 2023-04-12)
inspector/remote-cljs.edn (68, 2023-04-12)
inspector/src/ (0, 2023-04-12)
inspector/src/cljs_data_browser/ (0, 2023-04-12)
inspector/src/cljs_data_browser/actions.cljs (81, 2023-04-12)
inspector/src/cljs_data_browser/inspector.cljs (5373, 2023-04-12)
inspector/src/cljs_data_browser/panel.cljs (838, 2023-04-12)
... ...

# ClojureScript Data Browser Developer tooling for inspecting ClojureScript data structures from running programs. Inspect data in devtools using the Chrome or Firefox extension, or in any other browser using the remote inspector. ## WARNING This is software in the making, not even alpha level. It *will* have breaking changes. If you're curious, please see below for usage. If you can wait, this tool will at some point become stable, at which point breaking changes will never occur intentionally. ## Inspecting a page You need the small agent library to expose data for inspection. It is available from Clojars: ```clj cjohansen/gadget-inspector {:mvn/version "0.2023.04.12"} ``` *NB!* Gadget requires `clojure.datafy`, and will only work with ClojureScript 1.9.520 or newer. Then, either create your app-wide atom with the inspector, or inspect an existing atom: ```clj (require '[gadget.inspector :as inspector]) ;; Either (def store (inspector/create-atom "App state" {})) ;; ...or (def my-store (atom {})) (inspector/inspect "App state" my-store) ``` You can also inspect regular persistent data structures, for example the data going into a UI component, with the `inspect` function: ```clj (def data {:band "Rush"}) (inspector/inspect "Band data" data) ``` The label operates as both an identifier for your data, and a header, so you can tell structures apart. Inspecting another piece of data with the same label will replace the corresponding section in the inspector. ### Controlling the liveness of the inspector By default, the inspector will only update its UI 250ms after changes to your data occurred. This should help avoid the inspector detracting from your app's performance. You can override this value if you wish: ```clj (require '[gadget.inspector :as inspector]) ;; Render less frequently (inspector/set-render-debounce-ms! 1000) ;; Render synchronously on every change (inspector/set-render-debounce-ms! 0) ``` ### Temporarily pausing inspection Even with debouncing, you may find that the work done by the inspector is too much in performance critical moments. While this will never be a problem for regular users in production, it can still be annoying during development. For those cases, you can pause the inspector, and resume it when the intensive work has completed: ```clj (require '[gadget.inspector :as inspector] '[cljs.core.async :refer [go s js/atob js/JSON.parse (js->clj :keywordize-keys true))) (defmethod datafy/datafy :jwt [token] (let [[header data sig] (str/split token #"\.")] {:header (base64json header) :data (base64json data) :signature sig})) (defmethod gadget/render [:inline :jwt] [_ {:keys [raw]}] [:strong "JWT: " [:gadget/string raw]]) ``` Let's see this in practice. Given this data: ```clj (def data {:token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}) ``` When Gadget renders this map, the token will be rendered with the `:inline` view. This view is passed both the token string, and the map returned from the `datafy` implementation. This particular inline view renders the token string with the `"JWT: "` prefix. Since the datafy result is a map, the token will be navigable in the browser. When you click the token, Gadget will render the token in the `:full` view. For `:jwt`, this view renders the datafyed value with the map browser. Since this is a map, it can be navigated deeper without any further ado. ### Rendering custom data types The first step in rendering custom data types is to define a custom type inference. Let's say we have some literals from the server that we want to preserve with their literal form, such as [java.time literals](https://github.com/cjohansen/gadget-inspector/blob/master/https://github.com/magnars/java-time-literals). Step 1 is to define the type inference: ```clj (require '[gadget.datafy :as datafy]) (datafy/add-type-inference (fn [data] (when (and (string? data) (re-find #"^#time" data)) :java-time-literal))) ``` The Java time literals are just strings on the client - if we do nothing else, they will be rendered as strings, e.g. `"#time/ld \"2019-08-01\""`. To make them render as literals, we'll implement the renderer function for inline views of the `:java-time-literal` type: ```cl (require '[clojure.string :as str] '[gadget.core :as gadget]) (defmethod gadget/render [:inline :java-time-literal] [_ {:keys [raw]}] (let [[prefix str] (str/split raw " ")] [:gadget/literal {:prefix prefix :value (cljs.reader/read-string str)}])) ``` There is no point in implementing the `:full` view, because the literal is a string, and strings are not navigable by default, thus it will never be rendered with the `:full` view. We could implement `datafy` for the literal and produce a JS date object, and then use that to power a `:full` view: ```clj (require '[clojure.string :as str] '[gadget.datafy :as datafy]) (defmethod datafy/datafy :java-time-literal [literal] (let [[prefix str] (str/split raw " ")] (case prefix "#time/ld" (let [date-str (cljs.reader/read-string str) [y m d] (map #(js/parseInt % 10) (str/split date-str #"-"))] (js/Date. y (dec m) d))))) ``` Gadget's built-in instant tooling would pick this up and allow you to navigate into this value to see year, month, date, etc. Please disregard the abomination that is converting a local date to an instant like this. ### Sorting When adding custom types for maps, you might want a different sorting than the default. By default, Gadget will try to sort keys alpha-numerically. You can override the default behavior by implementing the `gadget.core/Browsable` protocol. It defines a single method, `(entries [d])`, which takes the data (e.g. a map), and returns a vector of key value pairs, in preferred order. You can implement this for individual maps by including an implementation as metadata: ```clj (def key-order [:preferred :order :of :keys]) (defmethod gadget.datafy/datafy :my-type [m] (with-meta m {`entries (fn [m] (sort-by (gadget.core/key-order key-order)))})) ``` ## Components Gadget allows renderers to return pure unadulterated [hiccup](https://github.com/cjohansen/gadget-inspector/blob/master/https://github.com/weavejester/hiccup), essentially allowing you to dictate the exact rendering of a piece of data. To avoid re-implementing components that the Gadget inspector already uses in an uncanny valley all-you-can-eat, Gadget allows you to use some components via namespaced keywords. ### Basic types Dedicated inline components for basic types. All of these take the value as their only argument, e.g: ```clj ;; Just the string component [:gadget/string "Some string"] ;; Embedded in other markup [:div {} [:gadget/string "Some string"] [:gadget/number 12]] ``` The available types are: - `:gadget/string` - `:gadget/number` - `:gadget/keyword` - `:gadget/boolean` - `:gadget/date` ### Literals ```clj [`:gadget/literal` {:prefix "#inst" :str "2019-01-01T12:00:00Z"}] ``` ### Link Renders a value like a link. ```clj [`:gadget/link` "{100 keys}"] ``` ### Code Inline code samples can be created with `[:gadget/code code-string]`. ### Map browser Most `:full` renders use the browser component. It takes a sequence of key-value pairs: ```clj [:gadget/browser kv-coll] ``` `kv-coll` should be a collection of maps with keys `{:k :v :actions}` where: - `:k` is hiccup for the key/index - `:v` is hiccup for the value - `:actions` is an actions map - `:go` and `:copy` are currently supported ## Reference All functions that are exposed for extension. ### `(defmethod gadget.core/copy type-kw [v])` Returns the value copied to the copy buffer when clicking the copy button next to this value. Dispatches on the synthetic keyword type. The default implementation returns `(pr-str v)`. ### `(defmethod gadget.core/render [view type] [view data & [view-opts]])` Render the data of type `type` with view `view`. Currently `view` is one of `:inline` or `:full`. `data` is a map with keys `:raw` - the raw data, `:type` - the synthetic type, and `:data` - the datafied data. ### `(gadget.core/add-type-inference type [f])` Add type inference. Type inference is done by calling each registered function until a non-nil value is returned. LIFO - the last registered inference will be tried first. The function should return `nil` for unknown values, otherwise a keyword that names the "type". Any other return value will cause an error. ### `(gadget.datafy/datafy type [val])` A wrapper around `clojure.datafy/datafy` that dispatches on Gadget's synthtic types. The default implementation calls `clojure.datafy/datafy`. ## Developing Gadget To develop gadget inspector, clone the repo and open [lib/deps.edn](https://github.com/cjohansen/gadget-inspector/blob/master/lib/deps.edn). From there, open CIDER (assuming Emacs). If not in Emacs, you should be able to run a Figwheel REPL with: ``` clojure -A:dev -m figwheel.main --build dev --repl ``` The [lib/dev/gadget/dev.clj](https://github.com/cjohansen/gadget-inspector/blob/master/dev namespace) provides some test data for you to play with. The REPL runs the inspector in a regular browser tab in [http://localhost:9570](https://github.com/cjohansen/gadget-inspector/blob/master/http://localhost:9500). ## License Copyright 2018-2023 Christian Johansen Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

近期下载者

相关文件


收藏者