Bitbucket is a code hosting site with unlimited public and private repositories. We're also free for small teams!

Close
  _    __          __          __                 _______
 | |  / /__  _____/ /_  ____  / /____  ____      / / ___/
 | | / / _ \/ ___/ __ \/ __ \/ __/ _ \/ __ \__  / /\__ \
 | |/ /  __/ /  / /_/ / /_/ / /_/  __/ / / / /_/ /___/ /
 |___/\___/_/  /_.___/\____/\__/\___/_/ /_/\____//____/
        
 zip archive: http://www.verbotenjs.com/ver/1.0.0/archive.zip
 hg source: https://www.bitbucket.org/marcuspope/verbotenjs
 npm package: https://npmjs.org/package/verbotenjs

 Introduction
 ================================================== 

 Because everybody will think it is verboten anyway, I present to you VerbotenJS.
 
   “Maintainable JavaScript: Don't modify objects you don't own. - Nicholas C. Zakas”

 I, Marcus Pope, by imperial proclamation hereby declare ownership of
 Object.prototype. As sole owner I am the only authorized person to modify the
 prototype definition. Nope, too late I already called it and double stamped it.
 You can't triple stamp a double stamp!

 What Is VerbotenJS?
 ------------------- 

 VerbotenJS is a general application development framework designed for NodeJS &
 Browser JavaScript hosts. In addition to a bunch of base prototype enhancements
 and terse programming patterns, the framework also includes extension libraries
 for various domains such as databases, filesystems, shell scripts etc.
 
 Who Should Use VerbotenJS?
 -------------------------- 

 Nobody, it's verboten remember?!? No I'm kidding, you can use it for any
 personal project you want. I don't recommend using it for production systems
 since it is version 1.0 and I'm just one man trying to support his own personal
 JS framework. I'll probably change framework logic on a whim too, because that
 too is considered verboten right?
 
 Why Is VerbotenJS 750k Uncompressed, and do you really expect me to download
 that to a client?
 -------------------------------------------------------------- 

 No, I don't, it's verboten to do so remember? Actually here's the deal. jQuery
 is not compatible with Object.prototype extensions. I had intended on releasing
 my own DOM, Event and Ajax wrapper but I ran out of time. So I decided to
 inject a forked version of jQuery which added almost 350k to the footprint. My
 DOM wrapper will probably put the library in the 500k realm for browser hosts.
 For NodeJS hosts modules are dynamically included on access so the run-time
 memory usage requirements are dynamic based on the modules you use.

 But by today's standards 750k is not really that bad except for mobile devices
 and cellular networks. If you must you can compress and gzip it down to 75k but
 with modern bandwidth and caching infrastructures it really isn't that bad.

 But I Heard/Read/Know That Object Prototype Extensions Are Bad, mkay?
 -------------------------------------------------------------- 

 Good for you. Play around a little, find out how good it feels to be bad for
 once in your life :D

 Well, If Object Prototype Extensions Are Good, Then Why Does VerbotenJS Break
 My Application/Library/3rd Party Code?
 -------------------------------------------------------------- 

 Some people write bad JavaScript code, including myself. jQuery authors, for
 instance, recognize that their codebase has a bug that makes jQuery
 incompatible with object prototype extensions, however they choose to ignore
 the issue for various artificial reasons. ExpressJS authors just don't
 understand how JavaScript reflection works, and they think OPE's are code
 smell. And yet in other cases VerbotenJS may conflict with existing namespaces
 in your application. In the latter case I recommend either opening a bug if the
 issue is caused by a non-conforming standard on my part, or refactoring your
 application if you want to use VerbotenJS.

 Where Do I Start?
 ----------------- 

 First grab a copy of verbotenjs from npm.
 
    npm install verbotenjs
 
 In node hosts use:
 
    require('verbotenjs');
    
 For browser hosts include a reference to this file
 
    [verbotenjs]/web/verboten.js 
 
 There are no init functions that you have to worry about, and there is no real
 global entry point to the verboten framework. Everything you need is either
 declared globally, or attached to the prototypes of existing data types
 including Objects.

 I Kinda Like Where This Is Going, How Do I Help?
 ------------------------------------------------ 

 Well, I'm not really in a position to coordinate a team of developers at the
 moment. I have a newborn daughter and a full time job, so to avoid the
 frustration of not hearing from me for a few weeks at a time, which totally
 happens, send me small patches, <500 lines, and I'll review them. Since I doubt
 this will be much of an issue either way, I'll leave it at that for now.

 What If I Wanted To Create A Commercial Product?
 ------------------------------------------------ 

 Well, let's talk licensing and target market. But really you should probably
 wait until 2.0 at least before considering something for production.

 What's In Store For The Future Of VerbotenJS?
 --------------------------------------------- 

 Jesus, what isn't in a state of almost complete! Documentation, Bugs, Dom.js,
 Cross Platform Compatibility, JSDom, Unit Tests, etc. You know, all the stuff
 you'd expect from a professional open source project. The same stuff you should
 expect to be missing from a project named VerbotenJS.

 Documentation
 ================================================= 

 Ha!

 No, but I'm working on it. You'll notice some documentation tags in the source
 code, that's about as far as I've made it on the documentation front. Much of
 the codebase is pretty self explanatory, much of it is not. I do have a couple
 of other projects and a bunch of scripts that I've written over the years that
 will be used as examples, but otherwise I have no documentation other than
 comments in the source.

 Examples
 -------- 

 Here are some before and after code samples to show how VerbotenJS can make
 your coding efforts easier.

 Grepping The File System Without VerbotenJS:
 
    function grep(dir, query, filemask, recurse, hidden, cb) {
      //grep for 'query' in 'dir'.
      //'recurse' if necessary,
      //ignore 'hidden' files if necessary.
      //'cb' required.
      if (typeof query == "string") {
        query = new RegExp(query, "i");
      }
      
      //optionally filter by filemask
      if (typeof filemask == "string") {
        filemask = new RegExp(filemask);
      }
      
      var count = 1, //file count
        async = 0, //async callback count
        out = [],
        list = [],
        fs = require('fs'),
        fp = require('path');
      
      dir = dir || process.cwd();
      
      function search(path) {
        fs.stat(path, function(err, stat){
          count--;
          
          if (err) throw err;
          
          if (stat.isDirectory()) {
            
            async++;
            
            fs.readdir(path, function(err, files){
              async--;
              
              if (err) throw err;
              
              for (var i=0; i < files.length; i++) {
                if (!hidden && files[i][0] == '.') return;
                count++;
                search(fp.join(path, files[i]));
              }
            });
          } else if (stat.isFile()) {
            //ignore unmatched file masks
            if (!filemask.test(path)) {
               return;
            }
            
            async++;
            fs.readFile(path, 'utf8', function(err, str){
              async--;
              
              if (err) throw err;
              
              var lines = str.split('\n');
              
              for (var i=0; i < lines.length; i++) {
                var line = lines[i].trim(); 
                //return matching lines & line number
                if (query.test(line)) return [i, line];
              }
              
              if (lines.length) {
                out.push(path);
                for (var i=0; i < lines.length; i++) {
                  out.push((lines[i][0]+1) + ": " + lines[i][1]);
                  list.push({
                    path : path,
                    line : lines[i][0],
                    text : lines[i][1]
                  });
                }
                out.push('');
              }
              
              if(count == 0 && async == 0) {
                cb(out.join("\n") || "", list);
              }
            });
          }
        });
      }
      
      search(dir);
    };
    
 About 50 lines of code (minus empty lines, comments and closing brackets) to
 implement a grep-like file system search in NodeJS. Here's the same function
 implemented with VerbotenJS conventions.
 
    function grep(dir, query, filemask, recurse, hidden, cb) {
      //grep for 'query' in 'dir'.
      //'recurse' if necessary,
      //ignore 'hidden' files if necessary.
      //'cb' required.
      dir = dir || process.cwd();
      query = query.toRegex('i');
      filemask = filemask.toRegex('i');
      
      //recursively search the filesystem
      q.fs.ls(dir, recurse, function(list) {
        //filter files we don't need
        var files = list.ea(function(f) {
          if (!hidden && f[0] == ".") return; //things like .hg/.git
          if (!filemask.test(f)) return;
          return f;
        });
        
        var matches = [];
        
        //read each file and collect matching line info
        files.sort().ea(function(next, f) {
          q.f.utf8(f, function(txt) {
            txt.split('\n').trim().ea(function(line, i) {
              //if line matches query, return info
              if (query.test(line)) {
                matches.push({
                  path : f,
                  line : i,
                  text : line
                });
              }
            });
            
            //process next file
            next();
          });
        }, function() {
          //replicate grep stdout
          var stdout = matches.ea(function(o) {
            return [o.path, o.line + 1, ": ", o.text, ''].join('\n');
          });
          
          //return stdout and matches obj
          cb(stdout, matches);
        });
      });
    };
    
 Here it only took 22 lines of code to implement the same logic. And in reality,
 the VerbotenJS version is more robust than the raw JavaScript version due to
 the flexibility of functions like .toRegex() and .test().

 And my .ea() function operates like Array.forEach, except that it allows for
 Object key iteration, asynchronous or synchronous iteration based on the
 presence of a callback function, and enhanced iteration workflows with helpers
 like ea.exit(), ea.merge() and ea.join(). Basically .ea() precludes the need to
 ever use for loops, for-in loops, or any of the new ES5 array extensions 
 Array.forEach|map|filter|some|every|reduce* functions.

 That's all I have time to report on now, but I'll put up some more examples as
 I find well isolated examples.

 Conclusion
 ==================================================

 VerbotenJS has been a career long project of mine. I've renamed/rewritten the
 project multiple times over, for various different JavaScript hosts like
 WScript/JScript, HTA's, Rhino, J#, Jaxer and even a custom C# host I wrote for
 fun. With the growing popularity of NodeJS I think VerbotenJS has finally found
 a good home. And the architecture is finally to a point that I consider it
 stable and worthy of peer review. So get reviewing peers!

 Thanks for reading,
 Marcus Pope

Recent activity

Marcus Pope

Marcus Pope pushed 1 commit to marcuspope/verbotenjs

8988456 - Fixed a bug in array.proto.random. Added a bunch of html parsing functions and bug fixes. Added uri object feature to http get for tor access. ...
Marcus Pope

Marcus Pope pushed 2 commits to marcuspope/verbotenjs

9acceb4 - package update
68c5640 - fixed some bugs because I didn't quite understand string prototypes apparently. Enhanced shell functions pipe and run to prevent hangs, capture more output and support ...
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.