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.
[](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