Crocon 🐊
Crocon makes developer console great again.
Crocon is a Javascript wrapper for browser's developer console. Its goal is to make debugging painless, convenient and beautiful.
This is a Rails gem version of the library. For source files and an npm package, go here.
Installation
Add this to your Gemfile
:
gem 'crocon'
Add this to your application.js
:
//= require crocon
Add this to your application.css
:
*= require crocon
Why?
The builtin developer console in modern browsers suffers from a number of problems. Here are some of the big ones:
There's no good way to turn logging on/off.
Most of the time you don't want your clients to
see debugging output in their console on your production website. But, console.log
does not
care if it runs in development or production, it's going to log anyway. This leads to developers
seldom using the console or writing console.log
over and over again just to erase
it afterwards (...just to write it back again afterwards, and so on). Disabling the console
is still possible (e.x. if (!debug) console.log = function () {}
), but it's not a good solution
if you use other console methods (which you should!). Also, imagine you want to be able to
see debugging output in production while normal website users don't see anything. What do you do?
Crocon solves this problem by introducing a flexible enable/disable mechanism. First of all, you
can enable or disable it during initialization: crocon = new Crocon({ enabled: debug })
(assuming that debug
is true
in development and false
in production). But also, you can
enable or disable Crocon in your browser (crocon.enable()
or crocon.disable()
), which will
override the global enabled
option. Thus, you can easily switch Crocon on/off in any environment,
and it will only affect your console.
console.group
is a great idea, but it's not implemented well
With console.group
you can split your output in foldable groups, which is a very good thing
to be able to do. However, a lot of JS these days is asynchronous, which is something you have
to constantly think about if you want to group your output.
Consider this simple scenario:
async function f1() {
console.group('group 1');
console.log('function 1 start');
await sleep(1000);
console.log('function 1 end');
console.groupEnd();
}
async function f2() {
console.group('group 2');
console.log('function 2 start');
await sleep(500);
console.log('function 2 end');
console.groupEnd();
}
f1(); f2()
Result:
Crocon solves this by creating a different implementation of groups. With Crocon, you can use groups like this:
crocon.group('my namespace').log('hello from my namespace')
/* or */
crocon.group('my namespace', function () {
crocon.log('hello from my namespace')
/* ... */
})
See grouping
console.log
supports formatting with CSS, but it's not convenient
console
supports formatting with CSS rules:
console.log('roses are %cred%c, violets are %cblue', 'color: red;', 'color: black;', 'color: blue;')
Result:
This is awesome, but really not convenient.
Crocon makes formatting much easier by introducing a markdown-like syntax. See formatting.
Browser support
TBD
Usage
Methods that work exactly like their console's counterparts:
assert
count
debug
also supports formattingdir
dirxml
error
also supports formatting, see known issuesinfo
also supports formattinglog
also supports formattingtimeStamp
trace
see known issueswarn
also supports formatting
Also:
profile
andprofileEnd
as well astime
andtimeEnd
support lambda syntax:
crocon.profile('profile1')
myVar = myFunction()
crocon.profileEnd()
/* is the same as */
myVar = crocon.profile('profile1', myFunction)
group
is described in grouping.
Initialization options
crocon = new Crocon({
enabled: true,
enableFormatting: true,
collapseGroups: false,
modifyConsole: true
})
enabledByDefault
: Defines whether to enable or disable Crocon. When Crocon is disabled, it will not produce any output. However, lambda versions ofprofile
,time
andgroup
will still execute given functions. Default:true
.enableFormatting
: Defines whether formatting should be enabled. Default:true
.collapseGroups
: Defines whether groups should be collapsed or not. Default:false
(expanded).modifyConsole
: Defines whether Crocon needs to modifyconsole
upon initialization. Generally, modifying global objects is a bad thing to do, but this is required if you want Crocon to handle console output correctly. Crocon is modifyingconsole
functions very carefully (it just needs to hook to those methods). You can safely disable this options, but regular console output will occasionally get stuck inside groups it does not belong to. see known issues. Default:true
.
Grouping
Groups in Crocon work a little different from console's groups. There are two ways to group the output.
/* method 1 */
crocon.group('group one').log('inside group 1')
/* method 2 */
crocon.group('group one', function () {
crocon.log('inside group 1')
})
You can easily mix methods together and nest groups however you want:
crocon.group('user login', function () {
crocon.info('user login started')
crocon.group('credentials').log('credentials are [correct].green')
/* code */
crocon.info('[success].badge.green')
})
crocon.group('group 1').log('some more output')
crocon.group('group 1', 'another group!').log('still nested correctly')
Output:
When document
is not in focus (e.g. your console is in focus), the output becomes:
This behaviour is explained in known issues.
Formatting
Crocon supports Markdown-like string formatting. Here's the options:
**bold**
*italic*
~strikethrough~
_underline_
[custom text].classOne.classTwo...
. This syntax allows you to apply CSS classes to text in square brackets. Available classes are:badge
,bold
,italic
,strikethrough
,underline
and color classes.
At the moment, you cannot nest formatting options into each other. Objects and functions are not formattable, but they likely will be in the future.
Color classes
Crocon supports following color classes (both for badges and normal text):
.blue
.orange
.red
.green
.cyan
.purple
Adding custom / overriding existing styles
All styles are declared in a stylesheet and thus are easily extensible.
See index.scss
.
At the moment, only these attributes are supported: margin
, color
, background-color
,
border-radius
, padding
, font-weight
, font-style
, text-decoration
.
Known issues
There's no way to detect when console output happens. Development tools are separate from
window
anddocument
, and there is no way to know if the output is happening. We can detect things likeconsole.log
by modifying those functions (hence themodifyConsole
init parameter), but we cannot know when, say, an error thrown withthrow
is going to appear in console. Groups are implemented in such a way that they don't get closed until it's necessary, so that leads to console output being stuck inside groups it doesn't belong to. Part of the problem is solved by modifyingconsole
, but another part is not solvable without a browser extension. The best we can do is to detect whether or notdocument
is in focus (withdocument.hasFocus()
). This enables us to change how groups work ifdocument
is not in focus (say,console
is in focus). However, some things (likethrow
or click on the "clear console" button) are simply not catchable. So, some output will inevitably get stuck in a group it doesn't belong. Beware of this, especially when usingcollapseGroups = true
.Stack traces from
crocon.error
andcrocon.trace
contain unneeded information. Sincecrocon.error
andcrocon.trace
call some functions under the hood, the stack trace produced by those functions will contain several unneeded calls.
All of this is according to the author's research. If you know a solution to this problem, you're highly encouraged to open an issue and/or a pull request at akxcv/crocon.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/akxcv/crocon.
License
The package is available as open source under the terms of the MIT License.
TODO
- Support nested styles
- Log history
- Replace stylesheet with in-memory CSS?
- Focus mode (see only the logs you need right now)
- Custom styles in formatting (e.x.
[my text]{color: #434433;}
) - Browser support
- Object and function formatting