0.0.0 • Published 9 years ago

slush-ease v0.0.0

Weekly downloads
3
License
MIT
Repository
github
Last release
9 years ago

slush-ease

Slush generators made dead easy.

Philosophy

Tools like Yeoman and Slush make scaffolding pretty easy. But, for a few reasons, they just didn't quite do it for me. In particular, I found myself spending more time on the generator than I felt like I was saving by using the generator. With that in mind, I have created slush-ease, which is centered around the idea of getting your generator up and running as quickly as possible, and with as few lines of code as possible.

But why reinvent the wheel? Slush isn't so bad. It just needs a little cherry on top. I hope that slush-ease can be the cherry atop your slush.

Quickstart

As promised, I hope to get you up and running with a usable generator as quickly as possible. Here's how to do just that:

$ npm install -g slush slush-ease
$ cd path/to/where/you/want/the/generator
$ slush ease

Answer the prompts that come up.

If you don't know what ES6 is, say 'No' when the generator asks you if you want to use ES6. Then, later when you have a chance, learn ES6.

Documentation

slush-ease is both a Slush generator and a package that makes it dead easy to whip out a slush generator. This documentation is about the package part of slush-ease. To use the Slush generator part, see Quickstart above.

slushease.quick(options)

Quickest way to a working generator. Accounts for the common use cases. Use slushease.BaseGenerator.as_task instead (see below) for more "advanced" generator configuration.

arguments

options: (Object) Hash of generator configuration options. Accepts the following keys, all of which are optional, except in_glob (which is required):

  • in_glob: (String) Path glob to a template file structure. This key is required.
  • dotfiles: List of file basenames (from the template file structure) that should be prefixed with dots. For example, ['gitignore'] would mean that any file captured by in_glob with basename gitignore would be output instead with basename .gitignore.
  • named: (Boolean) Whether or not to automatically prompt the user for the name of the component they are generating. (Default: true)
  • prompts: (Array) List of Inquirer prompts to ask the user.
  • pre_messages: (Array) List of messages to log before running the generator.
  • post_messages: (Array) List of messages to log after running the generator.
  • do_installing: (Boolean) Whether or not to automatically install npm and bower packages after scaffolding. Uses gulp-install, which checks to see if the file stream captured by in_glob includes a package.json and/or bower.json and then installs packages accordingly. (Default: true)
  • do_templating: (Boolean) Whether or not to pass all files captured by in_glob through (lodash) templating. (Defalt: true)
  • context: (Object) Hash of key-value pairs to use in the templating context (only matters if do_templating flag is set). All answers to the inquirer session (and the component name if named flag is set) will already automatically be a part of the templating context, so this hash should only include values you want in addition to those.

returns

(Function) Routine that can be registered as gulp task, or used within a gulp task, or whatever you like.

example

// slushfile.js

var path = require('path')
var gulp = require('gulp')
var chalk = require('chalk')
var slushease = require('slush-ease')

// quickly register the default gulp task
gulp.task('default', slushease.quick({
    // path glob to project's template file structure
    in_glob: path.join(__dirname, 'templates', 'project', '**'),

    // list of file basenames to prefix with dots
    dotfiles: [ 'gitignore' ],

    // list of inquirer prompts to ask the user
    // (they will already be asked for the project name)
    prompts: [
        {
            name: 'description',
            message: 'Provide a short description of your project'
        }, {
            name: 'license',
            message: 'Pick a license for your project'
            type: 'list',
            choices: [
                'Apache-2.0',
                'BSD-3-Clause',
                'GPL-3.0',
                'MIT',
            ],
        }
    ],

    // add extra key-value pairs to the templating context
    // (the project name, and all answers to inquirer session are already included)
    context: { fun_level: 9001 },

    // list of messages to log before running generator
    pre_messages: [ "Get ready to have some fun!" ],

    // list of messages to log after running generator
    post_messages: [
        "I've installed the " + chalk.red("node") + " dependencies for you.",
        "Have a great day!"
    ]
}))

slushease.BaseGenerator

This is an ES6 class.

If you don't know what that is, don't worry. You don't need to take advantage of that aspect of it in order to use it successfully.

If you do know what that is, feel free to subclass this and extend it as you see fit! Use the slush-ease generator (see Quickstart above) to quickly scaffold out a new slush generator equipped with ES6 transpiling and configuration all done for you (using gulp to call webpack with babel loader).

attributes

slushease.BaseGenerator.beginner()

(Function) Routine to call before the generator is run. (Defaults to no-op)

slushease.BaseGenerator.prompts

(Array) List of Inquirer prompts to ask the user. (Default: [])

slushease.BaseGenerator.props

(Object) Hash to store various other generator specific properties on. (Default: {})

slushease.BaseGenerator.dotfiles

(Array) List of file basenames (from the template file structure) that should be prefixed with dots. For example, ['gitignore'] would mean that any file captured by in_glob with basename gitignore would be output instead with basename .gitignore. (Default: [])

slushease.BaseGenerator.in_glob

(String) Path glob to a template file structure. (Defaults to '' so you must set this if you want to capture any files)

slushease.BaseGenerator.out_dir

(String) Path to directory where scaffolded file structure should be output. (Default: process.cwd())

slushease.BaseGenerator.context

(Object) Hash to use as context for (lodash) templating. (Default: {})

slushease.BaseGenerator.renamer(file)

(Function) Function to use for file renaming on all files captured by in_glob. See the "rename via function" example on gulp-rename's README. (Defaults to no-op)

slushease.BaseGenerator.ender()

(Function) Routine to call after the generator is run. (Defaults to no-op)

class methods

slushease.BaseGenerator.as_task(options)

Takes a hash of generator options and returns a function that can be registered as a gulp task.

arguments

options: (Object) Hash of generator configuration options. Accepts the following keys, all of which are optional (although you ought to at least provide utilize_answers to set this.in_glob, for otherwise you will not capture any template files to scaffold):

  • utilize_args: (Function) This function will be executed in the context of the generator instance (within the function body, this refers to the generator instance) immediately after the generator is invoked from the command line. It will be passed the single argument gulp.args (an Array of the arguments passed from the command line). Within it, you are free to utilize (or not) these arguments as you see fit. However, I suggest that you use this function to set the following attributes on the generator instance:

    • beginner
    • prompts
    • props
  • utilize_answers: (Function) This function will be executed in the context of the generator instance (within the function body, this refers to the generator instance) immediately after the Inquirer session has been completed. It will be passed the single argument answers (as received directly from Inquirer). Within it, you are free to utilize (or not) this answers hash as you see fit. However, I suggest that you use this function to set the following attributes on the generator instance:

    • dotfiles
    • in_glob
    • out_dir
    • context
    • renamer
    • ender
  • do_installing: (Boolean) Whether or not to automatically install npm and bower packages after scaffolding. Uses gulp-install, which checks to see if the file stream captured by in_glob includes a package.json and/or bower.json and then installs packages accordingly. (Default: true)

  • do_templating: (Boolean) Whether or not to pass all files captured by in_glob through (lodash) templating. (Defalt: true)

returns

(Function) Routine that can be registered as gulp task, or used within a gulp task, or whatever you like.

example
// slushfile.js

var path = require('path')
var gulp = require('gulp')
var gutil = require('gulp-util')
var slushease = require('slushease')

gulp.task('default', slushease.BaseGenerator.as_task({
    utilize_args: function(args) {
        // add some inquirer prompts
        this.prompts.push(
            {
                name: 'description',
                message: 'Provide a breif description for your project'
            }, {
                name: 'license',
                type: 'list',
                message: 'Pick a license for your project',
                choices: [
                    'None',
                    'Apache-2.0',
                    'BSD-3-Clause',
                    'GPL-3.0',
                    'MIT'
                ],
            }
        )
    },

    utilize_answers: function(answers) {
        // path glob to project's template file structure
        this.in_glob = path.join(__dirname, 'templates', 'project', '**')

        // prefix (with a dot) any template files with basename 'gitignore' or 'npmignore'
        this.dotfiles.push(
            'gitignore',
            'npmignore'
        )

        // merge user's answers onto templating context
        assign(this.context, answers)

        // save reference to old implementation
        var old_ender = this.ender
        // provide new implementation
        this.ender = function() {
            // call old implementation
            old_ender()

            // provide a friendly reminder after the generator is done
            gutil.log("Don't forget to initialize a new git repository!")
        }
    }
}))
slushease.BaseGenerator.named(question)

Extends slushease.BaseGenerator to automatically asks the user for the name of the component they are generating (unless they pass a valid one as the first argument from the command line).

arguments

question: (Object) Optional Inquirer question object. The following keys (which are available on an Inquirer question object) will be ignored:

  • name: Will always be set to "name".
  • when: Will always be set to true.

Here are the default values for the remaining question object keys:

  • type: "input"
  • message: "What will you call this thing?"
  • default: path.basename(process.cwd())
  • validate: function(answer) { return true }
  • filter: function(answer) { return answer }
returns

(Class) An (ES6 class) extension of slushease.BaseGenerator that will automatically ask the user for a name of the component they are generating (unless they pass a valid name as the first argument from the command line).

example
// slushfile.js

var path = require('path')
var gulp = require('gulp')
var slushease = require('slushease')

gulp.task('default', slushease.BaseGenerator
    .named({
        message: 'Name your project',
        validate: function(name) {
            return kebabCase(name) !== ''
        },
        filter: kebabCase
    }).as_task({
        utilize_args: function(args) {
            // add some inquirer prompts
            // Note: Be sure to use `push` rather than overwrite `this.prompts`
            //       if you want the generator to actually ask for a name!
            this.prompts.push(
                {
                    name: 'description',
                    message: 'Provide a breif description for your project'
                }, {
                    name: 'license',
                    type: 'list',
                    message: 'Pick a license for your project',
                    choices: [
                        'None',
                        'Apache-2.0',
                        'BSD-3-Clause',
                        'GPL-3.0',
                        'MIT'
                    ],
                }
            )
        },

        utilize_answers: function(answers) {
            // path glob to project's template file structure
            this.in_glob = path.join(__dirname, 'templates', 'project', '**')

            // prefix (with a dot) any template files with basename 'gitignore' or 'npmignore'
            this.dotfiles.push(
                'gitignore',
                'npmignore'
            )

            // merge `this.props` and user's answers onto templating context
            // Note: this guarantees that the project name is on `this.context` since
            //       it is either on `this.props` or `answers`
            assign(this.context, this.props, answers)

            // save reference to old implementation
            var old_renamer = this.renamer
            // provide new implementation
            this.renamer = function(file) {
                // call old implementation
                old_renamer(file)

                // replace `NAME` with `this.context.name` everywhere within
                // each file path
                file.basename = file.basename.replace(/NAME/g, this.context.name)
                file.dirname = file.dirname.replace(/NAME/g, this.context.name)
            // don't forget to bind to `this` if you want to refer to
            // the generator instance within your `renamer`!
            }.bind(this)
        }
    })
)

slushease.NamedGenerator

Just a shorthand for slushease.BaseGenerator.named(). See above.