Coder Social home page Coder Social logo

pgilad / grunt-jade-usemin Goto Github PK

View Code? Open in Web Editor NEW
20.0 4.0 18.0 180 KB

Grunt plugin for running Usemin on Jade files

License: MIT License

JavaScript 96.70% HTML 2.61% CSS 0.69%
grunt-plugins jade-files grunt-usemin filetype javascript gruntfile target-jade

grunt-jade-usemin's Introduction

grunt-jade-usemin

Grunt plugin for processing jade files and building production js & css files

NPM Version NPM Downloads Build Status Built with Grunt

Getting Started

This plugin requires Grunt.

If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

npm install --save-dev grunt-jade-usemin

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of Javascript:

grunt.loadNpmTasks('grunt-jade-usemin');

The "jadeUsemin" task

This project is based on the grunt-usemin Project. grunt-jade-usemin is meant to be an assisting tool in preparing projects for build.

The steps of this plugin are as follows:

  1. Scan src jade files.
  2. Locate build blocks defined by <!-- build:type(alternate path) target -->.
  3. Gather css and js files in build blocks and run them through defined tasks for each filetype.
  4. Optionally output an optimized jade with with only targets to replace the build block.

Currently only 2 types of build blocks are supported: css and js.

jadeUsemin also:

  • Writes optimized jade files
  • You choose which tasks to run for each filetype.

For example use grunt-filerev to add cache-busting to scripts/css.

Usage

For more usage examples head on to the examples section.

Basic Example

To simply use the task, define your build blocks like so:

//-<!-- build:js public/js/scripts.min.js -->
script(src='./src/js/script1.js')
script(src='./src/js/script2.js')
//-<!-- endbuild -->

//-<!-- build:css test/compiled/style.min.css -->
link(rel='stylesheet', href='/test/fixtures/style1.css')
link(rel='stylesheet', href='/test/fixtures/style2.css')
//-<!-- endbuild -->

Then you need to define grunt-jade-usemin as a task in your grunt config. You can use the following setup to process the above pattern:

//...
jadeUsemin: {
    scripts: {
        options: {
            tasks: {
                js: ['concat', 'uglify'],
                css: ['concat', 'cssmin']
            }
        },
        files: [{
            dest: './src/partials/index.jade',
            src: './public/partials/index.jade'
        }]
    }
}
//...

Running grunt jadeUsemin:scripts will now concat and uglify script1.js and script2.js and output them as public/js/scripts.min.js. This will also output an optimized jade file that will remove the build block and contain:

script(src='public/js/scripts.min.js')

Optimized Jade Files

Writing target jade files is optional. jadeUsemin is smart enough that if you don't specify a target for your src jade files, it won't output a jade file. This is useful if you are working on server side jade files that build blocks still need to be optimized.

In your grunt configuration you need to configure a destination file (see: grunt files).

Then if your src jade file is:

//-<!-- build:css test/compiled/style.min.css -->
link(rel='stylesheet', href='/test/fixtures/style1.css')
link(rel='stylesheet', href='/test/fixtures/style2.css')
//-<!-- endbuild -->

Your target jade file will turn into:

link(rel='stylesheet', href='test/compiled/style.min.css')

Note: in order to create the optimized target, grunt-jade-usemin takes the first src in the relevant build block found and uses that as a template

API

Build blocks

Build blocks have a strict design, so that they may be correctly caught by the regex.

<!-- build:type(alternate path) target -->
<!-- endbuild -->
  • Build blocks must be all of the same type (or filetype).
  • You can have as many different build blocks in the same file.
  • Currently only supported blocks are of js or css types.
  • If writing an optimized jade file, it uses the pattern of the first item to insert optimized script.
  • alternate path is optional (along with the parenthesis). If used this task will also try to find the script/css src files in the alternate path.

Grunt Task

Tasks are configurable and run in the order you specify. This gives you great flexibility in choosing which and how to run tasks on your build blocks.

The main task you need to define is called jadeUsemin.

Besides specifying the files object, you can use the following options:

Tasks

This is an array of objects, where key=filetype and value is an array of tasks to be run in order.

Default value is:

tasks: {
    js: ['concat', 'uglify'],
    css: ['concat', 'cssmin']
}

In order to allow you to configure your tasks, jadeUsemin looks in the following places, which are ordered by precedence:

  1. task.jadeUsemin.options. For example: uglify.jadeUsemin.options.
  2. task.options. For example: uglify.options.
  3. Predefined default options for task if they exists.

This will allow you to control the options with which your tasks are being run on the build blocks.

Please note that the first task in each filetype runs against the original src files, and writes the destination target file. All the rest of the tasks in the context of the filetype run on the destination file.

So basically saying - it makes the most sense to run concat first on the build blocks.

Specifying no destination for directory tasks (such as filerev)

grunt-jade-usemin will look in options for noDest and will just specify a src for the file

So a possible way to configure grunt-filerev to rewrite the original files with the rev files would be:

//in your grunt config
filerev: {
    jadeUsemin: {
        options: {
            noDest: true
        }
    }
},
Example usage with grunt-autoprefixer
tasks: {
    js: ['concat', 'uglify'],
    css: ['concat', 'autoprefixer', 'cssmin']
}

dirTasks

Type: string[]|string Default: []

If you have tasks that require a directory as destination (i.e grunt-filerev) than you can use the dirTasks option to specify those in an array or string.

Example:

dirTasks: ['filerev']
// or dirTasks: 'filerev'

This will parse the destination target as a directory, and not a file.

important note - If you use this option for any task, please make sure it is the last task that runs for a file type, as it will output a file with different name as the original target.

Prefix

String Default: ''

This adds some flexibility to where you keep your public folder. It allows you to add a prefix to the path.

failOnMissingSource

Boolean Default: false

Should task fail if there are missing source files in the jade. If false there will only be a warning.

targetPrefix

String Default: ''

Same as the prefix but used for target location. If you specify a string here it will be prefixed to the output of the target file.

replacePath

Object Default: {}

This option allows you to specify interpolation patterns for the source and build paths of your js/css. Each key value you specify here will be interpolated in the src paths that the plugin finds. For example if you add: '#{env}': 'dist' then all occurrences of #{env} in src paths will be replaced with dist. This gives you the power to change the paths according to different working environments.

Gruntfile.js full example

In your project's Gruntfile, add a section named jadeUsemin to the data object passed into grunt.initConfig().

grunt.initConfig({
  jadeUsemin: {
    main: {
      options: {
        tasks: { //optional if you want to use defaults
            js: ['concat', 'uglify', 'filerev'],
            css: ['concat', 'autoprefixer', 'cssmin']
        },
        dirTasks: 'filerev',       //optional
        failOnMissingSource: false // optional
        prefix: '',                //optional
        targetPrefix: '',          //optional
        replacePath: {             //optional
            '#{env}': 'dist'
        }
      },
      files: [{
        src: ['src/index.jade', 'src/index2.jade']
      },{
        src: ['src/index.jade'],
        dest: 'dist/index.jade'
     }]
    }
  },
})

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.

Contributors

License

MIT © Gilad Peleg

grunt-jade-usemin's People

Contributors

arturokunder avatar gurucomkz avatar izifortune avatar jdewit avatar lamplightdev avatar pgilad avatar ppitonak avatar shawncarr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

grunt-jade-usemin's Issues

location is not defined

output from running code similar to your examples

Verifying property jadeUsemin.dist exists in config...OK
Files: app/views/index.jade -> src
Files: dist/views/index.jade -> dest
Options: uglify
Processing jade file app/views/index.jade
Reading app/views/index.jade...OK
Found build:<type> pattern in line: 49
Warning: location is not defined Use --force to continue.

Looked at the source code too and location is not defined

filerev task doesn't work when using the same output file per two pages with targetPrefix

Let's say I have the following two jade pages (with same content for simplification):

//-<!-- build:js compiled/jquery.min.js -->
script(src='/src/script1.js')
//-<!-- endbuild -->

And the following Gruntfile config:

jadeUsemin: {
  withPrefixTwoFiles: {
    options: {
      tasks: {
        js: ['concat', 'uglify', 'filerev'],
        css: ['concat', 'cssmin']
      },
      dirTasks: ['filerev'],
      prefix: 'test/',
      targetPrefix: 'test/'
    },
    files: [{
      src: 'test/fixtures/layout.jade',
      dest: 'test/compiled/layout.jade'
    }, {
      src: 'test/fixtures/layout2.jade',
      dest: 'test/compiled/layout2.jade'
    }]
  }
}

After running jadeUsemin task compiled link in one file is correct (compiled/jquery.min.aaa4f100.js) but in the other file stays non-revisioned (compiled/jquery.min.js).

grunt-jade-usemin doesn't replace references in jade file

I've configured my jade-usemin task using this Gruntfile.coffee

jadeUsemin:
  main:
    options:
      uglify: true
    files:
      src: 'dist/views/**.jade'

my jade file looks like the following

 //-<!-- build:css dist/public/styles/foo.min.css -->
 link(rel='stylesheet', href='../bower_components/bootstrap/dist/css/bootstrap.min.css')
 link(rel='stylesheet', href='../public/styles/foo.css')
 //-<!-- endbuild -->

It's actually generating the concated and minified file foo.min.css within the right directory. but it didn't replace the build expression within the jade files.
Am I missing something. I've reviewed the source but I'm not sure if there is a hook which I'm missing for prepareUsemin or something like that.

filerev usage

I use jade server-side, and I'm trying to figure out a structure where I can do dev easily and then when I build with grunt, have it export to a build directory, then uglify, minify and tag with filerev.

So right now, in my template, I have something like this:

    //-<!-- build:js /javascripts/lib/jquery.min.js -->
    script(src='/javascripts/lib/jquery.js')
    //-<!-- endbuild -->

When I need to deploy, the output is going into a build directory and the jadeUsemin relevant part is:

    jadeUsemin: {
        build: {
            options: {
                tasks: {
                },
                prefix:'public/' //public is a mount in express
            },
            files: [{
                dest: './build/views/layout.jade',
                src: './build/views/layout.jade'
            }]
        }
    }

Which yields this in the template:

    script(src='/javascripts/lib/jquery.min.js')

Is there any way to keep the paths as is, but feed the filerev information into jade-usemin separately? i.e. somehow given the same input block, output this instead:

    script(src='/javascripts/lib/jquery.min.0defab41.js')

I think in the regular usemin, you can pass the revmap directly to it via an option. Does that exist for jade-usemin?

i.e. if I add this task:

    filerev:{
        build: {
            src: './build/public/javascripts/lib/jquery.min.js'
        }
    },

Of course... There's all kinds of reference to the build directory in there, which isn't what I'd want exactly... But I could munge the filerev.summary object before I hand it to jade-usemin. Or is there a better way???

How to override source js/css files with revved ones?

I have the following jadeUsemin config:

grunt.initConfig({
    jadeUsemin: {
       main: {
         options: {
           tasks: {
               js: ['concat', 'filerev'],
               css: ['concat', 'filerev']
           },
          dirTasks: 'filerev',
       },
       files: [{
          src: ['src/index.jade'],
          dest: 'dist/index.jade'
       }]
    }
 },
});

After I run this task I get source asset and revved one like the following:

js/main.js
js/main.9d713a59.js

Is it possible to setup jadeUsemin to remove source like js/main.js and stay js/main.9d713a59.js only?

Included assets don't bundled?

I have the following layout.jade file with block styles slot for including styles:

// layout.jade
doctype html
html
  head
    //- <!-- build:css static/css/layout.min.css -->
    link(href="static/vendor/html5-boilerplate/css/normalize.css", rel="stylesheet")

    //- Include page styles
    block styles

    //- <!-- endbuild -->

And child index.jade page that extends layout.jade file:

// index.jade
block styles
    link(href="static/css/pages/create.css", rel="stylesheet")

After processing jade files my layout.min.css file has no styles resided in block styles of index.jade file

Image path in css is not being replaced with relative or absolute path

I have a folder structure as follows:

|--css
|  |--build
|    |--compiled.css
|  |--style1.css
|  |--style2.css
|--images

As you can see that i have compiled style1.css and style2.css into a folder build for compiled.css. Due to the relative path for background: url(../images/btn.png) in style1 and style2, the path did not get updated in compiled.css. Is there anyway to replace the url path in css as reference to the build folder?

filerev task doesn't work when using the same output file per two pages

Let's say I have the following two jade pages:

//page a.jade

//-<!-- build:css test/compiled/style.min.css -->
link(rel='stylesheet', href='/test/fixtures/style1.css')
link(rel='stylesheet', href='/test/fixtures/style2.css')
//-<!-- endbuild -->

//page b.jade

//-<!-- build:css test/compiled/style.min.css -->
link(rel='stylesheet', href='/test/fixtures/style1.css')
link(rel='stylesheet', href='/test/fixtures/style2.css')
//-<!-- endbuild -->

And the following Gruntfile

grunt.initConfig({
    jadeUsemin: {
        main: {
           options: {
               tasks: {
                   css: ['concat', 'filerev']
               },
               dirTasks: 'filerev'
           },
           files: [{
               src: ['a.jade', 'b.jade']
           }]
        }
    }
});

After running jadeUsemin task compiled links looks like the following test/compiled/style.min.css instead test/compiled/style.min.bfb0a478.css. What's wrong?

possibly wrong warning on css&js build types

I see that file tasks/lib/jade_usemin.js complains about lines like
//-<!-- build:css /styles/bundle.min.css -->
//-<!-- build:js /scripts/bundle.min.js -->

But plugin continues to work and does what it is supposed to do well.

Running "jadeUsemin:main" (jadeUsemin) task
Processing jade file ./.tmp/views/partials/scripts.pug
>``> Unsupported build type: js
>``> Finished with target block: .tmp/scripts/bundle.min.js
Processing jade file ./.tmp/views/partials/styles.pug
>``> Unsupported build type: css
>``> Finished with target block: .tmp/styles/bundle.min.css

Code that produce warning tasks/lib/jade_usemin.js:317:

if (includes(['css', 'js'], type)) {
    grunt.log.warn('Unsupported build type: ' + type);
}

Maybe negations is missing before includes call? I assume that css and js build types are the only ones supported, right?

Pug files are not processed

I wanted to process .pug files with grunt-jade-usemin but could not without patching it.
Would you consider allowing *.pug files to be processed by this plugin?

I wrote a patch to fix this issue.
patch-allow-pug.txt

Plugin fails when minblock has no tags

When there is a minblock with no content, the plugin fails to proccess it due to a replace on an undefined object.
The problem seems to be in jade_usemin.js line 324

Warning: Cannot call method 'replace' of undefined Use --force to continue.

to reproduce the problem, just set an empty min block

//-<!-- build:js /js/index.min.js -->
//-<!-- endbuild -->

It does not work for me, is there anything wrong?

directory structure:

/
|- views/layout.jade
|- dist/
|- Gruntfile.js

Gruntfile.js:

var yeomanConfig = {
    views: 'views'
}
...
jadeUsemin: {
    dist: {
        options: {},
        files: {
            src: ['<%= yeoman.views %>/layout.jade']
        }
    }
},
...

layout.jade:

//-<!-- build:js scripts/main.js -->
script(src='bower_components/jquery/jquery.js')
script(src='bower_components/jquery.validation/jquery.validate.js')
script(src='bower_components/jquery.validation/localization/messages_zh.js')
script(src='bower_components/momentjs/min/moment-with-langs.min.js')
script(src='scripts/main.js')
//-<!-- endbuild -->

outputs:

Running "jadeUsemin:dist" (jadeUsemin) task

Running "jadeUseminComplete" task
>> jadeUsemin finished after processing 0 files.

Did I miss someting?

Task "concat:jadeUsemin" not found

Hi,

I'm trying to set up a jadeUsemin task, but fails because can't find concat:jadeUsemin task:

grunt jadeUsemin
Running "jadeUsemin:main" (jadeUsemin) task
Running concat, cssmin & uglify
Processing jade file app/views/layouts/application_layout.jade
>> Finished with target block: public_static/build/vendor.min.css
>> Finished with target block: public_static/build/hh.min.css
Processing jade file app/views/layouts/cart_layout.jade
Processing jade file app/views/layouts/products_layout.jade
Processing jade file app/views/layouts/srv_layout.jade
Processing jade file app/views/layouts/user_layout.jade
Processing jade file app/views/layouts/web_layout.jade
>> Target public_static/build/vendor.min.css contains 3 files.
>> Target public_static/build/hh.min.css contains 4 files.
Warning: Task "concat:jadeUsemin" not found. Use --force to continue.

These are my settings:

    grunt.loadNpmTasks "grunt-jade-usemin"
    ...
    jadeUsemin:
      main:
        options:
          uglify: true
          prefix: '../../../'
          replacePath:
            '/static': '/public_static'
        files:
          src: [ 'app/views/layouts/*.jade' ]

What am I missing?

Thank you!

Should we fail when script src does not exist?

If some script is not found now the usemin task doesn't fail.
This doesn't play very nice with CI logic, because we dont notice the error right away.

Shouldn't we do grunt.fail or grunt.log.error for this?

grunt.log.warn("Found script src that doesn't exist: " + src);

Source Maps

It would be nice if there was an easy way to enable source maps. I've added this to my gruntfile, which seems to be working. But it is surely boilerplate which would better serve most people as an option in jadeUsemin.

        cssmin: {
            options: {
                sourceMap: true
            }
        },
        concat: {
            options: {
                sourceMap: true,
                sourceMapName: function(dest) {
                    var fileName = dest.split('/').pop();
                    return '.tmp/' + fileName + '.map';
               }
            }
        },
        uglify: {
            options: {
                sourceMap: true,
                sourceMapIncludeSources: true,
                sourceMapIn: function(dest) {
                    var fileName = dest.split('/').pop();
                    return '.tmp/' + fileName + '.map';
                }
            }
        },

Feature request - write target jade files after replacing build blocks

Similar to Usemin - write a target jade file (if specified) that has the build blocks replaced with the optimized script/css.

This requires the following:

  • Iterate over task src files & dest
  • Output jade file (currently - same input)
  • Extract build block & optimize it
  • Generate a correct optimized jade
  • Test jade concatenation with several src (optional)

PRs (including tests) are welcomed!

Warning: Task "concat:jadeUsemin-css" not found.

Hey, I can't get the task to work. Seeing this error:

Running "jadeUsemin:css" (jadeUsemin) task
Processing jade file src/cloud/views/public.jade
>> Finished with target block: public/stylesheets/app.css
Warning: Task "concat:jadeUsemin-css" not found. Use --force to continue.

Aborted due to warnings.

Here is my jadeUsemin grunt config:

    jadeUsemin: {
      css: {
        files: [{
          src:  'src/cloud/views/public.jade',
          dest: 'clous/views/public.jade'
        }, {
          src:  'src/cloud/views/private.jade',
          dest: 'cloud/views/private.jade'
        }]
        options: {
          tasks: {
            css: ['concat', 'cssmin']
          }
          prefix: 'temp/public/"
        }
      }
    }

And my jade file:

    //-<!-- build:css public/stylesheets/app.css -->
    link(rel="stylesheet", href="stylesheets/test.css")
    link(rel="stylesheet", href="stylesheets/test2.css")
    //-<!-- endbuild -->

Am I doing something wrong?

It's not clear how to add config for tasks

Sorry for the question because maybe it's my misunderstanding but I don't understand how to add config for tasks. Let's say I want use filerev task to my compiled files and save into ones that generates jadeUsemin?

Add option to specify destination directory for taks

It would be cool if you add option to specify destination directory for taks like the following:

jadeUsemin: {
    scripts: {
        options: {
            tasks: {
                js: ['concat', 'uglify'],
                css: ['concat', 'cssmin']
            },
            taskDestDir: './build'
        },
        files: [{
            dest: './src/partials/index.jade',
            src: './public/partials/index.jade'
        }]
    }
}

Unable to use absolute path to compiled source

In your examples you use relative path to compiled source like the following:

//-<!-- build:js public/js/scripts.min.js -->
script(src='./src/js/script1.js')
script(src='./src/js/script2.js')
//-<!-- endbuild -->

But I need to use absolute path to scripts.min.js like the following:

//-<!-- build:js /public/js/scripts.min.js -->
script(src='./src/js/script1.js')
script(src='./src/js/script2.js')
//-<!-- endbuild -->

But if do as above then my scripts.min.js will be saved on my file system in root public directory instead my deployment path.

How could I set absolute path /public/js/scripts.min.js to my compiled script and reside it in my deployment folder instead root one?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.