4 |
5 | Sample Page
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/02-grunt-contrib-uglifyjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "grunt-contrib-uglifyjs",
3 | "version": "0.0.0",
4 | "description": "A tutorial on how to use grunt-contrib-uglifyjs",
5 | "keywords": "grunt, gruntjs",
6 | "main": "Gruntfile.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "Jay Kanakiya",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "grunt": "^0.4.5",
14 | "grunt-contrib-uglify": "^0.6.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/03-grunt-contrib-watch/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | grunt.initConfig({
3 | pkg: grunt.file.readJSON('package.json'),
4 | watch: {
5 | express: {
6 | files: ["src/js/*.js", "index.html"],
7 | tasks: ["uglify:dev", "express:defaults"],
8 | options: {
9 | livereload: true,
10 | spawn: false
11 | }
12 | }
13 | },
14 | uglify: {
15 | all: {
16 | files: {
17 | 'dest/lib.js': ['src/lib/jquery.js', 'src/lib/jquery.mobile.js'],
18 | 'dest/script.js': ['src/js/init.js']
19 | }
20 | },
21 | dev: {
22 | 'dest/script.js': ['src/js/init.js']
23 | }
24 | },
25 | express: {
26 | options: {
27 | script: 'server.js',
28 | port: 3000
29 | },
30 | defaults: {}
31 | }
32 | });
33 |
34 | grunt.loadNpmTasks('grunt-contrib-watch');
35 | grunt.loadNpmTasks('grunt-contrib-uglify');
36 | grunt.loadNpmTasks('grunt-express-server');
37 |
38 | grunt.registerTask('default', ['express', 'watch']);
39 |
40 | };
--------------------------------------------------------------------------------
/03-grunt-contrib-watch/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog Post](http://grunt-tasks.com/grunt-contrib-watch/ "Grunt Watch")
2 |
3 | grunt contrib watch is an amazing plugin that does one simple thing, run a grunt task whenever a file changes.
4 | This post should get you up and running with grunt-watch as fast as possible with some tips on how to leverage its full potential.
5 | So if your development workflow is like this
6 |
7 | > Editor -> Save -> Restart Server -> Refresh browser -> See Changes -> Repeat.
8 |
9 | It will change to just :
10 |
11 | > Save -> Refresh Browser -> See Changes -> Repeat
12 |
13 | Congratulations, you just eliminated one step.
14 | You can eliminate one step even further:
15 |
16 | > Save -> See Changes -> Repeat*
17 |
18 | This might seem like a small change in time, but overtime the difference this minor workflow change will cause is huge.
19 |
20 | ## Step1: Sample Gruntfile.js
21 |
22 | Lets start with a sample Gruntfile.js :-
23 |
24 | ```
25 | module.exports = function(grunt) {
26 | grunt.initConfig({
27 | pkg: grunt.file.readJSON('package.json'),
28 | watch: {
29 | files: ["src/*.js"],
30 | tasks: ["uglify"]
31 | },
32 | uglify: {
33 | target: {
34 | files: {
35 | 'dest/script.js': ['src/jquery.js', 'src/jquery.mobile.js', 'src/init.js']
36 | }
37 | }
38 | }
39 | });
40 |
41 | grunt.loadNpmTasks('grunt-contrib-watch');
42 | grunt.loadNpmTasks('grunt-contrib-uglify');
43 | grunt.registerTask('default', ['watch']);
44 | };
45 | ```
46 | The grunt configuration will run uglify command whenever any file inside changes.
47 | After running grunt from the command line
48 |
49 | ```
50 | $ grunt
51 | Running "watch" task
52 | Waiting...
53 | >> File "README.md" changed.
54 | Running "uglify:target" (uglify) task
55 | >> 1 file created.
56 |
57 | Done, without errors.
58 | Completed in 12.352s at Sat Nov 22 2014 10:39:12 GMT+0530 (India Standard Time) - Waiting...
59 | ```
60 |
61 | ## Step 2: Only watch certain files
62 |
63 | Ideally, we dont want this because it took 12 secs to run the command and it should only be run when the related javascript file changes.
64 |
65 | Just change the files that are being watched:
66 | ```
67 | watch: {
68 | src: {
69 | files: ["src/js/*.js"],
70 | tasks: ["uglify"]
71 | }
72 | }
73 |
74 | // Also the file configuration
75 | files: {
76 | 'dest/script.js': ['src/lib/jquery.js', 'src/lib/jquery.mobile.js', 'src/js/init.js']
77 | }
78 | ```
79 | This will make sure that when js files in src/js/* changes and then run uglify task.
80 |
81 | ```
82 | $ grunt
83 | Running "watch" task
84 | Waiting...
85 | >> File "src\js\init.js" changed.
86 | Running "uglify:target" (uglify) task
87 | >> 1 file created.
88 |
89 | Done, without errors.
90 | Completed in 12.359s at Sat Nov 22 2014 10:53:34 GMT+0530 (India Standard Time) - Waiting...
91 | ```
92 |
93 | You can have multiple watch configurations using the same patterns:
94 |
95 | ### Multiple Configurations
96 |
97 | ```
98 | watch: {
99 | task1: {
100 | files: ["src/js/*.js"],
101 | tasks: ["uglify"]
102 | },
103 | task2: {
104 | files: ["src/js/*.js"],
105 | tasks: ["jshint"]
106 | }
107 | }
108 | ```
109 |
110 | ## Live Refresh and Reload using Watch
111 |
112 | > Eliminate the most repititive tasks by using grunt server and live reload.
113 |
114 | It is critical to the `save->change->observe` cycle as fast as possible. Chances are if you are a developer you will be doing this multiple times in a day. Get started with the following template.
115 |
116 | We are going to be using express 4.0 and a very simple app for demonstration.
117 | The express app will run on port 3000 and live reload on port 35729
118 | You will also need another plugin grunt-express-server
119 |
120 | `npm install grunt-express-server --save-dev`
121 |
122 | And here is the grunt file:
123 | ```
124 | module.exports = function(grunt) {
125 | grunt.initConfig({
126 | pkg: grunt.file.readJSON('package.json'),
127 | watch: {
128 | express: {
129 | files: ["src/js/*.js", "index.html"],
130 | tasks: ["uglify:dev", "express:defaults"],
131 | options: {
132 | livereload: true,
133 | spawn: false
134 | }
135 | }
136 | },
137 | uglify: {
138 | all: {
139 | files: {
140 | 'dest/lib.js': ['src/lib/jquery.js', 'src/lib/jquery.mobile.js'],
141 | 'dest/script.js': ['src/js/init.js']
142 | }
143 | },
144 | dev: {
145 | 'dest/script.js': ['src/js/init.js']
146 | }
147 | },
148 | express: {
149 | options: {
150 | script: 'server.js',
151 | port: 3000
152 | },
153 | defaults: {}
154 | }
155 | });
156 |
157 | grunt.loadNpmTasks('grunt-contrib-watch');
158 | grunt.loadNpmTasks('grunt-contrib-uglify');
159 | grunt.loadNpmTasks('grunt-express-server');
160 |
161 | grunt.registerTask('default', ['express', 'watch']);
162 |
163 | };
164 | ```
165 |
166 | The default task first runs express server and watches the resp. files for changes, once a file changes, uglify:dev task is run and livereload will refresh the page.
167 | So your workflow just went to *Save -> Observe*.
168 |
169 | We will cover more options, how to run parallel tasks etc. in the next blog posts.
--------------------------------------------------------------------------------
/03-grunt-contrib-watch/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Sample Live Reload File
6 |
7 |
8 |
9 |
10 | The following script tag is added,
11 | <script src="//localhost:35729/livereload.js"></script>
12 | It will listen on port 35729 server and refresh the page whenever a the init.js file is changed.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/03-grunt-contrib-watch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "03-grunt-contrib-watch",
3 | "version": "0.0.0",
4 | "description": "Simple way to use grunt watch",
5 | "main": "Gruntfile.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "grunt": "^0.4.5",
13 | "grunt-contrib-watch": "^0.6.1",
14 | "grunt-contrib-uglify": "^0.6.0",
15 | "grunt-express-server": "^0.4.19"
16 | },
17 | "dependencies": {
18 | "express": "^4.10.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/03-grunt-contrib-watch/server.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var path = require("path");
3 | var app = express();
4 |
5 | app.get("/", function (req, res) {
6 | res.sendFile(path.join(__dirname, "index.html"));
7 | });
8 |
9 | app.listen(3000);
10 | console.log("Listening on 3000");
11 |
12 | module.exports = app;
--------------------------------------------------------------------------------
/03-grunt-contrib-watch/src/js/init.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 | console.log(" Jay Kanakiya ");
3 | $("body").on("click", function () {
4 | console.log("Clicked");
5 | });
6 | });
--------------------------------------------------------------------------------
/04-grunt-jscs/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 | "disallowSpacesInNamedFunctionExpression": {
3 | "beforeOpeningRoundBrace": true
4 | },
5 | "disallowSpacesInFunctionExpression": {
6 | "beforeOpeningRoundBrace": true
7 | },
8 | "disallowSpacesInAnonymousFunctionExpression": {
9 | "beforeOpeningRoundBrace": true
10 | },
11 | "disallowSpacesInFunctionDeclaration": {
12 | "beforeOpeningRoundBrace": true
13 | },
14 | "disallowEmptyBlocks": true,
15 | "disallowSpacesInsideArrayBrackets": true,
16 | "disallowSpacesInsideParentheses": true,
17 | "disallowQuotedKeysInObjects": true,
18 | "disallowSpaceAfterObjectKeys": true,
19 | "disallowSpaceAfterPrefixUnaryOperators": true,
20 | "disallowSpaceBeforePostfixUnaryOperators": true,
21 | "disallowSpaceBeforeBinaryOperators": [
22 | ","
23 | ],
24 | "disallowMixedSpacesAndTabs": true,
25 | "disallowTrailingWhitespace": true,
26 | "disallowTrailingComma": true,
27 | "disallowYodaConditions": true,
28 | "disallowKeywords": [ "with" ],
29 | "disallowMultipleLineBreaks": true,
30 | "requireSpaceBeforeBlockStatements": true,
31 | "requireParenthesesAroundIIFE": true,
32 | "requireSpacesInConditionalExpression": true,
33 | "requireMultipleVarDecl": "onevar",
34 | "requireBlocksOnNewline": 1,
35 | "requireCommaBeforeLineBreak": true,
36 | "requireSpaceBeforeBinaryOperators": true,
37 | "requireSpaceAfterBinaryOperators": true,
38 | "requireCamelCaseOrUpperCaseIdentifiers": true,
39 | "requireLineFeedAtFileEnd": true,
40 | "requireCapitalizedConstructors": true,
41 | "requireDotNotation": true,
42 | "requireCurlyBraces": [
43 | "do"
44 | ],
45 | "requireSpaceAfterKeywords": [
46 | "if",
47 | "else",
48 | "for",
49 | "while",
50 | "do",
51 | "switch",
52 | "case",
53 | "return",
54 | "try",
55 | "catch",
56 | "typeof"
57 | ],
58 | "safeContextKeyword": "_this",
59 | "validateLineBreaks": "LF",
60 | "validateQuoteMarks": "'",
61 | "validateIndentation": 2
62 | }
--------------------------------------------------------------------------------
/04-grunt-jscs/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | grunt.initConfig({
3 | jscs: {
4 | src: 'Gruntfile.js',
5 | options: {
6 | config: '.jscsrc'
7 | }
8 | }
9 | });
10 | grunt.loadNpmTasks('grunt-jscs');
11 | grunt.registerTask('default', ['jscs']);
12 | };
13 |
--------------------------------------------------------------------------------
/04-grunt-jscs/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-jscs/ "grunt jscs")
2 |
3 | grunt jscs is grunt plugin for javascript code linting of all the javascript files for coding conventions.
4 | The jscs has got over 60 code validation rules coveringn wide range of options like indentation, maximum line length, maximum function block length, maximum file length, line breaks. curly braces, spaces before functions, array declaration etc.
5 |
6 | For your front-end project, you should have a .jscsrc file which contains javascript style checklist for that project.
7 | This is the ".jscsrc" file for Airbnb style guide
8 | *[Sample jscsrc files](https://github.com/jscs-dev/node-jscs/tree/master/presets)*
9 | ```
10 | {
11 | "disallowSpacesInNamedFunctionExpression": {
12 | "beforeOpeningRoundBrace": true
13 | },
14 | "disallowSpacesInFunctionExpression": {
15 | "beforeOpeningRoundBrace": true
16 | },
17 | "disallowSpacesInAnonymousFunctionExpression": {
18 | "beforeOpeningRoundBrace": true
19 | },
20 | "disallowSpacesInFunctionDeclaration": {
21 | "beforeOpeningRoundBrace": true
22 | },
23 | "disallowEmptyBlocks": true,
24 | "disallowSpacesInsideArrayBrackets": true,
25 | "disallowSpacesInsideParentheses": true,
26 | "disallowQuotedKeysInObjects": true,
27 | "disallowSpaceAfterObjectKeys": true,
28 | "disallowSpaceAfterPrefixUnaryOperators": true,
29 | "disallowSpaceBeforePostfixUnaryOperators": true,
30 | "disallowSpaceBeforeBinaryOperators": [
31 | ","
32 | ],
33 | "disallowMixedSpacesAndTabs": true,
34 | "disallowTrailingWhitespace": true,
35 | "disallowTrailingComma": true,
36 | "disallowYodaConditions": true,
37 | "disallowKeywords": [ "with" ],
38 | "disallowMultipleLineBreaks": true,
39 | "requireSpaceBeforeBlockStatements": true,
40 | "requireParenthesesAroundIIFE": true,
41 | "requireSpacesInConditionalExpression": true,
42 | "requireMultipleVarDecl": "onevar",
43 | "requireBlocksOnNewline": 1,
44 | "requireCommaBeforeLineBreak": true,
45 | "requireSpaceBeforeBinaryOperators": true,
46 | "requireSpaceAfterBinaryOperators": true,
47 | "requireCamelCaseOrUpperCaseIdentifiers": true,
48 | "requireLineFeedAtFileEnd": true,
49 | "requireCapitalizedConstructors": true,
50 | "requireDotNotation": true,
51 | "requireCurlyBraces": [
52 | "do"
53 | ],
54 | "requireSpaceAfterKeywords": [
55 | "if",
56 | "else",
57 | "for",
58 | "while",
59 | "do",
60 | "switch",
61 | "case",
62 | "return",
63 | "try",
64 | "catch",
65 | "typeof"
66 | ],
67 | "safeContextKeyword": "_this",
68 | "validateLineBreaks": "LF",
69 | "validateQuoteMarks": "'",
70 | "validateIndentation": 2
71 | }
72 | ```
73 |
74 | ## Getting Started. (Commit: 37e6a597c)
75 |
76 | Lets start by writing a sample jscs grunt task that should check Gruntfile.js for code covention errors according to the AirBnb javascript style guide. Save it as .jscsrc.
77 | Here's its grunt file:
78 |
79 | ```
80 | module.exports = function(grunt) {
81 | grunt.initConfig({
82 | jscs: {
83 | src: 'Gruntfile.js',
84 | options: {
85 | config: '.jscsrc'
86 | }
87 | }
88 | });
89 |
90 | grunt.loadNpmTasks('grunt-jscs');
91 | grunt.registerTask('default', ['jscs']);
92 | };
93 | ```
94 |
95 | On running grunt from cmd, you should get this error:
96 |
97 | ```
98 | $ grunt
99 | Running "jscs:src" (jscs) task
100 | Invalid line break at Gruntfile.js :
101 | 1 |module.exports = function(grunt) {
102 | ------------------------------------------^
103 | 2 | grunt.initConfig({
104 | 3 | jscs: {
105 | Missing line feed at file end at Gruntfile.js :
106 | 11 | grunt.loadNpmTasks('grunt-jscs');
107 | 12 | grunt.registerTask('default', ['jscs']);
108 | 13 |};
109 | --------^
110 | >> 2 code style errors found!
111 | Warning: Task "jscs:src" failed. Use --force to continue.
112 |
113 | Aborted due to warnings.
114 | ```
115 |
116 | Both of them are related to line endings for windows line ending are "CRLF" for linux its "LF", this can be easily fixed in Sublime (or your text editor) by setting Settings -> Users -> as
117 |
118 | ```
119 | "default_line_ending": "LF",
120 | "default_line_ending": "unix",
121 | ```
122 |
123 | After running grunt you should now be able to successfully run grunt on it.
124 | If you want to check all the rules visit this [link](http://catatron.com/node-jscs/rules/ "jscs rules")
125 |
126 | ## For multiple files
127 |
128 | ```
129 | module.exports = function(grunt) {
130 | grunt.initConfig({
131 | jscs: {
132 | main: "app.js",
133 | controllers: {
134 | src: ['Gruntfile.js', 'src/js/*.js'],
135 | options: {
136 | config: '.jscsrc'
137 | }
138 | }
139 | // You can add more configurations over here
140 | }
141 | });
142 |
143 | grunt.loadNpmTasks('grunt-jscs');
144 | grunt.registerTask('default', ['jscs']);
145 | };
146 | ```
--------------------------------------------------------------------------------
/04-grunt-jscs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "04-grunt-jscs",
3 | "version": "0.0.0",
4 | "description": "A tutorial on how to use grunt jscs",
5 | "keywords": [
6 | "grunt",
7 | "grunt-jscs",
8 | "jscs"
9 | ],
10 | "main": "Gruntfile.js",
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "Jay Kanakiya",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "grunt": "^0.4.5",
18 | "grunt-jscs": "^1.0.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/06-grunt-contrib-copy/.gitignore:
--------------------------------------------------------------------------------
1 | dist/*
--------------------------------------------------------------------------------
/06-grunt-contrib-copy/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | grunt.initConfig({
3 | copy: {
4 | main: {
5 | files: [{
6 | expand: true,
7 | cwd: 'src/',
8 | src: ['**'],
9 | dest: 'dist/'
10 | }]
11 | }
12 | }
13 | });
14 |
15 | grunt.loadNpmTasks('grunt-contrib-copy');
16 | grunt.registerTask('default', ['copy']);
17 | };
--------------------------------------------------------------------------------
/06-grunt-contrib-copy/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-contrib-imagemin/ "grunt imagemin")
2 |
3 | grunt-contrib-copy is an official grunt plugin for advanced files and folders copying/moving for automated front end development.
4 | You can set up a grunt task in your 'build' that will copy certain files and folders to locations that you specify, for example config files, pdf assets.
5 | To install this in your project just run :
6 | `npm install grunt-contrib-copy --save-dev`
7 | This will add it in node_modules and the flag --save-dev will also add it in devDependencies of package.json
8 |
9 | ## Getting started. (1eccb4a)
10 |
11 | First we will create a simple grunt task that just copies all files and folders from src/* and saves them to dist/*.
12 |
13 | Folder and File Structure:
14 |
15 | ```
16 | ├── Gruntfile.js
17 | ├── package.json
18 | ├── README.md
19 | └── src
20 | └── assets
21 | └── copyThis.txt
22 | ```
23 |
24 | Gruntfile.js
25 | ```
26 | module.exports = function(grunt) {
27 | grunt.initConfig({
28 | copy: {
29 | main: {
30 | files: [{
31 | expand: true,
32 | cwd: 'src/',
33 | src: ['**'],
34 | dest: 'dist/'
35 | }]
36 | }
37 | }
38 | });
39 |
40 | grunt.loadNpmTasks('grunt-contrib-copy');
41 | grunt.registerTask('default', ['copy']);
42 | };
43 | ```
44 |
45 | On running grunt from cmd:
46 |
47 | ```
48 | $ grunt
49 | Running "copy:main" (copy) task
50 | Created 2 directories, copied 1 file
51 |
52 | Done, without errors.
53 | ```
54 |
55 | New folder structure
56 |
57 | ```
58 | .
59 | ├── dist
60 | │ └── assets
61 | │ └── copyThis.txt
62 | ├── Gruntfile.js
63 | ├── package.json
64 | ├── README.md
65 | └── src
66 | └── assets
67 | └── copyThis.txt
68 | ```
69 |
70 | ## Files and Folders settings
71 |
72 | You can use different combinations of src and dest for advanced copying configuration.
73 |
74 | * To include files within path
75 | `{expand: true, src: ['path/*'], dest: 'dest/', filter: 'isFile'}`
76 |
77 | * To include files within path and its sub-directories
78 | `{expand: true, src: ['path/**'], dest: 'dest/'}`
79 |
80 | * To make all src relative to cwd
81 | `{expand: true, cwd: 'path/', src: ['**'], dest: 'dest/'}`
82 |
83 | * To flatten results to a single level
84 | `{expand: true, flatten: true, src: ['path/**'], dest: 'dest/', filter: 'isFile'}`
85 |
86 | ## Process while copying
87 |
88 | grunt-contrib-copy also provides a to replace certain placeholders in all your files but correct value.
89 | This can be done via the `options` param
90 | This config will replace PATH to /hello/world wherever it finds it.
91 | ```
92 | copy: {
93 | main: {
94 | src: 'src/a',
95 | dest: 'src/a.bak',
96 | options: {
97 | process: function (content, srcpath) {
98 | return content.replace(/[PATH]/,"/hello/world");
99 | },
100 | },
101 | },
102 | },
103 | ```
104 | You can use this simple functions to do more things not just do regex replace, Eg: inform how many files contain a particular word, do some textual analysis of code.. , replacing html anchor links to point to different paths when in production etc
105 |
--------------------------------------------------------------------------------
/06-grunt-contrib-copy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "06-grunt-contrib-copy",
3 | "version": "0.0.0",
4 | "description": "grunt contrib copy for advanced automated copying of files and folders",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Jay Kanakiya",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "grunt": "^0.4.5",
13 | "grunt-contrib-copy": "^0.7.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/06-grunt-contrib-copy/src/assets/copyThis.txt:
--------------------------------------------------------------------------------
1 | This file should get copied.
--------------------------------------------------------------------------------
/07-grunt-concurrent/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | grunt.initConfig({
3 | pkg: grunt.file.readJSON('package.json'),
4 | uglify: {
5 | main: {
6 | files: [
7 | { src: 'libraries/*.js', dest: 'dist/library.js' }
8 | ]
9 | }
10 | },
11 | copy: {
12 | main: {
13 | files: [{
14 | expand: true,
15 | cwd: 'src/',
16 | src: ['**'],
17 | dest: 'dist/'
18 | }]
19 | }
20 | },
21 | concurrent: {
22 | target1: ['copy', 'uglify']
23 | }
24 | });
25 |
26 | grunt.loadNpmTasks('grunt-contrib-copy');
27 | grunt.loadNpmTasks('grunt-contrib-uglify');
28 | grunt.loadNpmTasks('grunt-concurrent');
29 |
30 | grunt.registerTask('default', ['concurrent:target1']);
31 | };
--------------------------------------------------------------------------------
/07-grunt-concurrent/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-concurrent/ "grunt concurrent")
2 |
3 | grunt-concurrent is an amazing grunt plugin that allows you to run grunt tasks concurrently / in parallel.
4 | This is important because many grunt tasks are slower or take a lot of time which hampers your build process.You dont want your build time to be more than 5 minutes.
5 | Using grunt-concurrent will speed up your build process by running grunt-tasks in parallel using your machines multiple cores, thus saving you critical time.
6 |
7 | To install this in your project, run
8 | `npm install grunt-concurrent --save-dev`
9 | This will add it in node_modules and the flag --save-dev will also add it in devDependencies of package.json
10 |
11 | ## Getting Started
12 |
13 | For your current project, you have two grunt tasks run [copy](http://grunt-tasks.com/grunt-contrib-copy/ "copy" ) and [grunt-uglify](http://grunt-tasks.com/grunt-contrib-uglify/ "grunt uglify") and we want them to run in parallel.
14 | First lets install them:
15 | `npm install grunt-contrib-copy grunt-contrib-uglify --save-dev`
16 |
17 | The below code will make sure that target1 tasks run concurrently, if you have got an 4 core machine, this will mean 4 tasks can be carried out in parallel.
18 | ```
19 | concurrent: {
20 | target1: ['copy', 'uglify']
21 | }
22 | ```
23 |
24 | > The full Gruntfile.js
25 |
26 | ```
27 | module.exports = function(grunt) {
28 | grunt.initConfig({
29 | pkg: grunt.file.readJSON('package.json'),
30 | uglify: {
31 | main: {
32 | files: [
33 | { src: 'libraries/*.js', dest: 'dist/library.js' }
34 | ]
35 | }
36 | },
37 | copy: {
38 | main: {
39 | files: [{
40 | expand: true,
41 | cwd: 'src/',
42 | src: ['**'],
43 | dest: 'dist/'
44 | }]
45 | }
46 | },
47 | concurrent: {
48 | target1: ['copy', 'uglify']
49 | }
50 | });
51 |
52 | grunt.loadNpmTasks('grunt-contrib-copy');
53 | grunt.loadNpmTasks('grunt-contrib-uglify');
54 | grunt.loadNpmTasks('grunt-concurrent');
55 |
56 | grunt.registerTask('default', ['concurrent:target1']);
57 | };
58 | ```
59 | The above code will copy whatever is inside src/ to dist/ while also running uglify-js on the js files in libraries folder and minifying them to dist/library.js
60 |
61 | Folder and File structure
62 |
63 | ```
64 | .
65 | ├── dist
66 | │ ├── jquery.js
67 | │ ├── jquery.mobile.js
68 | │ └── library.js
69 | ├── Gruntfile.js
70 | ├── libraries
71 | │ ├── jquery.js
72 | │ └── jquery.mobile.js
73 | ├── package.json
74 | ├── README.md
75 | ├── server.js
76 | └── src
77 | ├── jquery.js
78 | └── jquery.mobile.js
79 | ```
80 |
81 | ## Other options
82 |
83 | You can specify some options in grunt-concurrent like :-
84 |
85 | - limit > limits the number of grunt tasks carried out simultaneously.[]
86 | - logConcurrentOutput > log the output of your concurrent tasks together. [Default is false]
87 |
--------------------------------------------------------------------------------
/07-grunt-concurrent/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "07-grunt-concurrent",
3 | "version": "0.0.0",
4 | "description": "grunt concurrent to run tasks in parallel",
5 | "main": "Gruntfile.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "grunt"
11 | ],
12 | "author": "Jay Kanakiya",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "grunt-concurrent": "^1.0.0",
16 | "grunt": "^0.4.5",
17 | "grunt-contrib-copy": "^0.7.0",
18 | "grunt-contrib-uglify": "^0.6.0"
19 | },
20 | "dependencies": {}
21 | }
22 |
--------------------------------------------------------------------------------
/07-grunt-concurrent/server.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var path = require("path");
3 | var app = express();
4 |
5 | app.get("/", function (req, res) {
6 | res.sendFile(path.join(__dirname, "index.html"));
7 | });
8 |
9 | app.listen(3000);
10 | console.log("Listening on 3000");
11 |
12 | module.exports = app;
--------------------------------------------------------------------------------
/08-grunt-usemin/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | grunt.initConfig({
3 | copy: {
4 | generated: {
5 | src: 'index.html',
6 | dest: 'dist/index.html'
7 | }
8 | },
9 | filerev: {
10 | options: {
11 | encoding: 'utf8',
12 | algorithm: 'md5',
13 | length: 20
14 | },
15 | source: {
16 | files: [{
17 | src: [
18 | 'dist/js/*.js',
19 | 'dist/css/*.css'
20 | ]
21 | }]
22 | }
23 | },
24 | useminPrepare: {
25 | html: 'index.html',
26 | options: {
27 | dest: 'dist'
28 | }
29 | },
30 | usemin: {
31 | html: 'dist/index.html',
32 | options: {
33 | assetsDirs: ['dist', 'dist/css', 'dist/js', 'css', 'js']
34 | }
35 | }
36 | });
37 |
38 | grunt.loadNpmTasks('grunt-usemin');
39 | grunt.loadNpmTasks('grunt-contrib-copy');
40 | grunt.loadNpmTasks('grunt-contrib-cssmin');
41 | grunt.loadNpmTasks('grunt-contrib-uglify');
42 | grunt.loadNpmTasks('grunt-contrib-concat');
43 | grunt.loadNpmTasks('grunt-filerev');
44 |
45 | grunt.registerTask('default', [
46 | 'copy:generated',
47 | 'useminPrepare',
48 | 'concat',
49 | 'uglify',
50 | 'cssmin',
51 | 'filerev',
52 | 'usemin'
53 | ]);
54 | };
--------------------------------------------------------------------------------
/08-grunt-usemin/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-usemin/ "grunt usemin")
2 |
3 | grunt-usemin is an amazing grunt plugin that allows you to specify the build and concatenation stylesheets and javascript inside html references. This helps you to maintain only one file from where you can define dependencies as well as how to minify them.
4 |
5 | It scans your html files or your template files and optimizes javascript files and stylesheets as specified.
6 |
7 | ## Getting Started
8 |
9 | To install this in your project, run
10 | `npm install grunt-usemin --save-dev`
11 |
12 | This will add it in node_modules and the flag --save-dev will also add it in devDependencies of package.json
13 |
14 | Usemin exports two tasks, viz. usemin and useminPrepare as well as other grunt plugins like [concat](http://grunt-tasks.com/grunt-contrib-copy/), [uglify](http://grunt-tasks.com/grunt-contrib-uglify/), cssmin, filerev
15 |
16 | You will also have to install them manually.
17 | `npm install grunt-contrib-copy grunt-contrib-uglify grunt-contrib-cssmin grunt-filerev --save-dev`
18 |
19 | We will also require [grunt-contrib-copy](http://grunt-tasks.com/grunt-contrib-copy/) for copying the index.html to the
20 |
21 | dist folder which will be for production only.
22 | *useminPrepare* : This task prepares the configuration to transform specific blocks in the scrutinized file into a single line, targeting an optimized version of the files. This is done by generating subtasks called generated for each of the optimization steps handled by the Grunt plugins
23 |
24 | *usemin*: This task replaces the blocks by the file they reference, and replaces all references to assets by their revisioned version if it is found on the disk. This target modifies the files it is working on.
25 |
26 | In short, useminPrepare is where you define the configuration while usemin is where you define the files.
27 | How to specify dependencies inside html:
28 |
29 | ``` html
30 |
31 | ... HTML Markup, list of script / link tags.
32 |
33 | ```
34 |
35 | > The full Gruntfile.js
36 |
37 | js
38 | ```
39 | module.exports = function(grunt) {
40 | grunt.initConfig({
41 | copy: {
42 | generated: {
43 | src: 'index.html',
44 | dest: 'dist/index.html'
45 | }
46 | },
47 | filerev: {
48 | options: {
49 | encoding: 'utf8',
50 | algorithm: 'md5',
51 | length: 20
52 | },
53 | source: {
54 | files: [{
55 | src: [
56 | 'dist/js/*.js',
57 | 'dist/css/*.css'
58 | ]
59 | }]
60 | }
61 | },
62 | useminPrepare: {
63 | html: 'index.html',
64 | options: {
65 | dest: 'dist'
66 | }
67 | },
68 | usemin: {
69 | html: 'dist/index.html',
70 | options: {
71 | assetsDirs: ['dist', 'dist/css', 'dist/js', 'css', 'js']
72 | }
73 | }
74 | });
75 |
76 | grunt.loadNpmTasks('grunt-usemin');
77 | grunt.loadNpmTasks('grunt-contrib-copy');
78 | grunt.loadNpmTasks('grunt-contrib-cssmin');
79 | grunt.loadNpmTasks('grunt-contrib-uglify');
80 | grunt.loadNpmTasks('grunt-contrib-concat');
81 | grunt.loadNpmTasks('grunt-filerev');
82 |
83 | grunt.registerTask('default', [
84 | 'copy:generated',
85 | 'useminPrepare',
86 | 'concat',
87 | 'uglify',
88 | 'cssmin',
89 | 'filerev',
90 | 'usemin'
91 | ]);
92 | };
93 | ```
94 |
95 | Folder and File structure
96 |
97 | ```
98 | .
99 | ├── css
100 | │ ├── bootstrap.css
101 | │ ├── codemirror.css
102 | │ └── jquery.sidr.light.css
103 | ├── dist <- folder where all new files are generated
104 | │ ├── css
105 | │ │ └── styles.7dea81d829f10a1fc486.css <- filerev
106 | │ ├── index.html
107 | │ └── js
108 | │ └── script.459446c51efa85dbade2.js <- filerev
109 | ├── Gruntfile.js
110 | ├── index.html
111 | ├── js
112 | │ ├── angular.min.js
113 | │ ├── bootstrap.min.js
114 | │ ├── jquery.js
115 | │ └── jquery.superscrollorama.js
116 | ├── package.json
117 | └── README.md
118 | ```
119 |
120 | Grunt usemin first copies index.html to dist/, concat then copies as well as concatenates all css and js files to
121 | dist/js and dist/css. Uglify and cssmin then minifies the javascript and css files.
122 | Filerev runs then runs the concatenated files through a file content has and gives a revision to each file.
123 | usemin is the final task that changes index.html to point to the rev version.
124 |
125 | Therefore you can grunt-usemin for your build process easily.
126 | Using the same above configuration you can add more html files and folders and make a complex build process easier to manage, change and use.
127 |
128 | Futher: [How to use grunt-usemin with grunt-remove-logging](http://grunt-tasks.com/grunt-remove-logging/)
129 |
130 | Above post will explain how you can still keep those pesky yet required console.log statements in your development folder and remove them in your production files.
131 |
132 | Further 2: [How to use grunt-usmin with grunt-htmlmin](http://grunt-tasks.com/grunt-htmlmin/)
133 |
134 | Above post explains the steps to minify html, css and js files using the above plugins.
135 |
136 | Further 3: [Usage with time-grunt](http://grunt-tasks.com/time-grunt/)
137 |
138 | Further 4: [Usage with grunt-image-embed](http://grunt-tasks.com/grunt-image-embed/)
139 |
140 | Above post will explain how to replace your small image assets referenced in your css files by data-uris.
--------------------------------------------------------------------------------
/08-grunt-usemin/css/codemirror.css:
--------------------------------------------------------------------------------
1 | /* BASICS */
2 |
3 | .CodeMirror {
4 | /* Set height, width, borders, and global font properties here */
5 | font-family: monospace;
6 | height: 100%;
7 | }
8 | .CodeMirror-scroll {
9 | /* Set scrolling behaviour here */
10 | overflow: auto;
11 | }
12 |
13 | /* PADDING */
14 |
15 | .CodeMirror-lines {
16 | padding: 4px 0; /* Vertical padding around content */
17 | }
18 | .CodeMirror pre {
19 | padding: 0 4px; /* Horizontal padding of content */
20 | }
21 |
22 | .CodeMirror-scrollbar-filler {
23 | background-color: white; /* The little square between H and V scrollbars */
24 | }
25 |
26 | /* GUTTER */
27 |
28 | .CodeMirror-gutters {
29 | border-right: 1px solid #ddd;
30 | background-color: #f7f7f7;
31 | }
32 | .CodeMirror-linenumbers {}
33 | .CodeMirror-linenumber {
34 | padding: 0 3px 0 5px;
35 | min-width: 20px;
36 | text-align: right;
37 | color: #999;
38 | }
39 |
40 | /* CURSOR */
41 |
42 | .CodeMirror pre.CodeMirror-cursor {
43 | border-left: 1px solid black;
44 | }
45 | /* Shown when moving in bi-directional text */
46 | .CodeMirror pre.CodeMirror-secondarycursor {
47 | border-left: 1px solid silver;
48 | }
49 | .cm-keymap-fat-cursor pre.CodeMirror-cursor {
50 | width: auto;
51 | border: 0;
52 | background: transparent;
53 | background: rgba(0, 200, 0, .4);
54 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
55 | }
56 | /* Kludge to turn off filter in ie9+, which also accepts rgba */
57 | .cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
58 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
59 | }
60 | /* Can style cursor different in overwrite (non-insert) mode */
61 | .CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
62 |
63 | /* DEFAULT THEME */
64 |
65 | .cm-s-default .cm-keyword {color: #708;}
66 | .cm-s-default .cm-atom {color: #219;}
67 | .cm-s-default .cm-number {color: #164;}
68 | .cm-s-default .cm-def {color: #00f;}
69 | .cm-s-default .cm-variable {color: black;}
70 | .cm-s-default .cm-variable-2 {color: #05a;}
71 | .cm-s-default .cm-variable-3 {color: #085;}
72 | .cm-s-default .cm-property {color: black;}
73 | .cm-s-default .cm-operator {color: black;}
74 | .cm-s-default .cm-comment {color: #a50;}
75 | .cm-s-default .cm-string {color: #a11;}
76 | .cm-s-default .cm-string-2 {color: #f50;}
77 | .cm-s-default .cm-meta {color: #555;}
78 | .cm-s-default .cm-error {color: #f00;}
79 | .cm-s-default .cm-qualifier {color: #555;}
80 | .cm-s-default .cm-builtin {color: #30a;}
81 | .cm-s-default .cm-bracket {color: #997;}
82 | .cm-s-default .cm-tag {color: #170;}
83 | .cm-s-default .cm-attribute {color: #00c;}
84 | .cm-s-default .cm-header {color: blue;}
85 | .cm-s-default .cm-quote {color: #090;}
86 | .cm-s-default .cm-hr {color: #999;}
87 | .cm-s-default .cm-link {color: #00c;}
88 |
89 | .cm-negative {color: #d44;}
90 | .cm-positive {color: #292;}
91 | .cm-header, .cm-strong {font-weight: bold;}
92 | .cm-em {font-style: italic;}
93 | .cm-emstrong {font-style: italic; font-weight: bold;}
94 | .cm-link {text-decoration: underline;}
95 |
96 | .cm-invalidchar {color: #f00;}
97 |
98 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
99 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
100 |
101 | /* STOP */
102 |
103 | /* The rest of this file contains styles related to the mechanics of
104 | the editor. You probably shouldn't touch them. */
105 |
106 | .CodeMirror {
107 | line-height: 1;
108 | position: relative;
109 | overflow: hidden;
110 | }
111 |
112 | .CodeMirror-scroll {
113 | /* 30px is the magic margin used to hide the element's real scrollbars */
114 | /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
115 | margin-bottom: -30px; margin-right: -30px;
116 | padding-bottom: 30px; padding-right: 30px;
117 | height: 100%;
118 | outline: none; /* Prevent dragging from highlighting the element */
119 | position: relative;
120 | }
121 | .CodeMirror-sizer {
122 | position: relative;
123 | }
124 |
125 | /* The fake, visible scrollbars. Used to force redraw during scrolling
126 | before actuall scrolling happens, thus preventing shaking and
127 | flickering artifacts. */
128 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
129 | position: absolute;
130 | z-index: 6;
131 | display: none;
132 | }
133 | .CodeMirror-vscrollbar {
134 | right: 0; top: 0;
135 | overflow-x: hidden;
136 | overflow-y: scroll;
137 | }
138 | .CodeMirror-hscrollbar {
139 | bottom: 0; left: 0;
140 | overflow-y: hidden;
141 | overflow-x: scroll;
142 | }
143 | .CodeMirror-scrollbar-filler {
144 | right: 0; bottom: 0;
145 | z-index: 6;
146 | }
147 |
148 | .CodeMirror-gutters {
149 | position: absolute; left: 0; top: 0;
150 | height: 100%;
151 | z-index: 3;
152 | }
153 | .CodeMirror-gutter {
154 | height: 100%;
155 | display: inline-block;
156 | /* Hack to make IE7 behave */
157 | *zoom:1;
158 | *display:inline;
159 | }
160 | .CodeMirror-gutter-elt {
161 | position: absolute;
162 | cursor: default;
163 | z-index: 4;
164 | }
165 |
166 | .CodeMirror-lines {
167 | cursor: text;
168 | }
169 | .CodeMirror pre {
170 | /* Reset some styles that the rest of the page might have set */
171 | -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
172 | border-width: 0;
173 | background: transparent;
174 | font-family: inherit;
175 | font-size: inherit;
176 | margin: 0;
177 | white-space: pre;
178 | word-wrap: normal;
179 | line-height: inherit;
180 | color: inherit;
181 | z-index: 2;
182 | position: relative;
183 | overflow: visible;
184 | }
185 | .CodeMirror-wrap pre {
186 | word-wrap: break-word;
187 | white-space: pre-wrap;
188 | word-break: normal;
189 | }
190 | .CodeMirror-linebackground {
191 | position: absolute;
192 | left: 0; right: 0; top: 0; bottom: 0;
193 | z-index: 0;
194 | }
195 |
196 | .CodeMirror-linewidget {
197 | position: relative;
198 | z-index: 2;
199 | }
200 |
201 | .CodeMirror-wrap .CodeMirror-scroll {
202 | overflow-x: hidden;
203 | }
204 |
205 | .CodeMirror-measure {
206 | position: absolute;
207 | width: 100%; height: 0px;
208 | overflow: hidden;
209 | visibility: hidden;
210 | }
211 | .CodeMirror-measure pre { position: static; }
212 |
213 | .CodeMirror pre.CodeMirror-cursor {
214 | position: absolute;
215 | visibility: hidden;
216 | border-right: none;
217 | width: 0;
218 | }
219 | .CodeMirror-focused pre.CodeMirror-cursor {
220 | visibility: visible;
221 | }
222 |
223 | .CodeMirror-selected { background: #d9d9d9; }
224 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
225 |
226 | .CodeMirror-searching {
227 | background: #ffa;
228 | background: rgba(255, 255, 0, .4);
229 | }
230 |
231 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */
232 | .CodeMirror span { *vertical-align: text-bottom; }
233 |
234 | @media print {
235 | /* Hide the cursor when printing */
236 | .CodeMirror pre.CodeMirror-cursor {
237 | visibility: hidden;
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/08-grunt-usemin/css/jquery.sidr.light.css:
--------------------------------------------------------------------------------
1 | /* line 3, ../../src/scss/sidr/_base.scss */
2 | .sidr {
3 | /* Default Settings */
4 | display: none;
5 | position: absolute;
6 | position: fixed;
7 | top: 0;
8 | height: 100%;
9 | z-index: 999999;
10 | width: 260px;
11 | overflow-x: none;
12 | overflow-y: auto;
13 | /* Theme Settings */
14 | font-family: "lucida grande", tahoma, verdana, arial, sans-serif;
15 | font-size: 15px;
16 | background: #f8f8f8;
17 | color: #333333;
18 | -webkit-box-shadow: inset 0 0 5px 5px #ebebeb;
19 | -moz-box-shadow: inset 0 0 5px 5px #ebebeb;
20 | box-shadow: inset 0 0 5px 5px #ebebeb;
21 | }
22 | /* line 15, ../../src/scss/sidr/_base.scss */
23 | .sidr .sidr-inner {
24 | padding: 0 0 15px;
25 | }
26 | /* line 18, ../../src/scss/sidr/_base.scss */
27 | .sidr .sidr-inner > p {
28 | margin-left: 15px;
29 | margin-right: 15px;
30 | }
31 | /* line 24, ../../src/scss/sidr/_base.scss */
32 | .sidr.right {
33 | left: auto;
34 | right: -260px;
35 | }
36 | /* line 29, ../../src/scss/sidr/_base.scss */
37 | .sidr.left {
38 | left: -260px;
39 | right: auto;
40 | }
41 | /* line 41, ../../src/scss/sidr/_base.scss */
42 | .sidr h1, .sidr h2, .sidr h3, .sidr h4, .sidr h5, .sidr h6 {
43 | font-size: 11px;
44 | font-weight: normal;
45 | padding: 0 15px;
46 | margin: 0 0 5px;
47 | color: #333333;
48 | line-height: 24px;
49 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #dfdfdf));
50 | background-image: -webkit-linear-gradient(#ffffff, #dfdfdf);
51 | background-image: -moz-linear-gradient(#ffffff, #dfdfdf);
52 | background-image: -o-linear-gradient(#ffffff, #dfdfdf);
53 | background-image: linear-gradient(#ffffff, #dfdfdf);
54 | -webkit-box-shadow: 0 5px 5px 3px rgba(0, 0, 0, 0.2);
55 | -moz-box-shadow: 0 5px 5px 3px rgba(0, 0, 0, 0.2);
56 | box-shadow: 0 5px 5px 3px rgba(0, 0, 0, 0.2);
57 | }
58 | /* line 52, ../../src/scss/sidr/_base.scss */
59 | .sidr p {
60 | font-size: 13px;
61 | margin: 0 0 12px;
62 | }
63 | /* line 55, ../../src/scss/sidr/_base.scss */
64 | .sidr p a {
65 | color: rgba(51, 51, 51, 0.9);
66 | }
67 | /* line 60, ../../src/scss/sidr/_base.scss */
68 | .sidr > p {
69 | margin-left: 15px;
70 | margin-right: 15px;
71 | }
72 | /* line 65, ../../src/scss/sidr/_base.scss */
73 | .sidr ul {
74 | display: block;
75 | margin: 0 0 15px;
76 | padding: 0;
77 | border-top: 1px solid #dfdfdf;
78 | border-bottom: 1px solid white;
79 | }
80 | /* line 72, ../../src/scss/sidr/_base.scss */
81 | .sidr ul li {
82 | display: block;
83 | margin: 0;
84 | line-height: 48px;
85 | border-top: 1px solid white;
86 | border-bottom: 1px solid #dfdfdf;
87 | }
88 | /* line 81, ../../src/scss/sidr/_base.scss */
89 | .sidr ul li:hover, .sidr ul li.active, .sidr ul li.sidr-class-active {
90 | border-top: none;
91 | line-height: 49px;
92 | }
93 | /* line 85, ../../src/scss/sidr/_base.scss */
94 | .sidr ul li:hover > a, .sidr ul li:hover > span, .sidr ul li.active > a, .sidr ul li.active > span, .sidr ul li.sidr-class-active > a, .sidr ul li.sidr-class-active > span {
95 | -webkit-box-shadow: inset 0 0 15px 3px #ebebeb;
96 | -moz-box-shadow: inset 0 0 15px 3px #ebebeb;
97 | box-shadow: inset 0 0 15px 3px #ebebeb;
98 | }
99 | /* line 90, ../../src/scss/sidr/_base.scss */
100 | .sidr ul li a, .sidr ul li span {
101 | padding: 0 15px;
102 | display: block;
103 | text-decoration: none;
104 | color: #333333;
105 | }
106 | /* line 97, ../../src/scss/sidr/_base.scss */
107 | .sidr ul li ul {
108 | border-bottom: none;
109 | margin: 0;
110 | }
111 | /* line 100, ../../src/scss/sidr/_base.scss */
112 | .sidr ul li ul li {
113 | line-height: 40px;
114 | font-size: 13px;
115 | }
116 | /* line 104, ../../src/scss/sidr/_base.scss */
117 | .sidr ul li ul li:last-child {
118 | border-bottom: none;
119 | }
120 | /* line 110, ../../src/scss/sidr/_base.scss */
121 | .sidr ul li ul li:hover, .sidr ul li ul li.active, .sidr ul li ul li.sidr-class-active {
122 | border-top: none;
123 | line-height: 41px;
124 | }
125 | /* line 114, ../../src/scss/sidr/_base.scss */
126 | .sidr ul li ul li:hover > a, .sidr ul li ul li:hover > span, .sidr ul li ul li.active > a, .sidr ul li ul li.active > span, .sidr ul li ul li.sidr-class-active > a, .sidr ul li ul li.sidr-class-active > span {
127 | -webkit-box-shadow: inset 0 0 15px 3px #ebebeb;
128 | -moz-box-shadow: inset 0 0 15px 3px #ebebeb;
129 | box-shadow: inset 0 0 15px 3px #ebebeb;
130 | }
131 | /* line 119, ../../src/scss/sidr/_base.scss */
132 | .sidr ul li ul li a, .sidr ul li ul li span {
133 | color: rgba(51, 51, 51, 0.8);
134 | padding-left: 30px;
135 | }
136 | /* line 128, ../../src/scss/sidr/_base.scss */
137 | .sidr form {
138 | margin: 0 15px;
139 | }
140 | /* line 132, ../../src/scss/sidr/_base.scss */
141 | .sidr label {
142 | font-size: 13px;
143 | }
144 | /* line 146, ../../src/scss/sidr/_base.scss */
145 | .sidr input[type="text"],
146 | .sidr input[type="password"],
147 | .sidr input[type="date"],
148 | .sidr input[type="datetime"],
149 | .sidr input[type="email"],
150 | .sidr input[type="number"],
151 | .sidr input[type="search"],
152 | .sidr input[type="tel"],
153 | .sidr input[type="time"],
154 | .sidr input[type="url"],
155 | .sidr textarea, .sidr select {
156 | width: 100%;
157 | font-size: 13px;
158 | padding: 5px;
159 | -webkit-box-sizing: border-box;
160 | -moz-box-sizing: border-box;
161 | box-sizing: border-box;
162 | margin: 0 0 10px;
163 | -webkit-border-radius: 2px;
164 | -moz-border-radius: 2px;
165 | -ms-border-radius: 2px;
166 | -o-border-radius: 2px;
167 | border-radius: 2px;
168 | border: none;
169 | background: rgba(0, 0, 0, 0.1);
170 | color: rgba(51, 51, 51, 0.6);
171 | display: block;
172 | clear: both;
173 | }
174 | /* line 160, ../../src/scss/sidr/_base.scss */
175 | .sidr input[type=checkbox] {
176 | width: auto;
177 | display: inline;
178 | clear: none;
179 | }
180 | /* line 167, ../../src/scss/sidr/_base.scss */
181 | .sidr input[type=button],
182 | .sidr input[type=submit] {
183 | color: #f8f8f8;
184 | background: #333333;
185 | }
186 | /* line 171, ../../src/scss/sidr/_base.scss */
187 | .sidr input[type=button]:hover,
188 | .sidr input[type=submit]:hover {
189 | background: rgba(51, 51, 51, 0.9);
190 | }
191 |
--------------------------------------------------------------------------------
/08-grunt-usemin/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Grunt Usemin Example
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/08-grunt-usemin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Grunt Usemin Example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/08-grunt-usemin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "08-grunt-usemin",
3 | "version": "0.0.0",
4 | "description": "grunt usemin for optimizing your stylesheets and javascripts",
5 | "main": "Gruntfile.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "grunt": "^0.4.5",
13 | "grunt-usemin": "^3.0.0",
14 | "grunt-filerev": "^2.1.2",
15 | "grunt-contrib-concat": "^0.5.0",
16 | "grunt-contrib-uglify": "^0.7.0",
17 | "grunt-contrib-cssmin": "^0.11.0",
18 | "grunt-contrib-copy": "^0.7.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/09-grunt-newer/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | grunt.initConfig({
4 | uglify: {
5 | all: {
6 | files: {
7 | 'dist/js/minified.js': ['src/**/*.js']
8 | }
9 | }
10 | }
11 | });
12 |
13 | grunt.loadNpmTasks('grunt-contrib-uglify');
14 | grunt.loadNpmTasks('grunt-newer');
15 |
16 | grunt.registerTask('default', ['uglify:all']);
17 | grunt.registerTask('nw', ['newer:uglify:all']);
18 |
19 | };
--------------------------------------------------------------------------------
/09-grunt-newer/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-newer/ "grunt newer")
2 |
3 | grunt-newer is an simple yet extremely useful grunt plugin that allows you to configure specific tasks to run only when the the file has changed. If you have a long build process or one that takes a lot of time, you can use this to cut down that time, by only running certain tasks when its related files has changed.
4 |
5 | For example, you can use this for uglify which sometimes take a good deal of them. By correctly configuring both the tasks you can only run 'uglify' when its source files have changed.
6 |
7 | ## Getting Started
8 |
9 | The best way to integrate grunt-newer in your build process is to add newer as the first argument when running other tasks. For example `jscs:all` will become `newer:jscs:all`
10 | Lets create a simple Grunt file that will uglify js src files into minified files.
11 |
12 | Heres the folder file structure:
13 | ```
14 | .
15 | ├── dist
16 | │ └── js
17 | │ └── minified.js
18 | ├── Gruntfile.js
19 | ├── package.json
20 | ├── README.md
21 | └── src
22 | └── js
23 | ├── app.js
24 | ├── jquery.js
25 | └── jquery.superscrollorama.js
26 | ```
27 | Heres the Gruntfile.js:
28 | ```
29 | module.exports = function(grunt) {
30 |
31 | grunt.initConfig({
32 | uglify: {
33 | all: {
34 | files: {
35 | 'dist/js/minified.js': ['src/**/*.js']
36 | }
37 | }
38 | }
39 | });
40 |
41 | grunt.loadNpmTasks('grunt-contrib-uglify');
42 | grunt.loadNpmTasks('grunt-newer');
43 |
44 | grunt.registerTask('default', ['uglify:all']);
45 | grunt.registerTask('nw', ['newer:uglify:all']);
46 |
47 | };
48 | ```
49 |
50 | The default task runs uglify while the nw task will only run uglify if either of the three files have changed.
51 | On running `grunt nw` first time:
52 |
53 | ```
54 | $ grunt nw
55 | Running "newer:uglify:all" (newer) task
56 |
57 | Running "uglify:all" (uglify) task
58 | >> 1 file created.
59 |
60 | Running "newer-postrun:uglify:all:1:H:\grunt-tasks.com\github\09-grunt-newer\node_modules\grunt-newer\.cache" (newer-postrun) task
61 |
62 | Done, without errors.
63 | ```
64 |
65 | On running `grunt nw` second time
66 | ```
67 | $ grunt nw
68 | Running "newer:uglify:all" (newer) task
69 | No newer files to process.
70 |
71 | Done, without errors.
72 | ```
73 |
74 | If you see the outputs of the commands, grunt-newer does not uglify task once again.
75 | It does all this by keeping track of the last modified time of each file and keeping them in .cache
76 | Then during runtime if theres a diff in any files last modified time, run the task, and update in .cache
77 |
78 |
--------------------------------------------------------------------------------
/09-grunt-newer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "09-grunt-newer",
3 | "version": "0.0.1",
4 | "description": "Run grunt tasks on new files",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "grunt-contrib-uglify": "^0.7.0",
17 | "grunt": "^0.4.5",
18 | "grunt-newer": "^1.1.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/09-grunt-newer/src/js/app.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 | console.log('Hello World');
3 | });
4 |
--------------------------------------------------------------------------------
/10-grunt-bump/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | grunt.initConfig({
4 | bump: {
5 | options: {
6 | files: ['package.json'],
7 | commitFiles: ['package.json', 'Gruntfile.js', 'README.md'],
8 | commitMessage: 'Release v%VERSION%',
9 | createTag: true,
10 | tagName: 'v%VERSION%',
11 | tagMessage: 'The Release %VERSION%'
12 | }
13 | }
14 | });
15 |
16 | grunt.loadNpmTasks('grunt-bump');
17 |
18 | grunt.registerTask('bm', ['bump']);
19 | };
--------------------------------------------------------------------------------
/10-grunt-bump/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-bump/ "grunt bump")
2 |
3 | grunt-newer is an simple utility grunt plugin for automatic updation of package versions. grunt-bump allows you to update your versions in your file and additionally do a git-commit with pre-defined tagnames, descriptions
4 |
5 | ## [Semantic Versioning](http://semver.org/) in short
6 |
7 | Given a version number MAJOR.MINOR.PATCH, increment the:
8 |
9 | MAJOR version when you make incompatible API changes,
10 | MINOR version when you add functionality in a backwards-compatible manner, and
11 | PATCH version when you make backwards-compatible bug fixes.
12 | Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
13 |
14 | ## Getting Started
15 |
16 | Install grunt-bump by
17 | `npm install grunt-bump --save-dev`
18 | Lets create a simple gruntfile that will just update the version param of package.json
19 |
20 | ```
21 | module.exports = function(grunt) {
22 |
23 | grunt.initConfig({
24 | bump: {
25 | options: {
26 | files: ['package.json'],
27 | commit: false,
28 | createTag: false,
29 | push: false,
30 | }
31 | }
32 | });
33 |
34 | grunt.loadNpmTasks('grunt-bump');
35 |
36 | grunt.registerTask('bm', ['bump']);
37 | };
38 | ```
39 | On running grunt the version will be updated to 0.0.2
40 |
41 | ```
42 | $ grunt bm
43 | Running "bump" task
44 | >> Version bumped to 0.0.2 (in package.json)
45 |
46 | Done, without errors.
47 | ```
48 |
49 | The `files` parameter in options object takes in an array of files where you want to update the versions.
50 | For example, component.json, bower.json or any application specific versioning files.
51 |
52 | ## Git and grunt-bump
53 |
54 |
--------------------------------------------------------------------------------
/10-grunt-bump/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "10-grunt-bump",
3 | "version": "0.0.7",
4 | "description": "Automatic incrementation of plugin versions",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "keywords": "grunt, grunt-bump",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "grunt": "^0.4.5",
18 | "grunt-bump": "^0.1.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/11-load-grunt-tasks/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | require('load-grunt-tasks')(grunt);
3 | grunt.initConfig({
4 | copy: {
5 | generated: {
6 | src: 'index.html',
7 | dest: 'dist/index.html'
8 | }
9 | },
10 | filerev: {
11 | options: {
12 | encoding: 'utf8',
13 | algorithm: 'md5',
14 | length: 20
15 | },
16 | source: {
17 | files: [{
18 | src: [
19 | 'dist/js/*.js',
20 | 'dist/css/*.css'
21 | ]
22 | }]
23 | }
24 | },
25 | useminPrepare: {
26 | html: 'index.html',
27 | options: {
28 | dest: 'dist'
29 | }
30 | },
31 | usemin: {
32 | html: 'dist/index.html',
33 | options: {
34 | assetsDirs: ['dist', 'dist/css', 'dist/js', 'css', 'js']
35 | }
36 | }
37 | });
38 |
39 | grunt.registerTask('default', [
40 | 'copy:generated',
41 | 'useminPrepare',
42 | 'concat',
43 | 'uglify',
44 | 'cssmin',
45 | 'filerev',
46 | 'usemin'
47 | ]);
48 | };
--------------------------------------------------------------------------------
/11-load-grunt-tasks/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/load-grunt-tasks/ "load grunt tasks")
2 |
3 | load-grunt-tasks is a grunt plugin to quickly install all the required packages just using 1 line instead of loading one by one. Lets say that you have a around 10 to 12 dependencies for grunt, as the project goes older and older, manually taking care of which grunt dependency to add, and which grunt dependency to remove becomes cumbersome.
4 | So instead, use package.json as your main configuration file, from which only load the grunt-dependencies defined inside it.
5 |
6 | "load-grunt-tasks" automatically reads the "devDependencies" of package.json and loads them in your Gruntfile.js just using the following line;
7 | `require('load-grunt-tasks')(grunt);`
8 |
9 | To install:
10 | ` npm install --save-dev load-grunt-tasks`
11 |
12 | In your Gruntfile.js replace all this lines:
13 |
14 | ```
15 | grunt.loadNpmTasks('')
16 | grunt.loadNpmTasks('')
17 | grunt.loadNpmTasks('')
18 | grunt.loadNpmTasks('')
19 | ```
20 |
21 | by this single line
22 | `require('load-grunt-tasks')(grunt);`
23 |
24 | ## How to use load-grunt-tasks
25 |
26 | Lets consider a simple project with one html files and its css and js dependencies.
27 | You want to write a simple Gruntfile.js which can automatically that html's file dependencies and concatenates, minifies revisions and copies them to the dist folder.
28 |
29 | Heres that Gruntfile
30 | ```
31 | module.exports = function(grunt) {
32 | grunt.initConfig({
33 | copy: {
34 | generated: {
35 | src: 'index.html',
36 | dest: 'dist/index.html'
37 | }
38 | },
39 | filerev: {
40 | options: {
41 | encoding: 'utf8',
42 | algorithm: 'md5',
43 | length: 20
44 | },
45 | source: {
46 | files: [{
47 | src: [
48 | 'dist/js/*.js',
49 | 'dist/css/*.css'
50 | ]
51 | }]
52 | }
53 | },
54 | useminPrepare: {
55 | html: 'index.html',
56 | options: {
57 | dest: 'dist'
58 | }
59 | },
60 | usemin: {
61 | html: 'dist/index.html',
62 | options: {
63 | assetsDirs: ['dist', 'dist/css', 'dist/js', 'css', 'js']
64 | }
65 | }
66 | });
67 |
68 | grunt.loadNpmTasks('grunt-usemin');
69 | grunt.loadNpmTasks('grunt-contrib-copy');
70 | grunt.loadNpmTasks('grunt-contrib-cssmin');
71 | grunt.loadNpmTasks('grunt-contrib-uglify');
72 | grunt.loadNpmTasks('grunt-contrib-concat');
73 | grunt.loadNpmTasks('grunt-filerev');
74 |
75 | grunt.registerTask('default', [
76 | 'copy:generated',
77 | 'useminPrepare',
78 | 'concat',
79 | 'uglify',
80 | 'cssmin',
81 | 'filerev',
82 | 'usemin'
83 | ]);
84 | };
85 | ```
86 |
87 | Observe lines #38 to #43, doesn't it seem it violates DRY, this is where load-grunt-tasks comes into play.
88 | This is the new Gruntfile.js:
89 |
90 | ```
91 | module.exports = function(grunt) {
92 | require('load-grunt-tasks')(grunt);
93 | grunt.initConfig({
94 | copy: {
95 | generated: {
96 | src: 'index.html',
97 | dest: 'dist/index.html'
98 | }
99 | },
100 | filerev: {
101 | options: {
102 | encoding: 'utf8',
103 | algorithm: 'md5',
104 | length: 20
105 | },
106 | source: {
107 | files: [{
108 | src: [
109 | 'dist/js/*.js',
110 | 'dist/css/*.css'
111 | ]
112 | }]
113 | }
114 | },
115 | useminPrepare: {
116 | html: 'index.html',
117 | options: {
118 | dest: 'dist'
119 | }
120 | },
121 | usemin: {
122 | html: 'dist/index.html',
123 | options: {
124 | assetsDirs: ['dist', 'dist/css', 'dist/js', 'css', 'js']
125 | }
126 | }
127 | });
128 |
129 | grunt.registerTask('default', [
130 | 'copy:generated',
131 | 'useminPrepare',
132 | 'concat',
133 | 'uglify',
134 | 'cssmin',
135 | 'filerev',
136 | 'usemin'
137 | ]);
138 | };
139 | ```
140 |
141 | It produces the same output as before
142 | ```
143 | $ grunt
144 | Running "copy:generated" (copy) task
145 | Copied 1 file
146 |
147 | Running "useminPrepare:html" (useminPrepare) task
148 | Configuration changed for concat, uglify, cssmin
149 |
150 | Running "concat:generated" (concat) task
151 | File .tmp\concat\css\styles.css created.
152 | File .tmp\concat\js\script.js created.
153 |
154 | Running "uglify:generated" (uglify) task
155 | >> 1 file created.
156 |
157 | Running "cssmin:generated" (cssmin) task
158 |
159 | Running "filerev:source" (filerev) task
160 | Revved 6 files
161 |
162 | Running "usemin:html" (usemin) task
163 | Replaced 1 reference to assets
164 |
165 | Done, without errors.
166 | ```
167 |
168 | If you have any comments, feel free to drop it below.
--------------------------------------------------------------------------------
/11-load-grunt-tasks/css/codemirror.css:
--------------------------------------------------------------------------------
1 | /* BASICS */
2 |
3 | .CodeMirror {
4 | /* Set height, width, borders, and global font properties here */
5 | font-family: monospace;
6 | height: 100%;
7 | }
8 | .CodeMirror-scroll {
9 | /* Set scrolling behaviour here */
10 | overflow: auto;
11 | }
12 |
13 | /* PADDING */
14 |
15 | .CodeMirror-lines {
16 | padding: 4px 0; /* Vertical padding around content */
17 | }
18 | .CodeMirror pre {
19 | padding: 0 4px; /* Horizontal padding of content */
20 | }
21 |
22 | .CodeMirror-scrollbar-filler {
23 | background-color: white; /* The little square between H and V scrollbars */
24 | }
25 |
26 | /* GUTTER */
27 |
28 | .CodeMirror-gutters {
29 | border-right: 1px solid #ddd;
30 | background-color: #f7f7f7;
31 | }
32 | .CodeMirror-linenumbers {}
33 | .CodeMirror-linenumber {
34 | padding: 0 3px 0 5px;
35 | min-width: 20px;
36 | text-align: right;
37 | color: #999;
38 | }
39 |
40 | /* CURSOR */
41 |
42 | .CodeMirror pre.CodeMirror-cursor {
43 | border-left: 1px solid black;
44 | }
45 | /* Shown when moving in bi-directional text */
46 | .CodeMirror pre.CodeMirror-secondarycursor {
47 | border-left: 1px solid silver;
48 | }
49 | .cm-keymap-fat-cursor pre.CodeMirror-cursor {
50 | width: auto;
51 | border: 0;
52 | background: transparent;
53 | background: rgba(0, 200, 0, .4);
54 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
55 | }
56 | /* Kludge to turn off filter in ie9+, which also accepts rgba */
57 | .cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
58 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
59 | }
60 | /* Can style cursor different in overwrite (non-insert) mode */
61 | .CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
62 |
63 | /* DEFAULT THEME */
64 |
65 | .cm-s-default .cm-keyword {color: #708;}
66 | .cm-s-default .cm-atom {color: #219;}
67 | .cm-s-default .cm-number {color: #164;}
68 | .cm-s-default .cm-def {color: #00f;}
69 | .cm-s-default .cm-variable {color: black;}
70 | .cm-s-default .cm-variable-2 {color: #05a;}
71 | .cm-s-default .cm-variable-3 {color: #085;}
72 | .cm-s-default .cm-property {color: black;}
73 | .cm-s-default .cm-operator {color: black;}
74 | .cm-s-default .cm-comment {color: #a50;}
75 | .cm-s-default .cm-string {color: #a11;}
76 | .cm-s-default .cm-string-2 {color: #f50;}
77 | .cm-s-default .cm-meta {color: #555;}
78 | .cm-s-default .cm-error {color: #f00;}
79 | .cm-s-default .cm-qualifier {color: #555;}
80 | .cm-s-default .cm-builtin {color: #30a;}
81 | .cm-s-default .cm-bracket {color: #997;}
82 | .cm-s-default .cm-tag {color: #170;}
83 | .cm-s-default .cm-attribute {color: #00c;}
84 | .cm-s-default .cm-header {color: blue;}
85 | .cm-s-default .cm-quote {color: #090;}
86 | .cm-s-default .cm-hr {color: #999;}
87 | .cm-s-default .cm-link {color: #00c;}
88 |
89 | .cm-negative {color: #d44;}
90 | .cm-positive {color: #292;}
91 | .cm-header, .cm-strong {font-weight: bold;}
92 | .cm-em {font-style: italic;}
93 | .cm-emstrong {font-style: italic; font-weight: bold;}
94 | .cm-link {text-decoration: underline;}
95 |
96 | .cm-invalidchar {color: #f00;}
97 |
98 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
99 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
100 |
101 | /* STOP */
102 |
103 | /* The rest of this file contains styles related to the mechanics of
104 | the editor. You probably shouldn't touch them. */
105 |
106 | .CodeMirror {
107 | line-height: 1;
108 | position: relative;
109 | overflow: hidden;
110 | }
111 |
112 | .CodeMirror-scroll {
113 | /* 30px is the magic margin used to hide the element's real scrollbars */
114 | /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
115 | margin-bottom: -30px; margin-right: -30px;
116 | padding-bottom: 30px; padding-right: 30px;
117 | height: 100%;
118 | outline: none; /* Prevent dragging from highlighting the element */
119 | position: relative;
120 | }
121 | .CodeMirror-sizer {
122 | position: relative;
123 | }
124 |
125 | /* The fake, visible scrollbars. Used to force redraw during scrolling
126 | before actuall scrolling happens, thus preventing shaking and
127 | flickering artifacts. */
128 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
129 | position: absolute;
130 | z-index: 6;
131 | display: none;
132 | }
133 | .CodeMirror-vscrollbar {
134 | right: 0; top: 0;
135 | overflow-x: hidden;
136 | overflow-y: scroll;
137 | }
138 | .CodeMirror-hscrollbar {
139 | bottom: 0; left: 0;
140 | overflow-y: hidden;
141 | overflow-x: scroll;
142 | }
143 | .CodeMirror-scrollbar-filler {
144 | right: 0; bottom: 0;
145 | z-index: 6;
146 | }
147 |
148 | .CodeMirror-gutters {
149 | position: absolute; left: 0; top: 0;
150 | height: 100%;
151 | z-index: 3;
152 | }
153 | .CodeMirror-gutter {
154 | height: 100%;
155 | display: inline-block;
156 | /* Hack to make IE7 behave */
157 | *zoom:1;
158 | *display:inline;
159 | }
160 | .CodeMirror-gutter-elt {
161 | position: absolute;
162 | cursor: default;
163 | z-index: 4;
164 | }
165 |
166 | .CodeMirror-lines {
167 | cursor: text;
168 | }
169 | .CodeMirror pre {
170 | /* Reset some styles that the rest of the page might have set */
171 | -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
172 | border-width: 0;
173 | background: transparent;
174 | font-family: inherit;
175 | font-size: inherit;
176 | margin: 0;
177 | white-space: pre;
178 | word-wrap: normal;
179 | line-height: inherit;
180 | color: inherit;
181 | z-index: 2;
182 | position: relative;
183 | overflow: visible;
184 | }
185 | .CodeMirror-wrap pre {
186 | word-wrap: break-word;
187 | white-space: pre-wrap;
188 | word-break: normal;
189 | }
190 | .CodeMirror-linebackground {
191 | position: absolute;
192 | left: 0; right: 0; top: 0; bottom: 0;
193 | z-index: 0;
194 | }
195 |
196 | .CodeMirror-linewidget {
197 | position: relative;
198 | z-index: 2;
199 | }
200 |
201 | .CodeMirror-wrap .CodeMirror-scroll {
202 | overflow-x: hidden;
203 | }
204 |
205 | .CodeMirror-measure {
206 | position: absolute;
207 | width: 100%; height: 0px;
208 | overflow: hidden;
209 | visibility: hidden;
210 | }
211 | .CodeMirror-measure pre { position: static; }
212 |
213 | .CodeMirror pre.CodeMirror-cursor {
214 | position: absolute;
215 | visibility: hidden;
216 | border-right: none;
217 | width: 0;
218 | }
219 | .CodeMirror-focused pre.CodeMirror-cursor {
220 | visibility: visible;
221 | }
222 |
223 | .CodeMirror-selected { background: #d9d9d9; }
224 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
225 |
226 | .CodeMirror-searching {
227 | background: #ffa;
228 | background: rgba(255, 255, 0, .4);
229 | }
230 |
231 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */
232 | .CodeMirror span { *vertical-align: text-bottom; }
233 |
234 | @media print {
235 | /* Hide the cursor when printing */
236 | .CodeMirror pre.CodeMirror-cursor {
237 | visibility: hidden;
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/11-load-grunt-tasks/css/jquery.sidr.light.css:
--------------------------------------------------------------------------------
1 | /* line 3, ../../src/scss/sidr/_base.scss */
2 | .sidr {
3 | /* Default Settings */
4 | display: none;
5 | position: absolute;
6 | position: fixed;
7 | top: 0;
8 | height: 100%;
9 | z-index: 999999;
10 | width: 260px;
11 | overflow-x: none;
12 | overflow-y: auto;
13 | /* Theme Settings */
14 | font-family: "lucida grande", tahoma, verdana, arial, sans-serif;
15 | font-size: 15px;
16 | background: #f8f8f8;
17 | color: #333333;
18 | -webkit-box-shadow: inset 0 0 5px 5px #ebebeb;
19 | -moz-box-shadow: inset 0 0 5px 5px #ebebeb;
20 | box-shadow: inset 0 0 5px 5px #ebebeb;
21 | }
22 | /* line 15, ../../src/scss/sidr/_base.scss */
23 | .sidr .sidr-inner {
24 | padding: 0 0 15px;
25 | }
26 | /* line 18, ../../src/scss/sidr/_base.scss */
27 | .sidr .sidr-inner > p {
28 | margin-left: 15px;
29 | margin-right: 15px;
30 | }
31 | /* line 24, ../../src/scss/sidr/_base.scss */
32 | .sidr.right {
33 | left: auto;
34 | right: -260px;
35 | }
36 | /* line 29, ../../src/scss/sidr/_base.scss */
37 | .sidr.left {
38 | left: -260px;
39 | right: auto;
40 | }
41 | /* line 41, ../../src/scss/sidr/_base.scss */
42 | .sidr h1, .sidr h2, .sidr h3, .sidr h4, .sidr h5, .sidr h6 {
43 | font-size: 11px;
44 | font-weight: normal;
45 | padding: 0 15px;
46 | margin: 0 0 5px;
47 | color: #333333;
48 | line-height: 24px;
49 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #dfdfdf));
50 | background-image: -webkit-linear-gradient(#ffffff, #dfdfdf);
51 | background-image: -moz-linear-gradient(#ffffff, #dfdfdf);
52 | background-image: -o-linear-gradient(#ffffff, #dfdfdf);
53 | background-image: linear-gradient(#ffffff, #dfdfdf);
54 | -webkit-box-shadow: 0 5px 5px 3px rgba(0, 0, 0, 0.2);
55 | -moz-box-shadow: 0 5px 5px 3px rgba(0, 0, 0, 0.2);
56 | box-shadow: 0 5px 5px 3px rgba(0, 0, 0, 0.2);
57 | }
58 | /* line 52, ../../src/scss/sidr/_base.scss */
59 | .sidr p {
60 | font-size: 13px;
61 | margin: 0 0 12px;
62 | }
63 | /* line 55, ../../src/scss/sidr/_base.scss */
64 | .sidr p a {
65 | color: rgba(51, 51, 51, 0.9);
66 | }
67 | /* line 60, ../../src/scss/sidr/_base.scss */
68 | .sidr > p {
69 | margin-left: 15px;
70 | margin-right: 15px;
71 | }
72 | /* line 65, ../../src/scss/sidr/_base.scss */
73 | .sidr ul {
74 | display: block;
75 | margin: 0 0 15px;
76 | padding: 0;
77 | border-top: 1px solid #dfdfdf;
78 | border-bottom: 1px solid white;
79 | }
80 | /* line 72, ../../src/scss/sidr/_base.scss */
81 | .sidr ul li {
82 | display: block;
83 | margin: 0;
84 | line-height: 48px;
85 | border-top: 1px solid white;
86 | border-bottom: 1px solid #dfdfdf;
87 | }
88 | /* line 81, ../../src/scss/sidr/_base.scss */
89 | .sidr ul li:hover, .sidr ul li.active, .sidr ul li.sidr-class-active {
90 | border-top: none;
91 | line-height: 49px;
92 | }
93 | /* line 85, ../../src/scss/sidr/_base.scss */
94 | .sidr ul li:hover > a, .sidr ul li:hover > span, .sidr ul li.active > a, .sidr ul li.active > span, .sidr ul li.sidr-class-active > a, .sidr ul li.sidr-class-active > span {
95 | -webkit-box-shadow: inset 0 0 15px 3px #ebebeb;
96 | -moz-box-shadow: inset 0 0 15px 3px #ebebeb;
97 | box-shadow: inset 0 0 15px 3px #ebebeb;
98 | }
99 | /* line 90, ../../src/scss/sidr/_base.scss */
100 | .sidr ul li a, .sidr ul li span {
101 | padding: 0 15px;
102 | display: block;
103 | text-decoration: none;
104 | color: #333333;
105 | }
106 | /* line 97, ../../src/scss/sidr/_base.scss */
107 | .sidr ul li ul {
108 | border-bottom: none;
109 | margin: 0;
110 | }
111 | /* line 100, ../../src/scss/sidr/_base.scss */
112 | .sidr ul li ul li {
113 | line-height: 40px;
114 | font-size: 13px;
115 | }
116 | /* line 104, ../../src/scss/sidr/_base.scss */
117 | .sidr ul li ul li:last-child {
118 | border-bottom: none;
119 | }
120 | /* line 110, ../../src/scss/sidr/_base.scss */
121 | .sidr ul li ul li:hover, .sidr ul li ul li.active, .sidr ul li ul li.sidr-class-active {
122 | border-top: none;
123 | line-height: 41px;
124 | }
125 | /* line 114, ../../src/scss/sidr/_base.scss */
126 | .sidr ul li ul li:hover > a, .sidr ul li ul li:hover > span, .sidr ul li ul li.active > a, .sidr ul li ul li.active > span, .sidr ul li ul li.sidr-class-active > a, .sidr ul li ul li.sidr-class-active > span {
127 | -webkit-box-shadow: inset 0 0 15px 3px #ebebeb;
128 | -moz-box-shadow: inset 0 0 15px 3px #ebebeb;
129 | box-shadow: inset 0 0 15px 3px #ebebeb;
130 | }
131 | /* line 119, ../../src/scss/sidr/_base.scss */
132 | .sidr ul li ul li a, .sidr ul li ul li span {
133 | color: rgba(51, 51, 51, 0.8);
134 | padding-left: 30px;
135 | }
136 | /* line 128, ../../src/scss/sidr/_base.scss */
137 | .sidr form {
138 | margin: 0 15px;
139 | }
140 | /* line 132, ../../src/scss/sidr/_base.scss */
141 | .sidr label {
142 | font-size: 13px;
143 | }
144 | /* line 146, ../../src/scss/sidr/_base.scss */
145 | .sidr input[type="text"],
146 | .sidr input[type="password"],
147 | .sidr input[type="date"],
148 | .sidr input[type="datetime"],
149 | .sidr input[type="email"],
150 | .sidr input[type="number"],
151 | .sidr input[type="search"],
152 | .sidr input[type="tel"],
153 | .sidr input[type="time"],
154 | .sidr input[type="url"],
155 | .sidr textarea, .sidr select {
156 | width: 100%;
157 | font-size: 13px;
158 | padding: 5px;
159 | -webkit-box-sizing: border-box;
160 | -moz-box-sizing: border-box;
161 | box-sizing: border-box;
162 | margin: 0 0 10px;
163 | -webkit-border-radius: 2px;
164 | -moz-border-radius: 2px;
165 | -ms-border-radius: 2px;
166 | -o-border-radius: 2px;
167 | border-radius: 2px;
168 | border: none;
169 | background: rgba(0, 0, 0, 0.1);
170 | color: rgba(51, 51, 51, 0.6);
171 | display: block;
172 | clear: both;
173 | }
174 | /* line 160, ../../src/scss/sidr/_base.scss */
175 | .sidr input[type=checkbox] {
176 | width: auto;
177 | display: inline;
178 | clear: none;
179 | }
180 | /* line 167, ../../src/scss/sidr/_base.scss */
181 | .sidr input[type=button],
182 | .sidr input[type=submit] {
183 | color: #f8f8f8;
184 | background: #333333;
185 | }
186 | /* line 171, ../../src/scss/sidr/_base.scss */
187 | .sidr input[type=button]:hover,
188 | .sidr input[type=submit]:hover {
189 | background: rgba(51, 51, 51, 0.9);
190 | }
191 |
--------------------------------------------------------------------------------
/11-load-grunt-tasks/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Grunt Usemin Example
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/11-load-grunt-tasks/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Grunt Usemin Example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/11-load-grunt-tasks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "11-load-grunt-tasks",
3 | "version": "0.0.1",
4 | "description": "Automatically Grunt Tasks from package.json into your Gruntfile.js",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "keywords": "grunt, load-grunt-tasks",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "grunt": "^0.4.5",
18 | "grunt-contrib-concat": "^0.5.0",
19 | "grunt-contrib-copy": "^0.7.0",
20 | "grunt-contrib-cssmin": "^0.11.0",
21 | "grunt-contrib-uglify": "^0.7.0",
22 | "grunt-filerev": "^2.1.2",
23 | "grunt-usemin": "^3.0.0",
24 | "load-grunt-tasks": "^3.1.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/12-autoprefixer/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | grunt.initConfig({
6 | autoprefixer: {
7 | options: {
8 | browsers: ['last 2 versions', 'ie 8', 'ie 9', '> 1%']
9 | },
10 | main: {
11 | expand: true,
12 | flatten: true,
13 | src: 'css/*.css',
14 | dest: 'dist/'
15 | }
16 | }
17 | });
18 |
19 | grunt.registerTask('default', ['autoprefixer']);
20 | };
--------------------------------------------------------------------------------
/12-autoprefixer/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/autoprefixer/ "autoprefixer")
2 |
3 | Grunt AutoPrefixer is a grunt plugin that parses all your css files in your web app and adds vendor specifix prefixes like -webkit- or -moz depending upon [Can I Use](http://caniuse.com/).
4 | Its extremely easy to setup and requires little configuration and is recommended by Google and is actively used by Twitter.
5 |
6 | ## Some of the examples that this plugin can add :-
7 |
8 | The following css property applied on an anchor element
9 | ```css
10 | :fullscreen a {
11 | display: flex;
12 | transition: 1s all;
13 | }
14 | ```
15 |
16 | will be automatically converted to
17 |
18 | ```css
19 | :-webkit-full-screen a {
20 | display: -webkit-box;
21 | display: -webkit-flex;
22 | display: flex;
23 | -webkit-transition: 1s all;
24 | transition: 1s all;
25 | }
26 | :-moz-full-screen a {
27 | display: flex;
28 | transition: 1s all;
29 | }
30 | :-ms-fullscreen a {
31 | display: -ms-flexbox;
32 | display: flex;
33 | transition: 1s all;
34 | }
35 | :fullscreen a {
36 | display: -webkit-box;
37 | display: -webkit-flex;
38 | display: -ms-flexbox;
39 | display: flex;
40 | -webkit-transition: 1s all;
41 | transition: 1s all;
42 | }
43 | ```
44 |
45 | It requires autoprefixer-core to be explicitly declared.
46 | To start using this in your build configuration first install it
47 | `npm install grunt-postcss autoprefixer-core --save-dev`
48 |
49 | Here's the grunt file that we have used:
50 | ```js
51 | module.exports = function(grunt) {
52 |
53 | var autoprefixer = require('autoprefixer-core');
54 | require('load-grunt-tasks')(grunt);
55 |
56 | grunt.initConfig({
57 | postcss: {
58 | options: {
59 | processors: [
60 | autoprefixer({
61 | browers: ['> 0.5%', 'last 2 versions', 'Firefox ESR', 'Opera 12.1']
62 | }).postcss
63 | ]
64 | },
65 | dist: {
66 | files: {
67 | 'dist/': 'css/*.css'
68 | }
69 | }
70 | }
71 | });
72 |
73 | grunt.registerTask('default', ['postcss']);
74 | };
75 | ```
76 |
77 | After running grunt on the sample.css inside folder, its replaced by the vendor prefixed version.
78 |
79 | Another great grunt plugin that does the same thing is [grunt-autoprefixer](https://github.com/nDmitry/grunt-autoprefixer).
80 | Its easier to install
81 | `npm install grunt-autoprefixer autoprefixer-core --save-dev`
82 |
83 | According to this configuration:
84 | ```js
85 | autoprefixer: {
86 | options: {
87 | browsers: ['last 2 versions', 'ie 8', 'ie 9', '> 1%']
88 | },
89 | main: {
90 | expand: true,
91 | flatten: true,
92 | src: 'css/*.css',
93 | dest: 'dist/'
94 | }
95 | }
96 | ```
97 | On running Grunt this time, it will scan css/sample.css and vendor prefixes to dist/sample.css.
98 | This is a much better option to keep your source files as clean as possible without browser prefixes or some weird browser behaviours.
--------------------------------------------------------------------------------
/12-autoprefixer/css/sample.css:
--------------------------------------------------------------------------------
1 | :fullscreen a {
2 | display: flex;
3 | transition: 1s all;
4 | }
--------------------------------------------------------------------------------
/12-autoprefixer/dist/sample.css:
--------------------------------------------------------------------------------
1 | :-webkit-full-screen a {
2 | display: -webkit-box;
3 | display: -webkit-flex;
4 | display: flex;
5 | -webkit-transition: 1s all;
6 | transition: 1s all;
7 | }
8 | :-moz-full-screen a {
9 | display: flex;
10 | transition: 1s all;
11 | }
12 | :-ms-fullscreen a {
13 | display: -ms-flexbox;
14 | display: flex;
15 | transition: 1s all;
16 | }
17 | :fullscreen a {
18 | display: -webkit-box;
19 | display: -webkit-flex;
20 | display: -ms-flexbox;
21 | display: flex;
22 | -webkit-transition: 1s all;
23 | transition: 1s all;
24 | }
--------------------------------------------------------------------------------
/12-autoprefixer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "12-autoprefixer",
3 | "version": "0.0.1",
4 | "description": "Automatically prefix all your css files",
5 | "main": "Gruntfile.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "keywords": "grunt, css, autoprefixer",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "autoprefixer-core": "^5.1.7",
18 | "grunt": "^0.4.5",
19 | "grunt-autoprefixer": "^2.2.0",
20 | "load-grunt-tasks": "^3.1.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/13-grunt-responsive-images/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | grunt.initConfig({
6 | responsive_images: {
7 | main: {
8 | options: {
9 | engine: 'im'
10 | },
11 | files: [{
12 | expand: true,
13 | src: ['img/**/*.{gif,png,jpg,jpge}'],
14 | cwd: 'src/',
15 | dest: 'dist/'
16 | }]
17 | }
18 | },
19 | responsive_images_extender: {
20 | main: {
21 | options: {
22 | sizes: [{
23 | selector: 'img',
24 | sizeList: [{
25 | cond: 'min-width: 300px',
26 | size: '50vw'
27 | }, {
28 | cond: 'min-width: 700px',
29 | size: '70vw'
30 | }, {
31 | cond: 'default',
32 | size: '100vw'
33 | }]
34 | }]
35 | },
36 | files: [{
37 | expand: true,
38 | src: ['**/*.{html,htm,php}'],
39 | cwd: 'src/',
40 | dest: 'dist/'
41 | }]
42 | }
43 | }
44 | });
45 |
46 | grunt.registerTask('default', ['responsive_images', 'responsive_images_extender']);
47 | };
--------------------------------------------------------------------------------
/13-grunt-responsive-images/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/responsive-images/ "grunt responsive images")
2 |
3 | Grunt responsive images is a grunt-js plugin that automatically produces scales images to different sizes for different devices in order to create responsive images.
4 |
5 | Consider a medium based website. As with most new websites image form a big part of it. Now you don't want to load the same image for a person visiting the website on an iMac or his handheld device. You want to deliver the optimum experience on all devices and responsive images form a huge part in that.
6 |
7 | Thats why, browser vendors have come up with a new standard [picture](http://www.html5rocks.com/en/tutorials/responsive/picture-element/) that will solve the responsive images headache.
8 |
9 | Theres also a [demo](http://googlechrome.github.io/samples/picture-element/) available on how to use picture element.
10 |
11 | Instead of manually resizing all images, you can automate this task. Here's how:
12 |
13 | ## Getting Started
14 |
15 | Pre-requirements: You need to have GraphicsMagick or ImageMagick installed on your machine because grunt responsive images depends on this to do the resizing.
16 | If you are using ImageMagick, be sure to specify 'im' in engine in options.
17 |
18 | After that
19 |
20 | `npm install grunt-responsive-images --save-dev`
21 |
22 | This will add the grunt-responsive images in developer dependencies of package.json
23 | Lets say this is your folder-file structure:
24 | ```
25 | .
26 | ├── dist
27 | ├── Gruntfile.js
28 | ├── index.html
29 | └── src
30 | └── img
31 | └── grunt-usemin.jpg
32 | ```
33 | Where you have all your development files in your src/ folder and your minified/production files in dist/
34 |
35 | Add that as a task in your Gruntfile.js
36 | ```js
37 | responsive_images: {
38 | main: {
39 | options: {
40 | engine: 'im',
41 | sizes: [{
42 | width: 100
43 | }, {
44 | width: 250
45 | }]
46 | },
47 | files: [{
48 | expand: true,
49 | src: ['img/**/*.{gif,png,jpg,jpge}'],
50 | cwd: 'src/',
51 | dest: 'dist/'
52 | }]
53 | }
54 | }
55 | ```
56 |
57 | if you want to have scaled up images you have to add `upscale: true` in the sizes object property.
58 | After you run grunt it will resize the images and put them in img/
59 | ```
60 | ├── dist
61 | │ └── img
62 | │ ├── grunt-usemin-400.jpg
63 | │ └── grunt-usemin-800.jpg
64 | ```
65 |
66 |
67 | But this will only generate the images, not replace them in the src in your html.
68 | Ideally it should do both, replace all img tags with the picture polyfill as well as generate the new images.
69 |
70 | Thankfully, [Stephan Max](http://stephanmax.is/) has written another grunt plugin [grunt-responsive-images-extender](https://github.com/smaxtastic/grunt-responsive-images-extender) to complement grunt-responsive-image
71 |
72 | Similarly, install it and add it to devDependencies
73 | `npm install grunt-responsive-images-extender --save-dev`
74 |
75 | The default options for sizes in both the grunt plugins is
76 | ```js
77 | [{
78 | name: 'small', width: 320
79 | }, {
80 | name: 'medium', width: 640
81 | },{
82 | name: 'large', width: 1024
83 | }]
84 | ```
85 |
86 | This is the grunt task used for responsive images extender:
87 |
88 | ```js
89 | responsive_images_extender: {
90 | main: {
91 | options: {
92 | sizes: [{
93 | selector: 'img',
94 | sizeList: [{
95 | cond: 'min-width: 300px',
96 | size: '50vw'
97 | }, {
98 | cond: 'min-width: 700px',
99 | size: '70vw'
100 | }, {
101 | cond: 'default',
102 | size: '100vw'
103 | }]
104 | }]
105 | },
106 | files: [{
107 | expand: true,
108 | src: ['**/*.{html,htm,php}'],
109 | cwd: 'src/',
110 | dest: 'dist/'
111 | }]
112 | }
113 | }
114 | ```
115 |
116 | On running the above `grunt`, it will find all the images as specified in `selector` property and add the corresponding attributes as specified in `sizes`.
117 | In this case I am using the default grunt-responsive-image property of producing three images with suffix large, medium and small.
118 |
119 |
120 | Source: src/index.html
121 | ```html
122 |
123 | ```
124 |
125 | Production: dist/index.html
126 | ```html
127 |
128 | ```
129 |
130 | Read more about srcset and sizes [here](http://martinwolf.org/2014/05/07/the-new-srcset-and-sizes-explained/ "srcset")
131 |
132 | Make sure to also add picturefill.js to the head for older browsers.
133 |
--------------------------------------------------------------------------------
/13-grunt-responsive-images/dist/img/grunt-usemin-large.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/13-grunt-responsive-images/dist/img/grunt-usemin-large.jpg
--------------------------------------------------------------------------------
/13-grunt-responsive-images/dist/img/grunt-usemin-medium.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/13-grunt-responsive-images/dist/img/grunt-usemin-medium.jpg
--------------------------------------------------------------------------------
/13-grunt-responsive-images/dist/img/grunt-usemin-small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/13-grunt-responsive-images/dist/img/grunt-usemin-small.jpg
--------------------------------------------------------------------------------
/13-grunt-responsive-images/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Using Grunt Responsive Images
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/13-grunt-responsive-images/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "13-grunt-responsive-images",
3 | "version": "0.0.1",
4 | "description": "Automatically produce images at different sizes for different images",
5 | "main": "Gruntfile.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "keywords": "grunt, grunt-responsive-images, responsive",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "grunt": "^0.4.5",
18 | "grunt-responsive-images": "^0.1.6",
19 | "grunt-responsive-images-extender": "^1.0.0",
20 | "load-grunt-tasks": "^3.1.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/13-grunt-responsive-images/src/img/grunt-usemin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/13-grunt-responsive-images/src/img/grunt-usemin.jpg
--------------------------------------------------------------------------------
/13-grunt-responsive-images/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Using Grunt Responsive Images
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | grunt.initConfig({
6 | 'jsdoc-ng' : {
7 | dist : {
8 | src: ['src/*.js', 'README.md' ],
9 | dest: 'docs',
10 | template : 'jsdoc-ng',
11 | options: {
12 | }
13 | }
14 | }
15 | });
16 |
17 | grunt.registerTask('default', ['jsdoc-ng']);
18 | };
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/README.md:
--------------------------------------------------------------------------------
1 | ## [Blog post](http://grunt-tasks.com/grunt-jsdoc/ "grunt jsdoc")
2 |
3 | Grunt jsdoc-ng is an awesome grunt plugin that allows you to create documentation automatically from your javascript source code in your build process itself.
4 | Bonus point is that the docs which are generated is a single page web app based on angular-js for faster navigation.
5 |
6 | > We wont be using grunt-jsdoc because of [this issue](https://github.com/krampstudio/grunt-jsdoc/issues/124)
7 |
8 | jsdoc is a javascript documentation generation framework used to build custom documentation based on your source code comments. Using its block tags you can have a beautiful documentation of your code/API.
9 | By making use of grunt jsdoc you are removing the work of maintaining your code documentation. It is extremely important to keep your source code documented and an easy to use API.
10 |
11 | > For more information on how to use jsdoc please visit [jsdoc](http://usejsdoc.org/ "jsdoc")
12 |
13 | 
14 |
15 | > If you are using sublime then there's an awesome [plugin](https://github.com/spadgos/sublime-jsdocs) to create comments for your code:
16 |
17 | ## Getting it all set up
18 |
19 | To install grunt-jsdoc-ng:
20 |
21 | `npm install --save-dev grunt-jsdoc-ng`
22 |
23 | Lets consider a simple javascript file `area.js` which encompasses the @Area constructor and its methods and properties.
24 | It has got getters like fetching its width, its height, its total area and setters for setting its width or height.
25 |
26 | Here's the corresponding section in Gruntfile.js
27 | ```
28 | grunt.initConfig({
29 | 'jsdoc-ng' : {
30 | dist : {
31 | src: ['src/*.js', 'README.md' ],
32 | dest: 'docs',
33 | template : 'jsdoc-ng',
34 | options: {
35 | }
36 | }
37 | }
38 | });
39 | ```
40 |
41 | Here's the source code for area.js:
42 | and here's the [link](https://rawgit.com/kanakiyajay/grunt-tasks/master/14-grunt-jsdoc-ng/docs/index.html#!/Area) to what the generated documentation looks like.
43 |
44 | ```js
45 | "use strict";
46 | /**
47 | * Creates a new geometrical Area Block
48 | * @param {int} width the width of the area
49 | * @param {int} height the height of the area
50 | */
51 | function Area(width, height) {
52 | this.width = width;
53 | this.height = height;
54 |
55 | /**
56 | * Returns the width of the area
57 | * @return {int} the width of the area
58 | */
59 | this.getWidth = function() {
60 | return this.width;
61 | };
62 |
63 | /**
64 | * Returns the height of the area
65 | * @return {int} the height of the area
66 | */
67 | this.getHeight = function() {
68 | return this.height;
69 | };
70 |
71 | /**
72 | * Returns the 2D area of the object
73 | * @return {int} height x width
74 | */
75 | this.getTotalArea = function() {
76 | return this.height * this.width;
77 | };
78 |
79 | /**
80 | * Returns whether height or width is greater
81 | * @return {string}
82 | */
83 | this.getGreater = function() {
84 | var greater = this.height > this.width ? "height" : "width";
85 | return greater;
86 | };
87 |
88 | /**
89 | * Changes the Height of the area
90 | * @param {int} ht new height
91 | */
92 | this.setHeight = function(ht) {
93 | this.height = ht;
94 | return ht;
95 | };
96 |
97 | /**
98 | * Changes the Width of the area
99 | * @param {int} wd new width
100 | */
101 | this.setWidth = function(wd) {
102 | this.width = wd;
103 | return wd;
104 | };
105 | }
106 | ```
107 |
108 | On running grunt from the command line
109 |
110 | ```
111 | $ grunt
112 | Invoking JsDoc
113 | Parsing H:\grunt-tasks.com\github\14-grunt-jsdoc-ng\src\area.js ...>> complete.
114 | Generating output files...
115 | >> Output minification enabled
116 | >> Minifying JavaScript output
117 | Writing output files...>> complete.
118 | >> Finished running in 1.21 seconds.
119 |
120 | JsDoc completed
121 | ```
122 | It will automatically create the documentation from our comments in area.js, format it and output a beautiful html file containing the docs. It will parse our READMEmd file and generate its documentation.
123 |
124 | > In this app, because I am fetching the README.md and posting it on this blog post, the jsdoc documentation generated will also contain the blog post.
125 |
126 | This the final tree structure of our app:
127 |
128 | ```
129 | .
130 | ├── docs
131 | │ ├── fonts
132 | │ │ ├── fonts.min.css
133 | │ │ ├── LICENSE.txt
134 | │ │ ├── Ubuntu-Bold.ttf
135 | │ │ ├── Ubuntu-BoldItalic.ttf
136 | │ │ ├── Ubuntu-Italic.ttf
137 | │ │ ├── Ubuntu-Light.ttf
138 | │ │ ├── Ubuntu-LightItalic.ttf
139 | │ │ ├── Ubuntu-Medium.ttf
140 | │ │ ├── Ubuntu-MediumItalic.ttf
141 | │ │ ├── UbuntuMono-Bold.ttf
142 | │ │ ├── UbuntuMono-BoldItalic.ttf
143 | │ │ ├── UbuntuMono-Italic.ttf
144 | │ │ ├── UbuntuMono-Regular.ttf
145 | │ │ └── Ubuntu-Regular.ttf
146 | │ ├── index.html
147 | │ ├── jsdoc-ng.data.js
148 | │ ├── jsdoc-ng.min.css
149 | │ ├── jsdoc-ng.min.js
150 | │ └── libs
151 | │ ├── angular.min.js
152 | │ ├── angular.min.js.map
153 | │ ├── highlight.min.css
154 | │ └── highlight.min.js
155 | ├── Gruntfile.js
156 | ├── package.json
157 | ├── README.md
158 | └── src
159 | └── area.js
160 | ```
161 |
162 | Here'a [link](https://rawgit.com/kanakiyajay/grunt-tasks/master/14-grunt-jsdoc-ng/docs/index.html#!/Area) to the documentation generated and the screenshot is below
163 |
164 | 
165 |
166 | You can find all the other options for grunt-jsdoc-ng below.
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/LICENSE.txt:
--------------------------------------------------------------------------------
1 | -------------------------------
2 | UBUNTU FONT LICENCE Version 1.0
3 | -------------------------------
4 |
5 | PREAMBLE
6 | This licence allows the licensed fonts to be used, studied, modified and
7 | redistributed freely. The fonts, including any derivative works, can be
8 | bundled, embedded, and redistributed provided the terms of this licence
9 | are met. The fonts and derivatives, however, cannot be released under
10 | any other licence. The requirement for fonts to remain under this
11 | licence does not require any document created using the fonts or their
12 | derivatives to be published under this licence, as long as the primary
13 | purpose of the document is not to be a vehicle for the distribution of
14 | the fonts.
15 |
16 | DEFINITIONS
17 | "Font Software" refers to the set of files released by the Copyright
18 | Holder(s) under this licence and clearly marked as such. This may
19 | include source files, build scripts and documentation.
20 |
21 | "Original Version" refers to the collection of Font Software components
22 | as received under this licence.
23 |
24 | "Modified Version" refers to any derivative made by adding to, deleting,
25 | or substituting -- in part or in whole -- any of the components of the
26 | Original Version, by changing formats or by porting the Font Software to
27 | a new environment.
28 |
29 | "Copyright Holder(s)" refers to all individuals and companies who have a
30 | copyright ownership of the Font Software.
31 |
32 | "Substantially Changed" refers to Modified Versions which can be easily
33 | identified as dissimilar to the Font Software by users of the Font
34 | Software comparing the Original Version with the Modified Version.
35 |
36 | To "Propagate" a work means to do anything with it that, without
37 | permission, would make you directly or secondarily liable for
38 | infringement under applicable copyright law, except executing it on a
39 | computer or modifying a private copy. Propagation includes copying,
40 | distribution (with or without modification and with or without charging
41 | a redistribution fee), making available to the public, and in some
42 | countries other activities as well.
43 |
44 | PERMISSION & CONDITIONS
45 | This licence does not grant any rights under trademark law and all such
46 | rights are reserved.
47 |
48 | Permission is hereby granted, free of charge, to any person obtaining a
49 | copy of the Font Software, to propagate the Font Software, subject to
50 | the below conditions:
51 |
52 | 1) Each copy of the Font Software must contain the above copyright
53 | notice and this licence. These can be included either as stand-alone
54 | text files, human-readable headers or in the appropriate machine-
55 | readable metadata fields within text or binary files as long as those
56 | fields can be easily viewed by the user.
57 |
58 | 2) The font name complies with the following:
59 | (a) The Original Version must retain its name, unmodified.
60 | (b) Modified Versions which are Substantially Changed must be renamed to
61 | avoid use of the name of the Original Version or similar names entirely.
62 | (c) Modified Versions which are not Substantially Changed must be
63 | renamed to both (i) retain the name of the Original Version and (ii) add
64 | additional naming elements to distinguish the Modified Version from the
65 | Original Version. The name of such Modified Versions must be the name of
66 | the Original Version, with "derivative X" where X represents the name of
67 | the new work, appended to that name.
68 |
69 | 3) The name(s) of the Copyright Holder(s) and any contributor to the
70 | Font Software shall not be used to promote, endorse or advertise any
71 | Modified Version, except (i) as required by this licence, (ii) to
72 | acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
73 | their explicit written permission.
74 |
75 | 4) The Font Software, modified or unmodified, in part or in whole, must
76 | be distributed entirely under this licence, and must not be distributed
77 | under any other licence. The requirement for fonts to remain under this
78 | licence does not affect any document created using the Font Software,
79 | except any version of the Font Software extracted from a document
80 | created using the Font Software may only be distributed under this
81 | licence.
82 |
83 | TERMINATION
84 | This licence becomes null and void if any of the above conditions are
85 | not met.
86 |
87 | DISCLAIMER
88 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
89 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
90 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
91 | COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
92 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
93 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
94 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
96 | DEALINGS IN THE FONT SOFTWARE.
97 |
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Bold.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-BoldItalic.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Italic.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Light.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-LightItalic.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Medium.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-MediumItalic.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/Ubuntu-Regular.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-Bold.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-BoldItalic.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-Italic.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/14-grunt-jsdoc-ng/docs/fonts/UbuntuMono-Regular.ttf
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/fonts/fonts.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:'Ubuntu';font-style:normal;font-weight:300;src:local('Ubuntu Light'),local('Ubuntu-Light'),url(Ubuntu-Light.ttf) format('truetype')}@font-face{font-family:'Ubuntu';font-style:normal;font-weight:400;src:local('Ubuntu'),url(Ubuntu-Regular.ttf) format('truetype')}@font-face{font-family:'Ubuntu';font-style:normal;font-weight:700;src:local('Ubuntu Bold'),local('Ubuntu-Bold'),url(Ubuntu-Bold.ttf) format('truetype')}@font-face{font-family:'Ubuntu';font-style:italic;font-weight:300;src:local('Ubuntu Light Italic'),local('Ubuntu-LightItalic'),url(Ubuntu-LightItalic.ttf) format('truetype')}@font-face{font-family:'Ubuntu';font-style:italic;font-weight:400;src:local('Ubuntu Italic'),local('Ubuntu-Italic'),url(Ubuntu-Italic.ttf) format('truetype')}@font-face{font-family:'Ubuntu';font-style:italic;font-weight:700;src:local('Ubuntu Bold Italic'),local('Ubuntu-BoldItalic'),url(Ubuntu-BoldItalic.ttf) format('truetype')}@font-face{font-family:'Ubuntu Mono';font-style:normal;font-weight:400;src:local('Ubuntu Mono'),local('UbuntuMono-Regular'),url(UbuntuMono-Regular.ttf) format('truetype')}@font-face{font-family:'Ubuntu Mono';font-style:normal;font-weight:700;src:local('Ubuntu Mono Bold'),local('UbuntuMono-Bold'),url(UbuntuMono-Bold.ttf) format('truetype')}@font-face{font-family:'Ubuntu Mono';font-style:italic;font-weight:400;src:local('Ubuntu Mono Italic'),local('UbuntuMono-Italic'),url(UbuntuMono-Italic.ttf) format('truetype')}@font-face{font-family:'Ubuntu Mono';font-style:italic;font-weight:700;src:local('Ubuntu Mono Bold Italic'),local('UbuntuMono-BoldItalic'),url(UbuntuMono-BoldItalic.ttf) format('truetype')}
--------------------------------------------------------------------------------
/14-grunt-jsdoc-ng/docs/index.html:
--------------------------------------------------------------------------------
1 | Automatically create beautiful html documentation from your source code documentation (v. 0.0.1)
Grunt jsdoc-ng is an awesome grunt plugin that allows you to create documentation automatically from your javascript source code in your build process itself.\nBonus point is that the docs which are generated is a single page web app based on angular-js for faster navigation.
\n
\n
We wont be using grunt-jsdoc because of this issue
\n
\n
jsdoc is a javascript documentation generation framework used to build custom documentation based on your source code comments. Using its block tags you can have a beautiful documentation of your code/API.\nBy making use of grunt jsdoc you are removing the work of maintaining your code documentation. It is extremely important to keep your source code documented and an easy to use API.
\n
\n
For more information on how to use jsdoc please visit jsdoc
\n
\n
\n
\n
If you are using sublime then there\'s an awesome plugin to create comments for your code:
\n
\n
Getting it all set up
To install grunt-jsdoc-ng:
\n
npm install --save-dev grunt-jsdoc-ng
\n
Lets consider a simple javascript file area.js which encompasses the @Area constructor and its methods and properties.\nIt has got getters like fetching its width, its height, its total area and setters for setting its width or height.
15 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus sapiente tempora eligendi officia reiciendis cumque quaerat aspernatur! Iste fuga, expedita voluptas molestiae error velit laboriosam minima amet, dolore perspiciatis, ab.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/22-grunt-image-embed/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "22-grunt-image-embed",
3 | "version": "0.0.1",
4 | "description": "Grunt plugin to convert images into data URIs",
5 | "main": "Gruntfile.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "grunt": "^0.4.5",
17 | "grunt-contrib-concat": "^0.5.1",
18 | "grunt-contrib-copy": "^0.8.0",
19 | "grunt-contrib-cssmin": "^0.12.2",
20 | "grunt-contrib-htmlmin": "^0.4.0",
21 | "grunt-contrib-uglify": "^0.9.1",
22 | "grunt-filerev": "^2.3.1",
23 | "grunt-usemin": "^3.0.0",
24 | "grunt-image-embed": "^0.3.3",
25 | "load-grunt-tasks": "^3.1.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/23-grunt-browser-sync/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | grunt.initConfig({
6 | browserSync: {
7 | bsFiles: {
8 | src: 'css/*.css'
9 | },
10 | options: {
11 | proxy: 'localhost:80'
12 | }
13 | }
14 | });
15 |
16 | grunt.registerTask('default', ['browserSync']);
17 | };
18 |
--------------------------------------------------------------------------------
/23-grunt-browser-sync/README.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | Grunt-Browser-Sync is the official grunt-js plugin from BrowserSync to reload your browser on any css file changes. It can create its own server or hook into an existing server.
4 | BrowserSync also automatically reloads all tabs which are dependent on that css file which enables you to work seamlessly with multiple devices. If you haven't started using [browsersync](http://www.browsersync.io/) its recommended you should.
5 |
6 | In this tutorial I am going to demonstrate its usage with Grunt.
7 |
8 | ## Getting Started
9 |
10 | You can install it from the command line:
11 | `npm install grunt-browser-sync --save-dev`
12 | The flag --save-dev will get it installed in your project's package.json as well.
13 |
14 | For the first example we will consider a very basic html webpage linked to to 2 css files.
15 | On making a change inside the css file, all tabs with that html file open should refresh enabling us to quickly change properties.
16 |
17 | Heres the Gruntfile.js for that:
18 |
19 | ```js
20 | module.exports = function(grunt) {
21 |
22 | require('load-grunt-tasks')(grunt);
23 |
24 | grunt.initConfig({
25 | browserSync: {
26 | bsFiles: {
27 | src: 'css/*.css'
28 | },
29 | options: {
30 | server: {
31 | baseDir: './'
32 | }
33 | }
34 | }
35 | });
36 |
37 | grunt.registerTask('default', ['browserSync']);
38 | };
39 | ```
40 |
41 | On running grunt from the command line:
42 |
43 | ```
44 | $ grunt
45 | Running "browserSync:bsFiles" (browserSync) task
46 | [BS] Access URLs:
47 | -------------------------------------
48 | Local: http://localhost:3000
49 | External: http://192.168.1.33:3000
50 | -------------------------------------
51 | UI: http://localhost:3001
52 | UI External: http://192.168.1.33:3001
53 | -------------------------------------
54 | [BS] Serving files from: ./
55 | [BS] Watching files...
56 | ```
57 |
58 | Now you can open up the same url in multiple browsers as well as visit 192.168.1.33:3000 from your smartphone.
59 | Once you change anything inside custom.css all the tabs will reload.
60 | BrowserSync also has the ability to sync scroll, form, refresh actions and also provides you with a control panel UI.
61 | 
62 |
63 | ## External Server
64 |
65 | Many a times we will have an external server built on express / php / django / rails and we want to use BrowserSync and grunt with it.
66 | Sweat not! BrowserSync has this support built-in using its proxy featured.
67 |
68 | This is the only option that you need to change:
69 |
70 | ```js
71 | options: {
72 | proxy: 'localhost:80'
73 | }
74 | ```
75 |
76 | You can even add port, logs watchOptions and middlewares.
77 |
78 | Here is the [full list](http://www.browsersync.io/docs/options/) of options.
79 |
80 | Found something wrong in the above article, send a pull request in the [github repo](http://github.com/kanakiyajay/grunt-tasks/23-grunt-browser-sync/) or notify in the comments below.
81 | I will also love to hear about your cool hacks around grunt-image-embed.
82 |
--------------------------------------------------------------------------------
/23-grunt-browser-sync/css/custom.css:
--------------------------------------------------------------------------------
1 | .m-t {
2 | margin-top: 20px;
3 | }
4 |
5 | .jquer {
6 | width: 57px;
7 | height: 57px;
8 | background: url('http://jquer.in/favicons/apple-touch-icon-57x57.png') no-repeat;
9 | }
--------------------------------------------------------------------------------
/23-grunt-browser-sync/images/browsersync.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/23-grunt-browser-sync/images/browsersync.jpg
--------------------------------------------------------------------------------
/23-grunt-browser-sync/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Using Grunt Browsersync to keep multiple tabs in sync
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus sapiente tempora eligendi officia reiciendis cumque quaerat aspernatur! Iste fuga, expedita voluptas molestiae error velit laboriosam minima amet, dolore perspiciatis, ab.
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/23-grunt-browser-sync/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "23-grunt-browser-sync",
3 | "version": "0.0.1",
4 | "description": "Grunt plugin to reload browser on css changes",
5 | "main": "Gruntfile.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/kanakiyajay/grunt-tasks.git"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Jay Kanakiya",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "grunt": "^0.4.5",
17 | "grunt-browser-sync": "^2.1.3",
18 | "load-grunt-tasks": "^3.1.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/24-grunt-contrib-compress/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | grunt.initConfig({
6 | compress: {
7 | main: {
8 | options: {
9 | archive: 'project.zip'
10 | },
11 | files: [{
12 | cwd: 'assets/css/',
13 | expand: true,
14 | src: ['**/*'],
15 | dest: 'styles'
16 | }, {
17 | cwd: 'assets/js/',
18 | expand: true,
19 | src: ['**/*'],
20 | dest: 'scripts'
21 | }]
22 | }
23 | }
24 | });
25 |
26 | grunt.registerTask('default', ['compress']);
27 | };
28 |
--------------------------------------------------------------------------------
/24-grunt-contrib-compress/README.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | Grunt-contrib-compress is the official grunt-js plugin from Grunt Team to zip or tar your whole project or a part of your project file and folders.
4 | In this short tutorial I am going to demonstrate its usage:
5 |
6 | ## Getting Started
7 |
8 | You can install it from the command line:
9 | `npm install grunt-contrib-compress --save-dev`
10 | The flag --save-dev will get it installed in your project's package.json as well.
11 |
12 | Lets consider a very basic example where we have to just zip the project folder.
13 |
14 | ```
15 | assets
16 | ├── css
17 | │ ├── bootstrap.css
18 | │ └── custom.css
19 | ├── images
20 | │ └── browsersync.jpg
21 | ├── index.html
22 | └── js
23 | ├── angular.min.js
24 | ├── bootstrap.min.js
25 | └── jquery.js
26 | ```
27 |
28 | Heres our Gruntfile.js
29 |
30 | ```js
31 | module.exports = function(grunt) {
32 |
33 | require('load-grunt-tasks')(grunt);
34 |
35 | grunt.initConfig({
36 | compress: {
37 | main: {
38 | options: {
39 | archive: 'project.zip',
40 | pretty: true
41 | },
42 | expand: true,
43 | cwd: 'assets/',
44 | src: ['**/*'],
45 | dest: '/'
46 | }
47 | }
48 | });
49 |
50 | grunt.registerTask('default', ['compress']);
51 | };
52 | ```
53 |
54 | On running grunt:-
55 |
56 | ```
57 | $ grunt
58 | Running "compress:main" (compress) task
59 | Created project.zip (278018 bytes)
60 |
61 | Done, without errors.
62 | ```
63 |
64 | You will find a project.zip folder in your main directory which when unzipped will contain the css, js and images folder same as in the original.
65 |
66 | ## Configurations
67 |
68 | Lets say you wanted to configure the way the zip folder is created or you want to create a tar, all these options are available in grunt-contrib-compress.
69 |
70 | One of the things that you can configure is the name of the zip folder that is being generated.
71 | archive option also accepts functions which returns strings.
72 | ```js
73 | options: {
74 | archive: function() {
75 | return 'project' + (new Date()).getTime() + '.zip'
76 | }
77 | }
78 | ```
79 |
80 | Lets consider a case where we want to only compress only the javascript and the css files and you have a server that handles CDN and only accepts folder names of 'scripts' and 'styles'.
81 |
82 | You can use this the Globbing patterns for files available in this grunt plugin.
83 |
84 | Below is the configuration that will be required in order to do that.
85 | The `dest` parameter controls the destination folder for the zipped files, `expand` makes sure the file folder structure is preserved.
86 |
87 | ```js
88 | compress: {
89 | main: {
90 | options: {
91 | archive: 'project.zip'
92 | },
93 | files: [{
94 | cwd: 'assets/css/',
95 | expand: true,
96 | src: ['**/*'],
97 | dest: 'styles'
98 | }, {
99 | cwd: 'assets/js/',
100 | expand: true,
101 | src: ['**/*'],
102 | dest: 'scripts'
103 | }]
104 | }
105 | }
106 | ```
107 |
108 | On unzipping, this is the project structure:
109 | ```
110 | project
111 | ├── scripts
112 | │ ├── angular.min.js
113 | │ ├── bootstrap.min.js
114 | │ └── jquery.js
115 | └── styles
116 | ├── bootstrap.css
117 | └── custom.css
118 | ```
119 | Found something wrong in the above article, send a pull request in the [github repo](http://github.com/kanakiyajay/grunt-tasks/24-grunt-contrib-compress/) or notify in the comments below.
120 | I will also love to hear about your usage of grunt-contrib-compress in your projects.
121 |
--------------------------------------------------------------------------------
/24-grunt-contrib-compress/assets/css/custom.css:
--------------------------------------------------------------------------------
1 | .m-t {
2 | margin-top: 20px;
3 | }
4 |
5 | .jquer {
6 | width: 57px;
7 | height: 57px;
8 | background: url('http://jquer.in/favicons/apple-touch-icon-57x57.png') no-repeat;
9 | }
--------------------------------------------------------------------------------
/24-grunt-contrib-compress/assets/images/browsersync.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kanakiyajay/grunt-tasks/944013f2e30375c6d1928bc4f30564275b8adc2a/24-grunt-contrib-compress/assets/images/browsersync.jpg
--------------------------------------------------------------------------------
/24-grunt-contrib-compress/assets/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Using Grunt Browsersync to keep multiple tabs in sync
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus sapiente tempora eligendi officia reiciendis cumque quaerat aspernatur! Iste fuga, expedita voluptas molestiae error velit laboriosam minima amet, dolore perspiciatis, ab.
14 |
44 |
45 |
46 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## [Grunt Tasks](http://grunt-tasks.com/ "Grunt")
2 |
3 | This is the central github repository which contains all the grunt files as explained in grunt-tasks.com.
4 | [I](http://jaykanakiya.com/ "Jay Kanakiya") have used a simple configutation to sync my blog posts and github repository so that I can git push and change my blog posts at the same time.
5 |
6 | Also makes development work easier by only maintaining the Readme at only one place, while also getting the easier publishing of wordpress.
7 |
8 | ## Getting Started
9 |
10 | You can read this [blog post](http://grunt-tasks.com/start-using-grunt-js/) for getting started. The code and the blog post live in this git repository.
11 |
12 | You can find the initial templates for any plugin in this repository itself.
13 |
14 | `git clone https://github.com/kanakiyajay/grunt-tasks.git`
15 |
16 | cd to that folder and run
17 |
18 | `npm install`
19 |
20 | Following are the Blog posts that have been published
21 |
22 | - [Grunt Contrib Compress](http://grunt-tasks.com/grunt-contrib-compress/ "grunt contrib compress")
23 | - [Grunt Browser Sync](http://grunt-tasks.com/grunt-browser-sync/ "grunt browser sync")
24 | - [Grunt Image Embed](http://grunt-tasks.com/grunt-image-embed/ "image embed")
25 | - [time-grunt](http://grunt-tasks.com/time-grunt/ "time grunt")
26 | - [Grunt Contrib Htmlmin](http://grunt-tasks.com/grunt-htmlmin/ "grunt contrib htmlmin")
27 | - [Grunt Wiredep](http://grunt-tasks.com/grunt-wiredep/ "grunt wiredep")
28 | - [Grunt Jsonlint](http://grunt-tasks.com/grunt-jsonlint/ "grunt jsonlint")
29 | - [Grunt Remove logging calls](http://grunt-tasks.com/grunt-remove-logging-calls/ "grunt remove logging")
30 | - [Grunt csscomb](http://grunt-tasks.com/grunt-csscomb/ "grunt beautiful css")
31 | - [Grunt jsdoc](http://grunt-tasks.com/grunt-jsdoc-ng/ "Grunt Document generator")
32 | - [Grunt Responsive Images](http://grunt-tasks.com/responsive-images/ "grunt responsive images")
33 | - [AutoPrefixer](http://grunt-tasks.com/12-autoprefixer/ "autoprefixer")
34 | - [load grunt tasks](http://grunt-tasks.com/load-grunt-tasks/)
35 | - [Grunt newer](http://grunt-tasks.com/grunt-newer/)
36 | - [Grunt usemin](http://grunt-tasks.com/grunt-usemin/)
37 | - [Grunt concurrent](http://grunt-tasks.com/grunt-concurrent/)
38 | - [Grunt contrib copy](http://grunt-tasks.com/grunt-contrib-copy/)
39 | - [Grunt jscs](http://grunt-tasks.com/grunt-jscs/)
40 | - [Grunt contrib watch](http://grunt-tasks.com/grunt-contrib-watch/)
41 | - [Grunt contrib uglify](http://grunt-tasks.com/grunt-contrib-uglify/)
42 | - [How to start using Grunt](http://grunt-tasks.com/start-using-grunt-js/)
--------------------------------------------------------------------------------