diff --git a/CHANGELOG.md b/CHANGELOG.md index b482633f9..34962fed0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ _(none)_ -------------------- +## 4.12.2 (2015-02-27) +* @gkatsev fixed disabling of default text tracks ([view](https://github.com/videojs/video.js/pull/1892)) + ## 4.12.1 (2015-02-19) * @gkatsev fixed the track list reference while switching techs that use emulated tracks ([view](https://github.com/videojs/video.js/pull/1874)) * @gkatsev fixed a Firefox error with the captions settings select menu options ([view](https://github.com/videojs/video.js/pull/1877)) diff --git a/Gruntfile.js b/Gruntfile.js index 613d2191c..f3bb0bbf8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,10 +1,7 @@ module.exports = function(grunt) { - var pkg, s3, semver, version, verParts, uglify, exec; + var pkg, s3, version, verParts; - semver = require('semver'); pkg = grunt.file.readJSON('package.json'); - uglify = require('uglify-js'); - exec = require('child_process').exec; verParts = pkg.version.split('.'); version = { @@ -14,6 +11,7 @@ module.exports = function(grunt) { patch: verParts[2] }; version.majorMinor = version.major + '.' + version.minor; + grunt.vjsVersion = version; // loading predefined source order from source-loader.js // trust me, this is the easist way to do it so far @@ -22,6 +20,8 @@ module.exports = function(grunt) { var sourceFiles; // Needed to satisfy jshint eval(grunt.file.read('./build/source-loader.js')); + grunt.sourceFiles = sourceFiles; + // Project configuration. grunt.initConfig({ pkg: pkg, @@ -117,6 +117,27 @@ module.exports = function(grunt) { ] } }, + fastly: { + options: { + key: process.env.VJS_FASTLY_API_KEY + }, + minor: { + options: { + host: 'vjs.zencdn.net', + urls: [ + version.majorMinor+'/*' + ] + } + }, + patch: { + options: { + host: 'vjs.zencdn.net', + urls: [ + version.full+'/*' + ] + } + } + }, cssmin: { minify: { expand: true, @@ -307,11 +328,22 @@ module.exports = function(grunt) { src: ['package.json', 'bower.json', 'component.json'] } }, - tagrelease: { - file: 'package.json', - commit: true, - message: 'Release %version%', - prefix: 'v' + 'github-release': { + options: { + repository: 'videojs/video.js', + auth: { + user: process.env.VJS_GITHUB_USER, + password: process.env.VJS_GITHUB_TOKEN + }, + release: { + tag_name: 'v'+ version.full, + name: version.full, + body: require('chg').find(version.full).changesRaw + } + }, + files: { + src: ['dist/video-js-'+ version.full +'.zip'] // Files that you want to attach to Release + } } }); @@ -331,8 +363,9 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-zip'); grunt.loadNpmTasks('grunt-banner'); grunt.loadNpmTasks('grunt-version'); - grunt.loadNpmTasks('grunt-tagrelease'); grunt.loadNpmTasks('chg'); + grunt.loadNpmTasks('grunt-fastly'); + grunt.loadNpmTasks('grunt-github-releaser'); // grunt.loadTasks('./docs/tasks/'); // grunt.loadTasks('../videojs-doc-generator/tasks/'); @@ -344,357 +377,8 @@ module.exports = function(grunt) { grunt.registerTask('dev', ['jshint', 'less', 'vjslanguages', 'build', 'qunit:source']); grunt.registerTask('test-qunit', ['pretask', 'qunit']); - // The test task will run `karma:saucelabs` when running in travis, - // when running via a PR from a fork, it'll run qunit tests in phantom using - // karma otherwise, it'll run the tests in chrome via karma - // You can specify which browsers to build with by using grunt-style arguments - // or separating them with a comma: - // grunt test:chrome:firefox # grunt-style - // grunt test:chrome,firefox # comma-separated - grunt.registerTask('test', function() { - var tasks = this.args, - tasksMinified, - tasksMinifiedApi; - - grunt.task.run(['pretask']); - - if (process.env.TRAVIS_PULL_REQUEST !== 'false') { - grunt.task.run(['karma:phantomjs', 'karma:minified_phantomjs', 'karma:minified_api_phantomjs']); - } else if (process.env.TRAVIS) { - grunt.task.run(['karma:phantomjs', 'karma:minified_phantomjs', 'karma:minified_api_phantomjs']); - //Disabling saucelabs until we figure out how to make it run reliably. - //grunt.task.run([ - //'karma:chrome_sl', - //'karma:firefox_sl', - //'karma:safari_sl', - //'karma:ipad_sl', - //'karma:android_sl', - //'karma:ie_sl' - //]); - } else { - // if we aren't running this in a CI, but running it manually, we can - // supply arguments to this task. These arguments are either colon (`:`) - // separated which is the default grunt separator for arguments, or they - // are comma (`,`) separated to make it easier. - // The arguments are the names of which browsers you want. It'll then - // make sure you have the `minified` and `minified_api` for those browsers - // as well. - if (tasks.length === 0) { - tasks.push('chrome'); - } - if (tasks.length === 1) { - tasks = tasks[0].split(','); - } - - tasksMinified = tasks.slice(); - tasksMinifiedApi = tasks.slice(); - - tasksMinified = tasksMinified.map(function(task) { - return 'minified_' + task; - }); - - tasksMinifiedApi = tasksMinifiedApi.map(function(task) { - return 'minified_api_' + task; - }); - - tasks = tasks.concat(tasksMinified).concat(tasksMinifiedApi); - tasks = tasks.map(function(task) { - return 'karma:' + task; - }); - - grunt.task.run(tasks); - } - }); - - grunt.registerTask('saucelabs', function() { - var done = this.async(); - - if (this.args[0] == 'connect') { - exec('curl https://gist.githubusercontent.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash', - function(error, stdout, stderr) { - if (error) { - grunt.log.error(error); - return done(); - } - - grunt.verbose.error(stderr.toString()); - grunt.verbose.writeln(stdout.toString()); - grunt.task.run(['karma:saucelabs']); - done(); - }); - } else { - grunt.task.run(['karma:saucelabs']); - done(); - } - }); - - var fs = require('fs'); - - grunt.registerTask('vttjs', 'prepend vttjs to videojs source files', function() { - var vttjs, vttjsMin, vjs, vjsMin; - - // copy the current files to make a novttjs build - grunt.file.copy('build/files/combined.video.js', 'build/files/combined.video.novtt.js'); - grunt.file.copy('build/files/minified.video.js', 'build/files/minified.video.novtt.js'); - - // read in vttjs files - vttjs = grunt.file.read('node_modules/vtt.js/dist/vtt.js'); - vttjsMin = grunt.file.read('node_modules/vtt.js/dist/vtt.min.js'); - - // read in videojs files - vjs = grunt.file.read('build/files/combined.video.js'); - vjsMin = grunt.file.read('build/files/minified.video.js'); - - // write out the concatenated files - grunt.file.write('build/files/combined.video.js', vjs + '\n' + vttjs); - grunt.file.write('build/files/minified.video.js', vjsMin + '\n' + vttjsMin); - }); - - grunt.registerMultiTask('build', 'Building Source', function(){ - - // Fix windows file path delimiter issue - var i = sourceFiles.length; - while (i--) { - sourceFiles[i] = sourceFiles[i].replace(/\\/g, '/'); - } - - // Create a combined sources file. https://github.com/zencoder/video-js/issues/287 - var combined = ''; - sourceFiles.forEach(function(result){ - combined += grunt.file.read(result); - }); - // Replace CDN version ref in js. Use major/minor version. - combined = combined.replace(/GENERATED_CDN_VSN/g, version.majorMinor); - combined = combined.replace(/GENERATED_FULL_VSN/g, version.full); - - grunt.file.write('build/files/combined.video.js', combined); - - // Copy over other files - // grunt.file.copy('src/css/video-js.png', 'build/files/video-js.png'); - grunt.file.copy('node_modules/videojs-swf/dist/video-js.swf', 'build/files/video-js.swf'); - - // Inject version number into css file - var css = grunt.file.read('build/files/video-js.css'); - css = css.replace(/GENERATED_AT_BUILD/g, version.full); - grunt.file.write('build/files/video-js.css', css); - - // Copy over font files - grunt.file.recurse('src/css/font', function(absdir, rootdir, subdir, filename) { - // Block .DS_Store files - if ('filename'.substring(0,1) !== '.') { - grunt.file.copy(absdir, 'build/files/font/' + filename); - } - }); - - // Minify CSS - grunt.task.run(['cssmin']); - }); - - grunt.registerMultiTask('minify', 'Minify JS files using Closure Compiler.', function() { - var done = this.async(); - var exec = require('child_process').exec; - - var externs = this.data.externs || []; - var dest = this.data.dest; - var filePatterns = []; - - // Make sure deeper directories exist for compiler - grunt.file.write(dest, ''); - - if (this.data.sourcelist) { - filePatterns = filePatterns.concat(grunt.file.read(this.data.sourcelist).split(',')); - } - if (this.data.src) { - filePatterns = filePatterns.concat(this.data.src); - } - - // Build closure compiler shell command - var command = 'java -jar build/compiler/compiler.jar' - + ' --compilation_level ADVANCED_OPTIMIZATIONS' - // + ' --formatting=pretty_print' - + ' --js_output_file=' + dest - + ' --create_source_map ' + dest + '.map --source_map_format=V3' - + ' --jscomp_warning=checkTypes --warning_level=VERBOSE' - + ' --output_wrapper "(function() {%output%})();"'; - //@ sourceMappingURL=video.js.map - - // Add each js file - grunt.file.expand(filePatterns).forEach(function(file){ - command += ' --js='+file; - }); - - // Add externs - externs.forEach(function(extern){ - command += ' --externs='+extern; - }); - - // Run command - exec(command, { maxBuffer: 500*1024 }, function(err, stdout, stderr){ - - if (err) { - grunt.warn(err); - done(false); - } - - if (stdout) { - grunt.log.writeln(stdout); - } - - done(); - }); - }); - - grunt.registerTask('dist-copy', 'Assembling distribution', function(){ - var css, jsmin, jsdev, cdnjs; - - // Manually copy each source file - grunt.file.copy('build/files/minified.video.js', 'dist/video-js/video.js'); - grunt.file.copy('build/files/combined.video.js', 'dist/video-js/video.dev.js'); - grunt.file.copy('build/files/minified.video.novtt.js', 'dist/video-js/video.novtt.js'); - grunt.file.copy('build/files/combined.video.novtt.js', 'dist/video-js/video.novtt.dev.js'); - grunt.file.copy('build/files/video-js.css', 'dist/video-js/video-js.css'); - grunt.file.copy('build/files/video-js.min.css', 'dist/video-js/video-js.min.css'); - grunt.file.copy('node_modules/videojs-swf/dist/video-js.swf', 'dist/video-js/video-js.swf'); - grunt.file.copy('build/demo-files/demo.html', 'dist/video-js/demo.html'); - grunt.file.copy('build/demo-files/demo.captions.vtt', 'dist/video-js/demo.captions.vtt'); - grunt.file.copy('src/css/video-js.less', 'dist/video-js/video-js.less'); - - - // Copy over font files - grunt.file.recurse('build/files/font', function(absdir, rootdir, subdir, filename) { - // Block .DS_Store files - if ('filename'.substring(0,1) !== '.') { - grunt.file.copy(absdir, 'dist/video-js/font/' + filename); - } - }); - - // Copy over language files - grunt.file.recurse('build/files/lang', function(absdir, rootdir, subdir, filename) { - // Block .DS_Store files - if ('filename'.substring(0,1) !== '.') { - grunt.file.copy(absdir, 'dist/cdn/lang/' + filename); - grunt.file.copy(absdir, 'dist/video-js/lang/' + filename); - } - }); - - // ds_store files sometime find their way in - if (grunt.file.exists('dist/video-js/.DS_Store')) { - grunt.file['delete']('dist/video-js/.DS_Store'); - } - - // CDN version uses already hosted font files - // Minified version only, doesn't need demo files - grunt.file.copy('build/files/minified.video.js', 'dist/cdn/video.js'); - grunt.file.copy('build/files/video-js.min.css', 'dist/cdn/video-js.css'); - grunt.file.copy('node_modules/videojs-swf/dist/video-js.swf', 'dist/cdn/video-js.swf'); - grunt.file.copy('build/demo-files/demo.captions.vtt', 'dist/cdn/demo.captions.vtt'); - grunt.file.copy('build/demo-files/demo.html', 'dist/cdn/demo.html'); - - // Replace font urls with CDN versions - css = grunt.file.read('dist/cdn/video-js.css'); - css = css.replace(/font\//g, '../f/3/'); - grunt.file.write('dist/cdn/video-js.css', css); - - // Add CDN-specfic JS - jsmin = grunt.file.read('dist/cdn/video.js'); - // GA Tracking Pixel (manually building the pixel URL) - cdnjs = uglify.minify('src/js/cdn.js').code.replace('v0.0.0', 'v'+version.full); - grunt.file.write('dist/cdn/video.js', jsmin + cdnjs); - }); - - grunt.registerTask('cdn-links', 'Update the version of CDN links in docs', function(){ - var doc = grunt.file.read('docs/guides/setup.md'); - var version = pkg.version; - - // remove the patch version to point to the latest patch - version = version.replace(/(\d+\.\d+)\.\d+/, '$1'); - - // update the version in http://vjs.zencdn.net/4.3/video.js - doc = doc.replace(/(\/\/vjs\.zencdn\.net\/)\d+\.\d+(\.\d+)?/g, '$1'+version); - grunt.file.write('docs/guides/setup.md', doc); - }); - grunt.registerTask('dist', 'Creating distribution', ['dist-copy', 'zip:dist']); - grunt.registerTask('next-issue', 'Get the next issue that needs a response', function(){ - var done = this.async(); - var GitHubApi = require('github'); - var open = require('open'); - - var github = new GitHubApi({ - // required - version: '3.0.0', - // optional - debug: true, - protocol: 'https', - // host: 'github.my-GHE-enabled-company.com', - // pathPrefix: '/api/v3', // for some GHEs - timeout: 5000 - }); - - github.issues.repoIssues({ - // optional: - // headers: { - // 'cookie': 'blahblah' - // }, - user: 'videojs', - repo: 'video.js', - sort: 'updated', - direction: 'asc', - state: 'open', - per_page: 100 - }, function(err, res) { - var issueToOpen; - var usersWithWrite = ['heff', 'mmcc']; - var categoryLabels = ['enhancement', 'bug', 'question', 'feature']; - - console.log('Number of issues: '+res.length); - - // TODO: Find the best way to exclude an issue where a question has been asked of the - // issue owner/submitter that hasn't been answerd yet. - // A stupid simple first step would be to check for the needs: more info label - // and exactly one comment (the question) - - // find issues that need categorizing, no category labels - res.some(function(issue){ - if (issue.labels.length === 0) { - return issueToOpen = issue; // break - } - // look for category labels - var categorized = issue.labels.some(function(label){ - return categoryLabels.indexOf(label.name) >= 0; - }); - if (!categorized) { - return issueToOpen = issue; // break - } - }); - if (issueToOpen) { - open(issueToOpen.html_url); - return done(); - } - - // find issues that need confirming or answering - res.some(function(issue){ - // look for confirmed label - var confirmed = issue.labels.some(function(label){ - return label.name === 'confirmed'; - }); - // Was exluding questions, but that might leave a lot of people hanging - // var question = issue.labels.some(function(label){ - // return label.name === 'question'; - // }); - if (!confirmed) { // && !question - return issueToOpen = issue; // break - } - }); - if (issueToOpen) { - open(issueToOpen.html_url); - return done(); - } - - grunt.log.writeln('No next issue found'); - done(); - }); - }); - + // Load all the tasks in the tasks directory + grunt.loadTasks('tasks'); }; diff --git a/bower.json b/bower.json index fbc2c7494..deab65139 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "video.js", "description": "An HTML5 and Flash video player with a common API and skin for both.", - "version": "4.12.1", + "version": "4.12.2", "main": [ "dist/video-js/video.js", "dist/video-js/video-js.css", diff --git a/component.json b/component.json index 2c59b2d2d..c530e115b 100644 --- a/component.json +++ b/component.json @@ -1,7 +1,7 @@ { "name": "video.js", "description": "An HTML5 and Flash video player with a common API and skin for both.", - "version": "4.12.1", + "version": "4.12.2", "keywords": [ "videojs", "html5", diff --git a/contrib.json b/contrib.json index 5cc84d514..833bc1089 100644 --- a/contrib.json +++ b/contrib.json @@ -198,27 +198,31 @@ "run": { "steps": [ { "include": "branch check" }, - [ "git checkout stable", "Checkout the release branch" ], - [ "git pull upstream stable", "Update the release branch" ], - [ "npm install", "Ensure dependency updates have been installed" ], - [ "grunt test", "Run tests" ], - [ "grunt chg-release:{{ release_type }}", "Update the changelog with the new release" ], - [ "grunt version:{{ release_type }}", "Bump package versions" ], - [ "grunt", "Build the release" ], - [ "git add dist/video-js --force", "Add the (otherwise ignored) release files" ], - [ "grunt vjsdocs", "Rebuild the docs" ], - [ "grunt cdn-links", "Update the cdn urls in the docs" ], - [ "grunt tagrelease", "Tag the release" ], - [ "git push upstream stable", "Push changes to the remote" ], - [ "git push upstream --tags", "Push tags to the remote" ], - [ "npm publish", "Publish to npm" ], - [ "git checkout master", "Checkout the development branch" ], - [ "git pull upstream master", "Update the development branch" ], - [ "git merge stable", "Merge changes" ], - [ "grunt clean:dist", "Remove built dist files to re-ignore them" ], - [ "git add -u", "Add the changes for the removed dist files" ], - [ "git commit -m 'Removed dist files'", "Commit the removed dist files" ], - [ "git push upstream master", "Push development branch changes" ] + [ "git checkout stable", "Checkout the release branch" ], + [ "git pull upstream stable", "Update the release branch" ], + [ "npm install", "Ensure dependency updates have been installed" ], + [ "grunt test", "Run tests" ], + [ "grunt version:{{ release_type }}", "Bump package versions" ], + [ "grunt vjs-version", "Return the current VJS Version from the package.json file", "version" ], + [ "grunt chg-release:{{ version }}", "Update the changelog with the new release" ], + [ "grunt clean:dist", "Clean out the dist folder before the build" ], + [ "grunt", "Build the release" ], + [ "git add dist/video-js --force", "Add the (otherwise ignored) release files" ], + [ "grunt vjsdocs", "Rebuild the docs" ], + [ "grunt cdn-links", "Update the cdn urls in the docs" ], + [ "git commit -am 'Release v{{ version }}'", "Commit the unstaged changes (package.json, changelog, etc)" ], + [ "git tag -a v{{version}} -m 'v{{version}}'", "Tag the current version" ], + [ "git push upstream stable", "Push changes to the remote" ], + [ "git push upstream --tags", "Push tags to the remote" ], + [ "npm publish", "Publish to npm" ], + [ "grunt github-release", "Create a new release on Github" ], + [ "git checkout master", "Checkout the development branch" ], + [ "git pull upstream master", "Update the development branch" ], + [ "git merge stable", "Merge changes" ], + [ "grunt clean:dist", "Remove built dist files again to re-ignore them" ], + [ "git add -u", "Add the changes for the removed dist files" ], + [ "git commit -m 'Removed dist files'", "Commit the removed dist files" ], + [ "git push upstream master", "Push development branch changes" ] ] } }, diff --git a/docs/api/vjs.Html5.md b/docs/api/vjs.Html5.md index 2fe1e7046..747b22b8a 100644 --- a/docs/api/vjs.Html5.md +++ b/docs/api/vjs.Html5.md @@ -31,7 +31,7 @@ HTML5 Media Controller - Wrapper for HTML5 Media API ##### RETURNS: * `[type]` [description] -_defined in_: [src/js/media/html5.js#L541](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L541) +_defined in_: [src/js/media/html5.js#L542](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L542) --- @@ -43,7 +43,7 @@ _defined in_: [src/js/media/html5.js#L541](https://github.com/videojs/video.js/b ##### RETURNS: * `Boolean` -_defined in_: [src/js/media/html5.js#L531](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L531) +_defined in_: [src/js/media/html5.js#L532](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L532) --- @@ -64,7 +64,7 @@ _defined in_: [src/js/media/html5.js#L14](https://github.com/videojs/video.js/bl ##### RETURNS: * `Boolean` -_defined in_: [src/js/media/html5.js#L451](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L451) +_defined in_: [src/js/media/html5.js#L452](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L452) --- @@ -74,7 +74,7 @@ _defined in_: [src/js/media/html5.js#L451](https://github.com/videojs/video.js/b ##### RETURNS: * `Boolean` -_defined in_: [src/js/media/html5.js#L551](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L551) +_defined in_: [src/js/media/html5.js#L552](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L552) --- @@ -88,7 +88,7 @@ _defined in_: [src/js/media/html5.js#L551](https://github.com/videojs/video.js/b * __source__ `Object` The source object * __tech__ `vjs.Html5` The instance of the HTML5 tech -_defined in_: [src/js/media/html5.js#L471](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L471) +_defined in_: [src/js/media/html5.js#L472](https://github.com/videojs/video.js/blob/master/src/js/media/html5.js#L472) --- diff --git a/package.json b/package.json index 18930373f..83e22f187 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "video.js", "description": "An HTML5 and Flash video player with a common API and skin for both.", - "version": "4.12.1", + "version": "4.12.2", "copyright": "Copyright 2014 Brightcove, Inc. https://github.com/videojs/video.js/blob/master/LICENSE", "keywords": [ "videojs", @@ -26,7 +26,7 @@ }, "devDependencies": { "calcdeps": "~0.1.7", - "chg": "~0.1.8", + "chg": "~0.2.0", "contribflow": "~0.2.0", "github": "~0.1.14", "grunt": "^0.4.4", @@ -40,10 +40,12 @@ "grunt-contrib-less": "~0.6.4", "grunt-contrib-qunit": "~0.2.1", "grunt-contrib-watch": "~0.1.4", + "grunt-fastly": "^0.1.3", + "grunt-github-releaser": "^0.1.17", "grunt-karma": "^0.8.3", "grunt-s3": "~0.2.0-alpha", - "grunt-tagrelease": "~0.3.3", "grunt-version": "~0.3.0", + "grunt-videojs-languages": "0.0.4", "grunt-zip": "0.10.2", "karma": "^0.12.14", "karma-chrome-launcher": "^0.1.3", @@ -58,10 +60,8 @@ "mocha": "~1.8.1", "open": "0.0.4", "qunitjs": "~1.14.0", - "semver": "~1.1.4", "sinon": "~1.9.1", "uglify-js": "~2.3.6", - "videojs-doc-generator": "0.0.1", - "grunt-videojs-languages": "0.0.4" + "videojs-doc-generator": "0.0.1" } } diff --git a/src/js/media/html5.js b/src/js/media/html5.js index 4cb83ae5b..ee55d54e6 100644 --- a/src/js/media/html5.js +++ b/src/js/media/html5.js @@ -167,7 +167,7 @@ vjs.Html5.prototype.createEl = function(){ vjs.Html5.prototype.hideCaptions = function() { - var tracks = this.el_.textTracks, + var tracks = this.el_.querySelectorAll('track'), track, i = tracks.length, kinds = { @@ -176,8 +176,9 @@ vjs.Html5.prototype.hideCaptions = function() { }; while (i--) { - track = tracks[i]; - if (track && track['kind'] in kinds) { + track = tracks[i].track; + if ((track && track['kind'] in kinds) && + (!tracks[i]['default'])) { track.mode = 'disabled'; } } diff --git a/tasks/build.js b/tasks/build.js new file mode 100644 index 000000000..10b5d4e7c --- /dev/null +++ b/tasks/build.js @@ -0,0 +1,41 @@ +module.exports = function(grunt) { + grunt.registerMultiTask('build', 'Building Source', function(){ + + // Fix windows file path delimiter issue + var i = grunt.sourceFiles.length; + while (i--) { + grunt.sourceFiles[i] = grunt.sourceFiles[i].replace(/\\/g, '/'); + } + + // Create a combined sources file. https://github.com/zencoder/video-js/issues/287 + var combined = ''; + grunt.sourceFiles.forEach(function(result){ + combined += grunt.file.read(result); + }); + // Replace CDN version ref in js. Use major/minor version. + combined = combined.replace(/GENERATED_CDN_VSN/g, grunt.vjsVersion.majorMinor); + combined = combined.replace(/GENERATED_FULL_VSN/g, grunt.vjsVersion.full); + + grunt.file.write('build/files/combined.video.js', combined); + + // Copy over other files + // grunt.file.copy('src/css/video-js.png', 'build/files/video-js.png'); + grunt.file.copy('node_modules/videojs-swf/dist/video-js.swf', 'build/files/video-js.swf'); + + // Inject version number into css file + var css = grunt.file.read('build/files/video-js.css'); + css = css.replace(/GENERATED_AT_BUILD/g, grunt.vjsVersion.full); + grunt.file.write('build/files/video-js.css', css); + + // Copy over font files + grunt.file.recurse('src/css/font', function(absdir, rootdir, subdir, filename) { + // Block .DS_Store files + if ('filename'.substring(0,1) !== '.') { + grunt.file.copy(absdir, 'build/files/font/' + filename); + } + }); + + // Minify CSS + grunt.task.run(['cssmin']); + }); +} diff --git a/tasks/cdn-links.js b/tasks/cdn-links.js new file mode 100644 index 000000000..699f05f0f --- /dev/null +++ b/tasks/cdn-links.js @@ -0,0 +1,13 @@ +module.exports = function(grunt) { + grunt.registerTask('cdn-links', 'Update the version of CDN links in docs', function(){ + var doc = grunt.file.read('docs/guides/setup.md'); + var version = require('../package.json').version; + + // remove the patch version to point to the latest patch + version = version.replace(/(\d+\.\d+)\.\d+/, '$1'); + + // update the version in http://vjs.zencdn.net/4.3/video.js + doc = doc.replace(/(\/\/vjs\.zencdn\.net\/)\d+\.\d+(\.\d+)?/g, '$1'+version); + grunt.file.write('docs/guides/setup.md', doc); + }); +}; diff --git a/tasks/dist-copy.js b/tasks/dist-copy.js new file mode 100644 index 000000000..160d5bbc2 --- /dev/null +++ b/tasks/dist-copy.js @@ -0,0 +1,61 @@ +module.exports = function(grunt) { + grunt.registerTask('dist-copy', 'Assembling distribution', function(){ + var css, jsmin, jsdev, cdnjs, uglify; + + uglify = require('uglify-js'); + + // Manually copy each source file + grunt.file.copy('build/files/minified.video.js', 'dist/video-js/video.js'); + grunt.file.copy('build/files/combined.video.js', 'dist/video-js/video.dev.js'); + grunt.file.copy('build/files/minified.video.novtt.js', 'dist/video-js/video.novtt.js'); + grunt.file.copy('build/files/combined.video.novtt.js', 'dist/video-js/video.novtt.dev.js'); + grunt.file.copy('build/files/video-js.css', 'dist/video-js/video-js.css'); + grunt.file.copy('build/files/video-js.min.css', 'dist/video-js/video-js.min.css'); + grunt.file.copy('node_modules/videojs-swf/dist/video-js.swf', 'dist/video-js/video-js.swf'); + grunt.file.copy('build/demo-files/demo.html', 'dist/video-js/demo.html'); + grunt.file.copy('build/demo-files/demo.captions.vtt', 'dist/video-js/demo.captions.vtt'); + grunt.file.copy('src/css/video-js.less', 'dist/video-js/video-js.less'); + + + // Copy over font files + grunt.file.recurse('build/files/font', function(absdir, rootdir, subdir, filename) { + // Block .DS_Store files + if ('filename'.substring(0,1) !== '.') { + grunt.file.copy(absdir, 'dist/video-js/font/' + filename); + } + }); + + // Copy over language files + grunt.file.recurse('build/files/lang', function(absdir, rootdir, subdir, filename) { + // Block .DS_Store files + if ('filename'.substring(0,1) !== '.') { + grunt.file.copy(absdir, 'dist/cdn/lang/' + filename); + grunt.file.copy(absdir, 'dist/video-js/lang/' + filename); + } + }); + + // ds_store files sometime find their way in + if (grunt.file.exists('dist/video-js/.DS_Store')) { + grunt.file['delete']('dist/video-js/.DS_Store'); + } + + // CDN version uses already hosted font files + // Minified version only, doesn't need demo files + grunt.file.copy('build/files/minified.video.js', 'dist/cdn/video.js'); + grunt.file.copy('build/files/video-js.min.css', 'dist/cdn/video-js.css'); + grunt.file.copy('node_modules/videojs-swf/dist/video-js.swf', 'dist/cdn/video-js.swf'); + grunt.file.copy('build/demo-files/demo.captions.vtt', 'dist/cdn/demo.captions.vtt'); + grunt.file.copy('build/demo-files/demo.html', 'dist/cdn/demo.html'); + + // Replace font urls with CDN versions + css = grunt.file.read('dist/cdn/video-js.css'); + css = css.replace(/font\//g, '../f/3/'); + grunt.file.write('dist/cdn/video-js.css', css); + + // Add CDN-specfic JS + jsmin = grunt.file.read('dist/cdn/video.js'); + // GA Tracking Pixel (manually building the pixel URL) + cdnjs = uglify.minify('src/js/cdn.js').code.replace('v0.0.0', 'v'+ grunt.vjsVersion.full); + grunt.file.write('dist/cdn/video.js', jsmin + cdnjs); + }); +} diff --git a/tasks/minify.js b/tasks/minify.js new file mode 100644 index 000000000..09ec6e121 --- /dev/null +++ b/tasks/minify.js @@ -0,0 +1,55 @@ +module.exports = function(grunt) { + grunt.registerMultiTask('minify', 'Minify JS files using Closure Compiler.', function() { + var done = this.async(); + var exec = require('child_process').exec; + + var externs = this.data.externs || []; + var dest = this.data.dest; + var filePatterns = []; + + // Make sure deeper directories exist for compiler + grunt.file.write(dest, ''); + + if (this.data.sourcelist) { + filePatterns = filePatterns.concat(grunt.file.read(this.data.sourcelist).split(',')); + } + if (this.data.src) { + filePatterns = filePatterns.concat(this.data.src); + } + + // Build closure compiler shell command + var command = 'java -jar build/compiler/compiler.jar' + + ' --compilation_level ADVANCED_OPTIMIZATIONS' + // + ' --formatting=pretty_print' + + ' --js_output_file=' + dest + + ' --create_source_map ' + dest + '.map --source_map_format=V3' + + ' --jscomp_warning=checkTypes --warning_level=VERBOSE' + + ' --output_wrapper "(function() {%output%})();"'; + //@ sourceMappingURL=video.js.map + + // Add each js file + grunt.file.expand(filePatterns).forEach(function(file){ + command += ' --js='+file; + }); + + // Add externs + externs.forEach(function(extern){ + command += ' --externs='+extern; + }); + + // Run command + exec(command, { maxBuffer: 500*1024 }, function(err, stdout, stderr){ + + if (err) { + grunt.warn(err); + done(false); + } + + if (stdout) { + grunt.log.writeln(stdout); + } + + done(); + }); + }); +} diff --git a/tasks/next-issue.js b/tasks/next-issue.js new file mode 100644 index 000000000..dee2b01a7 --- /dev/null +++ b/tasks/next-issue.js @@ -0,0 +1,82 @@ +module.exports = function(grunt) { + grunt.registerTask('next-issue', 'Get the next issue that needs a response', function(){ + var done = this.async(); + var GitHubApi = require('github'); + var open = require('open'); + + var github = new GitHubApi({ + // required + version: '3.0.0', + // optional + debug: true, + protocol: 'https', + // host: 'github.my-GHE-enabled-company.com', + // pathPrefix: '/api/v3', // for some GHEs + timeout: 5000 + }); + + github.issues.repoIssues({ + // optional: + // headers: { + // 'cookie': 'blahblah' + // }, + user: 'videojs', + repo: 'video.js', + sort: 'updated', + direction: 'asc', + state: 'open', + per_page: 100 + }, function(err, res) { + var issueToOpen; + var usersWithWrite = ['heff', 'mmcc']; + var categoryLabels = ['enhancement', 'bug', 'question', 'feature']; + + console.log('Number of issues: '+res.length); + + // TODO: Find the best way to exclude an issue where a question has been asked of the + // issue owner/submitter that hasn't been answerd yet. + // A stupid simple first step would be to check for the needs: more info label + // and exactly one comment (the question) + + // find issues that need categorizing, no category labels + res.some(function(issue){ + if (issue.labels.length === 0) { + return issueToOpen = issue; // break + } + // look for category labels + var categorized = issue.labels.some(function(label){ + return categoryLabels.indexOf(label.name) >= 0; + }); + if (!categorized) { + return issueToOpen = issue; // break + } + }); + if (issueToOpen) { + open(issueToOpen.html_url); + return done(); + } + + // find issues that need confirming or answering + res.some(function(issue){ + // look for confirmed label + var confirmed = issue.labels.some(function(label){ + return label.name === 'confirmed'; + }); + // Was exluding questions, but that might leave a lot of people hanging + // var question = issue.labels.some(function(label){ + // return label.name === 'question'; + // }); + if (!confirmed) { // && !question + return issueToOpen = issue; // break + } + }); + if (issueToOpen) { + open(issueToOpen.html_url); + return done(); + } + + grunt.log.writeln('No next issue found'); + done(); + }); + }); +} diff --git a/tasks/saucelabs.js b/tasks/saucelabs.js new file mode 100644 index 000000000..2873c8621 --- /dev/null +++ b/tasks/saucelabs.js @@ -0,0 +1,24 @@ +module.exports = function(grunt) { + grunt.registerTask('saucelabs', function() { + var exec = require('child_process').exec; + var done = this.async(); + + if (this.args[0] == 'connect') { + exec('curl https://gist.githubusercontent.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash', + function(error, stdout, stderr) { + if (error) { + grunt.log.error(error); + return done(); + } + + grunt.verbose.error(stderr.toString()); + grunt.verbose.writeln(stdout.toString()); + grunt.task.run(['karma:saucelabs']); + done(); + }); + } else { + grunt.task.run(['karma:saucelabs']); + done(); + } + }); +} diff --git a/tasks/test.js b/tasks/test.js new file mode 100644 index 000000000..3f74b8d7a --- /dev/null +++ b/tasks/test.js @@ -0,0 +1,63 @@ +module.exports = function(grunt) { + // The test task will run `karma:saucelabs` when running in travis, + // when running via a PR from a fork, it'll run qunit tests in phantom using + // karma otherwise, it'll run the tests in chrome via karma + // You can specify which browsers to build with by using grunt-style arguments + // or separating them with a comma: + // grunt test:chrome:firefox # grunt-style + // grunt test:chrome,firefox # comma-separated + grunt.registerTask('test', function() { + var tasks = this.args, + tasksMinified, + tasksMinifiedApi; + + grunt.task.run(['pretask']); + + if (process.env.TRAVIS_PULL_REQUEST !== 'false') { + grunt.task.run(['karma:phantomjs', 'karma:minified_phantomjs', 'karma:minified_api_phantomjs']); + } else if (process.env.TRAVIS) { + grunt.task.run(['karma:phantomjs', 'karma:minified_phantomjs', 'karma:minified_api_phantomjs']); + //Disabling saucelabs until we figure out how to make it run reliably. + //grunt.task.run([ + //'karma:chrome_sl', + //'karma:firefox_sl', + //'karma:safari_sl', + //'karma:ipad_sl', + //'karma:android_sl', + //'karma:ie_sl' + //]); + } else { + // if we aren't running this in a CI, but running it manually, we can + // supply arguments to this task. These arguments are either colon (`:`) + // separated which is the default grunt separator for arguments, or they + // are comma (`,`) separated to make it easier. + // The arguments are the names of which browsers you want. It'll then + // make sure you have the `minified` and `minified_api` for those browsers + // as well. + if (tasks.length === 0) { + tasks.push('chrome'); + } + if (tasks.length === 1) { + tasks = tasks[0].split(','); + } + + tasksMinified = tasks.slice(); + tasksMinifiedApi = tasks.slice(); + + tasksMinified = tasksMinified.map(function(task) { + return 'minified_' + task; + }); + + tasksMinifiedApi = tasksMinifiedApi.map(function(task) { + return 'minified_api_' + task; + }); + + tasks = tasks.concat(tasksMinified).concat(tasksMinifiedApi); + tasks = tasks.map(function(task) { + return 'karma:' + task; + }); + + grunt.task.run(tasks); + } + }); +}; diff --git a/tasks/vjs-version.js b/tasks/vjs-version.js new file mode 100644 index 000000000..12b129a4c --- /dev/null +++ b/tasks/vjs-version.js @@ -0,0 +1,7 @@ +module.exports = function(grunt) { + grunt.registerTask('vjs-version', function() { + var version = grunt.vjsVersion.full; + grunt.log.writeln(version); + return version; + }); +} diff --git a/tasks/vtt.js b/tasks/vtt.js new file mode 100644 index 000000000..3407c8e4e --- /dev/null +++ b/tasks/vtt.js @@ -0,0 +1,20 @@ +module.exports = function(grunt) { + grunt.registerTask('vttjs', 'prepend vttjs to videojs source files', function() { + var vttjs, vttjsMin, vjs, vjsMin; + + // copy the current files to make a novttjs build + grunt.file.copy('build/files/combined.video.js', 'build/files/combined.video.novtt.js'); + grunt.file.copy('build/files/minified.video.js', 'build/files/minified.video.novtt.js'); + + // read in vttjs files + vttjs = grunt.file.read('node_modules/vtt.js/dist/vtt.js'); + vttjsMin = grunt.file.read('node_modules/vtt.js/dist/vtt.min.js'); + // read in videojs files + vjs = grunt.file.read('build/files/combined.video.js'); + vjsMin = grunt.file.read('build/files/minified.video.js'); + + // write out the concatenated files + grunt.file.write('build/files/combined.video.js', vjs + '\n' + vttjs); + grunt.file.write('build/files/minified.video.js', vjsMin + '\n' + vttjsMin); + }); +};