Repository: PrecursorApp/om-i Branch: master Commit: 30c1f248a046 Files: 10 Total size: 23.2 KB Directory structure: gitextract_8uedg_ze/ ├── .gitignore ├── CHANGES.md ├── README.md ├── circle.yml ├── project.clj ├── resources/ │ ├── om-i.css │ └── om-i.less └── src/ └── om_i/ ├── core.cljs ├── hacks.cljs └── keyboard.cljs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ pom.xml *jar /lib/ /classes/ /out/ /target/ .lein-deps-sum .lein-repl-history .lein-plugins/ /script/ ================================================ FILE: CHANGES.md ================================================ ## 0.1.8 ### Changes * Stop depending on _rootNodeId so that we can support React 0.13. ## 0.1.7 ### Changes * Fix ordering of render-ms and mount-ms ## 0.1.6 ### Changes * fix borked release to Clojars of 0.1.5 ## 0.1.5 ### Changes * Note: this released was messed up somehow, use 0.1.6 instead * fix un-required goog.string.format. Thanks [@cldwalker](https://github.com/cldwalker)! ## 0.1.4 ### Changes * fixes compilation error from requiring `goog` ## 0.1.3 ### Changes * remove unused cljs-time requires ================================================ FILE: README.md ================================================ # Om-instrumentation Instrumentation helper for Om applications. [![Circle CI](https://circleci.com/gh/PrecursorApp/om-i.svg?style=svg)](https://circleci.com/gh/PrecursorApp/om-i) ## Overview Om-i (pronounced "Oh, my!") helps you identify the components in your [Om](https://github.com/omcljs/om) application that are being passed too much of your app state and rendering unnecessarily. It provides useful statistics about render times and frequencies for all of your components. You can see it live on [Precursor](https://precursorapp.com), a collaborative drawing application. Use Ctrl+Alt+Shift+j to toggle it. ## Setup ### Dependencies Add Om-i to your project's dependencies ``` [precursor/om-i "0.1.8"] ``` ### Enable the instrumentation Use Om-i's custom descriptor so that it can gather render times for your components. To enable it globally, use the `:instrument` opt in `om/root` ```clojure (om/root app-component app-state {:target container :instrument (fn [f cursor m] (om/build* f cursor (assoc m :descriptor om-i.core/instrumentation-methods)))}) ``` ### Mount the component Add the following somewhere in your setup code. If you're using figwheel, place it somewhere that won't get reloaded. ```clojure (om-i.core/setup-component-stats!) ``` Om-i renders its statistics in a separate root so that it doesn't interact with your application. It will create a `div` in the body with classname "om-instrumentation" by default and assign three keyboard shortcuts: Ctrl+Alt+Shift+j to bring down the statistics menu, Ctrl+Alt+Shift+k to clear the statistics, and Ctrl+Alt+Shift+s to switch the sort order. You can override the defaults with: ```clojure (om-i.core/setup-component-stats! {:class "om-instrumentation" :clear-shortcut #{"ctrl" "alt" "shift" "k"} :toggle-shortcut #{"ctrl" "alt" "shift" "j"} :sort-shorcut #{"ctrl" "alt" "shift" "s"}}) ``` ### Styles You need to set up css styles to handle displaying the instrumentation when it's opened. There are sample less and css files in the resources directory. If you want to try out Om-i, or just use it in development, we've provided a helper that will embed a style tag with the syles from resources/om-i.min.css. ```clojure (om-i.hacks/insert-styles) ``` It's not recommended to use this in production. ### Wrapping a pre-existing descriptor If you're already using a custom descriptor, you can still use Om-i. Here's an example wrapping Om's `no-local-descriptor`. ```clojure (let [methods (om-i.core/instrument-methods om/no-local-state-methods) descriptor (om/no-local-descriptor methods)] (om/root app-component app-state {:target container :instrument (fn [f cursor m] (om/build* f cursor (assoc m :descriptor descriptor)))})) ``` ## Acknowledgements Thanks to [@sgrove](https://github.com/sgrove) for his keyboard handling code. Om-i uses a minimal version of the code he wrote for Precursor. There is an older, [public version of the code in Omchaya](https://github.com/sgrove/omchaya/blob/master/src/omchaya/components/key_queue.cljs). Thanks to [@brandonbloom](https://github.com/brandonbloom) for demonstrating how to use descriptors in Om. [Related blog post](http://blog.circleci.com/local-state-global-concerns/). Thanks to [@swannodette](https://github.com/swannodette) for releasing Om. ## License Copyright © 2015 PrecursorApp Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version. ================================================ FILE: circle.yml ================================================ dependencies: post: - lein cljsbuild once test: override: - echo no tests ================================================ FILE: project.clj ================================================ (defproject precursor/om-i "0.1.8" :description "Instrumentation helpers for Om applications" :url "https://github.com/PrecursorApp/om-i" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.6.0"] [org.clojure/clojurescript "0.0-2755" :scope "provided"] [org.omcljs/om "0.8.8" :scope "provided"]] :plugins [[lein-cljsbuild "1.0.4"]] :cljsbuild {:builds [{:id "test" :source-paths ["src"] :compiler {:output-to "script/tests.simple.js" :output-dir "script/out" :source-map "script/tests.simple.js.map" :output-wrapper false :optimizations :simple}}]} :source-paths ["src"]) ================================================ FILE: resources/om-i.css ================================================ @keyframes in-fade-top-soft { 0% { opacity: 0; transform: translate3d(0, -4rem, 0); } 100% { opacity: 1; transform: none; } } @-webkit-keyframes in-fade-top-soft { 0% { opacity: 0; -webkit-transform: translate3d(0, -4rem, 0); } 100% { opacity: 1; -webkit-transform: none; } } .om-instrumentation { user-select: none; -moz-user-select: none; -webkit-user-select: none; pointer-events: none; color: #888888; position: fixed; z-index: 1000; top: 0; left: 0; width: 100%; } .instrumentation-table { -webkit-animation: in-fade-top-soft 500ms; animation: in-fade-top-soft 500ms; background-color: rgba(0, 0, 0, 0.6); font-family: Monaco, monospace; font-size: .75rem; line-height: 2; width: 100%; } .instrumentation-table th { color: #ffffff; line-height: 1rem; padding: 1.5rem 0; text-transform: uppercase; text-align: left; } .instrumentation-table th:not(:first-child) { text-align: center; } .instrumentation-table th.left { text-align: left; } .instrumentation-table th.right { text-align: right; } .instrumentation-table th, .instrumentation-table td { white-space: pre-wrap; } .instrumentation-table th:first-child, .instrumentation-table td:first-child { padding-left: 1.5rem; } .instrumentation-table tbody tr:nth-child(odd) { background-color: rgba(0, 0, 0, 0.4); } .instrumentation-table tbody td:nth-child(even) { text-align: right; border-right: 1px dashed; padding-right: .5em; } .instrumentation-table tbody td:nth-child(odd) { text-align: left; padding-left: .5em; } .instrumentation-table tbody td:first-child { padding-left: 1.5rem; } .instrumentation-table tfoot td { line-height: 1rem; text-align: center; padding: 1.5rem 0; } .instrumentation-table small { font-size: 1em; opacity: .5; } ================================================ FILE: resources/om-i.less ================================================ @black: #000; @white: #fff; @gray: #888; @font_mono: Monaco, monospace; @zindex-instrumentation: 1000; @tile: (1rem * 4); @menu_padding: 1.5rem; @keyframes in-fade-top-soft { 0% { opacity: 0; transform: translate3d(0, -@tile, 0);} 100% { opacity: 1; transform: none;} } @-webkit-keyframes in-fade-top-soft { 0% { opacity: 0; -webkit-transform: translate3d(0, -@tile, 0);} 100% { opacity: 1; -webkit-transform: none;} } .om-instrumentation { user-select: none; -moz-user-select: none; -webkit-user-select: none; pointer-events: none; color: @gray; position: fixed; z-index: @zindex-instrumentation; top: 0; left: 0; width: 100%; } .instrumentation-table { -webkit-animation: in-fade-top-soft 500ms; animation: in-fade-top-soft 500ms; background-color: fade(@black, 60); font-family: @font_mono; font-size: .75rem; line-height: 2; width: 100%; th { color: @white; line-height: 1rem; padding: @menu_padding 0; text-transform: uppercase; text-align: left; &:not(:first-child) { text-align: center; } &.left { text-align: left; } &.right { text-align: right; } } th, td { white-space: pre-wrap; &:first-child { padding-left: @menu_padding; } } tbody { tr { &:nth-child(odd) { background-color: fade(@black, 40); } } td { &:nth-child(even) { text-align: right; border-right: 1px dashed; padding-right: .5em; } &:nth-child(odd) { text-align: left; padding-left: .5em; } &:first-child { padding-left: @menu_padding; } } } tfoot { td { line-height: 1rem; text-align: center; padding: @menu_padding 0; } } small { font-size: 1em; opacity: .5; } } ================================================ FILE: src/om_i/core.cljs ================================================ (ns om-i.core (:require [clojure.string :as str] [goog.dom] [goog.string :as gstring] [goog.string.format] [om.core :as om :include-macros true] [om.dom :as dom :include-macros true] [om-i.keyboard :as keyboard])) ;; map of display name to component render stats, e.g. ;; {"App" {:last-will-update