diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..9888ff8 --- /dev/null +++ b/.babelrc @@ -0,0 +1,7 @@ +{ + "presets": [ + "es3", + ["es2015", {"loose": true}] + ], + "plugins": ["transform-object-assign"] +} diff --git a/.gitignore b/.gitignore index 651c316..efc5fcf 100644 --- a/.gitignore +++ b/.gitignore @@ -31,5 +31,4 @@ node_modules/ # Build-related directories dist/ docs/api/ -es5/ test/dist/ diff --git a/.travis.yml b/.travis.yml index db88ed7..4deb53e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,12 @@ node_js: - 'node' - 'lts/argon' before_script: - # check if the current version is equal to the version for the env + + # Check if the current version is equal to the major version for the env. - 'export IS_INSTALLED="$(npm list video.js | grep "video.js@$VJS")"' - # we have to add semi colons to the end of each line in the if - # as travis runs this all on one line + + # We have to add semicolons to the end of each line in the if as Travis runs + # this all on one line. - 'if [ -z "$IS_INSTALLED" ]; then echo "INSTALLING video.js@>=$VJS.0.0-RC.0 <$(($VJS+1)).0.0"; npm i "video.js@>=$VJS.0.0-RC.0 <\$(($VJS+1)).0.0"; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 50bce10..a184176 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ Make sure you have NodeJS 0.10 or higher and npm installed. ### Making Changes -Refer to the [video.js plugin standards][standards] for more detail on best practices and tooling for video.js plugin authorship. +Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship. When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository. @@ -27,4 +27,4 @@ Testing is a crucial part of any software project. For all but the most trivial [karma]: http://karma-runner.github.io/ [local]: http://localhost:9999/test/ -[standards]: https://github.com/videojs/generator-videojs-plugin/docs/standards.md +[conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md diff --git a/README.md b/README.md index 0c92c18..f1d3be3 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,6 @@ For purposes of this plugin, a **long touch** is defined as a single touch which npm install --save videojs-contextmenu ``` -The npm installation is preferred, but Bower works, too. - -```sh -bower install --save videojs-contextmenu -``` - ## Usage The plugin is invoked as a method of a video.js `Player` object: diff --git a/bower.json b/bower.json deleted file mode 100644 index 1d41c7c..0000000 --- a/bower.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "videojs-contextmenu", - "author": "Brightcove, Inc.", - "license": "Apache-2.0", - "main": [ - "dist/videojs-contextmenu.min.js" - ], - "keywords": [ - "videojs", - "videojs-plugin" - ] -} - diff --git a/index.html b/index.html index 5d63553..e516625 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,8 @@ videojs-contextmenu Demo - + + - - + + + diff --git a/package.json b/package.json index d17bf76..b841e86 100644 --- a/package.json +++ b/package.json @@ -2,30 +2,32 @@ "name": "videojs-contextmenu", "version": "1.2.2", "description": "A cross-device context menu implementation for video.js players.", - "main": "es5/plugin.js", + "main": "dist/videojs-contextmenu.cjs.js", "scripts": { "prebuild": "npm run clean", "build": "npm-run-all -p build:*", - "build:js": "npm-run-all build:js:babel build:js:browserify build:js:bannerize build:js:uglify", - "build:js:babel": "babel src -d es5", + "build:js": "npm-run-all build:js:rollup-modules build:js:rollup-umd build:js:bannerize build:js:uglify", "build:js:bannerize": "bannerize dist/videojs-contextmenu.js --banner=scripts/banner.ejs", - "build:js:browserify": "browserify . -s videojs-contextmenu -o dist/videojs-contextmenu.js", - "build:js:uglify": "uglifyjs dist/videojs-contextmenu.js --comments --mangle --compress -o dist/videojs-contextmenu.min.js", - "build:test": "babel-node scripts/build-test.js", - "change": "chg add", - "clean": "rimraf dist test/dist es5 && mkdirp dist test/dist es5", + "build:js:rollup-modules": "rollup -c scripts/modules.rollup.config.js", + "build:js:rollup-umd": "rollup -c scripts/umd.rollup.config.js", + "build:js:uglify": "uglifyjs dist/videojs-contextmenu.js --comments --mangle --compress --ie8 -o dist/videojs-contextmenu.min.js", + "build:test": "rollup -c scripts/test.rollup.config.js", + "clean": "rimraf dist test/dist", + "postclean": "mkdirp dist test/dist", "lint": "vjsstandard", - "start": "babel-node scripts/server.js", + "prestart": "npm run build", + "start": "npm-run-all -p start:server watch", + "start:server": "static -a 0.0.0.0 -p 9999 -H '{\"Cache-Control\": \"no-cache, must-revalidate\"}' .", "pretest": "npm-run-all lint build", "test": "karma start test/karma.conf.js", - "test:chrome": "npm run pretest && karma start test/karma.conf.js --browsers Chrome", - "test:firefox": "npm run pretest && karma start test/karma.conf.js --browsers Firefox", - "test:ie": "npm run pretest && karma start test/karma.conf.js --browsers IE", - "test:safari": "npm run pretest && karma start test/karma.conf.js --browsers Safari", "preversion": "npm test", - "version": "babel-node scripts/version.js", - "postversion": "babel-node scripts/postversion.js", - "prepublish": "npm run build" + "version": "node scripts/version.js", + "watch": "npm-run-all -p watch:*", + "watch:js-modules": "rollup -c scripts/modules.rollup.config.js -w", + "watch:js-umd": "rollup -c scripts/umd.rollup.config.js -w", + "watch:test": "rollup -c scripts/test.rollup.config.js -w", + "prepublish": "npm run build", + "prepush": "npm run lint" }, "keywords": [ "videojs", @@ -33,77 +35,64 @@ ], "author": "Brightcove, Inc.", "license": "Apache-2.0", - "browserify": { - "transform": [ - "browserify-shim", - "browserify-versionify" - ] - }, - "browserify-shim": { - "qunit": "global:QUnit", - "sinon": "global:sinon", - "video.js": "global:videojs" - }, - "style": "dist/videojs-contextmenu.css", - "videojs-plugin": { - "style": "dist/videojs-contextmenu.css", - "script": "dist/videojs-contextmenu.min.js" + "module": "dist/videojs-contextmenu.es.js", + "generator-videojs-plugin": { + "version": "5.0.0-7" }, "vjsstandard": { "ignore": [ "dist", "docs", - "es5", + "scripts", "test/dist", "test/karma.conf.js" ] }, "files": [ "CONTRIBUTING.md", - "bower.json", "dist/", "docs/", - "es5/", "index.html", "scripts/", "src/", "test/" ], "dependencies": { - "video.js": "^5.10.1" + "global": "^4.3.2", + "video.js": "^5.19.2" }, "devDependencies": { - "babel": "^5.8.35", - "babelify": "^6.4.0", + "babel-plugin-external-helpers": "^6.22.0", + "babel-plugin-transform-object-assign": "^6.8.0", + "babel-preset-es2015": "^6.14.0", + "babel-preset-es3": "^1.0.1", "bannerize": "^1.0.2", - "bluebird": "^3.2.2", - "browserify": "^12.0.2", - "browserify-shim": "^3.8.12", - "browserify-versionify": "^1.0.6", - "budo": "^8.0.4", - "chg": "^0.3.2", - "ghooks": "^1.1.1", - "glob": "^6.0.3", - "global": "^4.3.0", - "karma": "^0.13.19", - "karma-chrome-launcher": "^0.2.2", - "karma-detect-browsers": "^2.0.2", - "karma-firefox-launcher": "^0.1.7", - "karma-ie-launcher": "^0.2.0", - "karma-qunit": "^0.1.9", - "karma-safari-launcher": "^0.1.1", - "lodash": "^4.11.2", + "conventional-changelog-cli": "^1.3.1", + "conventional-changelog-videojs": "^3.0.0", + "es5-shim": "^4.5.9", + "husky": "^0.13.3", + "karma": "~1.3.0", + "karma-chrome-launcher": "^2.1.1", + "karma-detect-browsers": "^2.2.5", + "karma-firefox-launcher": "^1.0.1", + "karma-ie-launcher": "^1.0.0", + "karma-qunit": "^1.2.1", + "karma-safari-launcher": "^1.0.0", "mkdirp": "^0.5.1", - "npm-run-all": "^1.5.1", + "node-static": "^0.7.9", + "npm-run-all": "^4.0.2", "qunitjs": "^1.21.0", - "rimraf": "^2.5.1", - "sinon": "~1.14.0", - "uglify-js": "^2.6.1", - "videojs-standard": "^4.0.0" - }, - "config": { - "ghooks": { - "pre-push": "npm run lint" - } + "rimraf": "^2.6.1", + "rollup": "^0.41.6", + "rollup-plugin-babel": "^2.7.1", + "rollup-plugin-commonjs": "^8.0.2", + "rollup-plugin-json": "^2.1.1", + "rollup-plugin-multi-entry": "^2.0.1", + "rollup-plugin-node-resolve": "^3.0.0", + "rollup-watch": "^3.2.2", + "semver": "^5.3.0", + "sinon": "^2.2.0", + "uglify-js": "^3.0.7", + "videojs-standard": "^6.0.0" } -} +} \ No newline at end of file diff --git a/scripts/build-test.js b/scripts/build-test.js deleted file mode 100644 index 6d25859..0000000 --- a/scripts/build-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import browserify from 'browserify'; -import fs from 'fs'; -import glob from 'glob'; - -/* eslint no-console: 0 */ - -glob('test/**/*.test.js', (err, files) => { - if (err) { - throw err; - } - browserify(files) - .transform('babelify') - .bundle() - .pipe(fs.createWriteStream('test/dist/bundle.js')); -}); diff --git a/scripts/modules.rollup.config.js b/scripts/modules.rollup.config.js new file mode 100644 index 0000000..3799259 --- /dev/null +++ b/scripts/modules.rollup.config.js @@ -0,0 +1,41 @@ +/** + * Rollup configuration for packaging the plugin in a module that is consumable + * by either CommonJS (e.g. Node or Browserify) or ECMAScript (e.g. Rollup). + * + * These modules DO NOT include their dependencies as we expect those to be + * handled by the module system. + */ +import babel from 'rollup-plugin-babel'; +import json from 'rollup-plugin-json'; + +export default { + moduleName: 'videojsContextmenu', + entry: 'src/plugin.js', + external: ['video.js'], + globals: { + 'video.js': 'videojs' + }, + legacy: true, + plugins: [ + json(), + babel({ + babelrc: false, + exclude: 'node_modules/**', + presets: [ + 'es3', + ['es2015', { + loose: true, + modules: false + }] + ], + plugins: [ + 'external-helpers', + 'transform-object-assign' + ] + }) + ], + targets: [ + {dest: 'dist/videojs-contextmenu.cjs.js', format: 'cjs'}, + {dest: 'dist/videojs-contextmenu.es.js', format: 'es'} + ] +}; diff --git a/scripts/postversion.js b/scripts/postversion.js deleted file mode 100644 index 203fbba..0000000 --- a/scripts/postversion.js +++ /dev/null @@ -1,33 +0,0 @@ -import {exec} from 'child_process'; -import fs from 'fs'; -import path from 'path'; - -/* eslint no-console: 0 */ - -/** - * Determines whether or not the project has the Bower setup by checking for - * the presence of a bower.json file. - * - * @return {Boolean} - */ -const hasBower = () => { - try { - fs.statSync(path.join(__dirname, '../bower.json')); - return true; - } catch (x) { - return false; - } -}; - -// If the project supports Bower, roll HEAD back one commit to avoid having -// the tagged commit - with `dist/` - in the main history. -if (hasBower()) { - exec('git reset --hard HEAD~1', (err, stdout, stderr) => { - if (err) { - process.stdout.write(err.stack); - process.exit(err.status || 1); - } else { - process.stdout.write(stdout); - } - }); -} diff --git a/scripts/server.js b/scripts/server.js deleted file mode 100644 index 913e834..0000000 --- a/scripts/server.js +++ /dev/null @@ -1,150 +0,0 @@ -import Promise from 'bluebird'; -import browserify from 'browserify'; -import budo from 'budo'; -import fs from 'fs'; -import glob from 'glob'; -import _ from 'lodash'; -import mkdirp from 'mkdirp'; -import path from 'path'; - -/* eslint no-console: 0 */ - -const pkg = require(path.join(__dirname, '../package.json')); - -// Replace "%s" tokens with the plugin name in a string. -const nameify = (str) => - str.replace(/%s/g, pkg.name.split('/').reverse()[0]); - -const srces = { - js: 'src/plugin.js', - tests: glob.sync('test/**/*.test.js') -}; - -const dests = { - js: nameify('dist/%s.js'), - tests: 'test/dist/bundle.js' -}; - -const tasks = { - - js: browserify({ - debug: true, - entries: [srces.js], - standalone: nameify('%s'), - transform: [ - 'babelify', - 'browserify-shim', - 'browserify-versionify' - ] - }), - - tests: browserify({ - debug: true, - entries: srces.tests, - transform: [ - 'babelify', - 'browserify-shim', - 'browserify-versionify' - ] - }) -}; - -/** - * Runs one of the builds from the tasks object. - * - * @param {String} name - * Should match a key from the `tasks` object. - * - * @return {Promise} - */ -const build = (name) => { - if (Array.isArray(name)) { - return Promise.all(name.map(build)); - } - - // This returns a Promise even in the case of synchronous tasks because - // a consistent contract is useful. Ideally, we'll make the synchronous - // tasks asynchronous, but it's not critical. - return new Promise((resolve, reject) => { - if (typeof tasks[name] === 'function') { - tasks[name](resolve, reject); - } else { - tasks[name] - .bundle() - .pipe(fs.createWriteStream(dests[name])) - .on('finish', resolve) - .on('error', reject); - } - }); -}; - -mkdirp.sync('dist'); - -// Start the server _after_ the initial bundling is done. -build(['js', 'tests']).then(() => { - const server = budo({ - port: 9999, - stream: process.stdout - }).on('reload', (f) => console.log('reloading %s', f || 'everything')); - - /** - * A collection of functions which are mapped to strings that are used to - * generate RegExp objects. If a filepath matches the RegExp, the function - * will be used to handle that watched file. - * - * @type {Object} - */ - const handlers = { - - /** - * Handler for JavaScript source and tests. - * - * @param {String} event - * @param {String} file - */ - '^(src|test)/.+\.js$': _.debounce((event, file) => { - console.log('bundling javascript and tests'); - build(['js', 'tests']).then(() => server.reload()); - }) - }; - - /** - * Finds the first handler function for the file that matches a RegExp - * derived from the keys. - * - * @param {String} file - * @return {Function|Undefined} - */ - const findHandler = (file) => { - const keys = Object.keys(handlers); - - for (let i = 0; i < keys.length; i++) { - const regexp = new RegExp(keys[i]); - - if (regexp.test(file)) { - return handlers[keys[i]]; - } - } - }; - - server - .live() - .watch([ - 'index.html', - 'src/**/*.js', - 'test/**/*.js', - '!test/dist/**/*.js', - 'test/index.html' - ]) - .on('watch', (event, file) => { - const handler = findHandler(file); - - console.log(`detected a "${event}" event in "${file}"`); - - if (handler) { - handler(event, file); - } else { - server.reload(); - } - }); -}); diff --git a/scripts/test.rollup.config.js b/scripts/test.rollup.config.js new file mode 100644 index 0000000..d6f8faa --- /dev/null +++ b/scripts/test.rollup.config.js @@ -0,0 +1,58 @@ +/** + * Rollup configuration for packaging the plugin in a test bundle. + * + * This includes all dependencies for both the plugin and its tests. + */ +import babel from 'rollup-plugin-babel'; +import commonjs from 'rollup-plugin-commonjs'; +import json from 'rollup-plugin-json'; +import multiEntry from 'rollup-plugin-multi-entry'; +import resolve from 'rollup-plugin-node-resolve'; + +export default { + moduleName: 'videojsContextmenuTests', + entry: 'test/**/*.test.js', + dest: 'test/dist/bundle.js', + format: 'iife', + external: [ + 'qunit', + 'qunitjs', + 'sinon', + 'video.js' + ], + globals: { + 'qunit': 'QUnit', + 'qunitjs': 'QUnit', + 'sinon': 'sinon', + 'video.js': 'videojs' + }, + legacy: true, + plugins: [ + multiEntry({ + exports: false + }), + resolve({ + browser: true, + main: true, + jsnext: true + }), + commonjs({ + sourceMap: false + }), + babel({ + babelrc: false, + exclude: 'node_modules/**', + presets: [ + 'es3', + ['es2015', { + loose: true, + modules: false + }] + ], + plugins: [ + 'external-helpers', + 'transform-object-assign' + ] + }) + ] +}; diff --git a/scripts/umd.rollup.config.js b/scripts/umd.rollup.config.js new file mode 100644 index 0000000..02a665f --- /dev/null +++ b/scripts/umd.rollup.config.js @@ -0,0 +1,48 @@ +/** + * Rollup configuration for packaging the plugin in a module that is consumable + * as the `src` of a `script` tag or via AMD or similar client-side loading. + * + * This module DOES include its dependencies. + */ +import babel from 'rollup-plugin-babel'; +import commonjs from 'rollup-plugin-commonjs'; +import json from 'rollup-plugin-json'; +import resolve from 'rollup-plugin-node-resolve'; + +export default { + moduleName: 'videojsContextmenu', + entry: 'src/plugin.js', + dest: 'dist/videojs-contextmenu.js', + format: 'umd', + external: ['video.js'], + globals: { + 'video.js': 'videojs' + }, + legacy: true, + plugins: [ + resolve({ + browser: true, + main: true, + jsnext: true + }), + json(), + commonjs({ + sourceMap: false + }), + babel({ + babelrc: false, + exclude: 'node_modules/**', + presets: [ + 'es3', + ['es2015', { + loose: true, + modules: false + }] + ], + plugins: [ + 'external-helpers', + 'transform-object-assign' + ] + }) + ] +}; diff --git a/scripts/version.js b/scripts/version.js index dfabfdd..d2e93ec 100644 --- a/scripts/version.js +++ b/scripts/version.js @@ -1,69 +1,10 @@ -import {exec} from 'child_process'; -import fs from 'fs'; -import path from 'path'; - -/* eslint no-console: 0 */ - -const pkg = require(path.join(__dirname, '../package.json')); - -/** - * Determines whether or not the project has the CHANGELOG setup by checking - * for the presence of a CHANGELOG.md file and the necessary dependency and - * npm script. - * - * @return {Boolean} - */ -const hasChangelog = () => { - try { - fs.statSync(path.join(__dirname, '../CHANGELOG.md')); - } catch (x) { - return false; - } - return pkg.devDependencies.hasOwnProperty('chg') && - pkg.scripts.hasOwnProperty('change'); -}; - -/** - * Determines whether or not the project has the Bower setup by checking for - * the presence of a bower.json file. - * - * @return {Boolean} - */ -const hasBower = () => { - try { - fs.statSync(path.join(__dirname, '../bower.json')); - return true; - } catch (x) { - return false; - } -}; - -const commands = []; - -// If the project has a CHANGELOG, update it for the new release. -if (hasChangelog()) { - commands.push(`chg release "${pkg.version}"`); - commands.push('git add CHANGELOG.md'); -} - -// If the project supports Bower, perform special extra versioning step. -if (hasBower()) { - commands.push('git add package.json'); - commands.push(`git commit -m "${pkg.version}"`); - - // We only need a build in the Bower-supported case because of the - // temporary addition of the dist/ directory. - commands.push('npm run build'); - commands.push('git add -f dist'); -} - -if (commands.length) { - exec(commands.join(' && '), (err, stdout, stderr) => { - if (err) { - process.stdout.write(err.stack); - process.exit(err.status || 1); - } else { - process.stdout.write(stdout); - } - }); +const execSync = require('child_process').execSync; +const path = require('path'); +const semver = require('semver'); +const pkg = require('../package.json'); + +if (!semver.prerelease(pkg.version)) { + process.chdir(path.resolve(__dirname, '..')); + execSync('conventional-changelog -p videojs -i CHANGELOG.md -s'); + execSync('git add CHANGELOG.md'); } diff --git a/test/index.html b/test/index.html index a037293..b505c00 100644 --- a/test/index.html +++ b/test/index.html @@ -3,16 +3,16 @@ videojs-contextmenu Unit Tests - - + +
- - - - - + + + + + diff --git a/test/karma.conf.js b/test/karma.conf.js index d42fc53..54dcffa 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -4,7 +4,7 @@ module.exports = function(config) { usePhantomJS: false }; - // On Travis CI, we can only run in Firefox. + // On Travis CI, we can only run in Firefox and Chrome; so, enforce that. if (process.env.TRAVIS) { config.browsers = ['Firefox', 'travisChrome']; } @@ -18,12 +18,12 @@ module.exports = function(config) { config.set({ basePath: '..', frameworks: ['qunit', 'detectBrowsers'], - files: [ + 'node_modules/video.js/dist/video-js.css', + + 'node_modules/es5-shim/es5-shim.js', 'node_modules/sinon/pkg/sinon.js', - 'node_modules/sinon/pkg/sinon-ie.js', 'node_modules/video.js/dist/video.js', - 'node_modules/video.js/dist/video-js.css', 'test/dist/bundle.js' ], customLaunchers: {