├── .gitattributes ├── examples ├── libglobal │ ├── README.md │ ├── principium │ │ └── convert.js │ ├── wrap │ │ ├── wrap.start │ │ └── wrap.end │ ├── principium.js │ ├── tests │ │ ├── index-dist-global.html │ │ ├── index.html │ │ ├── index-dist-amd.html │ │ ├── principium-tests.js │ │ └── qunit.css │ ├── package.json │ ├── Gruntfile.js │ └── lib │ │ └── underscore.js ├── multipage │ ├── www │ │ ├── js │ │ │ ├── app │ │ │ │ ├── controller │ │ │ │ │ ├── c1.js │ │ │ │ │ ├── c2.js │ │ │ │ │ └── Base.js │ │ │ │ ├── model │ │ │ │ │ ├── m1.js │ │ │ │ │ ├── m2.js │ │ │ │ │ └── Base.js │ │ │ │ ├── lib.js │ │ │ │ ├── main1.js │ │ │ │ └── main2.js │ │ │ ├── page1.js │ │ │ ├── page2.js │ │ │ └── common.js │ │ ├── page1.html │ │ └── page2.html │ ├── package.json │ ├── tests │ │ ├── index.html │ │ ├── index-dist.html │ │ ├── tests.js │ │ └── qunit.css │ ├── Gruntfile.js │ └── README.md └── multipage-shim │ ├── www │ ├── js │ │ ├── app │ │ │ ├── controller │ │ │ │ ├── c1.js │ │ │ │ ├── c2.js │ │ │ │ └── Base.js │ │ │ ├── model │ │ │ │ ├── m1.js │ │ │ │ ├── m2.js │ │ │ │ └── Base.js │ │ │ ├── lib.js │ │ │ ├── main2.js │ │ │ └── main1.js │ │ ├── page1.js │ │ ├── page2.js │ │ ├── common.js │ │ └── lib │ │ │ └── underscore.js │ ├── page1.html │ └── page2.html │ ├── package.json │ ├── Gruntfile.js │ └── README.md ├── test ├── fixtures │ ├── hello.js │ ├── world.js │ ├── replaceSingleAlmondDocFragment.html │ ├── project.js │ ├── replaceSingleAlmondNoDocType.html │ ├── replaceSingleAlmond.html │ ├── replaceSingleAlmondWithAttr.html │ ├── replaceSingleAlmondWithComplexAttr.html │ ├── replaceMultiAlmond.html │ ├── requirejs │ │ ├── README.md │ │ └── package.json │ ├── expected_sourcemap.txt │ ├── replaceConditionalComments.html │ └── replaceInDjangoTemplates.html └── require_test.js ├── .travis.yml ├── .npmignore ├── .editorconfig ├── .gitignore ├── .jshintrc ├── AUTHORS.md ├── lib ├── helper │ ├── errorhandler.js │ ├── rjsversion.js │ └── sizeInfo.js ├── almondify.js ├── replace.js └── optimize.js ├── docs ├── sourcemaps.md ├── customrjs.md └── almondIntegration.md ├── LICENSE-MIT ├── package.json ├── tasks └── require.js ├── CONTRIBUTING.md ├── CHANGELOG ├── README.md └── Gruntfile.js /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /examples/libglobal/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/hello.js: -------------------------------------------------------------------------------- 1 | define(function(){return "hello";}); 2 | -------------------------------------------------------------------------------- /test/fixtures/world.js: -------------------------------------------------------------------------------- 1 | define(function(){return "world";}); 2 | -------------------------------------------------------------------------------- /test/fixtures/replaceSingleAlmondDocFragment.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/fixtures/project.js: -------------------------------------------------------------------------------- 1 | require(['hello', 'world'], function(hello, world) { 2 | console.log(hello,world); 3 | }); 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.8" 4 | - "0.10" 5 | before_script: 6 | - npm install -g grunt-cli 7 | -------------------------------------------------------------------------------- /test/fixtures/replaceSingleAlmondNoDocType.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/controller/c1.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var c1 = new Base('Controller 1'); 3 | return c1; 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/controller/c2.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var c2 = new Base('Controller 2'); 3 | return c2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/replaceSingleAlmond.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/controller/c1.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var c1 = new Base('Controller 1'); 3 | return c1; 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/controller/c2.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var c2 = new Base('Controller 2'); 3 | return c2; 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/model/m1.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var m1 = new Base('This is the data for Page 1'); 3 | return m1; 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/model/m2.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var m2 = new Base('This is the data for Page 2'); 3 | return m2; 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/model/m1.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var m1 = new Base('This is the data for Page 1'); 3 | return m1; 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/model/m2.js: -------------------------------------------------------------------------------- 1 | define(['./Base'], function (Base) { 2 | var m2 = new Base('This is the data for Page 2'); 3 | return m2; 4 | }); 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /test/ 3 | /docs/ 4 | /examples/ 5 | .editorconfig 6 | .gitattributes 7 | .gitignore 8 | .jshinttrc 9 | .npmignore 10 | .travis.yml 11 | -------------------------------------------------------------------------------- /test/fixtures/replaceSingleAlmondWithAttr.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/lib.js: -------------------------------------------------------------------------------- 1 | define(['jquery'], function ($) { 2 | return { 3 | getBody: function () { 4 | return $('body'); 5 | } 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/lib.js: -------------------------------------------------------------------------------- 1 | define(['jquery'], function ($) { 2 | return { 3 | getBody: function () { 4 | return $('body'); 5 | } 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /examples/multipage/www/js/page1.js: -------------------------------------------------------------------------------- 1 | //Load common code that includes config, then load the app logic for this page. 2 | require(['./common'], function (common) { 3 | require(['app/main1']); 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage/www/js/page2.js: -------------------------------------------------------------------------------- 1 | //Load common code that includes config, then load the app logic for this page. 2 | require(['./common'], function (common) { 3 | require(['app/main2']); 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/page1.js: -------------------------------------------------------------------------------- 1 | //Load common code that includes config, then load the app logic for this page. 2 | require(['./common'], function (common) { 3 | require(['app/main1']); 4 | }); 5 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/page2.js: -------------------------------------------------------------------------------- 1 | //Load common code that includes config, then load the app logic for this page. 2 | require(['./common'], function (common) { 3 | require(['app/main2']); 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/replaceSingleAlmondWithComplexAttr.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/libglobal/principium/convert.js: -------------------------------------------------------------------------------- 1 | define(['underscore'], function (_) { 2 | 'use strict'; 3 | 4 | function convert(text) { 5 | return _.escape(text); 6 | } 7 | 8 | return convert; 9 | }); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true -------------------------------------------------------------------------------- /test/fixtures/replaceMultiAlmond.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/fixtures/requirejs/README.md: -------------------------------------------------------------------------------- 1 | # requirejs 2 | 3 | RequireJS for use in Node. includes: 4 | 5 | * r.js: the RequireJS optimizer, and AMD runtime for use in Node. 6 | * require.js: The browser-based AMD loader. 7 | 8 | More information at http://requirejs.org 9 | 10 | -------------------------------------------------------------------------------- /examples/multipage/www/page1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page 1 5 | 6 | 7 | 8 | Go to Page 2 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/multipage/www/page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page 2 5 | 6 | 7 | 8 | Go to Page 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/page1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page 1 5 | 6 | 7 | 8 | Go to Page 2 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page 2 5 | 6 | 7 | 8 | Go to Page 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /examples/libglobal/dist/ 3 | /examples/multipage/www-built/ 4 | /examples/multipage-shim/www-built/ 5 | /examples/libglobal/node_modules/ 6 | /examples/multipage/node_modules/ 7 | /examples/multipage-shim/node_modules/ 8 | /docs/complexity/ 9 | /tmp/ 10 | .DS_Store 11 | *.log 12 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/model/Base.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | function modelBase(title) { 3 | this.title = title; 4 | } 5 | 6 | modelBase.prototype = { 7 | getTitle: function () { 8 | return this.title; 9 | } 10 | }; 11 | 12 | return modelBase; 13 | }); 14 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/model/Base.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | function modelBase(title) { 3 | this.title = title; 4 | } 5 | 6 | modelBase.prototype = { 7 | getTitle: function () { 8 | return this.title; 9 | } 10 | }; 11 | 12 | return modelBase; 13 | }); 14 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "immed": true, 5 | "latedef": true, 6 | "newcap": true, 7 | "noarg": true, 8 | "sub": true, 9 | "undef": true, 10 | "boss": true, 11 | "eqnull": true, 12 | "node": true, 13 | "es5": true, 14 | "globals": { 15 | "exports": true, 16 | "require": true, 17 | "module": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/libglobal/wrap/wrap.start: -------------------------------------------------------------------------------- 1 | //Copyright 2012, etc. 2 | 3 | (function (root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | // AMD. 6 | define(['jquery', 'underscore'], factory); 7 | } else { 8 | // Browser globals 9 | root.principium = factory(root.$, root._); 10 | } 11 | }(this, function ($, _) { 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/multipage/www/js/common.js: -------------------------------------------------------------------------------- 1 | //The build will inline common dependencies into this file. 2 | 3 | //For any third party dependencies, like jQuery, place them in the lib folder. 4 | 5 | //Configure loading modules from the lib directory, 6 | //except for 'app' ones, which are in a sibling 7 | //directory. 8 | requirejs.config({ 9 | baseUrl: 'js/lib', 10 | paths: { 11 | app: '../app' 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/main1.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var $ = require('jquery'), 3 | lib = require('./lib'), 4 | controller = require('./controller/c1'), 5 | model = require('./model/m1'); 6 | 7 | //A fabricated API to show interaction of 8 | //common and specific pieces. 9 | controller.setModel(model); 10 | $(function () { 11 | controller.render(lib.getBody()); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/main2.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var $ = require('jquery'), 3 | lib = require('./lib'), 4 | controller = require('./controller/c2'), 5 | model = require('./model/m2'); 6 | 7 | //A fabricated API to show interaction of 8 | //common and specific pieces. 9 | controller.setModel(model); 10 | $(function () { 11 | controller.render(lib.getBody()); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/main2.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var $ = require('jquery'), 3 | lib = require('./lib'), 4 | controller = require('./controller/c2'), 5 | model = require('./model/m2'); 6 | 7 | //A fabricated API to show interaction of 8 | //common and specific pieces. 9 | controller.setModel(model); 10 | $(function () { 11 | controller.render(lib.getBody()); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Sebastian Golasch (http://github.com/asciidisco) 2 | 3 | Contributors: 4 | indieisaconcept 5 | 6 | Jörn Zaefferer (https://github.com/jzaefferer) 7 | 8 | Lauri Piispanen (https://github.com/lauripiispanen) 9 | 10 | bernos (https://github.com/bernos) 11 | 12 | Christopher Rogers (https://github.com/chrissrogers) 13 | 14 | Sven Lito (https://github.com/svnlto) 15 | 16 | Kengo TODA (https://github.com/eller86) 17 | 18 | Rodrigo Espinosa (https://github.com/RodEsp) 19 | -------------------------------------------------------------------------------- /lib/helper/errorhandler.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-requirejs 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 Sebastian Golasch, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | module.exports = function(grunt) { 10 | 'use strict'; 11 | 12 | // fail task & log the error 13 | return function(error) { 14 | grunt.log.error(error); 15 | // this.done referres to grunts ´async´ method 16 | this.done(false); 17 | }; 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /examples/libglobal/wrap/wrap.end: -------------------------------------------------------------------------------- 1 | //Register in the values from the outer closure for common dependencies 2 | //as local almond modules 3 | define('jquery', function () { 4 | return $; 5 | }); 6 | define('underscore', function () { 7 | return _; 8 | }); 9 | 10 | //Use almond's special top-level, synchronous require to trigger factory 11 | //functions, get the final module value, and export it as the public 12 | //value. 13 | return require('principium'); 14 | })); 15 | -------------------------------------------------------------------------------- /examples/multipage/www/js/app/controller/Base.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | function controllerBase(id) { 3 | this.id = id; 4 | } 5 | 6 | controllerBase.prototype = { 7 | setModel: function (model) { 8 | this.model = model; 9 | }, 10 | 11 | render: function (bodyDom) { 12 | bodyDom.prepend('

Controller ' + this.id + ' says "' + 13 | this.model.getTitle() + '"

'); 14 | } 15 | }; 16 | 17 | return controllerBase; 18 | }); 19 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/controller/Base.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | function controllerBase(id) { 3 | this.id = id; 4 | } 5 | 6 | controllerBase.prototype = { 7 | setModel: function (model) { 8 | this.model = model; 9 | }, 10 | 11 | render: function (bodyDom) { 12 | bodyDom.prepend('

Controller ' + this.id + ' says "' + 13 | this.model.getTitle() + '"

'); 14 | } 15 | }; 16 | 17 | return controllerBase; 18 | }); 19 | -------------------------------------------------------------------------------- /examples/libglobal/principium.js: -------------------------------------------------------------------------------- 1 | /*global define */ 2 | 3 | /** 4 | * The main module that defines the public interface for principium, 5 | * a made-up library to demonstrate how to construct a source from components. 6 | */ 7 | define(function (require) { 8 | 'use strict'; 9 | 10 | var $ = require('jquery'), 11 | convert = require('principium/convert'); 12 | 13 | //Return the module value. 14 | return { 15 | version: '0.0.1, jQuery version is: ' + $.fn.jquery, 16 | convert: convert 17 | }; 18 | }); 19 | -------------------------------------------------------------------------------- /examples/libglobal/tests/index-dist-global.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Suite - Dist Global 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/multipage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-requirejs-multipage-example", 3 | "version": "0.1.0", 4 | "engines": { 5 | "node": ">=0.6.0" 6 | }, 7 | "scripts": { 8 | "build": "grunt build", 9 | "test": "grunt qunit" 10 | }, 11 | "dependencies": { 12 | "grunt": "0.4.x", 13 | "grunt-requirejs": "0.3.x", 14 | "grunt-contrib-jshint": "0.1.x", 15 | "grunt-contrib-qunit": "0.1.x" 16 | }, 17 | "amd": {}, 18 | "volo": { 19 | "baseUrl": "www/js/lib", 20 | "dependencies": { 21 | "jquery": "github:jquery/jquery/1.7.2" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/multipage/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Suite 6 | 7 | 8 | 9 | 16 | 17 | 18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /examples/multipage/tests/index-dist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Suite 6 | 7 | 8 | 9 | 16 | 17 | 18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /examples/libglobal/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Suite 6 | 7 | 8 | 9 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/fixtures/expected_sourcemap.txt: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"requirejs-sourcemaps.js","sources":["../test/fixtures/hello.js","../test/fixtures/world.js","../test/fixtures/project.js"],"names":[],"mappings":"AACA,KAAA,gFCAA,KAAA,gFCAA,SAAA,QAAA,SAAA,SAAA,EAAA,GACA,QAAA,IAAA,EAAA,KAGA,OAAA,UAAA","sourcesContent":["\neval(\"define(\\'hello\\',[],function(){return \\\"hello\\\";});\\n\\n//# sourceURL=/hello.js\");\n","\neval(\"define(\\'world\\',[],function(){return \\\"world\\\";});\\n\\n//# sourceURL=/world.js\");\n","\nrequire(['hello', 'world'], function(hello, world) {\n console.log(hello,world);\n});\n\ndefine(\"project\", function(){});\n"]} -------------------------------------------------------------------------------- /docs/sourcemaps.md: -------------------------------------------------------------------------------- 1 | # Sourcemaps 2 | 3 | Sourcemaps can be used like described in the [requirejs docs](http://requirejs.org/docs/optimization.html#sourcemaps) 4 | 5 | Note: Make sure to set the optimize property to ´uglify2´! 6 | 7 | ## Example 8 | 9 | ```javascript 10 | requirejs: { 11 | mysourcemapped: { 12 | options: { 13 | baseUrl: 'my/project', 14 | name: 'project', 15 | out: 'dist/main-sourcemapped.js', 16 | optimize: 'uglify2', 17 | generateSourceMaps: true, 18 | preserveLicenseComments: false, 19 | useSourceUrl: true 20 | } 21 | }, 22 | ``` 23 | -------------------------------------------------------------------------------- /examples/libglobal/tests/index-dist-amd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Suite - Dist AMD 6 | 7 | 8 | 9 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/libglobal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-requirejs-libglobal-example", 3 | "version": "0.1.0", 4 | "engines": { 5 | "node": ">=0.6.0" 6 | }, 7 | "scripts": { 8 | "build": "grunt build", 9 | "test": "grunt qunit" 10 | }, 11 | "dependencies": { 12 | "grunt": ">=0.4.x" 13 | }, 14 | "amd": {}, 15 | "volo": { 16 | "baseUrl": "lib", 17 | "dependencies": { 18 | "jquery": "github:jquery/jquery/1.8.0", 19 | "underscore": "github:amdjs/underscore/1.3.3" 20 | } 21 | }, 22 | "devDependencies": { 23 | "grunt-contrib-jshint": "~0.1.0", 24 | "grunt-contrib-qunit": "~0.1.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/common.js: -------------------------------------------------------------------------------- 1 | //The build will inline common dependencies into this file. 2 | 3 | //For any third party dependencies, like jQuery, place them in the lib folder. 4 | 5 | //Configure loading modules from the lib directory, 6 | //except for 'app' ones, which are in a sibling 7 | //directory. 8 | requirejs.config({ 9 | baseUrl: 'js/lib', 10 | paths: { 11 | app: '../app' 12 | }, 13 | shim: { 14 | backbone: { 15 | deps: ['jquery', 'underscore'], 16 | exports: 'Backbone' 17 | }, 18 | underscore: { 19 | exports: '_' 20 | } 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /test/fixtures/replaceConditionalComments.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Testing 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/multipage-shim/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-requirejs-multipageshim-example", 3 | "version": "0.1.0", 4 | "engines": { 5 | "node": ">=0.6.0" 6 | }, 7 | "scripts": { 8 | "build": "grunt build", 9 | "test": "grunt qunit" 10 | }, 11 | "dependencies": { 12 | "grunt": "0.4.x", 13 | "grunt-requirejs": "0.3.x", 14 | "grunt-contrib-jshint": "0.1.x", 15 | "grunt-contrib-qunit": "0.1.x" 16 | }, 17 | "amd": {}, 18 | "volo": { 19 | "baseUrl": "www/js/lib", 20 | "dependencies": { 21 | "jquery": "github:jquery/jquery/1.8.0", 22 | "underscore": "github:documentcloud/underscore/1.3.3", 23 | "backbone": "github:documentcloud/backbone/0.9.2" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/fixtures/replaceInDjangoTemplates.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Testing 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/multipage-shim/www/js/app/main1.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var $ = require('jquery'), 3 | lib = require('./lib'), 4 | controller = require('./controller/c1'), 5 | model = require('./model/m1'), 6 | backbone = require('backbone'), 7 | underscore = require('underscore'); 8 | 9 | //A fabricated API to show interaction of 10 | //common and specific pieces. 11 | controller.setModel(model); 12 | $(function () { 13 | controller.render(lib.getBody()); 14 | 15 | //Display backbone and underscore versions 16 | $('body') 17 | .append('
backbone version: ' + backbone.VERSION + '
') 18 | .append('
underscore version: ' + underscore.VERSION + '
'); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /docs/customrjs.md: -------------------------------------------------------------------------------- 1 | # Using custom r.js versions 2 | 3 | Normally, grunt-requirejs instruments the latest r.js version to build your project. 4 | If you need to build your project against an older r.js version, you can do so by adding 5 | the special ´rjs´ option. 6 | 7 | ## Options 8 | 9 | ### rjs ```string``` (optional) 10 | 11 | This is used to define a path to a custom r.js version 12 | 13 | If you´re custom requirejs npm module is stored under ```node_modules/requirejs```, 14 | the rjs property should point to that folder. 15 | 16 | 17 | ## Example 18 | 19 | ```javascript 20 | requirejs: { 21 | mysourcemapped: { 22 | options: { 23 | rjs: '/path/to/my/custom/requirejs/version' 24 | baseUrl: 'my/project', 25 | name: 'project', 26 | out: 'dist/main-sourcemapped.js' 27 | } 28 | }, 29 | ``` 30 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 asciidisco 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /test/fixtures/requirejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "requirejs", 3 | "description": "Node adapter for RequireJS, for loading AMD modules. Includes RequireJS optimizer", 4 | "version": "2.0.6", 5 | "homepage": "http://github.com/jrburke/r.js", 6 | "author": { 7 | "name": "James Burke", 8 | "email": "jrburke@gmail.com", 9 | "url": "http://github.com/jrburke" 10 | }, 11 | "licenses": [ 12 | { 13 | "type": "BSD", 14 | "url": "https://github.com/jrburke/r.js/blob/master/LICENSE" 15 | }, 16 | { 17 | "type": "MIT", 18 | "url": "https://github.com/jrburke/r.js/blob/master/LICENSE" 19 | } 20 | ], 21 | "main": "./bin/r.js", 22 | "bin": { 23 | "r.js": "./bin/r.js" 24 | }, 25 | "engines": { 26 | "node": ">=0.4.0" 27 | }, 28 | "readme": "# requirejs\n\nRequireJS for use in Node. includes:\n\n* r.js: the RequireJS optimizer, and AMD runtime for use in Node.\n* require.js: The browser-based AMD loader.\n\nMore information at http://requirejs.org\n\n", 29 | "_id": "requirejs@2.0.6", 30 | "dist": { 31 | "shasum": "bc6dd244aa638185cf63698692f739a7c89d296c" 32 | }, 33 | "_from": "requirejs@2.0.x" 34 | } 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-requirejs", 3 | "description": "Building require.js based applications with grunt", 4 | "version": "0.4.2", 5 | "homepage": "https://github.com/asciidisco/grunt-requirejs", 6 | "author": { 7 | "name": "Sebastian Golasch", 8 | "email": "public@asciidisco.com" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "http://github.com/asciidisco/grunt-requirejs" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/asciidisco/grunt-requirejs/issues" 16 | }, 17 | "licenses": [ 18 | { 19 | "type": "MIT", 20 | "url": "https://github.com/asciidisco/grunt-requirejs/blob/master/LICENSE-MIT" 21 | } 22 | ], 23 | "main": "Grunfile.js", 24 | "engines": { 25 | "node": ">=0.8.0" 26 | }, 27 | "scripts": { 28 | "test": "grunt --verbose" 29 | }, 30 | "dependencies": { 31 | "requirejs": "2.1.x", 32 | "cheerio": "0.13.x", 33 | "almond": "0.2.x", 34 | "gzip-js": "0.3.x", 35 | "q": "0.8.x" 36 | }, 37 | "devDependencies": { 38 | "grunt": "~0.4.0", 39 | "grunt-contrib-clean": "~0.4.0", 40 | "grunt-contrib-copy": "~0.4.0", 41 | "grunt-contrib-jshint": "~0.1.1", 42 | "grunt-contrib-nodeunit": "~0.1.2", 43 | "grunt-contrib-qunit": "~0.1.1", 44 | "semver": "~1.1.4", 45 | "grunt-complexity": "~0.1.3", 46 | "grunt-plato": "~0.2.1" 47 | }, 48 | "peerDependencies": { 49 | "grunt": "~0.4.0" 50 | }, 51 | "keywords": [ 52 | "gruntplugin", 53 | "requirejs" 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /lib/helper/rjsversion.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-require 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 asciidisco 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | exports.init = function(grunt) { 10 | 'use strict'; 11 | 12 | var fs = require('fs'); 13 | var exports = {}; 14 | 15 | // privates 16 | var isDefaultVersion = true; 17 | var requirejs = null; 18 | 19 | // Returns a requirejs instance 20 | exports.getRequirejs = function(config) { 21 | var defaultRequire = require('requirejs'); 22 | 23 | // check if we should load a custom requirejs version 24 | if (config.rjs) { 25 | var rjsPathname = config.rjs + '/bin/r.js'; 26 | 27 | // check if the custom version is available, then load & return the 28 | // custom version, else default to the standard bundled requirejs 29 | if (fs.existsSync(rjsPathname)) { 30 | requirejs = require(rjsPathname); 31 | isDefaultVersion = false; 32 | return requirejs; 33 | } 34 | 35 | } 36 | 37 | isDefaultVersion = true; 38 | requirejs = defaultRequire; 39 | return requirejs; 40 | }; 41 | 42 | // Returns the version number of the currently used requirejs library 43 | exports.getRequirejsVersionInfo = function() { 44 | return requirejs.version; 45 | }; 46 | 47 | // Returns a boolean flag that determines if we´re using 48 | // the default bundled version or a user defined custom requirejs version 49 | exports.isCustomLibrary = function() { 50 | return !isDefaultVersion; 51 | }; 52 | 53 | return exports; 54 | }; 55 | -------------------------------------------------------------------------------- /examples/libglobal/tests/principium-tests.js: -------------------------------------------------------------------------------- 1 | /*global require, define, test, expect, strictEqual, location */ 2 | 3 | if (typeof require === 'function' && require.config) { 4 | require.config({ 5 | baseUrl: '../lib', 6 | paths: { 7 | //Path relative to baseUrl 8 | 'principium': '../principium' 9 | }, 10 | shim: { 11 | 'underscore': { 12 | exports: '_' 13 | } 14 | } 15 | }); 16 | 17 | //Override if in "dist" mode 18 | if (location.href.indexOf('-dist') !== -1) { 19 | //Set location of principium to the dist location 20 | require.config({ 21 | paths: { 22 | 'principium': '../dist/principium' 23 | } 24 | }); 25 | } 26 | } 27 | 28 | (function (root, factory) { 29 | 'use strict'; 30 | 31 | if (typeof define === 'function' && define.amd) { 32 | // AMD. 33 | define(['principium', 'jquery'], factory); 34 | } else { 35 | // Browser globals 36 | factory(root.principium, root.jQuery); 37 | } 38 | }(this, function (principium, $) { 39 | 'use strict'; 40 | 41 | test('version test', function () { 42 | expect(1); 43 | strictEqual(principium.version, 44 | '0.0.1, jQuery version is: ' + $.fn.jquery, 45 | 'Version concatenated'); 46 | }); 47 | 48 | test('conversion test', function () { 49 | expect(1); 50 | strictEqual(principium.convert('Harry & Sally'), 51 | 'Harry & Sally', 52 | 'Ampersand converted'); 53 | }); 54 | })); 55 | -------------------------------------------------------------------------------- /tasks/require.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-requirejs 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 Sebastian Golasch, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | module.exports = function (grunt) { 10 | 'use strict'; 11 | 12 | // External libs. 13 | var Q = require('q'); 14 | 15 | // Path to internal libs 16 | var intLibPath = '../lib/'; 17 | 18 | // Internal libs. 19 | var errorHandler = require(intLibPath + 'helper/errorhandler')(grunt); 20 | var optimize = require(intLibPath + 'optimize').init(grunt); 21 | var almondify = require(intLibPath + 'almondify').init(grunt); 22 | var replaceAlmondInHtmlFiles = require(intLibPath + 'replace').init(grunt); 23 | 24 | // requirejs Multitask 25 | // runs a promises chain of helper libraries 26 | // the order of the helper libraries is important 27 | // each helper runs independent & has no dependencies on the other helpers 28 | grunt.registerMultiTask('requirejs', 'Runs requirejs optimizer', function() { 29 | var done = this.async(); 30 | 31 | // The functions only accept the plugin 32 | // config as a parameter & only return the config. 33 | // The functions might modify the config during 34 | // the run or add arbitary data. 35 | // Calls ´done´ when all chain is comletely executed 36 | // Calls the ´errorhandler if an error occures during the build 37 | Q.fcall(almondify, this.options()) 38 | .then(optimize) 39 | .then(replaceAlmondInHtmlFiles) 40 | .then(this.data.cb || function () {}) 41 | .fail(errorHandler.bind({done: done})) 42 | .fin(done) 43 | .done(); 44 | 45 | }); 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /examples/libglobal/Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false*/ 2 | module.exports = function(grunt) { 3 | 4 | // replace this line with 5 | // grunt.loadNpmTasks("grunt-requirejs"); 6 | // if you use this example standalone 7 | grunt.loadTasks("../../tasks"); 8 | 9 | grunt.initConfig({ 10 | 11 | qunit: { 12 | all: ['tests/*.html'] 13 | }, 14 | 15 | requirejs: { 16 | std: { 17 | options: { 18 | almond: true, 19 | baseUrl: 'lib', 20 | paths: { 21 | principium: '../principium' 22 | }, 23 | include: ['principium'], 24 | exclude: ['jquery', 'underscore'], 25 | out: 'dist/principium.js', 26 | wrap: { 27 | startFile: 'wrap/wrap.start', 28 | endFile: 'wrap/wrap.end' 29 | } 30 | } 31 | } 32 | }, 33 | 34 | jshint: { 35 | options: { 36 | curly: true, 37 | eqeqeq: true, 38 | immed: true, 39 | latedef: true, 40 | newcap: true, 41 | noarg: true, 42 | sub: true, 43 | undef: true, 44 | eqnull: true, 45 | browser: true, 46 | nomen: true, 47 | globals: { 48 | define: true, 49 | jQuery: true 50 | } 51 | }, 52 | files: ['principium/*.js', 'principium.js'] 53 | } 54 | }); 55 | 56 | grunt.loadNpmTasks('grunt-contrib-jshint'); 57 | grunt.loadNpmTasks('grunt-contrib-qunit'); 58 | 59 | grunt.registerTask('default', ['jshint', 'qunit']); 60 | grunt.registerTask('build', 'requirejs'); 61 | }; 62 | -------------------------------------------------------------------------------- /examples/multipage/tests/tests.js: -------------------------------------------------------------------------------- 1 | /*global require, define, test, expect, strictEqual, location */ 2 | 3 | if (typeof require === 'function' && require.config) { 4 | require.config({ 5 | baseUrl: '../www/js', 6 | paths: { 7 | //Path relative to baseUrl 8 | 'jquery': 'lib/jquery' 9 | } 10 | }); 11 | 12 | //Override if in "dist" mode 13 | if (location.href.indexOf('-dist') !== -1) { 14 | //Set location of principium to the dist location 15 | require.config({ 16 | baseUrl: '../www-built/js' 17 | }); 18 | } 19 | } 20 | 21 | (function (root, factory) { 22 | 'use strict'; 23 | define(['jquery', 'app/model/Base', 'app/model/m1', 'app/model/m2', 'app/controller/c1', 'app/controller/c2'], factory); 24 | }(this, function ($, Base, m1, m2, c1, c2) { 25 | 'use strict'; 26 | 27 | test('base model test', function () { 28 | var base = new Base('Can set title'); 29 | expect(1); 30 | strictEqual(base.getTitle(), 'Can set title', 'Can set title'); 31 | }); 32 | 33 | test('title for page1 can be set', function () { 34 | expect(1); 35 | strictEqual(m1.getTitle(), 'This is the data for Page 1', 'title for page1 can be set'); 36 | }); 37 | 38 | test('title for page2 can be set', function () { 39 | expect(1); 40 | strictEqual(m2.getTitle(), 'This is the data for Page 2', 'title for page2 can be set'); 41 | }); 42 | 43 | test('html for page1 can be generated', function () { 44 | expect(1); 45 | c1.setModel(m1); 46 | c1.render($('#qunit-fixture')); 47 | strictEqual($('#qunit-fixture').text(), 'Controller Controller 1 says "This is the data for Page 1"', 'html for page1 can be set'); 48 | }); 49 | 50 | test('html for page2 can be generated', function () { 51 | expect(1); 52 | c2.setModel(m2); 53 | c2.render($('#qunit-fixture')); 54 | strictEqual($('#qunit-fixture').text(), 'Controller Controller 2 says "This is the data for Page 2"', 'html for page2 can be set'); 55 | }); 56 | 57 | })); 58 | -------------------------------------------------------------------------------- /lib/almondify.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-requirejs 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 Sebastian Golasch, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | exports.init = function(grunt) { 10 | 'use strict'; 11 | 12 | // External libs. 13 | var fs = require('fs'); 14 | // TODO: ditch this when grunt 0.4.0 is out 15 | var util = grunt.util; 16 | 17 | // Prepare the auto insertion of the almond library 18 | // by modifying the users config 19 | return function(config) { 20 | var configClone = util._.clone(config); 21 | var moduleIterator = configClone.modules; 22 | 23 | // check if we should inline almond 24 | if (config.almond === true) { 25 | 26 | // log that we´re including almond 27 | grunt.verbose.writeln('Including almond.js'); 28 | 29 | // prepare the paths object (in case it hasn´t been set yet) 30 | configClone.paths = configClone.paths || {}; 31 | 32 | // set almond path 33 | configClone.paths.almond = require.resolve('almond').replace(/\.js$/, ''); 34 | 35 | // check if the 'removeCombined' option is enabled 36 | // then use a temporary almond file to ensure that the 37 | // almond.js source file doesn´t get deleted 38 | if (config.removeCombined === true) { 39 | configClone.__origAlmond = String(fs.readFileSync(configClone.paths.almond + '.js')); 40 | } 41 | 42 | // modify modules data 43 | if (!util._.isArray(moduleIterator)) { 44 | moduleIterator = [{name: config.name}]; 45 | 46 | if (!util._.isArray(configClone.include)) { 47 | configClone.include = [configClone.name]; 48 | } else { 49 | configClone.include.unshift(configClone.name); 50 | } 51 | 52 | configClone.name = 'almond'; 53 | } 54 | 55 | // modify modules data 56 | moduleIterator.forEach(function(module, idx) { 57 | // log adding of almond to a specific module 58 | grunt.verbose.writeln('Adding almond to module: ' + module.name); 59 | 60 | // check if the module has its own includes 61 | // then append almond to them 62 | // else generate a new includes property 63 | if (util._.isArray(module.include)) { 64 | configClone.modules[idx].include.unshift('almond'); 65 | } else { 66 | if (!util._.isUndefined(configClone.modules)) { 67 | configClone.modules[idx].include = ['almond']; 68 | } 69 | } 70 | 71 | }); 72 | 73 | } 74 | 75 | return configClone; 76 | }; 77 | }; 78 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to grunt-requirejs 2 | 3 | ## Filing issues 4 | If something isn't working like you think it should, please read the documentation first. 5 | 6 | The best way to ensure an issue gets addressed is to file it in the appropriate issues tracker. 7 | 8 | ### Simplify the issue 9 | Try to [reduce your code](http://www.webkit.org/quality/reduction.html) to the bare minimum required to reproduce the issue. This makes it much easier (and much faster) to isolate and fix the issue. 10 | 11 | ### Explain the issue 12 | If we can't reproduce the issue, we can't fix it. Please list the exact steps required to reproduce the issue. Include versions of your OS, Node.js, grunt, etc. Include relevant logs or sample code. 13 | 14 | ## Modifying grunt-requirejs 15 | First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. 16 | 17 | 1. Fork and clone the repo. 18 | 2. Check out the correct branch. Currently, the development happens in the `devel` branch. 19 | 3. Run `npm install` to install all grunt-requirejs dependencies. 20 | 4. Run `grunt travis` to test & lint the plugin. 21 | 22 | Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing breaks. 23 | 24 | ### Submitting pull requests 25 | 26 | 1. Create a new branch, please don't work in your `master` or `devel` branch directly. 27 | 2. Add failing tests for the change you want to make. Run `grunt` to see the tests fail. 28 | 3. Fix stuff. 29 | 4. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done. 30 | 5. Update the documentation to reflect any changes. 31 | 6. Push to your fork and submit a pull request. 32 | 33 | ### Adding tests 34 | Tests are written in NodeUnit & QUnit style. 35 | NodeUnit tests can be run using the ´grunt test´ command. 36 | The tests from the examples directory can be run using ´grunt qunit´, but make sure 37 | you are running ´grunt setUp´ before & ´grunt tearDown´ afterwards. 38 | 39 | ### Syntax 40 | 41 | * Two space indents. Don't use tabs anywhere. Use `\t` if you need a tab character in a string. 42 | * No trailing whitespace, except in markdown files where a linebreak must be forced. 43 | * Don't go overboard with the whitespace. 44 | * No more than [one assignment](http://benalman.com/news/2012/05/multiple-var-statements-javascript/) per `var` statement. 45 | * Delimit strings with single-quotes `'`, not double-quotes `"`. 46 | * Prefer `if` and `else` to ["clever"](http://programmers.stackexchange.com/a/25281) uses of `? :` conditional or `||`, `&&` logical operators. 47 | * Comments are great. Just put them _before_ the line of code, _not_ at the _end_ of the line. 48 | * **When in doubt, follow the conventions you see used in the source already.** 49 | -------------------------------------------------------------------------------- /lib/replace.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-requirejs 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 Sebastian Golasch, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | exports.init = function(grunt) { 10 | 'use strict'; 11 | 12 | // External libs. 13 | var Q = require('q'); 14 | var cheerio = require('cheerio'); 15 | var util = grunt.util; 16 | 17 | return function(config) { 18 | var deferred = Q.defer(); 19 | 20 | // exit early if we're not replacing scripts 21 | if(!(config.replaceRequireScript instanceof Array) || !config.replaceRequireScript.length) { 22 | return config; 23 | } 24 | 25 | // iterate over all modules that are configured for replacement 26 | config.replaceRequireScript.forEach(function (file, idx) { 27 | var files = grunt.file.expand(file.files); 28 | var filesEvaluated = 0; 29 | var filesToEvaluate = files.length; 30 | var modulePath = file.modulePath; 31 | 32 | // iterate over found html files 33 | files.forEach(function (file) { 34 | // load file contents 35 | var contents = String(grunt.file.read(file, 'utf-8')); 36 | // reference to script regex https://github.com/jquery/jquery/blob/1.7.2/src/ajax.js#L14 37 | var script_re = /)<[^<]*)*<\/script>/gi, 38 | matches = contents.match(script_re); 39 | 40 | if(util._.isNull(matches)){ 41 | // decrement the amount of files we needed to evaluated 42 | // since one has nothing for us. 43 | filesToEvaluate--; 44 | } else { 45 | 46 | [].slice.call(matches).forEach(function(match, i){ 47 | var $ = cheerio.load(match), 48 | elm = $('script'); 49 | if (elm.attr('data-main')){ 50 | var insertScript = (modulePath || elm.attr('data-main')); 51 | elm.attr('src', insertScript + '.js'); 52 | elm.removeAttr('data-main'); 53 | // replace i'th occurrence in content 54 | var j = 0; 55 | contents = contents.replace(script_re, function(match){ 56 | j++; 57 | return (j-1 === i) ? $.html() : match; 58 | }); 59 | } 60 | }); 61 | 62 | grunt.log.writeln('Updating requirejs script tag for file', file); 63 | grunt.file.write(file, contents); 64 | // increment the amount of files successfully evaluated. 65 | filesEvaluated++; 66 | } 67 | 68 | if (filesEvaluated >= filesToEvaluate) { 69 | // only resolve after all files have been evaluated 70 | deferred.resolve(config); 71 | } 72 | 73 | }); 74 | }); 75 | 76 | return deferred.promise; 77 | }; 78 | }; 79 | -------------------------------------------------------------------------------- /lib/optimize.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-requirejs 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 Sebastian Golasch, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | exports.init = function(grunt) { 10 | 'use strict'; 11 | 12 | // External libs. 13 | var Q = require('q'); 14 | var fs = require('fs'); 15 | var util = grunt.util; 16 | 17 | // Internal libs. 18 | var sizeInfo = require('./helper/sizeInfo').init(grunt); 19 | var rjsversion = require('./helper/rjsversion').init(grunt); 20 | 21 | // Runs the requirejs optimizer 22 | // collects the fileSizes (before & after optimization) 23 | return function xxx(config) { 24 | var deferred = Q.defer(); 25 | var pathMap = {}; 26 | 27 | // load the requirejs optimizer 28 | var rjs = rjsversion.getRequirejs(config); 29 | 30 | // check if we have a user set onBuildWrite config option 31 | // if so, store locally 32 | if (config.onBuildWrite) { 33 | var onBuildWrite = config.onBuildWrite; 34 | } 35 | 36 | // check if we have a user set onBuildRead config option 37 | // if so, store locally 38 | if (config.onBuildRead) { 39 | var onBuildRead = config.onBuildRead; 40 | } 41 | 42 | // override the oldOnBuildRead to collect the single file contents 43 | // so we can generate file size stats later on 44 | config.onBuildRead = function (moduleName, path, contents) { 45 | // grab the file contents 46 | pathMap[path] = contents; 47 | 48 | // call old onBuildRead if defined 49 | if (onBuildRead) { 50 | return onBuildRead(moduleName, path, contents); 51 | } 52 | 53 | return contents; 54 | }; 55 | 56 | // call the requirejs optimizer 57 | rjs.optimize(config, function(result) { 58 | // log the original requirejs builder output 59 | grunt.verbose.write(result); 60 | 61 | // log requirejs optimizer process ended 62 | grunt.log.ok('RequireJS optimizer finished'); 63 | 64 | // check if we need to replace the original almond file with our temp contents 65 | if (config.__origAlmond) { 66 | fs.writeFileSync(config.paths.almond + '.js', config.__origAlmond); 67 | } 68 | 69 | // display sizes of modules 70 | if (util._.isArray(config.modules) && config.dir) { 71 | var modulesResolved = 0; 72 | var moduleCount = config.modules.length; 73 | 74 | // iterate over all defined modules 75 | config.modules.forEach(function(module) { 76 | sizeInfo.statsGenerator(module, result, config, pathMap); 77 | deferred.resolve(config); 78 | }); 79 | } else { 80 | if (config.out) { 81 | sizeInfo.statsGenerator(config.out, result, config, pathMap); 82 | } 83 | deferred.resolve(config); 84 | } 85 | 86 | }, function(error) { 87 | deferred.reject(error); 88 | }); 89 | 90 | return deferred.promise; 91 | }; 92 | }; 93 | -------------------------------------------------------------------------------- /examples/multipage/Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false*/ 2 | module.exports = function(grunt) { 3 | 4 | grunt.initConfig({ 5 | 6 | requirejs: { 7 | std: { 8 | options: { 9 | appDir: 'www', 10 | baseUrl: 'js/lib', 11 | paths: { 12 | app: '../app' 13 | }, 14 | dir: 'www-built', 15 | modules: [ 16 | //First set up the common build layer. 17 | { 18 | //module names are relative to baseUrl 19 | name: '../common', 20 | //List common dependencies here. Only need to list 21 | //top level dependencies, "include" will find 22 | //nested dependencies. 23 | include: [ 24 | 'jquery', 25 | 'app/lib', 26 | 'app/controller/Base', 27 | 'app/model/Base' 28 | ] 29 | }, 30 | //Now set up a build layer for each page, but exclude 31 | //the common one. "exclude" will exclude nested 32 | //the nested, built dependencies from "common". Any 33 | //"exclude" that includes built modules should be 34 | //listed before the build layer that wants to exclude it. 35 | //"include" the appropriate "app/main*" module since by default 36 | //it will not get added to the build since it is loaded by a nested 37 | //require in the page*.js files. 38 | { 39 | //module names are relative to baseUrl/paths config 40 | name: '../page1', 41 | include: ['app/main1'], 42 | exclude: ['../common'] 43 | }, 44 | { 45 | //module names are relative to baseUrl 46 | name: "../page2", 47 | include: ["app/main2"], 48 | exclude: ["../common"] 49 | } 50 | ] 51 | } 52 | } 53 | }, 54 | 55 | jshint: { 56 | options: { 57 | curly: true, 58 | eqeqeq: true, 59 | immed: true, 60 | latedef: true, 61 | newcap: true, 62 | noarg: true, 63 | sub: true, 64 | undef: true, 65 | eqnull: true, 66 | browser: true, 67 | nomen: true, 68 | globals: { 69 | define: true, 70 | requirejs: true, 71 | require: true 72 | } 73 | }, 74 | all: ['www/js/app/*.js', 'www/js/common.js', 'www/js/page1.js', 'www/js/page2.js'] 75 | }, 76 | 77 | qunit: { 78 | all: ['tests/index.html'] 79 | } 80 | }); 81 | 82 | // replace this line with 83 | // grunt.loadNpmTasks("require-js"); 84 | // if you use this example standalone 85 | grunt.loadTasks("../../tasks"); 86 | grunt.loadNpmTasks('grunt-contrib-jshint'); 87 | grunt.loadNpmTasks('grunt-contrib-qunit'); 88 | 89 | grunt.registerTask('default', ['jshint', 'qunit']); 90 | grunt.registerTask('build', 'requirejs'); 91 | }; 92 | -------------------------------------------------------------------------------- /examples/multipage-shim/Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false*/ 2 | module.exports = function(grunt) { 3 | 4 | grunt.initConfig({ 5 | 6 | requirejs: { 7 | std: { 8 | options: { 9 | appDir: 'www', 10 | mainConfigFile: 'www/js/common.js', 11 | dir: 'www-built', 12 | modules: [ 13 | //First set up the common build layer. 14 | { 15 | //module names are relative to baseUrl 16 | name: '../common', 17 | //List common dependencies here. Only need to list 18 | //top level dependencies, "include" will find 19 | //nested dependencies. 20 | include: [ 21 | 'jquery', 22 | 'app/lib', 23 | 'app/controller/Base', 24 | 'app/model/Base' 25 | ] 26 | }, 27 | //Now set up a build layer for each main layer, but exclude 28 | //the common one. "exclude" will exclude nested 29 | //the nested, built dependencies from "common". Any 30 | //"exclude" that includes built modules should be 31 | //listed before the build layer that wants to exclude it. 32 | //The "page1" and "page2" modules are **not** the targets of 33 | //the optimization, because shim config is in play, and 34 | //shimmed dependencies need to maintain their load order. 35 | //In this example, common.js will hold jquery, so backbone 36 | //needs to be delayed from loading until common.js finishes. 37 | //That loading sequence is controlled in page1.js. 38 | { 39 | //module names are relative to baseUrl/paths config 40 | name: 'app/main1', 41 | exclude: ['../common'] 42 | }, 43 | 44 | { 45 | //module names are relative to baseUrl 46 | name: 'app/main2', 47 | exclude: ['../common'] 48 | } 49 | ] 50 | } 51 | } 52 | }, 53 | 54 | jshint: { 55 | options: { 56 | curly: true, 57 | eqeqeq: true, 58 | immed: true, 59 | latedef: true, 60 | newcap: true, 61 | noarg: true, 62 | sub: true, 63 | undef: true, 64 | eqnull: true, 65 | browser: true, 66 | nomen: true, 67 | globals: { 68 | define: true, 69 | requirejs: true, 70 | require: true 71 | } 72 | }, 73 | all: ['www/js/app/*.js', 'www/js/common.js', 'www/js/page1.js', 'www/js/page2.js'] 74 | }, 75 | 76 | qunit: { 77 | all: ['tests/*.html'] 78 | } 79 | }); 80 | 81 | // replace this line with 82 | // grunt.loadNpmTasks("require-js"); 83 | // if you use this example standalone 84 | grunt.loadTasks("../../tasks"); 85 | grunt.loadNpmTasks('grunt-contrib-jshint'); 86 | grunt.loadNpmTasks('grunt-contrib-qunit'); 87 | 88 | grunt.registerTask('default', ['jshint', 'build']); 89 | grunt.registerTask('build', 'requirejs'); 90 | }; 91 | -------------------------------------------------------------------------------- /lib/helper/sizeInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-require 3 | * https://github.com/asciidisco/grunt-requirejs 4 | * 5 | * Copyright (c) 2012 asciidisco 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | exports.init = function(grunt) { 10 | 'use strict'; 11 | 12 | // External libs. 13 | var fs = require('fs'); 14 | var gzip = require('gzip-js'); 15 | // TODO: ditch this when grunt 0.4.0 is out 16 | var util = grunt.util; 17 | var exports = {}; 18 | 19 | // Return gzipped source. 20 | exports.gzip = function(src) { 21 | return src ? gzip.zip(src, {}) : ''; 22 | }; 23 | 24 | // Collect & output some size info about a file 25 | exports.info = function(module, optimized, filecontents, uncompressed, silent) { 26 | var gzipSize = String(exports.gzip(filecontents).length); 27 | var optFileSize = String(filecontents.length); 28 | var fileSize = String((!uncompressed) ? optFileSize : uncompressed.length); 29 | var messageUncompressed = 'Uncompressed size: ' + fileSize.green + ' bytes.'; 30 | var messageCompressed = 'Compressed size: ' + gzipSize.green + ' bytes gzipped.' + (optimized !== false ? ' (' + optFileSize.green + ' bytes minified)' : ''); 31 | 32 | // check if output is muted 33 | if (silent !== true) { 34 | grunt.log.writeln('\n' + module.underline); 35 | grunt.log.writeln(messageUncompressed); 36 | grunt.log.writeln(messageCompressed); 37 | } 38 | 39 | // return traced informations 40 | return {module: module, gzipSize: gzipSize, fileSize: fileSize, optFileSize: optFileSize, messageUncompressed: messageUncompressed, messageCompressed: messageCompressed}; 41 | }; 42 | 43 | // Collect the uncompressed modules file contents 44 | exports.uncompressedFilesContent = function(result, pathMap) { 45 | // split the requirejs result by its newlines 46 | // to have a proper source file map 47 | var files = result.split(/\r\n|\r|\n/); 48 | var fileContents = ''; 49 | var pathMapKeys = Object.keys(pathMap); 50 | var parsedModules = []; 51 | 52 | // iterate over all modules to collect the uncompressed size 53 | files.forEach(function (name) { 54 | util._.each(pathMapKeys, function (key) { 55 | // check if we havent processed the module yet 56 | if (key.search(name) !== -1 && name !== '' && !parsedModules[name]) { 57 | fileContents += pathMap[key]; 58 | } 59 | }); 60 | }); 61 | 62 | return fileContents; 63 | }; 64 | 65 | // Computes the uncompressed, compressed & gzipped file sizes 66 | exports.statsGenerator = function (module, result, config, pathMap) { 67 | if (fs.existsSync(module._buildPath)) { 68 | exports.info(module.name, (config.optimize !== 'none' ? true : false), grunt.file.read(module._buildPath), this.uncompressedFilesContent(result, pathMap), false); 69 | } else { 70 | if (fs.existsSync(module)) { 71 | exports.info(module, (config.optimize !== 'none' ? true : false), grunt.file.read(module), this.uncompressedFilesContent(result, pathMap), false); 72 | } else { 73 | grunt.fail.warn('File not found for module: ' + module.name); 74 | } 75 | } 76 | }; 77 | 78 | return exports; 79 | }; 80 | -------------------------------------------------------------------------------- /examples/multipage/README.md: -------------------------------------------------------------------------------- 1 | # requirejs/example-multipage 2 | 3 | This project shows how to set up a multi-page requirejs-based project that has 4 | the following goals: 5 | 6 | * Each page uses a mix of common and page-specific modules. 7 | * All pages share the same requirejs config. 8 | * After an optimization build, the common items should be in a shared common 9 | layer, and the page-specific modules should be in a page-specific layer. 10 | * The HTML page should not have to be changed after doing the build. 11 | 12 | **If you want to use [shim config](http://requirejs.org/docs/api.html#config-shim)**, for instance to load Backbone, see 13 | the [requirejs/example-multipage-shim](https://github.com/requirejs/example-multipage-shim) 14 | example instead. This project will not work well with shim config. This project works 15 | best when all the dependencies are AMD modules. 16 | 17 | ## Getting this project template 18 | 19 | If you are using [volo](https://github.com/volojs/volo): 20 | 21 | volo create projectname requirejs/example-multipage 22 | 23 | Otherwise, 24 | [download latest zipball of master](https://github.com/requirejs/example-multipage/zipball/master). 25 | 26 | ## Project layout 27 | 28 | This project has the following layout: 29 | 30 | * **tools**: The requirejs optimizer, **r.js**, and the optimizer config, 31 | **build.js.** 32 | * **www**: The code that runs in the browser while in development mode. 33 | * **www-built**: Generated after an optimizer build. Contains the built code 34 | that can be deployed to the live site. 35 | 36 | This **www** has the following layout: 37 | 38 | 39 | * **page1.html**: page 1 of the app. 40 | * **page2.html**: page 2 of the app. 41 | * **js** 42 | * **app**: the directory to store app-specific modules. 43 | * **lib**: the directory to hold third party modules, like jQuery. 44 | * **common.js**: contains the requirejs config, and it will be the build 45 | target for the set of common modules. 46 | * **page1.js**: used for the data-main for page1.html. Loads the common 47 | module, then loads **app/main1**, the main module for page 1. 48 | * **page2.js**: used for the data-main for page2.html. Loads the common 49 | module, then loads **app/main2**, the main module for page 2. 50 | 51 | To optimize, run: 52 | 53 | node tools/r.js -o tools/build.js 54 | 55 | That build command creates an optimized version of the project in a 56 | **www-built** directory. The **js/common.js** file will contain all the common 57 | modules. **js/page1.js** will contain the page1-specific modules, 58 | **js/page2.js** will contain the page2-specific modules. 59 | 60 | ## Building up the common layer 61 | 62 | As you do builds and see in the build output that each page is including the 63 | same module, add it to common's "include" array in **tools/build.js**. 64 | 65 | It is better to add these common modules to the **tools/build.js** config 66 | instead of doing a require([]) call for them in **js/common.js**. Modules that 67 | are not explicitly required at runtime are not executed when added to common.js 68 | via the include build option. So by using **tools/build.js**, you can include 69 | common modules that may be in 2-3 pages but not all pages. For pages that do 70 | not need a particular common module, it will not be executed. If you put in a 71 | require() call for it in **js/common.js**, then it will always be executed. 72 | 73 | ## More info 74 | 75 | For more information on the optimizer: 76 | http://requirejs.org/docs/optimization.html 77 | 78 | For more information on using requirejs: 79 | http://requirejs.org/docs/api.html 80 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v0.4.1: 2 | date: 2014-03-02 3 | changes: 4 | - Fixes #67 (Comments go missing when replacing script tag) 5 | 6 | v0.4.0: 7 | date: 2013-09-03 8 | changes: 9 | - Remove support for grunt-lodashbuilder (unmaintained module) 10 | - Remove support for grunt-jquerybuilder (can cause problems with installation) 11 | - Remove support for grunt-backbonebuilder 12 | - Remove support for hybrid builds (issue #70) 13 | 14 | v0.3.1: 15 | date: 2012-12-13 16 | changes: 17 | - Fixes #40 (Error messages eaten by 0.3.0) 18 | - Fixes #36 (npm issue installing grunt-requirejs 0.3.0) 19 | - Fixes #38 (Task won't run anymore on v0.3.0) 20 | - Examples are now converted to grunt 0.4.0 21 | 22 | v0.3.0: 23 | date: 2012-12-03 24 | changes: 25 | - Major refactoring (grunt-requirejs now uses deferreds to execute its 'subtasks') 26 | - Added a bunch of more tests 27 | - META file adds & fixes (README, AUTHORS, CONTRIBUTION GUIDE, DOCS) 28 | - Added .jshint & .editorconfig files 29 | - Support for grunt-jquerybuilder 30 | - Support for grunt-lodashbuilder 31 | - Support for grunt-backbonebuilder 32 | - Support for Hybrid builds 33 | - requirejs is now a multitask 34 | - Support for hybrid builds using 35 | - Make sure to use the latest r.js version from the 2.1.x branch 36 | - Custom requirejs versions can now be used by the user 37 | - Grunt 0.4.0 compatibility 38 | - Support for the ´removeCombined´ option, when using almond 39 | - Added support for sourceMaps when using 'uglify2' 40 | - Preparation for the merge with grunt-contrib-requirejs 41 | - Removed not needed Dual Config 42 | - Added code comments 43 | 44 | v0.2.14: 45 | date: 2012-10-01 46 | changes: 47 | - fixes package.json dependecy versions 48 | 49 | v0.2.13: 50 | date: 2012-10-01 51 | changes: 52 | - fixes according to the changes from the last cheerio release 53 | 54 | v0.2.12: 55 | date: 2012-09-25 56 | changes: 57 | - fixes issue of r.js almond-based dependency mixup (added by @chrissrogers) 58 | 59 | v0.2.11: 60 | date: 2012-09-13 61 | changes: 62 | - Fixed issue #17 (almond: false, causes build to fail) 63 | - Added example projects 64 | 65 | v0.2.10: 66 | date: 2012-09-10 67 | changes: 68 | - Fixed issue #4 69 | - Fixed issue #8 70 | 71 | v0.2.9: 72 | date: 2012-07-10 73 | changes: 74 | - Removed jQuery dependency and replaced it with cheerio 75 | - Updated versions of 3rd party libs 76 | 77 | v0.2.8: 78 | date: 2012-05-29 79 | changes: 80 | - RequireJS Version bump to 2.0 81 | 82 | v0.2.7: 83 | date: 2012-05-29 84 | changes: 85 | - Removed npm dependency for tracing the almond file 86 | - Added some informations in the readme about the almond 'wrap=true' 87 | 88 | v0.2.6: 89 | date: 2012-05-21 90 | changes: 91 | - Added 'modulePath' configuration option for specifying your modules path 92 | - Added 'modulePath' documentation 93 | 94 | v0.2.5: 95 | date: 2012-05-20 96 | changes: 97 | - Added dual config 98 | - Optimized almond integration (removed npm dependency) 99 | - Readme updates 100 | - requirejs isnt a multi task anymore 101 | 102 | v0.2.0: 103 | date: 2012-05-08 104 | changes: 105 | - Removed clearTarget (use grunt-contrib clean instead) 106 | - Added [almond](https://github.com/jrburke/almond) integration 107 | - Added automatic almond js module script tag replacement for html files 108 | - Improved documentation 109 | 110 | v0.1.0: 111 | date: 2012-04-23 112 | changes: 113 | - Initial Release 114 | -------------------------------------------------------------------------------- /docs/almondIntegration.md: -------------------------------------------------------------------------------- 1 | # Almond 2 | 3 | If you like to replace require.js with almond.js during the build process, grunt-requirejs comes with an [almond](https://github.com/jrburke/almond) injection mode. 4 | It even can be used to convert your require script calls in your html files to call the 'almondyfied' module, instead of calling require.js 5 | that then calls (e.g. loads) the module. 6 | 7 | ## Options 8 | 9 | ### almond `boolean` (optional) 10 | 11 | This is used indicate if grunt-requirejs should include almond in your combined js file. 12 | 13 | 14 | ### replaceRequireScript `array` (optional) 15 | 16 | This is used to define the files where the script tag attributes should be replaced 17 | and which modules should be taken into account. 18 | 19 | ## Including almond 20 | 21 | ```javascript 22 | requirejs: { 23 | myTaskDefinition: { 24 | options: { 25 | // *insert almond 26 | almond: true, 27 | dir: 'build', 28 | appDir: 'src', 29 | baseUrl: 'js', 30 | paths: { 31 | underscore: '../vendor/underscore', 32 | jquery : '../vendor/jquery', 33 | backbone : '../vendor/backbone' 34 | } 35 | } 36 | } 37 | } 38 | ``` 39 | 40 | ## Including almond & replacing ´script´ tags in html sources 41 | 42 | grunt-requirejs is also capable of automatically changing the src attribute 43 | in your html script tags. 44 | 45 | ```javascript 46 | requirejs: { 47 | myTaskDefinition: { 48 | options: { 49 | // *insert almond in all your modules 50 | almond: true, 51 | // *replace require script calls, with the almond modules 52 | // in the following files 53 | replaceRequireScript: [{ 54 | files: ['build/index.html'], 55 | module: 'main' 56 | }], 57 | // "normal" require config 58 | // *create at least a 'main' module 59 | // thats necessary for using the almond auto insertion 60 | modules: [{name: 'main'}], 61 | dir: 'build', 62 | appDir: 'src', 63 | baseUrl: 'js', 64 | paths: { 65 | underscore: '../vendor/underscore', 66 | jquery : '../vendor/jquery', 67 | backbone : '../vendor/backbone' 68 | } 69 | } 70 | } 71 | } 72 | ``` 73 | 74 | The only constraint for using the auto almond insertion is, that you at least define one module 75 | (mostly named 'main'). 76 | 77 | ## Special cases 78 | 79 | ### Special case, the 'out' property 80 | 81 | If you define a special output name for your generated module file, 82 | you have to specify a "modulePath" property inside your "replaceRequireScript" configuration 83 | 84 | ```javascript 85 | requirejs: { 86 | myTaskDefinition: { 87 | options: { 88 | almond: true, 89 | replaceRequireScript: [{ 90 | files: ['index.html'], 91 | module: 'main', 92 | modulePath: '/js/main-build' 93 | }], 94 | baseUrl: 'js', 95 | paths: { 96 | 'Handlebars': 'libs/Handlebars', 97 | 'Backbone': 'libs/backbone', 98 | 'underscore': 'libs/underscore', 99 | 'json2': 'libs/json2', 100 | }, 101 | out: 'js/main-build.js' 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | ### require function not found after almond integration 108 | First occured in [issue #3](https://github.com/asciidisco/grunt-requirejs/issues/3). 109 | You probably have to set 110 | 111 | ```javascript 112 | requirejs: { 113 | myTaskDefinition: { 114 | options: { 115 | wrap: true 116 | } 117 | } 118 | } 119 | ``` 120 | 121 | like described here: [https://github.com/jrburke/almond#usage](https://github.com/jrburke/almond#usage) 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # grunt-requirejs [![Build Status](https://secure.travis-ci.org/asciidisco/grunt-requirejs.png?branch=master)](http://travis-ci.org/asciidisco/grunt-requirejs) 2 | 3 | > Optimize [require.js](http://requirejs.org/) based projects 4 | 5 | ## Getting Started 6 | _If you haven't used [grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](https://github.com/cowboy/grunt/blob/master/docs/getting_started.md) guide._ 7 | 8 | From the same directory as your project's Gruntfile and package.json, install this plugin with the following command: 9 | 10 | ```bash 11 | npm install grunt-requirejs 12 | ``` 13 | 14 | Once that's done, add this line to your project's Gruntfile: 15 | 16 | ```js 17 | grunt.loadNpmTasks('grunt-requirejs'); 18 | ``` 19 | 20 | ## Overview 21 | 22 | Inside your `Gruntfile.js` file add a section named `requirejs`. This section specifies the options passed to [RequireJS Optimizer](http://requirejs.org/docs/optimization.html). 23 | 24 | ### Parameters 25 | 26 | #### options ```object``` 27 | 28 | This controls how this task (and its helpers) operate and should contain key:value pairs, see options below. 29 | 30 | ### Options 31 | 32 | For a full list of possible options, [see the r.js example build file](https://github.com/jrburke/r.js/blob/master/build/example.build.js). 33 | 34 | ## Config Example 35 | 36 | Example require js optimizer config entry: 37 | 38 | ```javascript 39 | requirejs: { 40 | compile: { 41 | options: { 42 | baseUrl: "path/to/base", 43 | mainConfigFile: "path/to/config.js", 44 | out: "path/to/optimized.js" 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | There is no difference between declaring your require config in your Gruntfile and using a separate requirejs config file. 51 | 52 | > Note: Minification via Closure Compiler is not supported! You can, however, use [grunt-closure-compiler](https://github.com/gmarty/grunt-closure-compiler) as a separate build step after grunt-requirejs. 53 | 54 | ## Almond 55 | _grunt-requirejs is capable of replacing require.js with almond.js automatically_ 56 | 57 | For more infos please take a look at the [Almond Integration](https://github.com/asciidisco/grunt-requirejs/blob/master/docs/almondIntegration.md) document 58 | 59 | ## Using custom r.js versions 60 | _grunt-requirejs lets you specify a custom r.js for your build_ 61 | 62 | For more infos please take a look at the [Using Custom r.js versions](https://github.com/asciidisco/grunt-requirejs/blob/master/docs/customrjs.md) document 63 | 64 | ## Using source maps 65 | _grunt-requirejs can generate sourcemaps when using the r.js v2.1.2 or higher_ 66 | 67 | For more infos please take a look at the [Using Source Maps](https://github.com/asciidisco/grunt-requirejs/blob/master/docs/sourcemaps.md) document 68 | 69 | ## Examples 70 | 71 | There are some project & configuration examples to get you started: 72 | 73 | - [libglobal](https://github.com/asciidisco/grunt-requirejs/tree/master/examples/libglobal) 74 | - [multipage](https://github.com/asciidisco/grunt-requirejs/tree/master/examples/multipage) 75 | - [multipage-shim](https://github.com/asciidisco/grunt-requirejs/tree/master/examples/multipage-shim) 76 | 77 | 78 | ## Release History 79 | Check the [Changleog](https://github.com/asciidisco/grunt-requirejs/blob/master/CHANGELOG) for more information 80 | 81 | ## Contributing 82 | If you like to file an issue or submit a pull request, please check the [contributing guidelines](https://github.com/asciidisco/grunt-requirejs/blob/master/CONTRIBUTING.md) 83 | 84 | ## Contributors 85 | Check the [AUTHORS File](https://github.com/asciidisco/grunt-requirejs/blob/master/AUTHORS.md) for more information 86 | 87 | ## Resources 88 | + [grunt](http://gruntjs.com/) 89 | + [Getting Started](https://github.com/cowboy/grunt/blob/master/docs/getting_started.md) 90 | + [requirejs](http://requirejs.org) 91 | + [almond](https://github.com/jrburke/almond) 92 | 93 | ## License 94 | Copyright (c) 2012 Sebastian Golasch 95 | Licensed under the [MIT license](https://github.com/asciidisco/grunt-requirejs/LICENSE-MIT). 96 | -------------------------------------------------------------------------------- /examples/multipage-shim/README.md: -------------------------------------------------------------------------------- 1 | # requirejs/example-multipage-shim 2 | 3 | This project shows how to set up a multi-page requirejs-based project that has 4 | the following goals: 5 | 6 | * Each page uses a mix of common and page-specific modules. 7 | * All pages share the same requirejs config. 8 | * After an optimization build, the common items should be in a shared common 9 | layer, and the page-specific modules should be in a page-specific layer. 10 | * The HTML page should not have to be changed after doing the build. 11 | * **[shim config](http://requirejs.org/docs/api.html#config-shim)** is used to 12 | load Backbone and underscore. 13 | 14 | This **project is different** from the standard 15 | [requirejs/example-multipage](https://github.com/requirejs/example-multipage) 16 | because [shim config](http://requirejs.org/docs/api.html#config-shim) 17 | is used. Shimmed modules need their dependencies loaded before they are executed. 18 | It is not as robust as normal modules. Additionally, the common.js file has 19 | shim config in it. See the js/app/main1.js file for the Backbone and underscore 20 | use. 21 | 22 | ## Getting this project template 23 | 24 | If you are using [volo](https://github.com/volojs/volo): 25 | 26 | volo create projectname requirejs/example-multipage-shim 27 | 28 | Otherwise, 29 | [download latest zipball of master](https://github.com/requirejs/example-multipage-shim/zipball/master). 30 | 31 | ## Project layout 32 | 33 | This project has the following layout: 34 | 35 | * **tools**: The requirejs optimizer, **r.js**, and the optimizer config, 36 | **build.js.** 37 | * **www**: The code that runs in the browser while in development mode. 38 | * **www-built**: Generated after an optimizer build. Contains the built code 39 | that can be deployed to the live site. 40 | 41 | This **www** has the following layout: 42 | 43 | * **page1.html**: page 1 of the app. 44 | * **page2.html**: page 2 of the app. 45 | * **js** 46 | * **app**: the directory to store app-specific modules. 47 | * **lib**: the directory to hold third party modules, like jQuery. 48 | * **common.js**: contains the requirejs config, and it will be the build 49 | target for the set of common modules. 50 | * **page1.js**: used for the data-main for page1.html. Loads the common 51 | module, then loads **app/main1**, the main module for page 1. 52 | * **page2.js**: used for the data-main for page2.html. Loads the common 53 | module, then loads **app/main2**, the main module for page 2. 54 | 55 | To optimize, run: 56 | 57 | node tools/r.js -o tools/build.js 58 | 59 | That build command creates an optimized version of the project in a 60 | **www-built** directory. The **js/common.js** file will contain all the common 61 | modules. **js/app/main1.js** will contain the main1-specific modules, 62 | **js/app/main2.js** will contain the main2-specific modules. 63 | 64 | This means that for page 1, after an optimization, there will be three scripts 65 | loaded: 66 | 67 | * js/page1.js 68 | * js/common.js 69 | * js/app/main1.js 70 | 71 | If shim config was not used, this could be cut down to two requests. See 72 | [requirejs/example-multipage](https://github.com/requirejs/example-multipage) 73 | for an example of that setup. But it means not using shim config. 74 | 75 | ## Building up the common layer 76 | 77 | As you do builds and see in the build output that each page is including the 78 | same module, add it to common's "include" array in **tools/build.js**. 79 | 80 | It is better to add these common modules to the **tools/build.js** config 81 | instead of doing a require([]) call for them in **js/common.js**. Modules that 82 | are not explicitly required at runtime are not executed when added to common.js 83 | via the include build option. So by using **tools/build.js**, you can include 84 | common modules that may be in 2-3 pages but not all pages. For pages that do 85 | not need a particular common module, it will not be executed. If you put in a 86 | require() call for it in **js/common.js**, then it will always be executed. 87 | 88 | ## More info 89 | 90 | For more information on the optimizer: 91 | http://requirejs.org/docs/optimization.html 92 | 93 | For more information on using requirejs: 94 | http://requirejs.org/docs/api.html 95 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 'use strict'; 3 | 4 | // Project configuration. 5 | grunt.initConfig({ 6 | pkg: '', 7 | 8 | clean: { 9 | examples: [ 10 | '/examples/libglobal/dist/', 11 | '/examples/multipage/www-built/', 12 | '/examples/multipage-shim/www-built/' 13 | ], 14 | tmp: ['tmp'] 15 | }, 16 | 17 | copy: { 18 | main: { 19 | files: [ 20 | {src: ['test/fixtures/*.js'], dest: 'tmp/doNotKillAlmond/', flatten: true, filter: 'isFile'}, // includes files in path 21 | ] 22 | } 23 | }, 24 | 25 | // Configuration to be run (and then tested). 26 | requirejs: { 27 | compile: { 28 | options: { 29 | baseUrl: 'test/fixtures', 30 | name: 'project', 31 | out: 'tmp/requirejs.js' 32 | } 33 | }, 34 | rmCombined: { 35 | options: { 36 | baseUrl: 'tmp/doNotKillAlmond/test/fixtures', 37 | name: 'project', 38 | out: 'tmp/requirejs-killed.js', 39 | almond: true, 40 | removeCombined: true 41 | } 42 | }, 43 | template: { 44 | options: { 45 | baseUrl: 'test/fixtures', 46 | name: 'project', 47 | out: 'tmp/requirejs-template.js' 48 | } 49 | }, 50 | sourcemaps: { 51 | options: { 52 | baseUrl: 'test/fixtures', 53 | name: 'project', 54 | out: 'tmp/requirejs-sourcemaps.js', 55 | optimize: "uglify2", 56 | generateSourceMaps: true, 57 | preserveLicenseComments: false, 58 | useSourceUrl: true 59 | } 60 | } 61 | }, 62 | 63 | nodeunit: { 64 | all: ['test/*_test.js'] 65 | }, 66 | 67 | qunit: { 68 | options: { 69 | timeout: 20000 70 | }, 71 | all: ['examples/**/tests/*.html'] 72 | }, 73 | 74 | complexity: { 75 | generic: { 76 | src: ['Gruntfile.js', 'tasks/**/*.js', 'test/require_test.js', 'lib/**/*.js'], 77 | options: { 78 | errorsOnly: false, 79 | cyclomatic: 10, 80 | halstead: 10, 81 | maintainability: 100 82 | } 83 | } 84 | }, 85 | 86 | plato: { 87 | bc: { 88 | src: ['Gruntfile.js', 'tasks/**/*.js', 'test/require_test.js', 'lib/**/*.js'], 89 | dest: 'docs/complexity' 90 | } 91 | }, 92 | 93 | watch: { 94 | files: '', 95 | tasks: 'default' 96 | }, 97 | 98 | jshint: { 99 | all: ['Gruntfile.js', 'tasks/**/*.js', 'test/require_test.js', 'lib/**/*.js'], 100 | options: { 101 | jshintrc: '.jshintrc' 102 | } 103 | } 104 | }); 105 | 106 | // build all the projects from the ´examples´ folder 107 | // to run some tests against them 108 | grunt.registerTask('buildExampleProjects', function () { 109 | var done = this.async(); 110 | var util = grunt.util; 111 | var examples = 'libglobal multipage multipage-shim'.split(' '); 112 | var preparation = []; 113 | 114 | var checkForPreparation = function () { 115 | if (util._.all(preparation, util._.identity)) { 116 | grunt.log.ok('all examples build'); 117 | done(); 118 | } 119 | }; 120 | 121 | examples.forEach(function () { 122 | preparation.push(false); 123 | }); 124 | 125 | // build examples 126 | examples.forEach(function (example, idx) { 127 | util.spawn({ 128 | cmd: 'grunt', 129 | args: ['build', '--force'], 130 | opts: {cwd: 'examples/' + example} 131 | }, function () { 132 | grunt.log.writeln('> "' + example + '" example build'); 133 | preparation[idx] = true; 134 | checkForPreparation(); 135 | }); 136 | }); 137 | }); 138 | 139 | // Load tasks. 140 | grunt.loadTasks('tasks'); 141 | grunt.loadNpmTasks('grunt-contrib-clean'); 142 | grunt.loadNpmTasks('grunt-contrib-copy'); 143 | grunt.loadNpmTasks('grunt-contrib-jshint'); 144 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 145 | grunt.loadNpmTasks('grunt-contrib-qunit'); 146 | grunt.loadNpmTasks('grunt-complexity'); 147 | grunt.loadNpmTasks('grunt-plato'); 148 | 149 | // Setup the test environment task. 150 | grunt.registerTask('setUp', ['buildExampleProjects', 'copy', 'requirejs']); 151 | 152 | // Default task. 153 | grunt.registerTask('default', ['setUp', 'jshint', 'nodeunit', 'qunit', 'clean']); 154 | }; 155 | -------------------------------------------------------------------------------- /examples/libglobal/tests/qunit.css: -------------------------------------------------------------------------------- 1 | /** 2 | * QUnit v1.9.0 - A JavaScript Unit Testing Framework 3 | * 4 | * http://docs.jquery.com/QUnit 5 | * 6 | * Copyright (c) 2012 John Resig, Jörn Zaefferer 7 | * Dual licensed under the MIT (MIT-LICENSE.txt) 8 | * or GPL (GPL-LICENSE.txt) licenses. 9 | */ 10 | 11 | /** Font Family and Sizes */ 12 | 13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 15 | } 16 | 17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 18 | #qunit-tests { font-size: smaller; } 19 | 20 | 21 | /** Resets */ 22 | 23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 24 | margin: 0; 25 | padding: 0; 26 | } 27 | 28 | 29 | /** Header */ 30 | 31 | #qunit-header { 32 | padding: 0.5em 0 0.5em 1em; 33 | 34 | color: #8699a4; 35 | background-color: #0d3349; 36 | 37 | font-size: 1.5em; 38 | line-height: 1em; 39 | font-weight: normal; 40 | 41 | border-radius: 5px 5px 0 0; 42 | -moz-border-radius: 5px 5px 0 0; 43 | -webkit-border-top-right-radius: 5px; 44 | -webkit-border-top-left-radius: 5px; 45 | } 46 | 47 | #qunit-header a { 48 | text-decoration: none; 49 | color: #c2ccd1; 50 | } 51 | 52 | #qunit-header a:hover, 53 | #qunit-header a:focus { 54 | color: #fff; 55 | } 56 | 57 | #qunit-testrunner-toolbar label { 58 | display: inline-block; 59 | padding: 0 .5em 0 .1em; 60 | } 61 | 62 | #qunit-banner { 63 | height: 5px; 64 | } 65 | 66 | #qunit-testrunner-toolbar { 67 | padding: 0.5em 0 0.5em 2em; 68 | color: #5E740B; 69 | background-color: #eee; 70 | } 71 | 72 | #qunit-userAgent { 73 | padding: 0.5em 0 0.5em 2.5em; 74 | background-color: #2b81af; 75 | color: #fff; 76 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 77 | } 78 | 79 | 80 | /** Tests: Pass/Fail */ 81 | 82 | #qunit-tests { 83 | list-style-position: inside; 84 | } 85 | 86 | #qunit-tests li { 87 | padding: 0.4em 0.5em 0.4em 2.5em; 88 | border-bottom: 1px solid #fff; 89 | list-style-position: inside; 90 | } 91 | 92 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 93 | display: none; 94 | } 95 | 96 | #qunit-tests li strong { 97 | cursor: pointer; 98 | } 99 | 100 | #qunit-tests li a { 101 | padding: 0.5em; 102 | color: #c2ccd1; 103 | text-decoration: none; 104 | } 105 | #qunit-tests li a:hover, 106 | #qunit-tests li a:focus { 107 | color: #000; 108 | } 109 | 110 | #qunit-tests ol { 111 | margin-top: 0.5em; 112 | padding: 0.5em; 113 | 114 | background-color: #fff; 115 | 116 | border-radius: 5px; 117 | -moz-border-radius: 5px; 118 | -webkit-border-radius: 5px; 119 | } 120 | 121 | #qunit-tests table { 122 | border-collapse: collapse; 123 | margin-top: .2em; 124 | } 125 | 126 | #qunit-tests th { 127 | text-align: right; 128 | vertical-align: top; 129 | padding: 0 .5em 0 0; 130 | } 131 | 132 | #qunit-tests td { 133 | vertical-align: top; 134 | } 135 | 136 | #qunit-tests pre { 137 | margin: 0; 138 | white-space: pre-wrap; 139 | word-wrap: break-word; 140 | } 141 | 142 | #qunit-tests del { 143 | background-color: #e0f2be; 144 | color: #374e0c; 145 | text-decoration: none; 146 | } 147 | 148 | #qunit-tests ins { 149 | background-color: #ffcaca; 150 | color: #500; 151 | text-decoration: none; 152 | } 153 | 154 | /*** Test Counts */ 155 | 156 | #qunit-tests b.counts { color: black; } 157 | #qunit-tests b.passed { color: #5E740B; } 158 | #qunit-tests b.failed { color: #710909; } 159 | 160 | #qunit-tests li li { 161 | padding: 5px; 162 | background-color: #fff; 163 | border-bottom: none; 164 | list-style-position: inside; 165 | } 166 | 167 | /*** Passing Styles */ 168 | 169 | #qunit-tests li li.pass { 170 | color: #3c510c; 171 | background-color: #fff; 172 | border-left: 10px solid #C6E746; 173 | } 174 | 175 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 176 | #qunit-tests .pass .test-name { color: #366097; } 177 | 178 | #qunit-tests .pass .test-actual, 179 | #qunit-tests .pass .test-expected { color: #999999; } 180 | 181 | #qunit-banner.qunit-pass { background-color: #C6E746; } 182 | 183 | /*** Failing Styles */ 184 | 185 | #qunit-tests li li.fail { 186 | color: #710909; 187 | background-color: #fff; 188 | border-left: 10px solid #EE5757; 189 | white-space: pre; 190 | } 191 | 192 | #qunit-tests > li:last-child { 193 | border-radius: 0 0 5px 5px; 194 | -moz-border-radius: 0 0 5px 5px; 195 | -webkit-border-bottom-right-radius: 5px; 196 | -webkit-border-bottom-left-radius: 5px; 197 | } 198 | 199 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 200 | #qunit-tests .fail .test-name, 201 | #qunit-tests .fail .module-name { color: #000000; } 202 | 203 | #qunit-tests .fail .test-actual { color: #EE5757; } 204 | #qunit-tests .fail .test-expected { color: green; } 205 | 206 | #qunit-banner.qunit-fail { background-color: #EE5757; } 207 | 208 | 209 | /** Result */ 210 | 211 | #qunit-testresult { 212 | padding: 0.5em 0.5em 0.5em 2.5em; 213 | 214 | color: #2b81af; 215 | background-color: #D2E0E6; 216 | 217 | border-bottom: 1px solid white; 218 | } 219 | #qunit-testresult .module-name { 220 | font-weight: bold; 221 | } 222 | 223 | /** Fixture */ 224 | 225 | #qunit-fixture { 226 | position: absolute; 227 | top: -10000px; 228 | left: -10000px; 229 | width: 1000px; 230 | height: 1000px; 231 | } 232 | -------------------------------------------------------------------------------- /examples/multipage/tests/qunit.css: -------------------------------------------------------------------------------- 1 | /** 2 | * QUnit v1.9.0 - A JavaScript Unit Testing Framework 3 | * 4 | * http://docs.jquery.com/QUnit 5 | * 6 | * Copyright (c) 2012 John Resig, Jörn Zaefferer 7 | * Dual licensed under the MIT (MIT-LICENSE.txt) 8 | * or GPL (GPL-LICENSE.txt) licenses. 9 | */ 10 | 11 | /** Font Family and Sizes */ 12 | 13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 15 | } 16 | 17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 18 | #qunit-tests { font-size: smaller; } 19 | 20 | 21 | /** Resets */ 22 | 23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 24 | margin: 0; 25 | padding: 0; 26 | } 27 | 28 | 29 | /** Header */ 30 | 31 | #qunit-header { 32 | padding: 0.5em 0 0.5em 1em; 33 | 34 | color: #8699a4; 35 | background-color: #0d3349; 36 | 37 | font-size: 1.5em; 38 | line-height: 1em; 39 | font-weight: normal; 40 | 41 | border-radius: 5px 5px 0 0; 42 | -moz-border-radius: 5px 5px 0 0; 43 | -webkit-border-top-right-radius: 5px; 44 | -webkit-border-top-left-radius: 5px; 45 | } 46 | 47 | #qunit-header a { 48 | text-decoration: none; 49 | color: #c2ccd1; 50 | } 51 | 52 | #qunit-header a:hover, 53 | #qunit-header a:focus { 54 | color: #fff; 55 | } 56 | 57 | #qunit-testrunner-toolbar label { 58 | display: inline-block; 59 | padding: 0 .5em 0 .1em; 60 | } 61 | 62 | #qunit-banner { 63 | height: 5px; 64 | } 65 | 66 | #qunit-testrunner-toolbar { 67 | padding: 0.5em 0 0.5em 2em; 68 | color: #5E740B; 69 | background-color: #eee; 70 | } 71 | 72 | #qunit-userAgent { 73 | padding: 0.5em 0 0.5em 2.5em; 74 | background-color: #2b81af; 75 | color: #fff; 76 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 77 | } 78 | 79 | 80 | /** Tests: Pass/Fail */ 81 | 82 | #qunit-tests { 83 | list-style-position: inside; 84 | } 85 | 86 | #qunit-tests li { 87 | padding: 0.4em 0.5em 0.4em 2.5em; 88 | border-bottom: 1px solid #fff; 89 | list-style-position: inside; 90 | } 91 | 92 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 93 | display: none; 94 | } 95 | 96 | #qunit-tests li strong { 97 | cursor: pointer; 98 | } 99 | 100 | #qunit-tests li a { 101 | padding: 0.5em; 102 | color: #c2ccd1; 103 | text-decoration: none; 104 | } 105 | #qunit-tests li a:hover, 106 | #qunit-tests li a:focus { 107 | color: #000; 108 | } 109 | 110 | #qunit-tests ol { 111 | margin-top: 0.5em; 112 | padding: 0.5em; 113 | 114 | background-color: #fff; 115 | 116 | border-radius: 5px; 117 | -moz-border-radius: 5px; 118 | -webkit-border-radius: 5px; 119 | } 120 | 121 | #qunit-tests table { 122 | border-collapse: collapse; 123 | margin-top: .2em; 124 | } 125 | 126 | #qunit-tests th { 127 | text-align: right; 128 | vertical-align: top; 129 | padding: 0 .5em 0 0; 130 | } 131 | 132 | #qunit-tests td { 133 | vertical-align: top; 134 | } 135 | 136 | #qunit-tests pre { 137 | margin: 0; 138 | white-space: pre-wrap; 139 | word-wrap: break-word; 140 | } 141 | 142 | #qunit-tests del { 143 | background-color: #e0f2be; 144 | color: #374e0c; 145 | text-decoration: none; 146 | } 147 | 148 | #qunit-tests ins { 149 | background-color: #ffcaca; 150 | color: #500; 151 | text-decoration: none; 152 | } 153 | 154 | /*** Test Counts */ 155 | 156 | #qunit-tests b.counts { color: black; } 157 | #qunit-tests b.passed { color: #5E740B; } 158 | #qunit-tests b.failed { color: #710909; } 159 | 160 | #qunit-tests li li { 161 | padding: 5px; 162 | background-color: #fff; 163 | border-bottom: none; 164 | list-style-position: inside; 165 | } 166 | 167 | /*** Passing Styles */ 168 | 169 | #qunit-tests li li.pass { 170 | color: #3c510c; 171 | background-color: #fff; 172 | border-left: 10px solid #C6E746; 173 | } 174 | 175 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 176 | #qunit-tests .pass .test-name { color: #366097; } 177 | 178 | #qunit-tests .pass .test-actual, 179 | #qunit-tests .pass .test-expected { color: #999999; } 180 | 181 | #qunit-banner.qunit-pass { background-color: #C6E746; } 182 | 183 | /*** Failing Styles */ 184 | 185 | #qunit-tests li li.fail { 186 | color: #710909; 187 | background-color: #fff; 188 | border-left: 10px solid #EE5757; 189 | white-space: pre; 190 | } 191 | 192 | #qunit-tests > li:last-child { 193 | border-radius: 0 0 5px 5px; 194 | -moz-border-radius: 0 0 5px 5px; 195 | -webkit-border-bottom-right-radius: 5px; 196 | -webkit-border-bottom-left-radius: 5px; 197 | } 198 | 199 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 200 | #qunit-tests .fail .test-name, 201 | #qunit-tests .fail .module-name { color: #000000; } 202 | 203 | #qunit-tests .fail .test-actual { color: #EE5757; } 204 | #qunit-tests .fail .test-expected { color: green; } 205 | 206 | #qunit-banner.qunit-fail { background-color: #EE5757; } 207 | 208 | 209 | /** Result */ 210 | 211 | #qunit-testresult { 212 | padding: 0.5em 0.5em 0.5em 2.5em; 213 | 214 | color: #2b81af; 215 | background-color: #D2E0E6; 216 | 217 | border-bottom: 1px solid white; 218 | } 219 | #qunit-testresult .module-name { 220 | font-weight: bold; 221 | } 222 | 223 | /** Fixture */ 224 | 225 | #qunit-fixture { 226 | position: absolute; 227 | top: -10000px; 228 | left: -10000px; 229 | width: 1000px; 230 | height: 1000px; 231 | } 232 | -------------------------------------------------------------------------------- /test/require_test.js: -------------------------------------------------------------------------------- 1 | // External libs. 2 | var grunt = require('grunt'); 3 | var Q = require('q'); 4 | 5 | // Load local tasks. 6 | grunt.loadTasks('tasks'); 7 | 8 | // Path to internal libs 9 | var intLibPath = '../lib/'; 10 | 11 | // Internal libs. 12 | var sizeInfo = require(intLibPath + 'helper/sizeInfo').init(grunt); 13 | var rjsversion = require(intLibPath + 'helper/rjsversion').init(grunt); 14 | var optimize = require(intLibPath + 'optimize').init(grunt); 15 | var almondify = require(intLibPath + 'almondify').init(grunt); 16 | var replaceAlmondInHtmlFiles = require(intLibPath + 'replace').init(grunt); 17 | 18 | exports.require = { 19 | setUp: function(done) { 20 | 'use strict'; 21 | done(); 22 | }, 23 | 24 | // require_size_info helper test 25 | testRequireSizeInfoHelper: function(test) { 26 | 'use strict'; 27 | var helperValuesSeriesA = sizeInfo.info('a', true, 'foo'), 28 | helperValuesSeriesB = sizeInfo.info('b', false, 'foobar'); 29 | test.expect(10); 30 | 31 | // tests here 32 | test.equal(helperValuesSeriesA.module, 'a', 'Should determine the module'); 33 | test.equal(helperValuesSeriesA.gzipSize, 23, 'Should determine the correct gzip size'); 34 | test.equal(helperValuesSeriesA.fileSize, 3, 'Should determine the correct "file" size'); 35 | test.equal(helperValuesSeriesA.messageUncompressed, 'Uncompressed size: \u001b[32m3\u001b[39m bytes.', 'Should output the correct message'); 36 | test.equal(helperValuesSeriesA.messageCompressed, 'Compressed size: \u001b[32m23\u001b[39m bytes gzipped. (\u001b[32m3\u001b[39m bytes minified)', 'Should output the correct message'); 37 | 38 | test.equal(helperValuesSeriesB.module, 'b', 'Should determine the module'); 39 | test.equal(helperValuesSeriesB.gzipSize, 26, 'Should determine the correct gzip size'); 40 | test.equal(helperValuesSeriesB.fileSize, 6, 'Should determine the correct "file" size'); 41 | test.equal(helperValuesSeriesB.messageUncompressed, 'Uncompressed size: \u001b[32m6\u001b[39m bytes.'); 42 | test.equal(helperValuesSeriesB.messageCompressed, 'Compressed size: \u001b[32m26\u001b[39m bytes gzipped.', 'Should output the correct message'); 43 | 44 | test.done(); 45 | }, 46 | 47 | // test the error handler 48 | testErrorHandlerHelper: function(test) { 49 | 'use strict'; 50 | test.expect(2); 51 | var errorHandler = require(intLibPath + 'helper/errorhandler')({ 52 | log: { 53 | error: function(message) { 54 | test.equal(message, 'error', 'Grunt error handler has been called'); 55 | } 56 | } 57 | }); 58 | 59 | errorHandler = errorHandler.bind({done: function(succeded) { 60 | test.equal(succeded, false, 'Done called with a not succeding argument'); 61 | }}); 62 | 63 | errorHandler('error'); 64 | 65 | test.done(); 66 | }, 67 | 68 | // test the require js default version return 69 | testGetDefaultRjsVersion: function(test) { 70 | 'use strict'; 71 | test.expect(3); 72 | var config = {}; 73 | 74 | var rjs = rjsversion.getRequirejs(config); 75 | var version = rjsversion.getRequirejsVersionInfo(); 76 | var isCustom = rjsversion.isCustomLibrary(); 77 | var semver = require('semver'); 78 | 79 | test.equal((typeof rjs === 'function'), true, 'Default library is used if no config given'); 80 | test.ok(semver.satisfies(version, '2.1.x'), 'Version is current'); 81 | test.equal(isCustom, false, 'Default library is used if no config given'); 82 | 83 | test.done(); 84 | }, 85 | 86 | // test the require js custom version return 87 | testGetCustomRjsVersion: function(test) { 88 | 'use strict'; 89 | test.expect(3); 90 | var config = {rjs: __dirname + '/fixtures/requirejs'}; 91 | 92 | var rjs = rjsversion.getRequirejs(config); 93 | var version = rjsversion.getRequirejsVersionInfo(); 94 | var isCustom = rjsversion.isCustomLibrary(); 95 | 96 | test.equal((typeof rjs === 'function'), true, 'Custom library is used if custom config given'); 97 | test.equal(version, '2.0.6', 'Custom version has been set'); 98 | test.equal(isCustom, true, 'Custom library is used if correct config is given'); 99 | 100 | test.done(); 101 | }, 102 | 103 | 'almond helper runs callback even if almond: false': function(test) { 104 | 'use strict'; 105 | test.expect(1); 106 | var config = { 107 | modules: [], 108 | almond: false, 109 | cb: function() { 110 | test.equal(true, true); 111 | test.done(); 112 | } 113 | }; 114 | 115 | Q.fcall(almondify, config) 116 | .then(config.cb || function () {}) 117 | .done(); 118 | }, 119 | 120 | main: function(test) { 121 | 'use strict'; 122 | var expect, result; 123 | test.expect(1); 124 | expect = 'define("hello",[],function(){return"hello"}),define("world",[],function(){return"world"}),require(["hello","world"],function(e,t){console.log(e,t)}),define("project",function(){});'; 125 | result = grunt.file.read('tmp/requirejs.js'); 126 | test.equal(expect, result, 'should optimize javascript modules with requireJS'); 127 | test.done(); 128 | }, 129 | 130 | template: function(test) { 131 | 'use strict'; 132 | var expect, result; 133 | test.expect(1); 134 | expect = 'define("hello",[],function(){return"hello"}),define("world",[],function(){return"world"}),require(["hello","world"],function(e,t){console.log(e,t)}),define("project",function(){});'; 135 | result = grunt.file.read('tmp/requirejs-template.js'); 136 | test.equal(expect, result, 'should process options with template variables.'); 137 | test.done(); 138 | }, 139 | 140 | 'sourcemaps can be generated using uglify2': function(test) { 141 | 'use strict'; 142 | test.expect(5); 143 | 144 | var resultMap = JSON.parse(grunt.file.read('tmp/requirejs-sourcemaps.js.map')); 145 | test.equal(resultMap.version, 3, 'should generate a valid ´.map´ sourcemap file'); 146 | test.equal(resultMap.file, 'requirejs-sourcemaps.js', 'should generate a valid ´.map´ sourcemap file'); 147 | test.equal(resultMap.sources[0], 'hello.js', 'should generate a valid ´.map´ sourcemap file'); 148 | test.equal(resultMap.sources[1], 'world.js', 'should generate a valid ´.map´ sourcemap file'); 149 | test.equal(resultMap.sources[2], 'project.js', 'should generate a valid ´.map´ sourcemap file'); 150 | 151 | test.done(); 152 | }, 153 | 154 | 'requirejs script tag can be replaced with almondified script tag': function(test) { 155 | 'use strict'; 156 | test.expect(1); 157 | var config = { 158 | replaceRequireScript: [{ 159 | files: ['tmp/replaceSingleAlmond.html'], 160 | module: 'main' 161 | }], 162 | modules: [{name: 'main'}], 163 | almond: true 164 | }; 165 | 166 | grunt.file.copy('test/fixtures/replaceSingleAlmond.html', 'tmp/replaceSingleAlmond.html'); 167 | replaceAlmondInHtmlFiles(config).then(function() { 168 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 169 | test.ok(replacedFileContents.search('') > -1, 'should replace script tag ´src´ contents'); 170 | test.done(); 171 | }); 172 | }, 173 | 174 | 'requirejs script tag can be replaced with almondified script tag with no doctype declared (#59)': function(test) { 175 | 'use strict'; 176 | test.expect(1); 177 | var config = { 178 | replaceRequireScript: [{ 179 | files: ['tmp/replaceSingleAlmondNoDocType.html'], 180 | module: 'main' 181 | }], 182 | modules: [{name: 'main'}], 183 | almond: true 184 | }; 185 | 186 | grunt.file.copy('test/fixtures/replaceSingleAlmondNoDocType.html', 'tmp/replaceSingleAlmondNoDocType.html'); 187 | replaceAlmondInHtmlFiles(config).then(function() { 188 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 189 | test.ok(replacedFileContents.search('') > -1, 'should replace script tag ´src´ contents'); 190 | test.done(); 191 | }); 192 | }, 193 | 194 | 'requirejs script tag can be replaced with almondified script tag & leaves attributes': function(test) { 195 | 'use strict'; 196 | test.expect(1); 197 | var config = { 198 | replaceRequireScript: [{ 199 | files: ['tmp/replaceSingleAlmondWithAttr.html'], 200 | module: 'main' 201 | }], 202 | modules: [{name: 'main'}], 203 | almond: true 204 | }; 205 | 206 | grunt.file.copy('test/fixtures/replaceSingleAlmondWithAttr.html', 'tmp/replaceSingleAlmondWithAttr.html'); 207 | replaceAlmondInHtmlFiles(config).then(function() { 208 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 209 | test.ok(replacedFileContents.search('') > -1, 'should replace script tag ´src´ contents, but leaves the other attrs alone'); 210 | test.done(); 211 | }); 212 | }, 213 | 214 | 'requirejs script tag can be replaced with almondified script tag & leaves weird attributes': function(test) { 215 | 'use strict'; 216 | test.expect(1); 217 | var config = { 218 | replaceRequireScript: [{ 219 | files: ['tmp/replaceSingleAlmondWithComplexAttr.html'], 220 | module: 'main' 221 | }], 222 | modules: [{name: 'main'}], 223 | almond: true 224 | }; 225 | 226 | grunt.file.copy('test/fixtures/replaceSingleAlmondWithComplexAttr.html', 'tmp/replaceSingleAlmondWithComplexAttr.html'); 227 | replaceAlmondInHtmlFiles(config).then(function() { 228 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 229 | test.ok(replacedFileContents.search('') > -1, 'should replace script tag ´src´ contents, but leaves the other (complex) attrs alone'); 230 | test.done(); 231 | }); 232 | }, 233 | 234 | 'multiple requirejs script tags can be replaced with almondified script tags': function(test) { 235 | 'use strict'; 236 | test.expect(2); 237 | var config = { 238 | replaceRequireScript: [{ 239 | files: ['tmp/replaceMultiAlmond.html'], 240 | module: ['module1', 'module2'] 241 | }], 242 | modules: [{name: 'module1'}, {name: 'module2'}], 243 | almond: true 244 | }; 245 | 246 | grunt.file.copy('test/fixtures/replaceMultiAlmond.html', 'tmp/replaceMultiAlmond.html'); 247 | replaceAlmondInHtmlFiles(config).then(function() { 248 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 249 | test.ok(replacedFileContents.search('') > -1, 'should replace multiple script tag ´src´ contents, but leaves the other attrs alone'); 250 | test.ok(replacedFileContents.search('') > -1, 'should replace multiple script tag ´src´ contents, but leaves the other attrs alone'); 251 | test.done(); 252 | }); 253 | }, 254 | 255 | 'requirejs script tag can be replaced with almondified script tag in multiple files': function(test) { 256 | 'use strict'; 257 | test.expect(2); 258 | var config = { 259 | replaceRequireScript: [{ 260 | files: ['tmp/multi1.html', 'tmp/multi2.html'], 261 | module: 'main' 262 | }], 263 | modules: [{name: 'main'}], 264 | almond: true 265 | }; 266 | 267 | grunt.file.copy('test/fixtures/replaceSingleAlmond.html', 'tmp/multi1.html'); 268 | grunt.file.copy('test/fixtures/replaceSingleAlmond.html', 'tmp/multi2.html'); 269 | replaceAlmondInHtmlFiles(config).then(function() { 270 | var replacedFileContents1 = grunt.file.read(config.replaceRequireScript[0].files[0]); 271 | var replacedFileContents2 = grunt.file.read(config.replaceRequireScript[0].files[1]); 272 | test.ok(replacedFileContents1.search('') > -1, 'should replace script tag ´src´ contents'); 273 | test.ok(replacedFileContents2.search('') > -1, 'should replace script tag ´src´ contents'); 274 | test.done(); 275 | }); 276 | }, 277 | 278 | 'requirejs script tag should be replaced without HTML/BODY elements when the file contains a fragment': function(test) { 279 | 'use strict'; 280 | test.expect(1); 281 | var config = { 282 | replaceRequireScript: [{ 283 | files: ['tmp/replaceSingleAlmondDocFragment.html'], 284 | module: 'main' 285 | }], 286 | modules: [{name: 'main'}], 287 | almond: true 288 | }; 289 | 290 | grunt.file.copy('test/fixtures/replaceSingleAlmondDocFragment.html', 'tmp/replaceSingleAlmondDocFragment.html'); 291 | replaceAlmondInHtmlFiles(config).then(function() { 292 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 293 | test.ok(replacedFileContents.trim() === '', 'should replace src attribute, and the resulting HTML only contains a script tag'); 294 | test.done(); 295 | }); 296 | }, 297 | 298 | 'using removeCombined option with almond doesnt touch original almond file': function(test) { 299 | 'use strict'; 300 | var result; 301 | test.expect(1); 302 | result = grunt.file.read('node_modules/almond/almond.js'); 303 | test.ok(result.length > 0, 'original almond.js should still be there'); 304 | test.done(); 305 | }, 306 | 307 | 'requirejs script tag should be replaced without messing with conditional html': function(test) { 308 | 'use strict'; 309 | test.expect(2); 310 | var config = { 311 | replaceRequireScript: [{ 312 | files: ['tmp/replaceConditionalComments.html'], 313 | module: 'main' 314 | }], 315 | modules: [{name: 'main'}], 316 | almond: true 317 | }; 318 | 319 | grunt.file.copy('test/fixtures/replaceConditionalComments.html', 'tmp/replaceConditionalComments.html'); 320 | replaceAlmondInHtmlFiles(config).then(function() { 321 | var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); 322 | test.ok(replacedFileContents.search('') > -1, 'should replace script tag ´src´ contents'); 323 | test.ok(replacedFileContents.search('