encapsulate

Really simple Javascript build system. Compile multiple source files into one, based on a build file named 'encapsulate.json' in the working directory.

npm install encapsulate
22 downloads in the last week
44 downloads in the last month

EncapsulateJS

Really simple Javascript build system.

Compile multiple source files into one, based on a build file named "encapsulate.json" in the working directory.

Install

npm install -g encapsulate

Or, if you're not going to run the built in command line utility, you can leave off the -g option and install it locally only for requiring in your own script.

npm install encapsulate

Command Line

encapsulate [target]
encapsulate --example
encapsulate --help

When called with no arguments or with a build target name, EncapsulateJS will look for an "encapsulate.json" file in the working directory and attempt to build all source files listed in it. The combined script will be printed to standard output so you can redirect it to a file or pipe it to another program.

See the Configuration section for more information about the expected structure of the "encapsulate.json" file.

--example creates an example "encapsulate.json" file that you can modify.

--help displays the command line usage message.

Configuration

The "encapsulate.json" file can contain an array or an object. Use the --example option to easily create a template in the working directory, that you can then modify.

Object

An object allows plugins to be called. Default plugins can be set and then overridden per build target.

  • "files" (required)
    • A list of files that EncapsulateJS will combine into a single file.
    • Value: Array
      • String values are paths to source files that will be included no matter the build target.
      • An object value allows a file to target a specific build target. The object should have a "filename" property and a "target" property.
        • To include a file only when no build target is given, set the "target" property to an empty string "".
        • To include a file in multiple build targets, add multiple items with the same "filename" value but different "target" values.
        • Example: { filename: "my/source/file.js", "target": "build_target" }
  • "target" (optional)
    • A map of build target names to plugin names. This allows plugins to be disabled, or enabled with different options, per build target.
    • Value: Object
      • The value given for a plugin name completely replaces any default value given at the top level.
      • Example: { "foo": { "minify": true }, "bar": { "minify": false } }
  • "each", "log" (reserved)
    • Because JSON cannot contain functions, these property names are not useful from the "encapsulate.json" file, but they can be used when EncapsulateJS is used programmatically.
  • Plugins Names
    • Any property name that is not one of the above four reserved property names, indicates a plugin by name. Property names that do not match a plugin name are silently ignored.
    • Value: Any
      • If value === false, the plugin will not be executed.
      • If value !== false, the plugin will be executed. The value will be passed to the plugin function.
    • Build-In Plugins
      • "coffee"
        • Convert CoffeeScript into javascript.
        • Only filenames that end with ".coffee" will be affected.
        • Priority: -10
      • "hint"
        • Check the source code using JSHint.
        • If an object value is given, it will be passed to JSHint as options.
        • Priority: 0
      • "minify"
        • Compress each source file using UglifyJS.
        • Priority: 10
      • "wrap"
        • Wrap each source file in its own closure.
        • Each closure exposes a reference to an object named "local", which can be used to explicitly share things between files.
          • The name "local" can be changed by setting a string value for this property.
          • If you do not want the local namespace, then set the value to "".
        • Priority: 15
      • "label"
        • Add a filename comment before each file's source. The filename will be realative to the working directory to avoid exposing more information about the originating file system than is necessary.
        • Priority: 20
    • Custom
      • See the "Require In Your Node" section for information about defining custom plugins. It's not as hard as you might think.

Here's a full example.

{
    "wrap": true,
    "hint": true,
    "files": [
        "foo.js",
        {
            "filename": "bar.js",
            "target": "web"
        },
        {
            "filename": "bar.js",
            "target": "node"
        },
        {
            "filename": "web.js",
            "target": "web"
        },
        {
            "filename": "node.js",
            "target": "node"
        },
        {
            "filename": "dev.js",
            "target": ""
        }
    ],
    "target": {
        "web": {
            "minify": true
        },
        "": {
            "hint": {
                "debug": true
            }
        }
    }
}

Here's the example breakdown.

  • All source files will be wrapped in their own closures and given a reference to a common namespace named "local".
  • JSHint will always be run.
  • "foo.js" will be included no matter what.
  • "bar.js" will only be included if either the "web" or "node" target is set.
  • "web.js" will only be included in the "web" target.
  • "node.js" will only be included in the "node" target.
  • "dev.js" will only be included if no build target is set.
  • Scripts will only be minified when the build target is "web".
  • JSHint will be run with the "debug" option when there is no build target.

Array

If "encapsulate.json" contains a JSON array, then it is used as the "files" array outlined above. This is a simpler option for when you don't need to run any plugins.

Source File Environment

The concatenated source is wrapped in a closure so that local variables do not accidentally escape. The "wrap" plugin will additionally wrap the contents of all source files in their own closures.

Require In Your Node

You can of course also use EncapsulateJS programmatically.

var encapsulate = require( 'encapsulate' );

If you have custom plugin functions that you want to use, you can add them using the plugin method. The first argument is the name of the plugin. The second is the function that will be called when the plugin is invoked. The third argument is an optional number priority.

The priority determines the order in which the plugin will be called. If no priority is given then it defaults to zero. Two plugins at the same priority will be called in the order they are added. So, you can just add your plugins in the order they should be called and forget about the priority if you want.

See the "Plugin Functions" section below for information about the arguments passed to the callback.

encapsulate.plugin( 'name', plugin_function, priority );

If a plugin needs to be notified when building begins, it can register a callback using the pluginInit method. The first argument is the name of the plugin. The second is the functin that will be called when building begins. There is no priority like there is for the plugin function. Initialization functions are run in the order that they are added.

encapsulate.pluginInit( 'name', init_function );

If a plugin needs to be notified when building ends, it can register a callback using the pluginTeardown method. It behaves exactly the same as pluginInit, except that the callback will be called after the last source file has been processed.

encapsulate.pluginTeardown( 'name', teardown_function );

To pass an options object and recieve the output as a string, use the run method. The options argument is required and must follow the same rules outlined in the Configuration section, with the addition of optional log and each callback functions. The build target parameter is optional, just like it is on the command line.

A log callback option will be passed two arguments whenever a plugin calls its log callback. The first parameter is the name of the plugin. The second parameter is the message that the plugin passed to its log callback.

An each callback option will be called before handling each source file. It is passed the filename of the file that is about to be parsed. When called, the source file has already been read.

var output_string = encapsulate.run( options, target );

If you just want to run the normal command line system after adding custom plugins, use the cli method. The config parameter is optional. If it's not given, the configuration will be read from "encapsulate.json" as it would be using the regular command line utility. This will exit the program when it's finished.

encapsulate.cli( config );

Read and decode the "encapsulate.json" file, returning the decoded JSON. Useful if you want to do any modification to the configuration before passing it on to the cli method.

encapsulate.readConfig();

Plugin Functions

When you add a function using the plugin method, it will be called once per source file if the configuration calls for it.

It will be passed, in order: A log function, filename, source, and an options object from the configuration file if available. The log function passed as the first argument accepts a single message parameter.

If the function returns a string, it will replace the source for the file. If the function returns false then the file will not be included.

plugin( Function log, String filename, String source, Any config_value )

Init callbacks will be called before any source files are processed. The first argument is the log function, then an array of filenames, and finally the value from configuration. If the function returns a string, it will be added to the output before all source files.

plugin_init( Function log, Array files, Any config_value )

Teardown callbacks will be called after all source files have been processed. The first argument is the log function, then the compiled source, and finally the value from configuration. If the function returns a string, it will be added to the output after all source files.

plugin_teardown( Function log, source, Any config_value )

License

The MIT License (MIT)

Copyright (c) 2013 Christopher Ackerman

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

npm loves you