├── .gitignore ├── chrome ├── chrome.zip ├── img │ ├── icon128.png │ ├── icon16.png │ ├── icon19.png │ ├── icon38.png │ └── icon48.png ├── popup.html ├── js │ ├── content.tpl.js │ ├── background.js │ └── content.js └── manifest.json ├── bower.json ├── package.json ├── LICENSE ├── README.md ├── lib └── deb.js └── example └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /chrome/chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krasimir/deb.js/master/chrome/chrome.zip -------------------------------------------------------------------------------- /chrome/img/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krasimir/deb.js/master/chrome/img/icon128.png -------------------------------------------------------------------------------- /chrome/img/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krasimir/deb.js/master/chrome/img/icon16.png -------------------------------------------------------------------------------- /chrome/img/icon19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krasimir/deb.js/master/chrome/img/icon19.png -------------------------------------------------------------------------------- /chrome/img/icon38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krasimir/deb.js/master/chrome/img/icon38.png -------------------------------------------------------------------------------- /chrome/img/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krasimir/deb.js/master/chrome/img/icon48.png -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deb.js", 3 | "description": "Minimalistic JavaScript library for debugging in the browser.", 4 | "license": "MIT", 5 | "_source": "git://github.com/krasimir/deb.js.git", 6 | "homepage": "https://github.com/krasimir/deb.js", 7 | "main": "build/deb.min.js", 8 | "keywords": [ 9 | "javascript", 10 | "js", 11 | "lib", 12 | "debug", 13 | "browser", 14 | "debugger" 15 | ], 16 | "ignore": [ 17 | "/.*", 18 | "chrome", 19 | "example" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /chrome/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 26 | 27 | 28 |

Add debjs to your URL to get Deb.js enabled.

29 | 30 | 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deb.js", 3 | "version": "0.0.1", 4 | "homepage": "https://github.com/krasimir/deb.js", 5 | "description": "Minimalistic JavaScript library for debugging in the browser", 6 | "author": { 7 | "name": "Krasimir Tsonev", 8 | "email": "info@krasimirtsonev.com", 9 | "url": "http://krasimirtsonev.com" 10 | }, 11 | "license": "MIT", 12 | "dependencies": { 13 | 14 | }, 15 | "devDependencies": { 16 | "uglify-js": "2.4.14" 17 | }, 18 | "keywords": [ 19 | "javascript", 20 | "browser", 21 | "debugger" 22 | ], 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/krasimir/deb.js" 26 | }, 27 | "scripts": { 28 | "build": "node ./build.js" 29 | } 30 | } -------------------------------------------------------------------------------- /chrome/js/content.tpl.js: -------------------------------------------------------------------------------- 1 | // Function to inject script into top of or 2 | function injectScript() { 3 | var s = document.createElement('script'); 4 | s.textContent = '{debjs}'; 5 | 6 | var root = document.head || document.documentElement; 7 | var newScript = root.insertBefore(s, root.firstChild); 8 | s.parentNode.removeChild(s); 9 | } 10 | 11 | // This logic decides if deb.js should be injected or not. 12 | if (sessionStorage.debJsState) injectScript(); 13 | 14 | // Listen for messages from background script 15 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 16 | if (message === 'getState') { // Get debJsState 17 | sendResponse(sessionStorage.debJsState); 18 | } else if (typeof message.setState === 'string') { // Set debJsState 19 | sessionStorage.debJsState = message.setState; 20 | sendResponse(); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Deb.js", 4 | "description": "The tiniest debugger in the world", 5 | "version": "0.0.5", 6 | "icons": { "16": "img/icon16.png", "48": "img/icon48.png", "128": "img/icon128.png" }, 7 | "browser_action": { 8 | "default_icon": { 9 | "19": "img/icon19.png", 10 | "38": "img/icon38.png" 11 | }, 12 | "default_title": "Deb.js" 13 | }, 14 | "permissions": [ 15 | "activeTab" 16 | ], 17 | "background": { 18 | "scripts": ["js/background.js"], 19 | "persistent": false 20 | }, 21 | "content_scripts": [ 22 | { 23 | "matches": ["http://*/*", "https://*/*"], 24 | "js": ["js/content.js"], 25 | "run_at": "document_start" 26 | } 27 | ], 28 | "web_accessible_resources": [ 29 | "js/deb.min.js" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /chrome/js/background.js: -------------------------------------------------------------------------------- 1 | function updateBadgeText(tabId, toggle) { 2 | if (typeof tabId !== 'number') return; // tabId is required 3 | 4 | chrome.tabs.sendMessage(tabId, 'getState', // Get state 5 | function(response) { // When state is retrieved... 6 | var state = response; 7 | 8 | if (toggle) state = !state; 9 | var badgeText = state ? 'ON' : ''; 10 | 11 | chrome.browserAction.setBadgeText({ // Update badge 12 | text: badgeText 13 | }); 14 | 15 | if (toggle) { 16 | chrome.tabs.sendMessage(tabId, { // Save state 17 | setState: badgeText 18 | }, function() { // When state is saved... 19 | chrome.tabs.reload(); // ...refresh page 20 | }); 21 | } 22 | }); 23 | } 24 | 25 | chrome.browserAction.onClicked.addListener(function(tab) { // On button click... 26 | updateBadgeText(tab.id, true); // ...(param 2 `true` => toggle value) 27 | }); 28 | 29 | chrome.tabs.onActivated.addListener(function(info) { // On active tab change... 30 | updateBadgeText(info.tabId); // ...update badge 31 | }); 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Krasimir Tsonev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /chrome/js/content.js: -------------------------------------------------------------------------------- 1 | // Function to inject script into top of or 2 | function injectScript() { 3 | var s = document.createElement('script'); 4 | s.textContent = '!function(o,n){"function"==typeof define&&define.amd?define([],n):n()}(this,function(){Function.prototype.debc=function(o){return Function.prototype.deb.apply(this,[o,!0])},Function.prototype.deb=function(o,n){var t,e=function(){return"rgb("+(Math.floor(76*Math.random())+200)+","+(Math.floor(76*Math.random())+200)+","+(Math.floor(76*Math.random())+200)+")"},r=function(o,e,r){"undefined"!=typeof console&&(p&&"string"==typeof o?r!==!1&&o.indexOf("%20")<0?console[e?n?"groupCollapsed":"group":"log"]("%c"+o,"background:"+t+";"+r):console[e?n?"groupCollapsed":"group":"log"](o):console[e?"group":"log"](o))},i=function(){"undefined"!=typeof console&&console.groupEnd()},u=function(o){return o.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[0]},c=function(n,t,e){var c=u(e);if(0===n[0].indexOf("Error")&&(n=n.slice(1)),r(o+c+")",l),t&&t.length>0){r("arguments:",!0);for(var a=0;a1){r("stack trace:",!0);for(var a=0;a-1;return function(){t=e();var o=Date.now();c((new Error).stack.split(new RegExp("\\n")),arguments,f);var n=f.apply(this,Array.prototype.slice.call(arguments,0));return a(o,n),n}}});'; 5 | 6 | var root = document.head || document.documentElement; 7 | var newScript = root.insertBefore(s, root.firstChild); 8 | s.parentNode.removeChild(s); 9 | } 10 | 11 | // This logic decides if deb.js should be injected or not. 12 | if (sessionStorage.debJsState) injectScript(); 13 | 14 | // Listen for messages from background script 15 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 16 | if (message === 'getState') { // Get debJsState 17 | sendResponse(sessionStorage.debJsState); 18 | } else if (typeof message.setState === 'string') { // Set debJsState 19 | sessionStorage.debJsState = message.setState; 20 | sendResponse(); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | deb.js 2 | ====== 3 | 4 | ### ~1.5K minimalistic JavaScript library for debugging in the browser 5 | 6 | * works on functional level 7 | * groups your `console.log` statements and place them in a proper context 8 | * displays stack traces, passed arguments and execution time 9 | 10 | ## Usage 11 | 12 | Add `deb.min.js` at the top of your page. Before every other script file. 13 | 14 | ```html 15 | 16 | ``` 17 | 18 | Add `.deb()` After the definition of your functions. 19 | 20 | ```js 21 | var calculateSomething = function(cb) { 22 | // ... 23 | }.deb(); 24 | ``` 25 | 26 | Open your console. You should see something like that: 27 | 28 | ![deb.js](http://work.krasimirtsonev.com/git/debjs/debjs.jpg) 29 | 30 | Use `.debc()` to collapse the output. 31 | 32 | ## Deb.js as Chrome extension 33 | 34 | [Deb.js in Google Web Store](https://chrome.google.com/webstore/detail/debjs/egmeoknjmgikkkcdicmajkbkmkcmbiah) 35 | 36 | There is extension for Chrome that injects `deb.min.js` into your page. All you have to do is to install the extension from [here](https://chrome.google.com/webstore/detail/debjs/egmeoknjmgikkkcdicmajkbkmkcmbiah) and click the icon in the upper right corner. 37 | 38 | Once you do that the extension will inject the file before your page's content and you will be able to use `.deb()` or `debc()` methods. 39 | 40 | ![deb.js](http://work.krasimirtsonev.com/git/debjs/debjschrome.png) 41 | 42 | ## Deb.js is available in Bower too 43 | 44 | To install the library via Bower just run: 45 | 46 | ``` 47 | bower install deb.js 48 | ``` 49 | 50 | The file that you probably want to use is `/bower_components/deb.js/build/deb.min.js`. 51 | 52 | ## Articles 53 | 54 | * [Deb.js: the Tiniest Debugger in the World](http://code.tutsplus.com/tutorials/debjs-the-tiniest-debugger-in-the-world--cms-21565) 55 | * [Deb.js: самый крохотный отладчик в мире](http://habrahabr.ru/post/228819/) 56 | 57 | ## Preview 58 | 59 | Here is an animated gif that demonstrates how Deb.js outputs information about the executed function. 60 | 61 | ![deb.js](http://work.krasimirtsonev.com/git/debjs/debjs_05.gif) 62 | 63 | ## Building 64 | 65 | 1. `npm install` 66 | 2. `npm run build` 67 | 68 | ## Contributers 69 | 70 | * [Krasimir Tsonev](http://krasimirtsonev.com/) 71 | * [Tyler Eich](https://github.com/TylerEich) 72 | * [The Code Destroyer](https://github.com/TheCodeDestroyer) 73 | * [Valentin Zwick](https://github.com/vzwick) 74 | * [kshirish](https://github.com/kshirish) 75 | -------------------------------------------------------------------------------- /lib/deb.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if (typeof define === 'function' && define.amd) { 3 | define([], factory); 4 | } else { 5 | factory(); 6 | } 7 | }(this, function() { 8 | Function.prototype.debc = function(desc) { 9 | return Function.prototype.deb.apply(this, [desc, true]) 10 | } 11 | Function.prototype.deb = function(desc, collapsed) { 12 | 13 | var getColor = function() { 14 | return 'rgb(' + (Math.floor((256-180)*Math.random()) + 200) + ',' + (Math.floor((256-180)*Math.random()) + 200) + ',' + (Math.floor((256-180)*Math.random()) + 200) + ')'; 15 | } 16 | var log = function(str, group, styles) { 17 | if(typeof console === 'undefined') return; 18 | if(is_chrome && typeof str === 'string') { 19 | if(styles !== false && str.indexOf('%20') < 0) { 20 | console[group ? (collapsed ? 'groupCollapsed' : 'group') : 'log']('%c' + str, 'background:' + bg + ';' + styles); 21 | } else { 22 | console[group ? (collapsed ? 'groupCollapsed' : 'group') : 'log'](str); 23 | } 24 | } else { 25 | console[group ? 'group' : 'log'](str); 26 | } 27 | } 28 | var groupEnd = function() { 29 | if(typeof console === 'undefined') return; 30 | console.groupEnd(); 31 | } 32 | var getFnDef = function(fn) { 33 | return fn.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[0]; 34 | } 35 | var fnIn = function(stack, args, fn) { 36 | var fnDef = getFnDef(fn); 37 | // in 38 | if (stack[0].indexOf('Error') === 0) { stack = stack.slice(1); } 39 | log(desc + fnDef + ')', grouping); 40 | // arguments 41 | if(args && args.length > 0) { 42 | log('arguments:', true); 43 | for(var i=0; i 1) { 51 | log('stack trace:', true); 52 | for(var i=0; i -1; 72 | 73 | return function() { 74 | bg = getColor(); 75 | var time = Date.now(); 76 | fnIn((new Error()).stack.split(new RegExp("\\n")), arguments, fn); 77 | var res = fn.apply(this, Array.prototype.slice.call(arguments, 0)); 78 | fnOut(time, res); 79 | return res; 80 | } 81 | } 82 | })); 83 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example 5 | 6 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 | 28 | 29 | 30 | 82 | 83 | --------------------------------------------------------------------------------