Categories
Uncategorized

Reply to Tantek.com

In reply to http://tantek.com/2019/171/t1/happy-14th-microformats-org.

Finally converted my site (https://jayhoffmann.com/) to microformats in celebration! Next step, POSSE ūüôā
Categories
WordPress

Editing Crop in WordPress Images Before Upload

For a recent project, I had a need for a pretty simple workflow. I had a couple of image sizes, which I added with the add_image_size function which required a hard crop to a certain aspect ratio. The workflow for authors I was looking for was:

  1. Upload Image
  2. Edit the crop for these special sizes if they feel like
  3. Insert into post

All of this on the same screen. After installing and downloading a bunch of different options, I’m going to formally recommend Manual Image Crop.

Screen Shot 2016-04-13 at 3.46.00 PM

It’s not the prettiest option (that’s Post Thumbnail Editor), but it is the simplest and most flexible. It has a few options for each image size, but basically once you upload your image you can select the “Crop Image” option and then automatically create a new image crop for each size. And everything is brought into a pop-up window so you never have to leave the Media Uploader.

Screen Shot 2016-04-13 at 3.46.58 PM

So anyway, if you’re looking for a good post thumbnail crop editor, try out Manual Image Crop.

Categories
WordPress

Using Gravity Forms with Bootstrap Styles

I use Bootstrap as a starting point for a lot of the themes that I build as a great starting point for reusable components. But one of the problems I’ve run into is trying to integrate Gravity Forms with Bootstrap. By default, Gravity Forms does not include Bootstrap classes, so the two don’t end up working very well together.

Fortunately, with a little bit of elbow grease, there’s a way to tweak Gravity Forms markup and styles to match a default Bootstrap form. The solution I’ve found is a combination of a single hook and some SASS / CSS tweaks to get everything off the ground.

For reference, a typical Bootstrap form should be marked up something like this:

<form>
  <fieldset class="form-group">
    <label for="formGroupExampleInput">Example label</label>
    <input type="text" class="form-control" id="formGroupExampleInput" placeholder="Example input">
  </fieldset>
  <fieldset class="form-group">
    <label for="formGroupExampleInput2">Another label</label>
    <input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input">
  </fieldset>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

I’m using version 4 of Bootstrap, but things are pretty much the same in older versions of Bootstrap as well. There are really two things that are important in this markup. The first is that a class of form-group is used on an input’s wrapper element (fieldset in this case). The second is that a class of form-group is added to each input. Cool, let’s step through this.

The first step is to wrap inputs in an element with a class of form-group then. That’s actually pretty simple. There’s a Gravity Form filter¬†called¬†gform_field_container that can be used to change the markup of the list item for each input. So all we have to do is ensure that the form-group class is added here, which we can do with a simple one-line function:

add_filter( 'gform_field_container', 'add_bootstrap_container_class', 10, 6 );
function add_bootstrap_container_class( $field_container, $field, $form, $css_class, $style, $field_content ) {
  $id = $field->id;
  $field_id = is_admin() || empty( $form ) ? "field_{$id}" : 'field_' . $form['id'] . "_$id";
  return '<li id="' . $field_id . '" class="' . $css_class . ' form-group">{FIELD_CONTENT}</li>';
}

Now each input will be wrapped in the proper form-group class, along with any classes Gravity Forms wants to add.

The second part, adding a form-group class to every input element, is a little trickier. There¬†are¬†actions that let you edit the actual markup of inputs, but there’s nothing that just lets you filter input classes, which means you’ll end up rewriting the entire input function. Things get complicated fast, and I just haven’t found that to be a very smart way to go. Here’s the solution I’ve found works best: Instead of adding Bootstrap classes to Gravity Forms, we customize Gravity Forms classes to match Bootstrap classes.

If you’re using¬†SASS,¬†this is super easy thanks to @extend, which allows you to apply styles from one class to another. So we just need to extend Bootstrap styles¬†to the Gravity Form’s CSS. Which looks like this:

.gform_fields {
  @extend .list-unstyled;
  @extend .row;
 
  input, select, textarea {
    @extend .form-control;
  }
 
  textarea {
    height: auto;
  }
 
}
 
.gfield_description {
  @extend .alert;
}
 
.validation_error {
  @extend .alert;
  @extend .alert-danger;
}
 
.validation_message {
  @extend .alert;
  @extend .alert-success;
}
 
.gform_button {
  @extend .btn;
}
 
.gfield_required {
  color: $alert-danger-text;
}
 
.gform_wrapper ul.gfield_radio li, .gform_wrapper ul.gfield_checkbox li {
  @extend .form-check;
}
 
.gform_validation_container {
  display: none;
}
 
.gfield_error .ginput_container {
  margin-bottom: 10px;
}

This will apply the styles from Bootstrap classes to the proper elements inside of Gravity Forms and make everything look just as it should. You may need to tweak a bit here and there on individual elements but this tends to get things working pretty well.

Looking for the fully compiled, vanilla CSS version of this? I set up a gist for you to drop into your project.

Note: Updated on August 22, 2016. Thanks to Josh Cranwell for some much-needed additions!

Categories
JavaScript

That Time the Internet Broke

RE: The Plight of NPM, etc.

I won’t pretend to be an expert on NPM, package managers or open source. But last week, something really interesting happened. And it brought into view two issues that have been swirling around in the ether: the dependency tangle that is the Node / Javascript community and the problems that arise from¬†private vs open source projects.

Here’s what happened. Azer Ko√ßulu announced that he was removing all of his publicly available modules from the NPM registry after his module Kik was removed, against his wishes, by the NPM team. See, NPM is a private company, owned in part by¬†Isaac Z. Schlueter. And when lawyers from the app Kik came knocking, Isaac was quick to comply over Azer’s head.

In Azer’s words:

This situation made me realize that NPM is someone’s private land where corporate is more powerful than the people, and I do open source because,Power To The People.

So Azer goes and removes his 273 modules from NPM, including some pretty global sounding ones like “map” and “attr” and, most importantly, “left-pad”. And just like that, a giant section of the Internet just flat out¬†breaks. Why? Because thousands and thousands of developers had one of these libraries as a dependency for their app. Or maybe one of their dependencies had one of these dependencies. Or maybe one of their dependencies’ dependencies had one of these libraries as… well, you get the point.¬†As The Register puts it:

Unfortunately, one of those dependencies was left-pad. The code is below. It pads out the lefthand-side of strings with zeroes or spaces. And thousands of projects including Node and Babel relied on it.

In the Javascript community, we’ve taken the concept of micro-packages to an unreal extreme, to the point where our careful web of dependencies can unravel at any moment. There are no standard libraries or robust toolkits, everything’s a tiny dependency bundled alongside a hundred others. So when one thing breaks, everything breaks. We like to think that we’ve created this neat, decoupled architecture but all we’ve proven is that things rely on external libraries that much more. And it’s way too easy for things to break.

I think David Haney probably had the best perspective on this whole problem:

On what possible plane of existence is this a better solution to past problems? How are hundreds of dependencies and 28,000 files for a blank project template anything but overly complicated and insane?

Or put simply:

Every package that you use adds yet another dependency to your project. Dependencies, by their very name, are things you need in order for your code to function. The more dependencies you take on, the more points of failure you have.

Honestly, Haney’s viewpoint on this whole thing is the most practical¬†I’ve read so I’d recommend giving it a read.

And then there’s the whole issue of open source libraries being hosted and distributed on a closed-source, private package manager. Because¬†¬†rather then take a second to see why this might be a problem,¬†the NPM team simply reacted by removing the ability to unpublish¬†packages altogether. Which does not sound very open-source friendly to me. Legally, it’s well within NPM’s rights to do what they did, and I actually think they made the right call with the situation they had, but it points to a bigger issue. There’s really no truly public place for open source. Without this, we rely on the wills and whims of individuals to manage the needs of entire communities.

From Dave Winer:

I worry about GitHub. It plays such a central role. But eventually the VCs are going to want an exit. Then what happens?… We need a framework, legal and social, for projects that are not “owned” but are just there.

This whole thing might seem ridiculous, and it is. But it might spark some interesting conversation. For now, it’s worth keeping an eye on. If you have some time to kill, there’s an interesting conversation about it over on Hacker News as well.

Categories
JavaScript

Chose Your Metric

I went to Wordcamp Lancaster this year. It was a great time. I gave a talk on Javascript and after the conference, I was perseverating about one of my favorite things: what the f%c Javascript framework should I use. Rami Abraham (who organized the crap of out of WC Lancaster by the way) was quick to point out that we had probably drunkenly discussed this very same topic on no less then seven different occasions. Like usual, Rami was right. Sometimes we do it on Twitter.

I think about this crap a lot and I’ve never really figured it out.

Stop me if you’ve heard this one. I’ve been working on this new project, trying to pull JavaScript and the WordPress API to pull together some pretty cool tools for writers and developers.

Awesome. Crack my knuckles and get started. I know things are going to be heavy on the client-side, but this is a learning opportunity and I want to dive into a solid framework to get me started.

Cool. Angular or Backbone or React or Ember or Vue or Mithril?

Ugh. Okay, forget it. Build process. That’s simple, right? Let’s see…¬†Gulp or Grunt or Brunch or Webpack or Browserify?

Wait, module bundling? Should I use ES6 Modules? Or CommonJS? Or AMD?

Well if I’m using ES6, I’ll need to transpile for sure. Traceur or Babel?

Cool, I’ll just need a client-side router, and an http request library, and a solid data store, and I’m just going to stop because this is ridiculous.

I didn’t know where to start. So I did the dumbest thing I could possibly think of. I rewrote the same thing five times with different approaches and frameworks. I doubt very much that I’m the first person to do this. But I’m almost (almost) glad I did this, because I learned two pretty important things.

  1. Most frameworks do a pretty good job when you’re doing something simple
  2. And …

 

Trying to Pick? Choose Your Metric

How do you figure out what that metric is? For me it’s simple. I let the project point me in the right direction.

I’m working with WordPress, which means I won’t be rendering any JavaScript on the server. And these large file size libraries¬†still put me off a bit. So I made my metric pretty simple. File size. So for me, some good options are things like Backbone, or Vue. Both keep things really lightweight purely in terms of initial download size.

Maybe you’re working on a team, so having strong conventions and solid documentation is important. That way any team member can just dive in. Ember’s probably a good choice here. Angular’s not far behind there.

Maybe you have a team that’s transitioning to the client side from a very functional approach to programming. That’s like, exactly what React is built for. It’s what Automattic did to help their PHP developers transition.

There are a ton of comparison posts out there, but at the end of the day all you’re going to do is agonize ¬†over the decision. For me the answer was to find that one principle and let it guide all the decisions that you make. This has the added benefit of connecting up the various bits and pieces of your project very nicely, and will inform decisions you make as you’re building the project.

For me the realization was that you can’t be wrong. You can waste a ton of time. So find your metric. And stick to it.

 

Categories
WordPress

Changing Field Keys in Advanced Custom Fields

I recently ran into a problem when using the Advanced Custom Fields plugin which is a bit esoteric. In the previous iteration of the site I was working on, fields were registered programmatically, using acf_add_local_field_group and acf_add_local_field. In the new version, we decided to move these back into the GUI on the admin panel.

For most of the fields, all we had to do was replicate the field group and field names / labels and everything worked fine, even on existing posts. However, repeatable and flexible fields would not show up for posts that had already been created.

The problem was with the field keys. When I created the fields in the admin panel, they were assigned a different field key, and thus existing content didn’t work anymore.

I found a post that outlined a fix¬†on the plugin’s forums and it actually worked pretty well. Basically, you can go into the edit screen in the admin, and inspect element or use firebug to open up the HTML source. Find the HTML element¬†that the repeatable parent field or flexible field¬†is wrapped¬†in, and remove the “meta” class from this. Then you can find the hidden field that has a the field key in it, and change it to the field key you had registered via PHP. Once that’s done just save the field group. For some reason, that works just fine.

Of course, another solution is to do a search and replace in the database. Just make sure you hit everything in the wp_postmeta table.

The main point is that if you run into a problem with Advanced Custom Fields transitioning from registering via PHP to using the admin panel, the problem with existing posts has to do with the field keys.

 

Categories
Development Inspiration Thoughts

Hemingway’s Advice for Coders

I’m an avid reader of Brain Pickings (check it out if you haven’t heard of it), and one thing caught my attention a few weeks ago. In the mid-1930’s a young writer by the name of Arnold Samuelson caught up with his hero, Ernest Hemingway. Rather then cast him away, Hemingway took him on as a sort of protege, and gave him some invaluable writing advice along the way. There was one thing that resonated with me in particular because I find myself in this trap all the time.

The most important thing I’ve learned about writing is never write too much at a time… Never pump yourself dry. Leave a little for the next day. The main thing is to know when to stop. Don’t wait till you’ve written yourself out. When you’re still going good and you come to an interesting place and you know what’s going to happen next, that’s the time to stop. Then leave it alone and don’t think about it; let your subconscious mind do the work.

I mostly write code for a living, not prose. But this rule still applies. I can’t tell you how many times I’ve been coding away when I finally get myself to a good place. Everything’s perfect. The bug is patched, the feature is solid.

Then I go just a little bit further. And that’s when I blow it. I get frustrated and lost. My motivation goes into free-fall and I alternate between my code editor and Twitter every five seconds. And no it’s late. It’s dinner time, or my wife is calling me, or the office is closing.

So don’t be me. Take Hemingway’s advice. It doesn’t matter if you have a little extra time, find that place where you still have some juice left and just stop. If you really need to keep going, go over the code you just wrote and refactor a bit. Or look at the next step enough to get pumped about it, but don’t write any code. When you get up and walk away from your computer, the levers in your brain will keep moving, even when you sleep through the night.

The next morning, when you’ve had a good sleep and you’re feeling fresh, rewrite what you wrote the day before. When you come to the interesting place and you know what is going to happen next, go on from there and stop at another high point of interest. That way, when you get through, your stuff is full of interesting places and when you write a novel you never get stuck and you make it interesting as you go along. Every day go back to the beginning and rewrite the whole thing and when it gets too long, read at least two or three chapters before you start to write and at least once a week go back to the start. That way you make it one piece.

More sound advice. When you start up again fresh, instead of jumping straight into a problem, go back over the work you did the day previous. Take 10 or 15 minutes and tweak little things, just enough to get the ball rolling. When you start developing the next step, you’ll already be in a good place. And by going back over code you’ve written before, you can make sure to keep things fluid and connected.

I’ve started to do this (when possible) and it feels really code. All of this, of course, requires nice blocks of time devoted to your tasks, not distracted by email and social media and meetings. That can be tough, but it is well worth it. You might not write For Whom the Bell Tolls, but your code will be a lot better for it. Give it a go.

Categories
JavaScript WordPress

First Steps with Javascript and WordPress

It starts with a simple maxim.

Learn Javascript Deeply.

That’s what Matt said. And it’s good advice. Javascript underpins everything we do, and it’s becoming more and more advanced every day. It’s not just the future of WordPress, it’s the future (and present) of the web.

Of course, Matt mentioned this right around the time he showed off a new admin dashboard written entirely in client-side Javascript with React, and proxied through a server also written in Javascript. Which is great for WordPress. But it’s not a great place for everyone to start.

The truth is there are a number of ways to start using¬†Javascript that are a little more… approachable. My goal here is to go through¬†a few ways you can start using Javascript, today, without completely changing your workflow.

I will be talking about a lot of things. There will be code. I won’t be diving too deep into any one thing. My hope is that I can spark some interest for you. That you connect with one of these new processes or patterns and you feel encouraged enough to keep digging.

Generally speaking, I think there are three great ways to approach Javascript.

  • Using Javascript to manage a front-end build process
  • Managing events, page transitions and AJAX with a watchful eye
  • Building a full-scale Single Page Application with the WordPress REST API.

I want to talk about that last bit a lot more in the future. But for now, I’m mostly going to focus on the first two.

Javascript Build Tools

If you develop front-end code in your plugins or themes, you’ve probably noticed yourself doing the same things over and over. Things like compiling SASS down to CSS, concatenating¬†JS files together and minifying them, creating SVG or icon fonts, linting your code for errors, the list goes on¬†You might have even heard of some nifty tools out there like CodeKit or Prepross that can do this for you. But there’s another way you can do this. With Javascript.

Javascript build tools allow you to create basic script¬†files that will automatically perform these tasks for you, with a little help from Node on the command line. Build tools are a great way to learn Javascript because the barrier to entry and the risk factor can’t be lower. If you screw up, it won’t effect your live site. You’ll just have to track down the error and try again.

These build tools typically run on top of Node, which is why you’re able to run it from your machine. And there are a lot of them out there. I’m just going to focus on two: Grunt and Gulp.

Since both use Node, they follow the same basic procedure.

  1. Install NodeJS, either from the site or with a tool like Homebrew
  2. Navigate to your theme or plugin folder in your Terminal and type one command:¬†npm init. This will automatically create a file called package.json. This stores a list of dependencies that the build tool will need to work. But don’t worry, you won’t be editing this¬†file directly.
  3. The way you do add packages is with npm install PACKAGENAME --save-dev. These packages will automatically get added to your package.json file for future use.
  4. Create a Gruntfile or Gulpfile (depending on your preference)

I’ll start with Grunt.¬†Grunt works by creating basic Javascript objects, which you use to pass in configurations for modules. There’s not a whole lot too it, but you can chain them together to do some pretty great stuff. For instance, if we wanted to concatenate our JS files and compile SASS files, we would install packages with npm install grunt-contrib-concat grunt-contrib-sass --save-dev. Then we would set up our Javascript in a file called Gruntfile.js.

Gruntfile.js
module.exports = function (grunt) {
  grunt.initConfig({
    concat: {
      dist: {
        src: [
          '/assets/scripts/vendor/*.js',
          '/assets/scripts/*.js'
        ],
        dest: '/js/app.js',
      }
    },
    sass: {
      all: {
        options: {
          style: 'compressed'
        },
        files: {
          'style.css': '/assets/styles/style.scss'
        },
      }
    },
  });
}
grunt.registerTask('styles', ['sass'])
grunt.registerTask('default', [sass', 'concat', 'uglify', 'watch']);

One thing that you’ll learn about in Javascript is that just about everything is an object. That means that inside of these objects¬†you can run any Javascript you want. So you can take grunt files, put them next to vanilla Javascript functions or variables and build anything. The possibilities are really endless.

Gulp is similar, with a few small differences. It works by chaining together tasks, one after another. It also uses CommonJS, so if you’re looking to learn more about Javascript modules and how to link together small packages, it may be a good starting point. To run the same tasks we have in the Grunt example, we just install our packages with npm install gulp-sass gulp-concat --save-dev, and then add our Gulpfile.js.

Gulpfile.js
var gulp           = require('gulp'),
    concat         = require('gulp-concat'),
    sass           = require('gulp-sass');
gulp.task('scripts', function() {
    return gulp.src('./assets/js/app/**/*.js;)
            .pipe(concat('scripts.js'))
            .pipe(gulp.dest('./assets/js/'))
            .pipe(rename({ extname: '.min.js' }))
            .pipe(gulp.dest('./assets/js/'));
});
gulp.task('sass', function () {
    return gulp.src(¬Ď./assets/
                     styles/style.scss')
            .pipe(sass.sync({
          outputStyle: ¬Ďcompressed'})
          .on('error', sass.logError))
            .pipe(gulp.dest('./'));
});
gulp.task('default', ['scripts', 'sass']);

Interested?

Organizing Javascript

But you can do even more with Javascript. It turns out that a lot can be learned simply from structuring your Javascript better.

If you’ve been coding up themes or plugins for a while, chances are you’ve written some jQuery. You know, click this button to show a¬†dropdown type stuff. And you’ve probably written out code that looks like this:


$('.btn-thing').on('click', function(e) {
    // Do your stuff
});

But there’s a better way. Learn yourself a few basic Javascript patterns to manage your events, and you’ll find yourself writing reusable code over and over.

The Module Pattern

The module pattern can be a great way to organize events like clicks, input changes, or other basic jQuery binded events. Remember how I said everything in Javascript is an object? Well the Module pattern uses this as an advantage. You basically store all of your events in a single object, decoupling your elements from the functions that is called when an event occurs. This is probably easiest to explain with some code:

The Module Pattern
var Module = {
    el : {
        $wrapper : $('#wrapper'),
        $button : $('.btn')
    },

    init : function() {
        this.bindUIActions();
    },

    bindUIActions : function() {
        Module.el.$button.on('click', 'onClickEvent');
        Module.el.$wrapper.each(function() {
            Module.doSomethingWithList($(this))
        })
    },

    onClickEvent : function(e) {
        // Do Something
    },

    doSomethingWithList : function(item) {
        // Do something with the item el
    }

}

Elements are stored in the “el” objects, events are controlled from the init function, which then passes the buck down to individual functions. Writing code like this makes things a lot easier to read, and it can make your job easier.

The Inheritance Pattern

If you wanted to take this a step further, the Inheritance pattern may do the trick. It starts out the same way, you build a simple object which sets up some basic functionality. But you also include a way to extend that object, so you can pass it a few options that will change functionality.

This is most commonly seen in jQuery plugins, but there’s no reason why you can’t start doing this today. That way, you don’t have to keep writing the same functionality over and over again. Instead you write it once, and then just pass an object a few options to change little things here and there. Then your code becomes a reusable module.

The Inheritance Pattern
var Object = {
  init: function( options, el ) {
    this.options = $.extend( {}, this.options, 
                    options );

    this.el  = el;
    this.$el = $(el);

    this.init();

    return this;
  },
  options: {
    option1: "default"
  },
  init: function(){
    // Do something with messages
  },
  myMethod: function( msg ){
    // this.$el or this.options is accessible
  }
};
// Basic create / extend of object for browser support
if ( typeof Object.create !== 'function' ) {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}


// Create a plugin based on a defined object
$.inherit = function( name, object ) {
  $.fn[name] = function( options ) {
    return this.each(function() {
      if ( ! $.data( this, name ) ) {
        $.data( this, name, Object.create(object).init( 
        options, this ) );
      }
    });
  };
};
$.inherit('inheritedObject', Object);('#elem').inheritedObject({option1: "Different"});

There are really two things to pay attention to here. The $.extend({}) function is what extracts options out to use within the main object. And the $.inherit() function is what will pass options back up to the Object when something is called.

Interested?

Managing AJAX and Page Transitions

AJAX stands for Asynchronous Javascript and XML. In practice, it means fetching chunks of HTML or data using Javascript and loading it into a page without a page refresh. Coupled with some new HTML5 features and Javascript libraries, AJAX can really add to your site. It can make screens transition from one to the next, as a user navigates seamlessly around your site.

There are lots of ways to manage AJAX in WordPress. But the way I prefer is to organize the server-side code into a single Class and then use the module pattern to interpret the requests. Rather then try to explain that all here, I’ll let Jay Wood over at WebDev Studios do it for me. Really, click that link. It’s a great article.

I will, however, mention two Javascript libraries of interest: smoothState.js and pjax.

Both libraries automatically fetch pages when a user clicks on any links and loads the content in. smoothState puts more of an emphasis on the transitions between pages, using CSS3 transitions and basic class switching to do most of the work. To set it up you just need a simple object.

smoothState
(function ($) {
  'use strict';
  var content  = $('#main').smoothState({
        onStart : {
          
          duration: 250,
          
          render: function () {
            content.toggleAnimationClass('is-exiting');
          }
        }
      }).data('smoothState');
})(jQuery);

pjax is even simpler to get started with, but can do a bit more if you dive in. To automatically start pulling in content without a page refresh you just need to load the code and write one line of Javascript.

$(document).pjax('a', '#pjax-container');

But there’s a lot more that can be done. Exploring the library and employing some of the patterns talked about earlier can go a long way. But check out the links below for some great implementations.

Interested?

The REST API and Beyond

The big news for WordPress this year was the REST API. Again, this isn’t the time to go too deep into this, but basically the REST API allows you to access your site’s content as basic data JSON objects. These data objects can be read by frameworks like Backbone, Angular and React to process content completely on the client-side (on the browser). This allows you to build more complex web¬†applications¬†instead of just sites. Think Gmail. Or Facebook.

And that’s just scratching the surface of the REST API. It can also be used to connect to third party platforms and services, and even more importantly I think, get sites talking to each other. Which is really cool. And will almost certainly require some Javascript. So roll up your sleeves, find your entry point, and get going.

Interested?

Just Keep Learning

I’m hoping I peeked your interest somewhere. I’m hoping you’re ready to learn Javascript and have some resources to get started with.¬†The trick is to start somewhere, get familiar and keep the ball rolling.

Categories
Development JavaScript WordPress

Gulp, LiveReload, SASS and WordPress

For a little while now, I’ve been using Gulp in my WordPress themes to automate my front-end workflow and add some handy helpers along the way. For those unaware, Gulp is a slick JavaScript task runner, which can be used to concatenate JS and CSS files, lint files, and generally automate your front-end workflow.

My goal was to write a short introduction to how this works. It ended up kind of long. But by the end you’ll be compiling SASS, minifying Javascript, working with livereload and implementing a SVG icon system. So not bad.

Setting Things Up

First off, gulp runs on top of NodeJS, and is generally operated from the command line. If you’re not set up with Node yet, I’d recommend following the steps on their website¬†(or better yet, installing Homebrew).

With Node installed, you can install gulp globally on your system by opening up your Terminal and running:

npm install -g gulp

This will ensure that you can use the gulp command from the command line. In the root directory of your theme file, you will also need to install and set up a local version of gulp, and add a package.json file to manage your dependencies. This is basically just a config file that Node uses to figure out which packages it needs to bring down and install (things like a SASS concatenate or a JavaScript linter or any number of other tools). To create this file, just navigate to your theme’s directory in the terminal and run:

npm init

This will step you through the process of creating a package.json file. When that’s finished, the last step is to install gulp locally to your WordPress theme folder.

npm install gulp --save-dev

That last flag, --save-dev will automatically save this to a list of dependencies in your package.json file, so you can easily pass the directory around. But more on that later.

More info at CSS-Tricks.

Folder Structure

I just want to quickly note my folder structure. You’ll notice that a lot of my decisions in gulp are dependent on this, but they can easily be changed. My theme folder looks like this:

screen-of-files

 

In the root directory, we’ve already created the package.json file, and we’ll create the gulpfile.js in just a minute. The other important folder is¬†assets¬†which includes all of my front-end files.

  • assets/js/app¬†– Contains all of my custom Javascript¬†files, which gulp will combine
  • assets/js/vendor¬†– Contains any vendor Javascript files, things like Bootstrap and Modernizr
  • assets/sass/style.scss –¬†My main SASS file, which contains imports for all the other sass files
  • assets/sass/ –¬†All the other SASS files
  • assets/svg/individual –¬†Contains any SVG files I would like to use in my SVG icon system

Hopefully this will be a bit more clear as we step through.

From here, it’s just a matter of installing the packages we need, and creating a gulp task for each one.

Getting Started with SASS

Ok, let’s start out with the SASS setup. The first thing we’ll need to do is install gulp-sass, a library which will compile SASS down into plain old CSS.

npm install gulp-sass --save-dev

With that, we can finally start setting up Gulp. Create a new file in the root directory titled gulpfile.js and at the very top add:

Gulpfile.js
var gulp     = require('gulp'),
    sass    = require('gulp-sass');

Gulp uses the require syntax in order to import dependencies, so all we are doing here is ensuring that the gulp and gulp-sass library are loaded into variables.

Gulp works in what’s known as tasks. Each task performs a simple operation, passing files through and spitting them out in a different format on the other end. We’ll call our first task sass, which will handle the process of processing the style.scss file located in the assets/sass directory of our theme.

Gulpfile.js
gulp.task('sass', function () {
    return gulp.src('./assets/sass/style.scss')
            .pipe(sass.sync({outputStyle: 'compressed'}).on('error', sass.logError))
            .pipe(gulp.dest('./'));
});

Pretty simple actually. We give the initial task a source, and then use pipe, a built in connector for tasks to process sass. You’ll notice on line 3 that we’re actually calling the sass variable in order to process our file. Now, if we run¬†gulp sass in the terminal, a new CSS file will be generated in the root directory of our theme. So far, so good.

Concatenating and Minifying Javascript

In a typical theme, I have two sets of Javascript files. The first are vendor files, and the other are my custom files. As seen above, I keep these in two separate folders helps to manage them better, and later on, I use gulp to combine them all together.

One thing I’ve run into over and over again is loading order for Javascript. If you’re using modules, you may not have to worry about this, but I’ve found that rather then trying weird naming conventions or separating files, I’ve opted to simply list out my Javascript files in the order I would like them to load. That way, gulp will process them one by one and spit them out into one big file. I know there are other methods, but this has worked best for me.

We’ll need to install a few other packages to get this up and running.

npm install gulp-concat gulp-uglify gulp-rename --save-dev

Gulp-concat will combine all of our Javascript files into one big file, gulp-ugilfy will minify them, compressing the file and saving us precious kilobytes, and gulp-rename will allow us to call this outputted file whatever we would like. Once again, at the top of our gulpfile we need to define the packages we just installed.

Gulpfile.js
var concat   = require('gulp-concat'),
    uglify  = require('gulp-uglify'),
   rename   = require('gulp-rename');

Next, we will create a config variable that defines all of the Javascript files we want to concat. This variable will be used by gulp to process the files in order. If you simply want to include all the files from a directory, you can use the /**/*.js syntax, as we will do for our app folder.

Gulpfile.js
var config = {
    scripts: [
                // Bootstrap
        './assets/js/vendor/bootstrap.js',
        // Modernizr
        './assets/js/vendor/modernizr/modernizr.shiv.js',
        // SVG Fallback
        './assets/js/vendor/svg/svg-fallback.js',
        // Any Custom Scripts
        './assets/js/app/**/*.js'
    ]
};

With that all set up, we can add a new task called scripts, which will run the files through concat and uglify and output the file:

Gulpfile.js
gulp.task('scripts', function() {
    return gulp.src(config.scripts)
            .pipe(concat('scripts.js'))
            .pipe(gulp.dest('./assets/js/'))
            .pipe(uglify())
            .pipe(rename({ extname: '.min.js' }))
            .pipe(gulp.dest('./assets/js/'));
});

This time for our source, we pass the variable we creaed, which has an array of the files we want to concat. This will output a file called scripts.js in our assets/js folder. Then uglify will compress this file even further, and output it as scripts.min.js. This will be our production-ready file. However, the scripts.js file can come in handy when debugging your theme.

If you want to see this in action, simply run gulp scripts.

SVG Icons

I won’t go too far into why I prefer SVG icons over any other systems, but if you want a lengthy introduction on how they work, CSS Tricks has a great tutorial. If you find yourself convinced, like I did, just make sure to save all of the individual SVG files you want to use in the assets/svg/individual folder. We will then use the gulp-svg-sprite and gulp-svg2png libraries to automatically create an SVG sprite and image fallbacks of our icons to easily use in our theme.

First step, install the two libraries we will need.

npm install gulp-svg-sprite gulp-svg2png --save-dev

Next, we’ll define our npm packages at the top of our gulpfile.

Gulpfile.js
var svgSprite    = require("gulp-svg-sprite"),
    svg2png     = require('gulp-svg2png');

Now it’s time to set up our SVG icon tasks. I’ve actually broken this up in my gulpfile into two tasks. The first creates the SVG sprite, which we can embed in our theme, and the second creates PNG fallbacks for our icons. The first we’ll call sprites:

Gulpfile.js
gulp.task('sprites', function () {
    return gulp.src('**/*.svg', {cwd: './assets/svg/individual'})
            .pipe(svgSprite({ shape: { transform: ['svgo'] }, mode: { defs: {dest: '.'} } } ) )
            .pipe(gulp.dest('./assets/svg/'));
});

As our source, we are simply looking in the ‘assets/svg/individual’ folder for anything with an .svg extension, and then processing it using the svg-sprite library. You will notice that I passed an svgo transformation, which will automatically optimize the SVG files. The final sprite will be saved to assets/svg as sprites.defs.svg. From there, you can follow the article linked above for how to include this in your theme.

Next up is the SVG fallbacks. For these fallbacks, I use a script from Luke Whitehouse. I had to modify it a bit to point to the proper URL (MyTheme + /assets/svg/png/”), but it works fairly well. You may also want to consider a library like SVG For Everybody. But in order for either method to work, they will need PNG images to fall back to. So we’ll create a gulp task that simply runs through our SVG files, converts them to PNG, and drops them in our assets/svg/png folder.

Gulpfile.js
gulp.task('svg2png', function () {
    return gulp.src('./assets/svg/individual/**/*.svg')
            .pipe(svg2png())
            .pipe(gulp.dest('./assets/svg/pngs/'));
});

This uses the gulp-svg2png library we installed to convert our SVG files on the fly.

Gulp tasks do not simply have to be one-off scripts. In fact, they can simply be an array of tasks to perform, in order. For our SVG workflow to be complete, we’ll want to combine the two tasks we created into a single task called icons. All we need to do is pass the names of these two tasks to a new one.

Gulpfile.js
gulp.task('icons', ['sprites', 'svg2png']);

Now, if you run gulp icons you will see this workflow in action.

Bonus Round: LiveReload

Livereload is an incredible library that can be used to automatically reload your site whenever changes are made. That way you don’t have to do the annoying Ctrl / CMD + R, check changes, switch to editor dance. And for CSS files, it will even inject styles on the fly, with no refresh needed. So you will see your styles change instantly.

The first step is to install the gulp-livereload library.

npm install gulp-livereload --save-dev

Next, we need to make sure that the livereload script is actually running on our site. H/T to Rob & Lauren for pointing me in the right direction with this one. We can add this to the functions.php file in our theme, automatically enqueueing the script on local environments.

functions.php
if (in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'))) {
  wp_register_script('livereload', 'http://localhost:35729/livereload.js?snipver=1', null, false, true);
  wp_enqueue_script('livereload');
}

 

With that added, we can go back our gulpfile.js file. At the top, make sure to define your dependency in a new variable.

Gulpfile.js
var livereload      = require('gulp-livereload');

Next we can add the livereload function to our SASS and JS tasks. This will call livereload at the appropriate times so that your development site is reloaded automatically in the browser whenever one of these tasks is called. So our SASS task will now be:

Gulpfile.js
gulp.task('sass', function () {
    return gulp.src('./assets/sass/style.scss')
            .pipe(sass.sync({outputStyle: 'compressed'}).on('error', sass.logError))
            .pipe(livereload())
            .pipe(gulp.dest('./'));
});

And our scripts task will now be:

Gulpfile.js
gulp.task('scripts', function() {
    return gulp.src(config.scripts)
            .pipe(concat('scripts.js'))
            .pipe(gulp.dest('./assets/js/'))
            .pipe(uglify())
            .pipe(rename({ extname: '.min.js' }))
            .pipe(livereload())
            .pipe(gulp.dest('./assets/js/'));
});

Wrapping It Up With Watch

The last thing we will want to do is use Gulp’s built-in watch feature to automatically watch for any changes to files and call the appropriate task when needed. So, if a SASS file is changed, the SASS task will be called, and if a JS file is changed then the scripts task will be called. We can also set up livereload here so that everything is wired up.

Gulpfile.js
gulp.task('watch', function () {
    livereload.listen(35729);
    gulp.watch('**/*.php').on('change', function(file) {
          livereload.changed(file.path);
      });
    gulp.watch('./assets/sass/**/*.scss', ['sass']);
    gulp.watch('./assets/js/**/*.js', ['scripts']);
});

 

Now all we have to do is add a default task which combines everything from before, calling each of our tasks and ending in watch.

Gulpfile.js
gulp.task('default', ['icons', 'sass', 'scripts', 'watch']);

And that’s that! All we have to do is run¬†gulp and¬†our tasks will be called in order and livereloading will begin. Try changing around some SASS or Javascript files and see what happens.

This is by no means an entirely exhaustive workflow, but it’s more then enough to get started. The trick is to understand how it works, and play around with it when you can. If you want to see what the full gulpfile looks like, well, here it is:

Full Gulpfile.js
var     gulp           = require('gulp'),
    concat         = require('gulp-concat'),
    uglify         = require('gulp-uglify'),
    rename         = require('gulp-rename'),
    sass           = require('gulp-sass'),
    livereload      = require('gulp-livereload'),
    svgSprite     = require("gulp-svg-sprite"),
    svg2png     = require('gulp-svg2png');

var config = {
    scripts: [
        './assets/js/vendor/bootstrap/bootstrap.min.js',
        // Modernizr
        './assets/js/vendor/modernizr/modernizr.shiv.js',
        // SVG Fallback
        './assets/js/vendor/svg/svg_fallback.js',
        // Any Custom Scripts
        './assets/js/app/**/*.js'
    ]
};

gulp.task('scripts', function() {
    return gulp.src(config.scripts)
            .pipe(concat('scripts.js'))
            .pipe(gulp.dest('./assets/js/'))
            .pipe(uglify())
            .pipe(rename({ extname: '.min.js' }))
            .pipe(livereload())
            .pipe(gulp.dest('./assets/js/'));
});

gulp.task('sass', function () {
    return gulp.src('./assets/sass/style.scss')
            .pipe(sass.sync({outputStyle: 'compressed'}).on('error', sass.logError))
            .pipe(livereload())
            .pipe(gulp.dest('./'));
});

gulp.task('sprites', function () {
    return gulp.src('**/*.svg', {cwd: './assets/svg/individual'})
            .pipe(svgSprite({ shape: { transform: ['svgo'] }, mode: { defs: {dest: '.'} } } ) )
            .pipe(gulp.dest('./assets/svg/'));
});

gulp.task('svg2png', function () {
    return gulp.src('./assets/svg/individual/**/*.svg')
            .pipe(svg2png())
            .pipe(gulp.dest('./assets/svg/pngs/'));
});

gulp.task('icons', ['sprites', 'svg2png']);

gulp.task('watch', function () {
    livereload.listen(35729);
    gulp.watch('**/*.php').on('change', function(file) {
          livereload.changed(file.path);
      });
    gulp.watch('./assets/sass/**/*.scss', ['sass']);
    gulp.watch('./assets/js/**/*.js', ['scripts']);
});

gulp.task('default', ['icons', 'sass', 'scripts', 'watch']);
Categories
Inspiration

Adam Phillips on Missing Out

We refer to them as our unlived lives because somewhere we believe that they were open to us; but for some reason ¬Ė and we might spend a great deal of our lived lives trying to find and give the reason ¬Ė they were not possible. And what was not possible all too easily becomes the story of our lives. Indeed, our lived lives might become a protracted mourning for, or an endless tantrum about, the lives we were unable to live. But the exemptions we suffer, whether forced or chosen, make us who we are.

Adam Phillips, Missing Out