JJJ's Blog

  • WordPress
  • GitHub
  • Twitter/X
  • Tone

    Tone is more important than the words you use, until all you have is words. On the web, we’ve skirted tone for a long while with emoticons. :) Thankfully, the wide adoption of Emoji is rescuing us from writing obscure combinations of syntactically invalid punctuation, and I think that’s a good thing.

    If you read as much as I do, then you already know words like “just” & “that” unintentionally discredit your ideas and pitches; you know body language & confidence will win people over more than a lexicon of jargon; you know how hard it is to put biases aside and trust the data.

    The data about written communication, is that we all suck at it.

    Everyone, across the board, at both reading & writing, sucks at it, including me. I spend a lot of time, most of my professional career, not just thinking about social software, but how to improve both the value and the return-on-investment of the ways people socialize online. I think the answer, for me, is etiquette.

    Different groups of people, teams, factions, etc… have an established rapport. They found communication styles & mechanisms that work well enough for them to have considered that problem solved-enough, so they can move onto solving bigger problems. When these patterns deviate outside of traditional or societal norms, is when it becomes increasingly difficult to break into those groups.

    On a large scale, I can’t break into the Japanese WordPress User Group because I don’t speak a lick of Japanese. On a smaller scale, I can’t help my village planning commission make decisions because I don’t know any of the ordinances. At home, I can’t tell what Paul the dog is really thinking because he only understands a few dozen words and I don’t speak dog very well.

    For teams of humans, working together to address intersecting needs, we’ve worked for thousands of years to lower the barrier of entry into these groups. Grunts turned into syllables, words, phrases, and sentences. We introduced syntactical structure to convey pauses, stops, and rests. But when the web exploded, we froze almost all written language because it’s now the web’s biggest dependency. We can’t delete “Q” from the English language entirely because wp_enqueue_script wouldn’t work anymore.

    All of this is to say, that we need to learn how to do better with what we have today, because there won’t be much new for the rest of our lives when it comes to written communication. To do that, means a few different things…

    • Lurk. We all need to read, listen, & absorb. This includes understanding the general vibe of who is all involved, and deciding if it’s compatible with you.
    • Respect. Groups of people have established processes. No one can change these easily, especially someone new & full of enthusiasm to rock everyone’s worlds.
    • Decide. You need to choose where you think you fall in the pecking order, and make no mistake, there is a pecking order. Even flat organizations have a hidden social hierarchy. Understanding Social Dominance Theory will help you, here.
    • Introduce. Once you have enough data from lurking, you can slowly start to apply what you’ve learned. Sometimes this means humor, sometimes strictly business, or other times it means only lurking and not getting involved at all.
    • Pace. Now that you understand the social dynamic, and have decided where you think you belong in the group, it’s time to try to keep the pace. Traditionally, this is called “fitting in” but it’s important to earning the trust of your new acquaintances.
    • Pass/fail. You’ll know pretty quickly whether any of your above efforts have resonated positively or negatively, and each interaction will echo through-out the group. Someone will mention you, one way or the other.
    • Stay/bail. The level of joy you receive from any group of people should be the underlying motivator for driving your decision to stay or leave. If it’s rewarding, healthy, and fun, then stay. If it’s causing harm to yourself or others, my advice would be to consider anything else.

    “Us vs. Them” is a real feeling, because we are – all of us – are constantly at odds with each other. In our base programming, we are animals, sizing each other up, and fighting for scraps. Sure; we are mostly domesticated animals, but during times of distress or high-anxiety, you can watch people become animals & treat other people that way too, and triggers could literally be anything from allergies to relationship issues to PTSD and on…

    When it comes to WordPress’s leadership, or BuddyPress/bbPress, or really anything else, these same rules apply, but increasingly so because almost all of our communication is non-verbal. This means a million people may read your words and hear kindness in your written voice, but the one person you want to hear kindness may only hear rage, for reasons that may or may not have anything to do with anything you did or did not do. Phew!

    My proposed solution, is etiquette. More pleases, more thank-you’s, more awareness of who is involved in what, who is in charge of what, who has earned what, and who the who’s are and what they want to be when they grow up. This means a base-level respect for everyone, regardless of your history or lack-there-of. It means reading your words back to yourself and trying to convey a smile without using :) or 😀.

    Ultimately, it means being patient, and taking the time to craft your words so they will sound like a well-intentioned contribution to your audience.

    For slowing down, I’ll recommend you try switching your keyboard layout. In 2010, I switched to Dvorak – when my 100wpm plummeted to 20, those 20 words needed to matter most. Twitter’s 140 character limit maybe helps with being succinct, but I don’t know that length is as important as word-choice and knowing your audience.

    Lastly, it helps to know yourself, and have a relatively clear idea of who the people around you think that you are, and how similar that is to who you think you are. If people think you’re always goofy, and you think you have something serious to offer, changing that perception is not going to be easy, and it may take a number of years to swing people around to accepting your style & approach for what it is.

    I think if everyone has a bit more patience with each other, and we all take the time to consider the ripples we leave in people’s lives, we can communicate with written words in ways that don’t sink ships or hurt feelings. <3

    JJJ

    August 23, 2016
    Rants, Opinion, Software
  • Today's Software is Terrible

    Are you a software developer? I am, and everyday I’m embarrassed by my profession.

    Every single day, I run across some website, app, video-game, program or plugin that is egregiously broken; embarrassingly broken; 5000-developers-with-six-figure-salaries-and-free-catered-lunches-and-still-can’t-get-it-right, broken.

    Apps on my phone, tablet, computer, tv, and car, crash constantly, sometimes resulting in actual data loss. We shoved television behind a pay-wall in a cube that buffers and loads more than it presents anything. We broke copy & paste, because who would ever want to paste a password anywhere? Form fields do this shit where they want to autocomplete and autocorrect and autofill 3 different suggestions at once. We connected wrist-watches to the internet to draw doodles back and forth that don’t even send half the time. We hid mechanical engines behind electronics so complex there is noticeable lag driving performance cars. We connected entertainment systems to airplane diagnostic systems, so passengers can see how high up they are. We connect doors to the web to unlock them remotely, but firmware updates brick them and now you’re locked out of your house. We connect smoke detectors to the web and now the entire house & every connected device in it is beeping because you grilled a burger-patty, and the app on your phone to stop them isn’t responding.

    Today’s software is a perpetual nightmare machine of non-stop frustrations.

    Writing software is hard, mostly for reasons that don’t actually involve the software itself. I could go on about stakeholders, or how project managers are whatever. I could say that developers should be left alone to concentrate. I could say it’s nobody’s fault because it’s everybody’s fault. I could say all kinds of trite crap to poorly defend the people that populate the position I hold most dear, and currently the most fun job I think anyone could ever hope to perform.

    I could say lots of things, but they’d all be lies.

    The harsh truth is that many of you shouldn’t be writing software for production use, because you’re just not that good at it yet. You’re not experienced. You haven’t shipped anything. You don’t know how to recover from the damage you will inevitably cause.

    You break people’s shit – constantly, anonymously, and without repercussion. You aren’t meticulous in your life, you don’t care about etiquette, so you won’t do your employer any better, and you certainly won’t care if any of your users complain on Twitter.

    Sure; mistakes happen. We all overlook stuff. That’s how you learn, right? By repeating and improving and discovering what you missed the previous times. And there is more to discover everyday, because there are more & more design patterns and philosophies and dependencies and processes and teams and stakeholders and deadlines and Carl called in sick and no one understands what he even does here anymore but it’s suddenly critical to today’s problems and why is this line of code 500 characters long and who messed up all this whitespace and why can’t we all agree not to use ternaries and why does this class inherit from 5 other classes and on and on and on.

    Software is eating the world, but… garbage in, garbage out. So, what can we do?

    1. Be meticulous. Someone will undoubtedly refer to you as OCD, or apply some other insulting derogatory bullshit label. Screw them; they suck at their job anyway.
    2. Pay attention, to everything. You are the Axel Foley of software development. Writing code and fixing bugs is target practice for your soul. Do it constantly, rearrange the pieces in your mind while you shower, and take everything in. This means watching, listening, learning, while writing less and solving more.
    3. Be vigilant. Everything around you is intricately balanced and ready to come crashing down at a misplaced semi-colon’s notice. I’m not joking. You can very easily cause millions of dollars in revenue losses by breaking just 1 dependency in a complex chain. Code is poetry, but it’s also contagious.
    4. Be respectful. Push your chair in. Hold the door for everyone. Smile at people, even when you’re grumpy. Someone has to maintain the terrible decisions you’ve made once you level-up & move-on, and that’s easier to do when you like the person who’s shadow you’re in.
    5. Contribute to open-source. This is where you earn your lumps; not behind closed doors, not in a sweet corporate environment, and not sitting at a desk sipping a mocha-latté. You need to jump up on stage, give your best performance, and embrace the tomatoes and boos, because you’re probably going to be terrible for your first few rounds.
    6. If it ain’t fun, it ain’t right. Once you stop feeling joy from the software you’re writing, it’s time to move onto something else. Sitting still and being complacent isn’t healthy, even if it feels pretty natural not to burn all those calories moving on to newer and more exciting endeavors.
    7. Make friends. Like, real ones. Ones that will come to your wedding from across the country. These are the people that will remind you how good you are when you need them to, and they’ll have your back when you’re not having fun anymore.
    8. Learn how to make soup. Not even kidding. Understanding how to make the best of what few ingredients you have is essential to writing good software. Embrace your constraints, and don’t be afraid of butter or salt because they’re universally delicious.
    9. Challenge authority constantly. Most people have no idea what they’re doing. They were asked or tasked with a problem, and either they follow the above methods or they pass the problem on to someone else. They’re in a holding pattern, until the next big thing happens to them, instead of making big things happen around them.
    10. Find mentors everywhere. Follow a person around that you want to be like, take bits of pieces of what works for them, and apply them to your life. Steal, plagiarize, and sample small enough traits until you’re an amalgamation of the hippest, funniest, most awesome people you’ve ever come across.

    Then, after all of that, sit down and write the best ‘effing software anyone has ever used. ❤️

    JJJ

    August 4, 2016
    Rants, Software
  • Apple carOS

    Imagine you’re a company, maybe even one as big, as innovative, and as reaching as Apple. Other technology companies have prototyped & released something ahead of you.

    What can you do?

    If you are anything like Apple, you use their head-start to your advantage, watching & learning from their expensive educations with an end-around in your playbook. You solve remaining problems from the complete opposite perspective, investing more on the fit & finish to put out a more polished product and winning over your competition in the long game.

    According to our friend Elon Musk, Tesla automobiles have logged many hundreds of millions of miles worth of data – not just about the cars, but also driver feedback, situational logging, and environmental stimuli like what the onboard cameras are seeing & calculating.

    With that many logged miles and that many cars already deployed, there’s no way anyone will be able to catch up to Tesla… without help.

    There are rumors of loud engine noises in buildings known to be owned by Apple subsidiaries. The web has countless renderings of what an Apple branded automobile could look like.

    All of that said, I (highly, highly) doubt anyone at Apple seriously explored the idea of a complete Apple Car until recently. More likely, a fork of iOS has been in the skunkworks, plugged in and listening to a variety of engines & motors, acting as the onboard diagnostics system for future iterations of existing maker’s platforms.

    carOS

    In the next 5 years, Apple will unveil the results of an amazingly ambitious R&D project – a “never been attempted before in the history of the world” type of project, as Apple likes to boast.

    They’ll take what they learned from scaling iCloud & HealthKit, what they learned from producing and shipping over a billion iPhones, and what they learned about third-party integration via HomeKit – after crunching billions of data points provided by humans over the course of 10 years, they’ll confidently duplicate those same efforts with people-carriers by releasing carOS.

    Apple is already using iPhone motion data – or lack there of – to predict traffic patterns, jams, and identify & alert people using Apple Maps that there is some type of anomaly ahead. Spooky, if not incredibly cool.

    They’ll funnel & analyze the input & output of every engine already and soon-to-be in production going forward, and be able to both make real-time decisions & provide graphical output about what your car thinks, sees, and feels.

    Apple mates hard with soft, so I doubt they’ll trust companies like Honda or Nissan with their secret sauces. You can’t have the hop if you don’t have the hip, and you can’t have a car anymore without it’s eyes & ears connected to the world around it.

    Naturally, you can’t copy & paste in carOS 1.0 though. Apple exercises enormous self-control, omitting the obvious to slow-roll the essential so that the stubborn masses have time to casually catch-up to their speed.

    Apple’s carOS efforts, from now until 2020, will moon-shot them around the competition without them ever having released their own car. They’ll sit idly by, researching, analyzing, privately blowing up all kinds of sweet motors & engines, until they’re ready to revolutionize the ways people are transported from A to B.

    Hey, Siri. Remind KITT to pick-up the kids from band practice at 5:30pm.

    OK. Searching the web for “Break me off a piece of that Kit-Kat bar.”

    JJJ

    August 2, 2016
    Software
    Apple, carOS
  • Upgrading MariaDB Ubuntu Server from 14.04 to 16.04

    First, I needed to remove the old apt repository and signing key. (This prevents do-release-upgrade -d from stopping halfway through.)

    Remove repos:

    cd /etc/apt/sources.list.d
    sudo rm maria*

    Remove old key:

    # List the keys
    sudo apt-key list
    # Remove the correct key, which is the second half of PUB STRING1/STRING2
    sudo apt-key del STRING2

    Second, I needed to add the new apt repository and signing key:

    # Probably is already installed
    sudo apt-get install software-properties-common
    # Get the key
    sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
    # Add the xenial repository
    sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://mirrors.accretive-networks.net/mariadb/repo/10.1/ubuntu xenial main'

    Now you are safe to run do-release-upgrade -d without any halts!

    You’ll probably want to backup your `my.cnf` file too. The upgrade process will ask you to keep or overwrite your old one, and neither of those options are usually very desirable if you have tuned your MariaDB configuration at all.

    <3

    JJJ

    July 14, 2016
    Software
  • XDebug, Laravel Valet, NetBeans

    Screen Shot 2016-05-10 at 11.09.35.png

    To get XDebug working with Laravel Valet & NetBeans, I needed to do the following:

    1. Install XDebug via Homebrew:
      brew install homebrew/php/php70-xdebug
    2. Enter NetBeans’s Preferences > PHP > Debugging:
      1. Change the port from 9000 to 9001.
        (This is because Valet runs on 9000 by default.)
      2. Uncheck “Stop at first line”.
        (This is because Valet is listening to all requests, and server.php will get hit a bunch of times in the same page refresh.)
    3. Edit /usr/local/etc/php/7.0/php.ini
    4. Add this bit to the end:
      [xdebug]
      xdebug.remote_enable=on
      xdebug.idekey="netbeans-xdebug"
      xdebug.remote_port=9001

      This turns on remote debugging, and tells XDebug to look for NetBeans’s IDE key.

    5. Restart Valet with valet restart in your favorite terminal app.
      Note that brew services restart php70 isn’t enough here; you need to restart Valet entirely.

    Also…

    Live debugging using XDebug will severely degrade Valet’s otherwise snappy performance. Composer will even tell you this:

    You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
    

    This is normal. XDebug is a hugely powerful realtime interpreter, debugger, and profiler, and it’s going to slow things down while it’s listening to all that PHP chug along. (You may be able to tune this a bit using all of XDebug’s extensive settings.)

    If you’re worried about battery life, most IDE’s (like NetBeans) will let you turn debug sessions on and off. So debug, do your thing, find the bug, kill the bug, and turn it off.

    JJJ

    May 10, 2016
    Software
  • Slow Vagrant?

    Maybe you’re a file hoarder, like me.

    I switched to using VVV a few years ago, when it became cool to use Vagrant and when unit testing became a must-have part of my daily WordPress development process.

    Truth be told, I’ve missed the simplicity of MAMP PRO ever since, even if I do prefer Nginx over Apache these days.

    And if you’re like me, you never really delete stuff, it just goes someplace else. Git enables this; I pack away repositories like a squirrel, thinking that I’ll clone something now and peek at it later.

    I have a 6 core Xeon powered Mac Pro at my office. It’s usually sitting idle as a task runner for all sorts of client work that requires a bit of additional TLC. I push some code from my MacBook to Gitlab; Gitlab tells my Mac Pro to make sure everything is still green; I move on to the next task.

    So lately, my Mac Pro has seen abysmal performance when it comes to Vagrant related tasks. Things like up, ssh, and box update would take several minutes to complete. Last night, it took 6 hours to vagrant up --provision so I finally gave up and decided to figure out what the heck was going on.

    Screen Shot 2016-05-05 at 12.58.27 PM.png
    73 seconds to vagrant ssh.

    I guess it was my own fault. I keep a local mirror of plugins.svn.wordpress.org on my Mac Pro, which pulls down about 70k WordPress plugins, creating over 339,000 directories.

    Screen Shot 2016-05-05 at 1.02.06 PM.png
    This kills the VVV.

    What I discovered is that the number of directories in your VVV’s www directory can have a severely negative impact on the performance of your vagrant commands, even if those directories are largely dormant and do not contain a relative vvv-hosts or vvv-init.sh files to treat them as actual sites.

    I have a few hunches about what’s causing the slow down, but haven’t the time to dig much deeper:

    • Guest Additions might front-load the directory tree, in such a way that locks the rest of Vagrant from proceeding, maybe part of the vagrant-vaguest plugin?
    • Some other plugin feels the need to traverse the directory tree without a max-depth flag
    • VVV or Vagrant have internally optimized for traditional web directories that do not have hundreds of thousands of directories

    Hope this helps, and if you figure out the rest of this, drop me a comment! <3

    JJJ

    May 5, 2016
    Software
  • Mother Nature's Toolbox Must Be Heavy

    Running npm install for WordPress is a terrifying experience. It installs so many libraries and dependencies, it would take a lifetime to learn them all. If you’ve never had the pleasure, here’s what it looks like today:

    WordPress@4.5.0 /Users/johnjamesjacoby/Work/VVV/www/wordpress-develop
    ├─┬ autoprefixer@6.1.2
    │ ├── browserslist@1.0.1
    │ ├── caniuse-db@1.0.30000384
    │ ├── num2fraction@1.2.2
    │ ├─┬ postcss@5.0.14
    │ │ ├── js-base64@2.1.9
    │ │ ├── source-map@0.5.3
    │ │ └─┬ supports-color@3.1.2
    │ │   └── has-flag@1.0.0
    │ └── postcss-value-parser@3.2.3
    ├─┬ grunt@0.4.5
    │ ├── async@0.1.22
    │ ├── coffee-script@1.3.3
    │ ├── colors@0.6.2
    │ ├── dateformat@1.0.2-1.2.3
    │ ├── eventemitter2@0.4.14
    │ ├── exit@0.1.2
    │ ├─┬ findup-sync@0.1.3
    │ │ ├─┬ glob@3.2.11
    │ │ │ └── minimatch@0.3.0
    │ │ └── lodash@2.4.2
    │ ├── getobject@0.1.0
    │ ├─┬ glob@3.1.21
    │ │ ├── graceful-fs@1.2.3
    │ │ └── inherits@1.0.2
    │ ├─┬ grunt-legacy-log@0.1.3
    │ │ ├─┬ grunt-legacy-log-utils@0.1.1
    │ │ │ ├── lodash@2.4.2
    │ │ │ └── underscore.string@2.3.3
    │ │ ├── lodash@2.4.2
    │ │ └── underscore.string@2.3.3
    │ ├── hooker@0.2.3
    │ ├── iconv-lite@0.2.11
    │ ├─┬ js-yaml@2.0.5
    │ │ └─┬ argparse@0.1.16
    │ │   ├── underscore@1.7.0
    │ │   └── underscore.string@2.4.0
    │ ├── lodash@0.9.2
    │ ├─┬ minimatch@0.2.14
    │ │ ├── lru-cache@2.7.3
    │ │ └── sigmund@1.0.1
    │ ├─┬ nopt@1.0.10
    │ │ └── abbrev@1.0.7
    │ ├── rimraf@2.2.8
    │ ├── underscore.string@2.2.1
    │ └── which@1.0.9
    ├─┬ grunt-browserify@4.0.1
    │ ├── async@0.9.2
    │ ├─┬ browserify@11.2.0
    │ │ ├── assert@1.3.0
    │ │ ├─┬ browser-pack@5.0.1
    │ │ │ ├─┬ combine-source-map@0.6.1
    │ │ │ │ ├── convert-source-map@1.1.3
    │ │ │ │ ├─┬ inline-source-map@0.5.0
    │ │ │ │ │ └── source-map@0.4.4
    │ │ │ │ ├── lodash.memoize@3.0.4
    │ │ │ │ └── source-map@0.4.4
    │ │ │ └── umd@3.0.1
    │ │ ├── browser-resolve@1.11.0
    │ │ ├─┬ browserify-zlib@0.1.4
    │ │ │ └── pako@0.2.8
    │ │ ├─┬ buffer@3.6.0
    │ │ │ ├── base64-js@0.0.8
    │ │ │ ├── ieee754@1.1.6
    │ │ │ └── isarray@1.0.0
    │ │ ├── builtins@0.0.7
    │ │ ├── commondir@0.0.1
    │ │ ├─┬ concat-stream@1.4.10
    │ │ │ ├── readable-stream@1.1.13
    │ │ │ └── typedarray@0.0.6
    │ │ ├─┬ console-browserify@1.1.0
    │ │ │ └── date-now@0.1.4
    │ │ ├── constants-browserify@0.0.1
    │ │ ├─┬ crypto-browserify@3.11.0
    │ │ │ ├─┬ browserify-cipher@1.0.0
    │ │ │ │ ├─┬ browserify-aes@1.0.5
    │ │ │ │ │ └── buffer-xor@1.0.3
    │ │ │ │ ├─┬ browserify-des@1.0.0
    │ │ │ │ │ └─┬ des.js@1.0.0
    │ │ │ │ │   └── minimalistic-assert@1.0.0
    │ │ │ │ └── evp_bytestokey@1.0.0
    │ │ │ ├─┬ browserify-sign@4.0.0
    │ │ │ │ ├── bn.js@4.6.2
    │ │ │ │ ├── browserify-rsa@4.0.0
    │ │ │ │ ├─┬ elliptic@6.0.2
    │ │ │ │ │ ├── brorand@1.0.5
    │ │ │ │ │ └── hash.js@1.0.3
    │ │ │ │ └─┬ parse-asn1@5.0.0
    │ │ │ │   └── asn1.js@4.3.0
    │ │ │ ├── create-ecdh@4.0.0
    │ │ │ ├─┬ create-hash@1.1.2
    │ │ │ │ ├── cipher-base@1.0.2
    │ │ │ │ └── ripemd160@1.0.1
    │ │ │ ├── create-hmac@1.1.4
    │ │ │ ├─┬ diffie-hellman@5.0.0
    │ │ │ │ └── miller-rabin@4.0.0
    │ │ │ ├── pbkdf2@3.0.4
    │ │ │ ├── public-encrypt@4.0.0
    │ │ │ └── randombytes@2.0.1
    │ │ ├── defined@1.0.0
    │ │ ├── deps-sort@1.3.9
    │ │ ├── domain-browser@1.1.7
    │ │ ├─┬ duplexer2@0.0.2
    │ │ │ └── readable-stream@1.1.13
    │ │ ├── events@1.0.2
    │ │ ├─┬ glob@4.5.3
    │ │ │ └── minimatch@2.0.10
    │ │ ├─┬ has@1.0.1
    │ │ │ └── function-bind@1.0.2
    │ │ ├── htmlescape@1.1.0
    │ │ ├── https-browserify@0.0.1
    │ │ ├── inherits@2.0.1
    │ │ ├─┬ insert-module-globals@6.6.3
    │ │ │ ├── is-buffer@1.1.1
    │ │ │ └─┬ lexical-scope@1.2.0
    │ │ │   └── astw@2.0.0
    │ │ ├── isarray@0.0.1
    │ │ ├─┬ JSONStream@1.0.7
    │ │ │ ├── jsonparse@1.2.0
    │ │ │ └── through@2.3.8
    │ │ ├─┬ labeled-stream-splicer@1.0.2
    │ │ │ └─┬ stream-splicer@1.3.2
    │ │ │   └── readable-stream@1.1.13
    │ │ ├─┬ module-deps@3.9.1
    │ │ │ ├── detective@4.3.1
    │ │ │ ├── readable-stream@1.1.13
    │ │ │ └─┬ stream-combiner2@1.0.2
    │ │ │   └─┬ through2@0.5.1
    │ │ │     ├── readable-stream@1.0.33
    │ │ │     └── xtend@3.0.0
    │ │ ├── os-browserify@0.1.2
    │ │ ├─┬ parents@1.0.1
    │ │ │ └── path-platform@0.11.15
    │ │ ├── path-browserify@0.0.0
    │ │ ├── process@0.11.2
    │ │ ├── punycode@1.4.0
    │ │ ├── querystring-es3@0.2.1
    │ │ ├─┬ read-only-stream@1.1.1
    │ │ │ ├── readable-stream@1.1.13
    │ │ │ └─┬ readable-wrap@1.0.0
    │ │ │   └── readable-stream@1.1.13
    │ │ ├─┬ readable-stream@2.0.5
    │ │ │ ├── core-util-is@1.0.2
    │ │ │ ├── process-nextick-args@1.0.6
    │ │ │ └── util-deprecate@1.0.2
    │ │ ├─┬ shasum@1.0.2
    │ │ │ ├─┬ json-stable-stringify@0.0.1
    │ │ │ │ └── jsonify@0.0.0
    │ │ │ └── sha.js@2.4.4
    │ │ ├── shell-quote@0.0.1
    │ │ ├── stream-browserify@2.0.1
    │ │ ├─┬ stream-http@1.7.1
    │ │ │ ├── builtin-status-codes@1.0.0
    │ │ │ ├── foreach@2.0.5
    │ │ │ ├── indexof@0.0.1
    │ │ │ └── object-keys@1.0.9
    │ │ ├── string_decoder@0.10.31
    │ │ ├─┬ subarg@1.0.0
    │ │ │ └── minimist@1.2.0
    │ │ ├─┬ syntax-error@1.1.4
    │ │ │ └── acorn@1.2.2
    │ │ ├─┬ through2@1.1.1
    │ │ │ └── readable-stream@1.1.13
    │ │ ├── timers-browserify@1.4.2
    │ │ ├── tty-browserify@0.0.0
    │ │ ├─┬ url@0.10.3
    │ │ │ ├── punycode@1.3.2
    │ │ │ └── querystring@0.2.0
    │ │ ├── util@0.10.3
    │ │ ├── vm-browserify@0.0.4
    │ │ └── xtend@4.0.1
    │ ├─┬ glob@5.0.15
    │ │ ├─┬ inflight@1.0.4
    │ │ │ └── wrappy@1.0.1
    │ │ ├─┬ minimatch@3.0.0
    │ │ │ └─┬ brace-expansion@1.1.2
    │ │ │   ├── balanced-match@0.3.0
    │ │ │   └── concat-map@0.0.1
    │ │ ├── once@1.3.3
    │ │ └── path-is-absolute@1.0.0
    │ ├── lodash@3.10.1
    │ ├── resolve@1.1.6
    │ └─┬ watchify@3.6.1
    │   ├─┬ anymatch@1.3.0
    │   │ ├── arrify@1.0.1
    │   │ └─┬ micromatch@2.3.7
    │   │   ├─┬ arr-diff@2.0.0
    │   │   │ └── arr-flatten@1.0.1
    │   │   ├── array-unique@0.2.1
    │   │   ├─┬ braces@1.8.3
    │   │   │ ├─┬ expand-range@1.8.1
    │   │   │ │ └─┬ fill-range@2.2.3
    │   │   │ │   ├── is-number@2.1.0
    │   │   │ │   ├── isobject@2.0.0
    │   │   │ │   ├── randomatic@1.1.5
    │   │   │ │   └── repeat-string@1.5.2
    │   │   │ ├── preserve@0.2.0
    │   │   │ └── repeat-element@1.1.2
    │   │   ├── expand-brackets@0.1.4
    │   │   ├─┬ extglob@0.3.1
    │   │   │ ├─┬ ansi-green@0.1.1
    │   │   │ │ └── ansi-wrap@0.1.0
    │   │   │ └── success-symbol@0.1.0
    │   │   ├── filename-regex@2.0.0
    │   │   ├── is-extglob@1.0.0
    │   │   ├── kind-of@3.0.2
    │   │   ├── normalize-path@2.0.1
    │   │   ├─┬ object.omit@2.0.0
    │   │   │ ├─┬ for-own@0.1.3
    │   │   │ │ └── for-in@0.1.4
    │   │   │ └── is-extendable@0.1.1
    │   │   ├─┬ parse-glob@3.0.4
    │   │   │ ├── glob-base@0.3.0
    │   │   │ └── is-dotfile@1.0.2
    │   │   └─┬ regex-cache@0.4.2
    │   │     ├── is-equal-shallow@0.1.3
    │   │     └── is-primitive@2.0.0
    │   ├─┬ browserify@12.0.1
    │   │ ├─┬ browser-pack@6.0.1
    │   │ │ └─┬ combine-source-map@0.7.1
    │   │ │   ├── inline-source-map@0.6.1
    │   │ │   └── source-map@0.4.2
    │   │ ├── concat-stream@1.5.1
    │   │ ├── constants-browserify@1.0.0
    │   │ ├── deps-sort@2.0.0
    │   │ ├── duplexer2@0.1.4
    │   │ ├── events@1.1.0
    │   │ ├─┬ glob@5.0.15
    │   │ │ └── minimatch@3.0.0
    │   │ ├── insert-module-globals@7.0.1
    │   │ ├─┬ labeled-stream-splicer@2.0.0
    │   │ │ └── stream-splicer@2.0.0
    │   │ ├─┬ module-deps@4.0.5
    │   │ │ └── stream-combiner2@1.1.1
    │   │ ├── read-only-stream@2.0.0
    │   │ ├── shell-quote@1.4.3
    │   │ ├── stream-http@2.0.2
    │   │ └─┬ url@0.11.0
    │   │   └── punycode@1.3.2
    │   ├─┬ chokidar@1.4.2
    │   │ ├── async-each@0.1.6
    │   │ ├─┬ fsevents@1.0.6
    │   │ │ └─┬ node-pre-gyp@0.6.17
    │   │ │   ├─┬ mkdirp@0.5.1
    │   │ │   │ └── minimist@0.0.8
    │   │ │   ├─┬ nopt@3.0.6
    │   │ │   │ └── abbrev@1.0.7
    │   │ │   ├─┬ npmlog@2.0.0
    │   │ │   │ ├── ansi@0.3.0
    │   │ │   │ ├─┬ are-we-there-yet@1.0.4
    │   │ │   │ │ ├── delegates@0.1.0
    │   │ │   │ │ └─┬ readable-stream@1.1.13
    │   │ │   │ │   ├── core-util-is@1.0.2
    │   │ │   │ │   ├── isarray@0.0.1
    │   │ │   │ │   └── string_decoder@0.10.31
    │   │ │   │ └─┬ gauge@1.2.2
    │   │ │   │   ├── has-unicode@1.0.1
    │   │ │   │   ├─┬ lodash.pad@3.1.1
    │   │ │   │   │ ├── lodash._basetostring@3.0.1
    │   │ │   │   │ └─┬ lodash._createpadding@3.6.1
    │   │ │   │   │   └── lodash.repeat@3.0.1
    │   │ │   │   ├── lodash.padleft@3.1.1
    │   │ │   │   └── lodash.padright@3.1.1
    │   │ │   ├─┬ rc@1.1.5
    │   │ │   │ ├── ini@1.3.4
    │   │ │   │ ├── minimist@1.2.0
    │   │ │   │ └── strip-json-comments@1.0.4
    │   │ │   ├─┬ request@2.67.0
    │   │ │   │ ├── aws-sign2@0.6.0
    │   │ │   │ ├─┬ bl@1.0.0
    │   │ │   │ │ └─┬ readable-stream@2.0.4
    │   │ │   │ │   ├── core-util-is@1.0.2
    │   │ │   │ │   ├── inherits@2.0.1
    │   │ │   │ │   ├── isarray@0.0.1
    │   │ │   │ │   ├── string_decoder@0.10.31
    │   │ │   │ │   └── util-deprecate@1.0.2
    │   │ │   │ ├── caseless@0.11.0
    │   │ │   │ ├─┬ combined-stream@1.0.5
    │   │ │   │ │ └── delayed-stream@1.0.0
    │   │ │   │ ├── extend@3.0.0
    │   │ │   │ ├── forever-agent@0.6.1
    │   │ │   │ ├── form-data@1.0.0-rc3
    │   │ │   │ ├─┬ har-validator@2.0.3
    │   │ │   │ │ ├─┬ chalk@1.1.1
    │   │ │   │ │ │ ├── ansi-styles@2.1.0
    │   │ │   │ │ │ ├─┬ has-ansi@2.0.0
    │   │ │   │ │ │ │ └── ansi-regex@2.0.0
    │   │ │   │ │ │ ├── strip-ansi@3.0.0
    │   │ │   │ │ │ └── supports-color@2.0.0
    │   │ │   │ │ ├─┬ commander@2.9.0
    │   │ │   │ │ │ └── graceful-readlink@1.0.1
    │   │ │   │ │ ├─┬ is-my-json-valid@2.12.3
    │   │ │   │ │ │ ├── generate-function@2.0.0
    │   │ │   │ │ │ ├─┬ generate-object-property@1.2.0
    │   │ │   │ │ │ │ └── is-property@1.0.2
    │   │ │   │ │ │ ├── jsonpointer@2.0.0
    │   │ │   │ │ │ └── xtend@4.0.1
    │   │ │   │ │ └─┬ pinkie-promise@2.0.0
    │   │ │   │ │   └── pinkie@2.0.1
    │   │ │   │ ├─┬ hawk@3.1.2
    │   │ │   │ │ ├── boom@2.10.1
    │   │ │   │ │ ├── cryptiles@2.0.5
    │   │ │   │ │ ├── hoek@2.16.3
    │   │ │   │ │ └── sntp@1.0.9
    │   │ │   │ ├─┬ http-signature@1.1.0
    │   │ │   │ │ ├── assert-plus@0.1.5
    │   │ │   │ │ ├─┬ jsprim@1.2.2
    │   │ │   │ │ │ ├── extsprintf@1.0.2
    │   │ │   │ │ │ ├── json-schema@0.2.2
    │   │ │   │ │ │ └── verror@1.3.6
    │   │ │   │ │ └─┬ sshpk@1.7.0
    │   │ │   │ │   ├── asn1@0.2.3
    │   │ │   │ │   ├── assert-plus@0.2.0
    │   │ │   │ │   ├── ecc-jsbn@0.1.1
    │   │ │   │ │   ├── jodid25519@1.0.2
    │   │ │   │ │   └── jsbn@0.1.0
    │   │ │   │ ├── is-typedarray@1.0.0
    │   │ │   │ ├── isstream@0.1.2
    │   │ │   │ ├── json-stringify-safe@5.0.1
    │   │ │   │ ├── node-uuid@1.4.7
    │   │ │   │ ├── oauth-sign@0.8.0
    │   │ │   │ ├── qs@5.2.0
    │   │ │   │ ├── stringstream@0.0.5
    │   │ │   │ └── tough-cookie@2.2.1
    │   │ │   ├─┬ rimraf@2.4.4
    │   │ │   │ └─┬ glob@5.0.15
    │   │ │   │   ├─┬ inflight@1.0.4
    │   │ │   │   │ └── wrappy@1.0.1
    │   │ │   │   ├── inherits@2.0.1
    │   │ │   │   ├─┬ minimatch@3.0.0
    │   │ │   │   │ └─┬ brace-expansion@1.1.1
    │   │ │   │   │   └── concat-map@0.0.1
    │   │ │   │   ├─┬ once@1.3.3
    │   │ │   │   │ └── wrappy@1.0.1
    │   │ │   │   └── path-is-absolute@1.0.0
    │   │ │   ├── semver@5.1.0
    │   │ │   ├─┬ tar@2.2.1
    │   │ │   │ ├── block-stream@0.0.8
    │   │ │   │ ├── fstream@1.0.8
    │   │ │   │ └── inherits@2.0.1
    │   │ │   └─┬ tar-pack@3.1.0
    │   │ │     ├── debug@0.7.4
    │   │ │     ├─┬ fstream-ignore@1.0.3
    │   │ │     │ └─┬ minimatch@3.0.0
    │   │ │     │   └─┬ brace-expansion@1.1.1
    │   │ │     │     └── concat-map@0.0.1
    │   │ │     ├── graceful-fs@4.1.2
    │   │ │     ├─┬ readable-stream@1.0.33
    │   │ │     │ ├── core-util-is@1.0.2
    │   │ │     │ ├── inherits@2.0.1
    │   │ │     │ ├── isarray@0.0.1
    │   │ │     │ └── string_decoder@0.10.31
    │   │ │     └── rimraf@2.2.8
    │   │ ├── glob-parent@2.0.0
    │   │ ├─┬ is-binary-path@1.0.1
    │   │ │ └── binary-extensions@1.4.0
    │   │ ├── is-glob@2.0.1
    │   │ └─┬ readdirp@2.0.0
    │   │   ├── graceful-fs@4.1.2
    │   │   └── minimatch@2.0.10
    │   ├─┬ outpipe@1.1.1
    │   │ └─┬ shell-quote@1.4.3
    │   │   ├── array-filter@0.0.1
    │   │   ├── array-map@0.0.0
    │   │   └── array-reduce@0.0.0
    │   └── through2@2.0.0
    ├── grunt-contrib-clean@0.6.0
    ├─┬ grunt-contrib-compress@0.14.0
    │ ├─┬ archiver@0.16.0
    │ │ ├── async@1.4.2
    │ │ ├── buffer-crc32@0.2.5
    │ │ ├─┬ glob@5.0.15
    │ │ │ └── minimatch@3.0.0
    │ │ ├─┬ lazystream@0.1.0
    │ │ │ └── readable-stream@1.0.33
    │ │ ├── lodash@3.10.1
    │ │ ├── readable-stream@1.0.33
    │ │ ├─┬ tar-stream@1.2.2
    │ │ │ ├── bl@1.0.0
    │ │ │ └── end-of-stream@1.1.0
    │ │ └─┬ zip-stream@0.6.0
    │ │   ├─┬ compress-commons@0.3.0
    │ │   │ ├─┬ crc32-stream@0.3.4
    │ │   │ │ └── readable-stream@1.0.33
    │ │   │ ├── node-int64@0.4.0
    │ │   │ └── readable-stream@1.0.33
    │ │   ├── lodash@3.10.1
    │ │   └── readable-stream@1.0.33
    │ ├─┬ chalk@1.1.1
    │ │ ├── ansi-styles@2.1.0
    │ │ ├── escape-string-regexp@1.0.4
    │ │ ├─┬ has-ansi@2.0.0
    │ │ │ └── ansi-regex@2.0.0
    │ │ ├── strip-ansi@3.0.0
    │ │ └── supports-color@2.0.0
    │ └─┬ pretty-bytes@2.0.1
    │   ├── get-stdin@4.0.1
    │   ├─┬ meow@3.7.0
    │   │ ├─┬ camelcase-keys@2.0.0
    │   │ │ └── camelcase@2.0.1
    │   │ ├── decamelize@1.1.2
    │   │ ├─┬ loud-rejection@1.2.0
    │   │ │ └── signal-exit@2.1.2
    │   │ ├── map-obj@1.0.1
    │   │ ├─┬ normalize-package-data@2.3.5
    │   │ │ ├── hosted-git-info@2.1.4
    │   │ │ ├─┬ is-builtin-module@1.0.0
    │   │ │ │ └── builtin-modules@1.1.1
    │   │ │ └─┬ validate-npm-package-license@3.0.1
    │   │ │   ├─┬ spdx-correct@1.0.2
    │   │ │   │ └── spdx-license-ids@1.1.0
    │   │ │   └─┬ spdx-expression-parse@1.0.2
    │   │ │     └── spdx-exceptions@1.0.4
    │   │ ├─┬ read-pkg-up@1.0.1
    │   │ │ ├─┬ find-up@1.1.0
    │   │ │ │ └── path-exists@2.1.0
    │   │ │ └─┬ read-pkg@1.1.0
    │   │ │   ├─┬ load-json-file@1.1.0
    │   │ │   │ ├── graceful-fs@4.1.2
    │   │ │   │ ├─┬ parse-json@2.2.0
    │   │ │   │ │ └─┬ error-ex@1.3.0
    │   │ │   │ │   └── is-arrayish@0.2.1
    │   │ │   │ └── pify@2.3.0
    │   │ │   └─┬ path-type@1.1.0
    │   │ │     └── graceful-fs@4.1.2
    │   │ ├─┬ redent@1.0.0
    │   │ │ ├─┬ indent-string@2.1.0
    │   │ │ │ └─┬ repeating@2.0.0
    │   │ │ │   └── is-finite@1.0.1
    │   │ │ └── strip-indent@1.0.1
    │   │ └── trim-newlines@1.0.0
    │   └── number-is-nan@1.0.0
    ├─┬ grunt-contrib-concat@0.5.1
    │ ├─┬ chalk@0.5.1
    │ │ ├── ansi-styles@1.1.0
    │ │ ├─┬ has-ansi@0.1.0
    │ │ │ └── ansi-regex@0.2.1
    │ │ ├── strip-ansi@0.3.0
    │ │ └── supports-color@0.2.0
    │ └─┬ source-map@0.3.0
    │   └── amdefine@1.0.0
    ├─┬ grunt-contrib-copy@0.8.2
    │ └── file-sync-cmp@0.1.1
    ├─┬ grunt-contrib-cssmin@0.14.0
    │ ├─┬ clean-css@3.4.9
    │ │ ├─┬ commander@2.8.1
    │ │ │ └── graceful-readlink@1.0.1
    │ │ └── source-map@0.4.4
    │ └─┬ maxmin@1.1.0
    │   ├── figures@1.4.0
    │   ├── gzip-size@1.0.0
    │   └── pretty-bytes@1.0.4
    ├─┬ grunt-contrib-imagemin@1.0.0
    │ ├── async@0.9.2
    │ ├── gulp-rename@1.2.2
    │ ├─┬ imagemin@4.0.0
    │ │ ├─┬ buffer-to-vinyl@1.1.0
    │ │ │ ├── file-type@3.4.0
    │ │ │ ├── uuid@2.0.1
    │ │ │ └─┬ vinyl@1.1.0
    │ │ │   ├── clone@1.0.2
    │ │ │   ├── clone-stats@0.0.1
    │ │ │   └── replace-ext@0.0.1
    │ │ ├─┬ imagemin-gifsicle@4.2.0
    │ │ │ ├─┬ gifsicle@3.0.3
    │ │ │ │ ├─┬ bin-build@2.2.0
    │ │ │ │ │ ├── archive-type@3.2.0
    │ │ │ │ │ ├─┬ decompress@3.0.0
    │ │ │ │ │ │ ├─┬ decompress-tar@3.1.0
    │ │ │ │ │ │ │ ├── is-tar@1.0.0
    │ │ │ │ │ │ │ ├── object-assign@2.1.1
    │ │ │ │ │ │ │ ├─┬ strip-dirs@1.1.1
    │ │ │ │ │ │ │ │ ├── is-natural-number@2.0.0
    │ │ │ │ │ │ │ │ └── sum-up@1.0.2
    │ │ │ │ │ │ │ ├─┬ through2@0.6.5
    │ │ │ │ │ │ │ │ └── readable-stream@1.0.33
    │ │ │ │ │ │ │ └─┬ vinyl@0.4.6
    │ │ │ │ │ │ │   └── clone@0.2.0
    │ │ │ │ │ │ ├─┬ decompress-tarbz2@3.1.0
    │ │ │ │ │ │ │ ├── is-bzip2@1.0.0
    │ │ │ │ │ │ │ ├── object-assign@2.1.1
    │ │ │ │ │ │ │ ├── seek-bzip@1.0.5
    │ │ │ │ │ │ │ ├─┬ through2@0.6.5
    │ │ │ │ │ │ │ │ └── readable-stream@1.0.33
    │ │ │ │ │ │ │ └─┬ vinyl@0.4.6
    │ │ │ │ │ │ │   └── clone@0.2.0
    │ │ │ │ │ │ ├─┬ decompress-targz@3.1.0
    │ │ │ │ │ │ │ ├── is-gzip@1.0.0
    │ │ │ │ │ │ │ ├── object-assign@2.1.1
    │ │ │ │ │ │ │ ├─┬ through2@0.6.5
    │ │ │ │ │ │ │ │ └── readable-stream@1.0.33
    │ │ │ │ │ │ │ └─┬ vinyl@0.4.6
    │ │ │ │ │ │ │   └── clone@0.2.0
    │ │ │ │ │ │ ├─┬ decompress-unzip@3.4.0
    │ │ │ │ │ │ │ ├── is-zip@1.0.0
    │ │ │ │ │ │ │ ├── stat-mode@0.2.1
    │ │ │ │ │ │ │ ├── through2@2.0.0
    │ │ │ │ │ │ │ └─┬ yauzl@2.4.1
    │ │ │ │ │ │ │   └─┬ fd-slicer@1.0.1
    │ │ │ │ │ │ │     └── pend@1.2.0
    │ │ │ │ │ │ ├─┬ stream-combiner2@1.1.1
    │ │ │ │ │ │ │ └── duplexer2@0.1.4
    │ │ │ │ │ │ └── vinyl-assign@1.2.1
    │ │ │ │ │ ├─┬ download@4.4.3
    │ │ │ │ │ │ ├─┬ caw@1.2.0
    │ │ │ │ │ │ │ ├─┬ get-proxy@1.0.1
    │ │ │ │ │ │ │ │ └─┬ rc@0.5.5
    │ │ │ │ │ │ │ │   ├── deep-extend@0.2.11
    │ │ │ │ │ │ │ │   ├── minimist@0.0.10
    │ │ │ │ │ │ │ │   └── strip-json-comments@0.1.3
    │ │ │ │ │ │ │ ├── is-obj@1.0.0
    │ │ │ │ │ │ │ └── object-assign@3.0.0
    │ │ │ │ │ │ ├─┬ filenamify@1.2.0
    │ │ │ │ │ │ │ ├── filename-reserved-regex@1.0.0
    │ │ │ │ │ │ │ ├── strip-outer@1.0.0
    │ │ │ │ │ │ │ └── trim-repeated@1.0.0
    │ │ │ │ │ │ ├─┬ got@5.3.0
    │ │ │ │ │ │ │ ├─┬ create-error-class@2.0.1
    │ │ │ │ │ │ │ │ └── capture-stack-trace@1.0.0
    │ │ │ │ │ │ │ ├── is-plain-obj@1.1.0
    │ │ │ │ │ │ │ ├── is-redirect@1.0.0
    │ │ │ │ │ │ │ ├── lowercase-keys@1.0.0
    │ │ │ │ │ │ │ ├── node-status-codes@1.0.0
    │ │ │ │ │ │ │ ├── timed-out@2.0.0
    │ │ │ │ │ │ │ ├── unzip-response@1.0.0
    │ │ │ │ │ │ │ └─┬ url-parse-lax@1.0.0
    │ │ │ │ │ │ │   └── prepend-http@1.0.3
    │ │ │ │ │ │ ├─┬ gulp-decompress@1.2.0
    │ │ │ │ │ │ │ └─┬ gulp-util@3.0.7
    │ │ │ │ │ │ │   ├── array-differ@1.0.0
    │ │ │ │ │ │ │   ├── array-uniq@1.0.2
    │ │ │ │ │ │ │   ├── beeper@1.1.0
    │ │ │ │ │ │ │   ├── dateformat@1.0.12
    │ │ │ │ │ │ │   ├─┬ fancy-log@1.1.0
    │ │ │ │ │ │ │   │ └── dateformat@1.0.12
    │ │ │ │ │ │ │   ├─┬ gulplog@1.0.0
    │ │ │ │ │ │ │   │ └── glogg@1.0.0
    │ │ │ │ │ │ │   ├─┬ has-gulplog@0.1.0
    │ │ │ │ │ │ │   │ └── sparkles@1.0.0
    │ │ │ │ │ │ │   ├── lodash._reescape@3.0.0
    │ │ │ │ │ │ │   ├── lodash._reevaluate@3.0.0
    │ │ │ │ │ │ │   ├── lodash._reinterpolate@3.0.0
    │ │ │ │ │ │ │   ├─┬ lodash.template@3.6.2
    │ │ │ │ │ │ │   │ ├── lodash._basecopy@3.0.1
    │ │ │ │ │ │ │   │ ├── lodash._basevalues@3.0.0
    │ │ │ │ │ │ │   │ ├── lodash._isiterateecall@3.0.9
    │ │ │ │ │ │ │   │ ├── lodash.escape@3.0.0
    │ │ │ │ │ │ │   │ ├─┬ lodash.keys@3.1.2
    │ │ │ │ │ │ │   │ │ ├── lodash._getnative@3.9.1
    │ │ │ │ │ │ │   │ │ ├── lodash.isarguments@3.0.4
    │ │ │ │ │ │ │   │ │ └── lodash.isarray@3.0.4
    │ │ │ │ │ │ │   │ ├── lodash.restparam@3.6.1
    │ │ │ │ │ │ │   │ └── lodash.templatesettings@3.1.0
    │ │ │ │ │ │ │   ├── multipipe@0.1.2
    │ │ │ │ │ │ │   ├── object-assign@3.0.0
    │ │ │ │ │ │ │   ├── through2@2.0.0
    │ │ │ │ │ │ │   └── vinyl@0.5.3
    │ │ │ │ │ │ ├── is-url@1.2.1
    │ │ │ │ │ │ ├─┬ read-all-stream@3.0.1
    │ │ │ │ │ │ │ └─┬ pinkie-promise@1.0.0
    │ │ │ │ │ │ │   └── pinkie@1.0.0
    │ │ │ │ │ │ ├─┬ stream-combiner2@1.1.1
    │ │ │ │ │ │ │ └── duplexer2@0.1.4
    │ │ │ │ │ │ └─┬ ware@1.3.0
    │ │ │ │ │ │   └─┬ wrap-fn@0.1.4
    │ │ │ │ │ │     └── co@3.1.0
    │ │ │ │ │ ├─┬ exec-series@1.0.2
    │ │ │ │ │ │ └── async-each-series@1.1.0
    │ │ │ │ │ └─┬ url-regex@3.1.0
    │ │ │ │ │   └── ip-regex@1.0.3
    │ │ │ │ ├─┬ bin-wrapper@3.0.2
    │ │ │ │ │ ├─┬ bin-check@2.0.0
    │ │ │ │ │ │ └── executable@1.1.0
    │ │ │ │ │ ├─┬ bin-version-check@2.1.0
    │ │ │ │ │ │ ├─┬ bin-version@1.0.4
    │ │ │ │ │ │ │ └─┬ find-versions@1.2.1
    │ │ │ │ │ │ │   └── semver-regex@1.0.0
    │ │ │ │ │ │ ├── semver@4.3.6
    │ │ │ │ │ │ └── semver-truncate@1.1.0
    │ │ │ │ │ ├── lazy-req@1.1.0
    │ │ │ │ │ └── os-filter-obj@1.0.3
    │ │ │ │ └─┬ logalot@2.1.0
    │ │ │ │   └─┬ squeak@1.3.0
    │ │ │ │     ├── console-stream@0.1.1
    │ │ │ │     └─┬ lpad-align@1.1.0
    │ │ │ │       ├── longest@1.0.1
    │ │ │ │       └── lpad@2.0.1
    │ │ │ ├── is-gif@1.0.0
    │ │ │ └─┬ through2@0.6.5
    │ │ │   └── readable-stream@1.0.33
    │ │ ├─┬ imagemin-jpegtran@4.3.2
    │ │ │ ├── is-jpg@1.0.0
    │ │ │ ├── jpegtran-bin@3.0.6
    │ │ │ └── through2@2.0.0
    │ │ ├─┬ imagemin-optipng@4.3.0
    │ │ │ ├─┬ exec-buffer@2.0.1
    │ │ │ │ └── tempfile@1.1.1
    │ │ │ ├── is-png@1.0.0
    │ │ │ ├── optipng-bin@3.0.4
    │ │ │ └─┬ through2@0.6.5
    │ │ │   └── readable-stream@1.0.33
    │ │ ├─┬ imagemin-svgo@4.2.0
    │ │ │ ├── is-svg@1.1.1
    │ │ │ ├─┬ svgo@0.6.1
    │ │ │ │ ├─┬ coa@1.0.1
    │ │ │ │ │ └── q@1.4.1
    │ │ │ │ ├── colors@1.1.2
    │ │ │ │ ├─┬ csso@1.4.4
    │ │ │ │ │ └── clap@1.0.10
    │ │ │ │ ├─┬ js-yaml@3.4.6
    │ │ │ │ │ ├─┬ argparse@1.0.3
    │ │ │ │ │ │ ├── lodash@3.10.1
    │ │ │ │ │ │ └── sprintf-js@1.0.3
    │ │ │ │ │ ├── esprima@2.7.1
    │ │ │ │ │ └── inherit@2.2.2
    │ │ │ │ ├── sax@1.1.4
    │ │ │ │ └── whet.extend@0.9.9
    │ │ │ └── through2@2.0.0
    │ │ ├── optional@0.1.3
    │ │ ├─┬ stream-combiner2@1.1.1
    │ │ │ └── duplexer2@0.1.4
    │ │ └─┬ vinyl-fs@2.2.1
    │ │   ├─┬ duplexify@3.4.2
    │ │   │ └── end-of-stream@1.0.0
    │ │   ├─┬ glob-stream@5.3.1
    │ │   │ ├─┬ glob@5.0.15
    │ │   │ │ └── minimatch@3.0.0
    │ │   │ ├─┬ ordered-read-streams@0.3.0
    │ │   │ │ └── is-stream@1.0.1
    │ │   │ ├─┬ through2@0.6.5
    │ │   │ │ └── readable-stream@1.0.33
    │ │   │ ├─┬ to-absolute-glob@0.1.1
    │ │   │ │ └── extend-shallow@2.0.1
    │ │   │ └── unique-stream@2.2.0
    │ │   ├── graceful-fs@4.1.2
    │ │   ├─┬ gulp-sourcemaps@1.6.0
    │ │   │ ├── graceful-fs@4.1.2
    │ │   │ └── through2@2.0.0
    │ │   ├── is-valid-glob@0.3.0
    │ │   ├── merge-stream@1.0.0
    │ │   ├─┬ strip-bom@2.0.0
    │ │   │ └── is-utf8@0.2.1
    │ │   ├─┬ strip-bom-stream@1.0.0
    │ │   │ └── first-chunk-stream@1.0.0
    │ │   ├── through2@2.0.0
    │ │   └─┬ through2-filter@2.0.0
    │ │     └── through2@2.0.0
    │ └── pretty-bytes@1.0.4
    ├─┬ grunt-contrib-jshint@0.11.3
    │ └─┬ jshint@2.8.0
    │   ├─┬ cli@0.6.6
    │   │ └─┬ glob@3.2.11
    │   │   └── minimatch@0.3.0
    │   ├─┬ htmlparser2@3.8.3
    │   │ ├── domelementtype@1.3.0
    │   │ ├── domhandler@2.3.0
    │   │ ├─┬ domutils@1.5.1
    │   │ │ └─┬ dom-serializer@0.1.0
    │   │ │   ├── domelementtype@1.1.3
    │   │ │   └── entities@1.1.1
    │   │ ├── entities@1.0.0
    │   │ └── readable-stream@1.1.13
    │   ├── lodash@3.7.0
    │   ├── minimatch@2.0.10
    │   ├── shelljs@0.3.0
    │   └── strip-json-comments@1.0.4
    ├─┬ grunt-contrib-qunit@0.7.0
    │ └─┬ grunt-lib-phantomjs@0.6.0
    │   ├─┬ phantomjs@1.9.19
    │   │ ├── adm-zip@0.4.4
    │   │ ├─┬ fs-extra@0.23.1
    │   │ │ ├── graceful-fs@4.1.2
    │   │ │ └── jsonfile@2.2.3
    │   │ ├── kew@0.4.0
    │   │ ├─┬ md5@2.0.0
    │   │ │ ├── charenc@0.0.1
    │   │ │ ├── crypt@0.0.1
    │   │ │ └── is-buffer@1.0.2
    │   │ ├─┬ npmconf@2.1.1
    │   │ │ ├── nopt@3.0.6
    │   │ │ └── semver@4.3.6
    │   │ ├── progress@1.1.8
    │   │ ├─┬ request@2.42.0
    │   │ │ ├── aws-sign2@0.5.0
    │   │ │ ├─┬ bl@0.9.4
    │   │ │ │ └── readable-stream@1.0.33
    │   │ │ ├── caseless@0.6.0
    │   │ │ ├── hawk@1.1.1
    │   │ │ ├── mime-types@1.0.2
    │   │ │ ├── oauth-sign@0.4.0
    │   │ │ └── qs@1.2.2
    │   │ └─┬ request-progress@0.3.1
    │   │   └── throttleit@0.0.2
    │   ├── semver@1.0.14
    │   └─┬ temporary@0.0.8
    │     └── package@1.0.1
    ├─┬ grunt-contrib-uglify@0.10.1
    │ ├─┬ chalk@1.0.0
    │ │ ├─┬ has-ansi@1.0.3
    │ │ │ └── ansi-regex@1.1.1
    │ │ ├── strip-ansi@2.0.1
    │ │ └── supports-color@1.3.1
    │ ├── lodash@3.2.0
    │ ├─┬ maxmin@1.0.1
    │ │ └── pretty-bytes@1.0.4
    │ ├─┬ uglify-js@2.5.0
    │ │ ├── async@0.2.10
    │ │ ├── uglify-to-browserify@1.0.2
    │ │ └─┬ yargs@3.5.4
    │ │   ├── camelcase@1.2.1
    │ │   ├── window-size@0.1.0
    │ │   └── wordwrap@0.0.2
    │ └── uri-path@1.0.0
    ├─┬ grunt-contrib-watch@0.6.1
    │ ├── async@0.2.10
    │ ├─┬ gaze@0.5.2
    │ │ └─┬ globule@0.1.0
    │ │   └── lodash@1.0.2
    │ ├── lodash@2.4.2
    │ └─┬ tiny-lr-fork@0.0.5
    │   ├── debug@0.7.4
    │   ├── faye-websocket@0.4.4
    │   ├─┬ noptify@0.0.3
    │   │ └── nopt@2.0.0
    │   └── qs@0.5.6
    ├── grunt-includes@0.5.2
    ├─┬ grunt-jsvalidate@0.2.2
    │ └── esprima@1.0.4
    ├── grunt-legacy-util@0.2.0
    ├─┬ grunt-patch-wordpress@0.3.0
    │ ├─┬ inquirer@0.2.5
    │ │ ├── async@0.2.10
    │ │ ├─┬ cli-color@0.2.3
    │ │ │ ├── es5-ext@0.9.2
    │ │ │ └─┬ memoizee@0.2.6
    │ │ │   ├── event-emitter@0.2.2
    │ │ │   └── next-tick@0.1.0
    │ │ ├── lodash@1.2.1
    │ │ └── mute-stream@0.0.3
    │ ├─┬ request@2.27.0
    │ │ ├── aws-sign@0.3.0
    │ │ ├── cookie-jar@0.3.0
    │ │ ├── forever-agent@0.5.2
    │ │ ├─┬ form-data@0.1.4
    │ │ │ ├── async@0.9.2
    │ │ │ └─┬ combined-stream@0.0.7
    │ │ │   └── delayed-stream@0.0.5
    │ │ ├─┬ hawk@1.0.0
    │ │ │ ├── boom@0.4.2
    │ │ │ ├── cryptiles@0.2.2
    │ │ │ ├── hoek@0.9.1
    │ │ │ └── sntp@0.2.4
    │ │ ├─┬ http-signature@0.10.1
    │ │ │ ├── asn1@0.1.11
    │ │ │ ├── assert-plus@0.1.5
    │ │ │ └── ctype@0.5.3
    │ │ ├── json-stringify-safe@5.0.1
    │ │ ├── mime@1.2.11
    │ │ ├── node-uuid@1.4.7
    │ │ ├── oauth-sign@0.3.0
    │ │ ├── qs@0.6.6
    │ │ └── tunnel-agent@0.3.0
    │ ├── underscore@1.5.2
    │ └── underscore.string@2.3.3
    ├─┬ grunt-postcss@0.7.1
    │ ├── diff@2.2.1
    │ └── es6-promise@3.0.2
    ├─┬ grunt-rtlcss@1.6.0
    │ └─┬ rtlcss@1.7.2
    │   ├─┬ findup@0.1.5
    │   │ └── commander@2.1.0
    │   ├─┬ mkdirp@0.5.0
    │   │ └── minimist@0.0.8
    │   └── strip-json-comments@1.0.4
    ├─┬ grunt-sass@1.1.0
    │ ├─┬ each-async@1.1.1
    │ │ ├── onetime@1.1.0
    │ │ └── set-immediate-shim@1.0.1
    │ ├─┬ node-sass@3.4.2
    │ │ ├── async-foreach@0.1.3
    │ │ ├─┬ cross-spawn@2.1.4
    │ │ │ ├─┬ cross-spawn-async@2.1.6
    │ │ │ │ ├─┬ lru-cache@4.0.0
    │ │ │ │ │ ├── pseudomap@1.0.2
    │ │ │ │ │ └── yallist@2.0.0
    │ │ │ │ └─┬ which@1.2.1
    │ │ │ │   └─┬ is-absolute@0.1.7
    │ │ │ │     └── is-relative@0.1.3
    │ │ │ └─┬ spawn-sync@1.0.15
    │ │ │   └── os-shim@0.1.3
    │ │ ├─┬ glob@5.0.15
    │ │ │ └── minimatch@3.0.0
    │ │ ├─┬ mkdirp@0.5.1
    │ │ │ └── minimist@0.0.8
    │ │ ├── nan@2.1.0
    │ │ ├─┬ node-gyp@3.2.1
    │ │ │ ├─┬ fstream@1.0.8
    │ │ │ │ └── graceful-fs@4.1.2
    │ │ │ ├── graceful-fs@4.1.2
    │ │ │ ├── minimatch@1.0.0
    │ │ │ ├── nopt@3.0.6
    │ │ │ ├─┬ npmlog@1.2.1
    │ │ │ │ ├── ansi@0.3.0
    │ │ │ │ ├─┬ are-we-there-yet@1.0.5
    │ │ │ │ │ └── delegates@0.1.0
    │ │ │ │ └─┬ gauge@1.2.2
    │ │ │ │   ├── has-unicode@1.0.1
    │ │ │ │   ├─┬ lodash.pad@3.1.1
    │ │ │ │   │ ├── lodash._basetostring@3.0.1
    │ │ │ │   │ └─┬ lodash._createpadding@3.6.1
    │ │ │ │   │   └── lodash.repeat@3.0.1
    │ │ │ │   ├── lodash.padleft@3.1.1
    │ │ │ │   └── lodash.padright@3.1.1
    │ │ │ ├─┬ osenv@0.1.3
    │ │ │ │ ├── os-homedir@1.0.1
    │ │ │ │ └── os-tmpdir@1.0.1
    │ │ │ ├─┬ path-array@1.0.0
    │ │ │ │ └── array-index@0.1.1
    │ │ │ ├── semver@5.1.0
    │ │ │ └─┬ tar@2.2.1
    │ │ │   └── block-stream@0.0.8
    │ │ ├─┬ npmconf@2.1.2
    │ │ │ ├─┬ config-chain@1.1.9
    │ │ │ │ └── proto-list@1.2.4
    │ │ │ ├── ini@1.3.4
    │ │ │ ├── nopt@3.0.6
    │ │ │ ├── semver@4.3.6
    │ │ │ └── uid-number@0.0.5
    │ │ ├─┬ request@2.67.0
    │ │ │ ├── aws-sign2@0.6.0
    │ │ │ ├── caseless@0.11.0
    │ │ │ ├─┬ combined-stream@1.0.5
    │ │ │ │ └── delayed-stream@1.0.0
    │ │ │ ├── extend@3.0.0
    │ │ │ ├── forever-agent@0.6.1
    │ │ │ ├─┬ form-data@1.0.0-rc3
    │ │ │ │ └── async@1.5.1
    │ │ │ ├─┬ har-validator@2.0.3
    │ │ │ │ ├── commander@2.9.0
    │ │ │ │ ├─┬ is-my-json-valid@2.12.3
    │ │ │ │ │ ├── generate-function@2.0.0
    │ │ │ │ │ ├─┬ generate-object-property@1.2.0
    │ │ │ │ │ │ └── is-property@1.0.2
    │ │ │ │ │ └── jsonpointer@2.0.0
    │ │ │ │ └─┬ pinkie-promise@2.0.0
    │ │ │ │   └── pinkie@2.0.1
    │ │ │ ├─┬ hawk@3.1.2
    │ │ │ │ ├── boom@2.10.1
    │ │ │ │ ├── cryptiles@2.0.5
    │ │ │ │ ├── hoek@2.16.3
    │ │ │ │ └── sntp@1.0.9
    │ │ │ ├─┬ http-signature@1.1.0
    │ │ │ │ ├─┬ jsprim@1.2.2
    │ │ │ │ │ ├── extsprintf@1.0.2
    │ │ │ │ │ ├── json-schema@0.2.2
    │ │ │ │ │ └── verror@1.3.6
    │ │ │ │ └─┬ sshpk@1.7.2
    │ │ │ │   ├── asn1@0.2.3
    │ │ │ │   ├── assert-plus@0.2.0
    │ │ │ │   ├── dashdash@1.11.0
    │ │ │ │   ├── ecc-jsbn@0.1.1
    │ │ │ │   ├── jodid25519@1.0.2
    │ │ │ │   ├── jsbn@0.1.0
    │ │ │ │   └── tweetnacl@0.13.3
    │ │ │ ├── is-typedarray@1.0.0
    │ │ │ ├── isstream@0.1.2
    │ │ │ ├─┬ mime-types@2.1.9
    │ │ │ │ └── mime-db@1.21.0
    │ │ │ ├── oauth-sign@0.8.0
    │ │ │ ├── qs@5.2.0
    │ │ │ ├── stringstream@0.0.5
    │ │ │ ├── tough-cookie@2.2.1
    │ │ │ └── tunnel-agent@0.4.2
    │ │ └─┬ sass-graph@2.0.1
    │ │   ├─┬ glob@5.0.15
    │ │   │ └── minimatch@3.0.0
    │ │   ├── lodash@3.10.1
    │ │   └─┬ yargs@3.31.0
    │ │     ├─┬ cliui@3.1.0
    │ │     │ └── wrap-ansi@1.0.0
    │ │     ├─┬ os-locale@1.4.0
    │ │     │ └─┬ lcid@1.0.0
    │ │     │   └── invert-kv@1.0.0
    │ │     ├─┬ string-width@1.0.1
    │ │     │ ├── code-point-at@1.0.0
    │ │     │ └── is-fullwidth-code-point@1.0.0
    │ │     ├── window-size@0.1.4
    │ │     └── y18n@3.2.0
    │ └── object-assign@4.0.1
    └─┬ matchdep@1.0.0
      ├─┬ findup-sync@0.3.0
      │ └─┬ glob@5.0.15
      │   └── minimatch@3.0.0
      ├─┬ globule@0.2.0
      │ ├─┬ glob@3.2.11
      │ │ └── minimatch@0.3.0
      │ ├── lodash@2.4.2
      │ └── minimatch@0.2.14
      └── stack-trace@0.0.9
    

    And this is just for WordPress core; it doesn’t include the tools we use for BuddyPress or bbPress.

    I don’t like this. I don’t like not knowing what these tools do or why they’re necessary. It feels like having one-thousand hammers instead of drill-bits and screwdrivers and power-tools. It’s not immediately obvious what the return on learning each or any of these unique tools is.

    And when a tool becomes obsolete or out-of-date, the rabbit hole is full of eels:

    npm WARN deprecated lodash@0.9.2: lodash@<2.0.0 is no longer maintained. Upgrade to lodash@^3.0.0
    npm WARN deprecated npmconf@2.1.1: this package has been reintegrated into npm and is now out of date with respect to npm
    npm WARN deprecated lodash@1.0.2: lodash@<2.0.0 is no longer maintained. Upgrade to lodash@^3.0.0
    npm WARN deprecated lodash@1.2.1: lodash@<2.0.0 is no longer maintained. Upgrade to lodash@^3.0.0
    npm WARN deprecated npmconf@2.1.2: this package has been reintegrated into npm and is now out of date with respect to npm
    npm WARN deprecated lodash@2.4.2: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^3.0.0.
    n
    

    These relatively helpful messages may be outside of your control. They might be directly your fault. They might be globally installed modules or locally installed ones. Upgrading might be good for WordPress but break everything else you work on without warning.

    Here’s usually what happens:

    • Something in the mystery toolbox breaks and complains about it
    • Try to upgrade the broken tool according to the feedback message(s)
    • The tool is still broken
    • Delete the entire `node_modules` directory and `npm install` again
    • Fixed!

    Now, I understand what’s going on here is a miracle of modern software engineering. An enormous amount of automation is going on here, and the fact it actually works most of the time I’ll consider another closely coupled miracle. It still feels like there must be a better way, even though I can’t claim the fame of knowing right now what that might actually be.

    I get that this is all awesome. I get that this process, and having & using these tools, is better than smashing things with rocks and hoping for the best. I get that a ton of work has gone into making this as seamless and wrinkle-free as possible.

    I accept it, and work with it, and try not to think about it, but the trend of installing and trusting hundreds of tiny unknown libraries feels a little too organic and alive for a man-made computing machine. Like millions of nerve-endings and neurons and vessels and muscles working in unison to blink your eyes and sip on some coffee, the line between being a software developer or a software doctor is an increasingly jagged one.

    If we aren’t careful, we’ll end up as lost amongst our own creations as we are inside of mother nature’s.

    JJJ

    January 7, 2016
    Rants, Opinion, Software, WordPress
  • Super Metroid and NUX

    If you enjoyed Matt’s post about the original Super Mario Bros. check out this video about Super Metroid’s hidden tutorials. I had posted this years ago internally while working at Automattic in a thread about new-user experience, specifically in regards to how WordPress (both .org and .com) can learn a lot from video-game design.

    I think this still holds true, both for new users and for how new features are rolled-out and introduced to users that have already achieved mastery with the platforms. Even if you don’t like or never played the Metroid series, this video may inspire you to do so.

    JJJ

    November 3, 2015
    Automattic, Software
    Metroid
  • Meet Stuttter

    Stuttter, like WordPress on the surface, is both product and organization.

    Spiritually it is a conduit for rethinking WordPress from the outside in. It’s a way to independently test the waters for what we can do with it, without deviating from it’s history, beauty, charm, and chutzpah.

    For me, it’s an empty canvas for code, and a place to create without prohibition. For everyone else, hopefully it’s a bunch of little widgets and do-dads that are valuable enough to maybe consider sponsoring or paying for.

    The name comes from what happens when I’m nervous, which doesn’t happen very frequently. I struggle to find the sequence of words that I think will most quickly bring calm, so I stumble and stammer for a bit until I find my stride. (Someone I adore, who does this quite endearingly, is Elon Musk.)

    There is a brief period of excitement while ideas are unraveling, and that’s what Stuttter represents.

    Like how auto-makers take off-the-shelf components and wrap them to design next-generation vehicles; how architects take pre-existing materials and specifications and add their flair and signature; how Apple, Adobe, and Automattic leverage open-source libraries to create beautiful software experiences; Stuttter is how I identify uniquely powerful aspects of open-source GPL friendly software, and extract them into neatly packaged design implementations for WordPress.

    Right now, you can follow Stuttter on GitHub, Flox, WordPress.org, and Packagist, until we get some websites up. Here are the first pass logo and icon, if you’re interested in using them:stuttter

    stuttter-circle

    JJJ

    October 16, 2015
    Software, WordPress
  • WP Chosen

    The WP Chosen plugin tames the power of WordPress’s filters, settings, and options with the simplicity and versatility of the Chosen jQuery library.

    I took some time to think about the recent passing of an old friend, and concluded the way to celebrate his life (and contributions to mine) was to build and open-source something I’ve wanted for a while, the way I think he would have.

    ❤️

    JJJ

    October 1, 2015
    Software, Uncategorized
Previous Page
1 2 3 4 5 6 7
Next Page

Proudly Powered by WordPress