1 module
.exports = function(grunt
) {
2 grunt
.loadNpmTasks('grunt-contrib-uglify');
3 grunt
.loadNpmTasks('grunt-gjslint');
4 grunt
.loadNpmTasks('grunt-checkrepo');
5 grunt
.loadNpmTasks('grunt-karma');
6 grunt
.loadNpmTasks('grunt-saucelabs');
7 grunt
.loadNpmTasks('grunt-git-status');
8 grunt
.loadNpmTasks('grunt-template');
10 var targetConfig
= require('./target-config.js');
12 var sourceMap
= require('source-map');
21 function concat(sources
, target
, defines
) {
22 config
.uglify
[target
] = {
25 sourceMapName
: target
+ '.map',
37 return 'uglify:' + target
;
40 function compress(source
, target
, defines
) {
41 var name
= concat([source
], target
, defines
);
42 var record
= config
.uglify
[target
];
43 record
.options
.sourceMapIn
= source
+ '.map';
44 record
.options
.banner
= grunt
.file
.read('templates/boilerplate');
45 record
.options
.wrap
= true;
46 record
.options
.compress
.dead_code
= true;
47 record
.options
.mangle
= { eval
: true };
51 function genTarget(target
) {
52 var config
= targetConfig
[target
];
54 generateFromTemplate('templates/web-animations.js', {target
: target
}, target
+ '.dev.js'),
55 generateFromTemplate('templates/web-animations.html', {src
: config
.src
}, target
+ '.dev.html'),
56 generateFromTemplate('templates/runner.html', {target
: target
}, 'test/runner-' + target
+ '.html')];
60 function generateFromTemplate(source
, data
, target
) {
62 targetSpec
[target
] = [source
];
63 config
.template
[target
] = {
69 return 'template:' + target
;
72 function guard(source
, target
) {
73 config
.wrap
[target
] = {
75 preamble
: '(function() {\n' +
76 ' if (document.documentElement.animate) {\n' +
77 ' var player = document.documentElement.animate([], 0);\n' +
78 ' var load = true;\n' +
81 ' "play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(t) {\n' +
82 ' if (player[t] === undefined) {\n' +
87 ' if (!load) { return; }' +
91 return 'wrap:' + target
;
94 function concatWithMaps(sources
, target
) {
95 config
.sourceMapConcat
[target
] = {
98 return 'sourceMapConcat:' + target
;
101 var concatDefines
= {
102 WEB_ANIMATIONS_TESTING
: false
105 function buildWebAnimations1(target
) {
106 var config
= targetConfig
[target
];
107 return genTarget(target
).concat([
108 concat(config
.scopeSrc
.concat(config
.sharedSrc
).concat(config
.webAnimations1Src
), 'inter-raw-' + target
+ '.js', concatDefines
),
109 guard('inter-raw-' + target
+ '.js', 'inter-' + target
+ '.js'),
110 compress('inter-' + target
+ '.js', target
+ '.min.js', concatDefines
)
114 function buildWebAnimationsNext(target
) {
115 var config
= targetConfig
[target
];
116 return genTarget(target
).concat([
117 concat(config
.scopeSrc
.concat(config
.sharedSrc
), 'inter-' + target
+ '-preamble.js', concatDefines
),
118 concat(config
.webAnimations1Src
, 'inter-component-' + target
+ 'web-animations-1.js', concatDefines
),
119 guard('inter-component-' + target
+ 'web-animations-1.js', 'inter-guarded-' + target
+ '-web-animations-1.js'),
120 concat(config
.webAnimationsNextSrc
, 'inter-component-' + target
+ '.js', concatDefines
),
121 concatWithMaps(['inter-' + target
+ '-preamble.js', 'inter-guarded-' + target
+ '-web-animations-1.js', 'inter-component-' + target
+ '.js'],
122 'inter-' + target
+ '.js'),
123 compress('inter-' + target
+ '.js', target
+ '.min.js', concatDefines
)
127 grunt
.registerTask('web-animations', buildWebAnimations1('web-animations'));
128 grunt
.registerTask('web-animations-next', buildWebAnimationsNext('web-animations-next'));
129 grunt
.registerTask('web-animations-next-lite', buildWebAnimationsNext('web-animations-next-lite'));
131 var testTargets
= {'web-animations': {}, 'web-animations-next': {}};
134 uglify
: config
.uglify
,
135 template
: config
.template
,
137 sourceMapConcat
: config
.sourceMapConcat
,
152 '--disable 7,121,110', // 7: Wrong blank line count
153 // 121: Illegal comma at end of object literal
154 // 110: Line too long
173 grunt
.task
.registerMultiTask('test', 'Run <target> tests under Karma', function() {
174 var done
= this.async();
175 var karmaConfig
= require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config.js'), {});
176 var config
= targetConfig
[this.target
];
177 karmaConfig
.files
= ['test/runner.js'].concat(config
.src
, config
.test
);
178 var karmaServer
= require('karma').server
;
179 karmaServer
.start(karmaConfig
, function(exitCode
) {
180 done(exitCode
=== 0);
184 grunt
.task
.registerMultiTask('sauce', 'Run <target> tests under Karma on Saucelabs', function() {
185 var done
= this.async();
186 var karmaConfig
= require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config-ci.js'), {});
187 var config
= targetConfig
[this.target
];
188 karmaConfig
.files
= ['test/runner.js'].concat(config
.src
, config
.test
);
189 karmaConfig
.sauceLabs
.testName
= 'web-animation-next ' + this.target
+ ' Unit tests';
190 var karmaServer
= require('karma').server
;
191 karmaServer
.start(karmaConfig
, function(exitCode
) {
192 done(exitCode
=== 0);
196 grunt
.task
.registerMultiTask('sourceMapConcat', 'concat source files and produce combined source map',
198 var sources
= this.data
.sources
.map(grunt
.file
.read
);
199 var sourceMaps
= this.data
.sources
.map(function(f
) { return grunt
.file
.read(f
+ '.map'); });
201 var outMapGenerator
= new sourceMap
.SourceMapGenerator({file
: this.target
});
203 for (var i
= 0; i
< sources
.length
; i
++) {
205 new sourceMap
.SourceMapConsumer(sourceMaps
[i
]).eachMapping(function(mapping
) {
206 outMapGenerator
.addMapping({
207 generated
: {line
: mapping
.generatedLine
+ lineDelta
, column
: mapping
.generatedColumn
},
208 original
: {line
: mapping
.originalLine
, column
: mapping
.originalColumn
},
209 source
: mapping
.source
, name
: mapping
.name
});
211 var sourceLines
= sources
[i
].split('\n');
212 lineDelta
+= sourceLines
.length
;
213 if (sources
[i
][sources
[i
].length
- 1] !== '\n') {
217 grunt
.file
.write(this.target
, out
);
218 grunt
.file
.write(this.target
+ '.map', outMapGenerator
.toString());
221 grunt
.task
.registerMultiTask('wrap', 'Wrap <target> source file and update source map',
223 var inFile
= grunt
.file
.read(this.data
.source
);
224 var inMap
= grunt
.file
.read(this.data
.source
+ '.map');
225 var inLines
= inFile
.split('\n');
228 // Discover copyright header
229 while (inLines
[i
].length
< 2 || inLines
[i
].substring(0, 2) == '//') {
233 // Fix mapping footer
234 var postamble
= this.data
.postamble
;
235 if (inLines
[inLines
.length
- 1].substring(0, 21) == '//# sourceMappingURL=') {
236 postamble
+= '\n//# sourceMappingURL=' + this.target
+ '.map';
240 var banner
= inLines
.slice(0, i
).join('\n') + '\n';
245 var source
= inLines
.slice(i
, inLines
.length
- 1).join('\n');
247 grunt
.file
.write(this.target
, banner
+ this.data
.preamble
+ source
+ postamble
);
248 var preLines
= this.data
.preamble
.split('\n');
249 var lineDelta
= preLines
.length
;
250 if (this.data
.preamble
[this.data
.preamble
.length
- 1] == '\n') {
253 var charDelta
= preLines
[lineDelta
- 1].length
;
256 var inMapConsumer
= new sourceMap
.SourceMapConsumer(inMap
);
257 var outMapGenerator
= new sourceMap
.SourceMapGenerator({file
: this.target
});
258 inMapConsumer
.eachMapping(function(mapping
) {
259 if (mapping
.generatedLine
== i
+ 1) {
260 mapping
.generatedColumn
+= charDelta
;
262 mapping
.generatedLine
+= lineDelta
;
263 outMapGenerator
.addMapping(
264 {generated
: {line
: mapping
.generatedLine
, column
: mapping
.generatedColumn
},
265 original
: {line
: mapping
.originalLine
, column
: mapping
.originalColumn
},
266 source
: mapping
.source
, name
: mapping
.name
});
268 grunt
.file
.write(this.target
+ '.map', outMapGenerator
.toString());
271 grunt
.task
.registerTask('clean', 'Remove files generated by grunt', function() {
272 grunt
.file
.expand('web-animations*').concat(grunt
.file
.expand('test/runner-*.html')).concat(grunt
.file
.expand('inter-*')).forEach(function(file
) {
273 grunt
.file
.delete(file
);
274 grunt
.log
.writeln('File ' + file
+ ' removed');
278 grunt
.task
.registerTask('default', ['web-animations', 'web-animations-next', 'web-animations-next-lite', 'gjslint']);