2015-02-06 09:43:06 +00:00
|
|
|
var gulp = require('gulp'),
|
|
|
|
gulp_util = require('gulp-util'),
|
2015-07-19 00:13:51 +00:00
|
|
|
watch = require('gulp-watch'),
|
2015-09-10 22:09:09 +00:00
|
|
|
rename = require('gulp-rename'),
|
2015-02-06 09:43:06 +00:00
|
|
|
run = require('gulp-run'),
|
2015-07-20 08:06:32 +00:00
|
|
|
less = require('gulp-less'),
|
2015-07-19 00:13:51 +00:00
|
|
|
bower_resolve = require('bower-resolve'),
|
|
|
|
browserify = require('browserify'),
|
2015-07-20 08:06:32 +00:00
|
|
|
debowerify = require('debowerify'),
|
2015-07-19 00:13:51 +00:00
|
|
|
uglify = require('gulp-uglify'),
|
|
|
|
vinyl_source = require('vinyl-source-stream'),
|
|
|
|
vinyl_buffer = require('vinyl-buffer'),
|
|
|
|
es = require('event-stream'),
|
|
|
|
path = require('path'),
|
Add eslint using the airbnb config. (#2905)
* Add eslint using the airbnb config.
In an effort to make the JS consistent, this adds an ESLint gulp task. ESLint
is *very* configurable, and has no defaults. Instead, this reaches for
airbnb's legacy config (which covers ES5), which is one of the most popular
configurations. As a last step, it turns off all of the rules which currently
fail. We can turn them on piecemeal, or override the airbnb style to use a
different format.
Rules to prioritize (as they likely indicate bugs):
* "array-callback-return": "off",
* "eqeqeq": "off",
* "guard-for-in": "off",
* "no-inner-declarations": "off",
* "no-loop-func": "off",
* "no-mixed-operators": "off",
* "no-undef": "off",
* "no-use-before-define": "off",
* "one-var": "off",
* Lint frontend in Travis.
This adds an ESLint step to the CI service so we prevent unlinted code from
making its way in.
* Create an ESLint tox env.
By adding a tox env for eslint, we allow users to run it locally as part of
tox runs.
Thanks for the suggestion @ericholscher!
* Fix tox call to gulp lint task
2017-05-24 23:12:33 +00:00
|
|
|
eslint = require('gulp-eslint'),
|
2015-07-19 00:13:51 +00:00
|
|
|
pkg_config = require('./package.json');
|
2015-02-06 09:43:06 +00:00
|
|
|
|
2015-07-19 00:13:51 +00:00
|
|
|
// Applications with primary static sources. We define these here to avoid
|
|
|
|
// picking up dependencies of the primary entry points and putting any
|
|
|
|
// limitations on directory structure for entry points.
|
2015-02-26 20:02:32 +00:00
|
|
|
var sources = {
|
2015-08-24 08:35:13 +00:00
|
|
|
builds: {'js/detail.js': {}},
|
|
|
|
core: {
|
2015-08-26 19:22:17 +00:00
|
|
|
'js/readthedocs-doc-embed.js': {expose: false},
|
2015-08-24 08:35:13 +00:00
|
|
|
'js/autocomplete.js': {},
|
Integrate on-site messaging that is persistent, combine message transports (#2406)
* WIP for integrating persistent messaging for users
Combines notifications so that email/on site messaging will all be maintained in
the same place, and can extend from each other using normal template semantics.
* Add email support, clean up implementation
* Add reqs
* Drop unnecessary string conversion
* Change admin email form to look at templates, not ask for template source
* Add docs, tests, views for processing redirects
* Do the thing I meant to do
* Drop views, just use javascript instead
This adds javascript that intercepts link clicks in notifications,
hits the dismiss url defined on the dom object, and then redirects
to the correct url of the original link.
* Move classes around and rename module
* Drop unused notification for testing
* Clean up usage, drop test uses of the views/notifications
* Add example usage that will be used for notification on resource usage
* Fix mock module path
* Add more docs around implementation
2016-10-01 17:19:51 +00:00
|
|
|
'js/site.js': {},
|
2015-09-10 22:09:09 +00:00
|
|
|
'css/badge_only.css': {src: 'bower_components/sphinx-rtd-theme/sphinx_rtd_theme/static/css/badge_only.css'},
|
2015-09-10 23:23:03 +00:00
|
|
|
'css/theme.css': {src: 'bower_components/sphinx-rtd-theme/sphinx_rtd_theme/static/css/theme.css'},
|
|
|
|
|
|
|
|
'font/Lato-Bold.ttf': {src: 'bower_components/lato-googlefont/Lato-Bold.ttf'},
|
|
|
|
'font/Lato-Regular.ttf': {src: 'bower_components/lato-googlefont/Lato-Regular.ttf'},
|
2018-05-22 16:46:43 +00:00
|
|
|
'font/Lato-Italic.ttf': {src: 'bower_components/lato-googlefont/Lato-Italic.ttf'},
|
2015-09-10 23:23:03 +00:00
|
|
|
'font/Inconsolata-Bold.ttf': {src: 'bower_components/inconsolata-googlefont/Inconsolata-Bold.ttf'},
|
|
|
|
'font/Inconsolata-Regular.ttf': {src: 'bower_components/inconsolata-googlefont/Inconsolata-Regular.ttf'},
|
|
|
|
'font/RobotoSlab-Bold.ttf': {src: 'bower_components/robotoslab-googlefont/RobotoSlab-Bold.ttf'},
|
|
|
|
'font/RobotoSlab-Regular.ttf': {src: 'bower_components/robotoslab-googlefont/RobotoSlab-Regular.ttf'},
|
|
|
|
'font/FontAwesome.otf': {src: 'bower_components/font-awesome/FontAwesome.otf'},
|
|
|
|
|
|
|
|
'font/fontawesome-webfont.eot': {src: 'bower_components/font-awesome/fonts/fontawesome-webfont.eot'},
|
|
|
|
'font/fontawesome-webfont.svg': {src: 'bower_components/font-awesome/fonts/fontawesome-webfont.svg'},
|
|
|
|
'font/fontawesome-webfont.ttf': {src: 'bower_components/font-awesome/fonts/fontawesome-webfont.ttf'},
|
|
|
|
'font/fontawesome-webfont.woff': {src: 'bower_components/font-awesome/fonts/fontawesome-webfont.woff'},
|
2018-05-22 16:46:43 +00:00
|
|
|
'font/fontawesome-webfont.woff2': {src: 'bower_components/font-awesome/fonts/fontawesome-webfont.woff2'},
|
2015-09-10 23:23:03 +00:00
|
|
|
'font/FontAwesome.otf': {src: 'bower_components/font-awesome/fonts/FontAwesome.otf'}
|
2015-08-24 08:35:13 +00:00
|
|
|
},
|
2015-09-19 00:17:32 +00:00
|
|
|
projects: {
|
|
|
|
'js/tools.js': {},
|
2015-09-21 23:52:26 +00:00
|
|
|
'js/import.js': {},
|
2015-09-19 00:17:32 +00:00
|
|
|
'css/import.less': {},
|
2016-03-09 23:11:10 +00:00
|
|
|
'css/admin.less': {},
|
2015-09-19 00:17:32 +00:00
|
|
|
},
|
2015-08-24 08:35:13 +00:00
|
|
|
gold: {'js/gold.js': {}},
|
|
|
|
donate: {'js/donate.js': {}}
|
2015-02-26 20:02:32 +00:00
|
|
|
};
|
|
|
|
|
2015-07-19 00:13:51 +00:00
|
|
|
// Standalone application to create vendor bundles for. These can be imported
|
|
|
|
// with require in the browser or with Node during testing.
|
2015-08-25 05:59:39 +00:00
|
|
|
var standalone = {
|
|
|
|
'jquery': {standalone: 'jquery'},
|
|
|
|
'knockout': {},
|
|
|
|
'jquery-migrate': {standalone: 'jquery-migrate'},
|
|
|
|
'jquery-ui': {standalone: 'jquery-ui'},
|
|
|
|
'underscore': {standalone: '_'}
|
|
|
|
};
|
2015-07-19 00:13:51 +00:00
|
|
|
|
|
|
|
// Build application call, wraps building entry point files for a single
|
|
|
|
// application. This is called by build and dev tasks.
|
|
|
|
function build_app_sources (application, minify) {
|
|
|
|
// Normalize file glob lists
|
2015-09-10 22:09:09 +00:00
|
|
|
var bundles = Object.keys(sources[application]).map(function (entry_path) {
|
2015-08-24 08:35:13 +00:00
|
|
|
var bundle_path = path.join(
|
2015-09-10 22:09:09 +00:00
|
|
|
pkg_config.name, application, 'static-src', '**', entry_path),
|
|
|
|
bundle_config = sources[application][entry_path] || {},
|
2015-08-24 08:35:13 +00:00
|
|
|
bundle;
|
2015-07-19 00:13:51 +00:00
|
|
|
|
2015-08-24 08:35:13 +00:00
|
|
|
if (/\.js$/.test(bundle_path)) {
|
|
|
|
// Javascript sources
|
|
|
|
bundle = gulp
|
|
|
|
.src(bundle_path)
|
|
|
|
.pipe(es.map(function (file, cb) {
|
2015-08-26 19:22:17 +00:00
|
|
|
if (typeof(bundle_config.expose) == 'undefined') {
|
|
|
|
var parts = [
|
|
|
|
application,
|
|
|
|
path.basename(file.path, '.js')
|
|
|
|
];
|
|
|
|
bundle_config.expose = parts.join('/');
|
|
|
|
}
|
|
|
|
else if (bundle_config.expose === false) {
|
|
|
|
bundle_config.expose = undefined;
|
|
|
|
}
|
|
|
|
return browserify_stream(
|
|
|
|
file, bundle_config, cb
|
|
|
|
);
|
2017-11-04 07:15:03 +00:00
|
|
|
}))
|
|
|
|
.pipe(rename(application + path.sep + entry_path));
|
2015-07-19 00:13:51 +00:00
|
|
|
|
2015-08-24 08:35:13 +00:00
|
|
|
if (minify) {
|
|
|
|
bundle = bundle
|
|
|
|
.pipe(vinyl_buffer())
|
|
|
|
.pipe(uglify())
|
|
|
|
.on('error', function (ev) {
|
|
|
|
gulp_util.beep();
|
|
|
|
gulp_util.log('Uglify error:', ev.message);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (/\.less$/.test(bundle_path)) {
|
2015-09-10 22:09:09 +00:00
|
|
|
// LESS sources
|
2015-08-24 08:35:13 +00:00
|
|
|
bundle = gulp.src(bundle_path)
|
|
|
|
.pipe(less({}))
|
|
|
|
.on('error', function (ev) {
|
|
|
|
gulp_util.beep();
|
|
|
|
gulp_util.log('LESS error:', ev.message);
|
|
|
|
});
|
|
|
|
}
|
2015-09-10 22:09:09 +00:00
|
|
|
else {
|
|
|
|
// Copy only sources, from bower_components/etc
|
|
|
|
var bundle = gulp;
|
|
|
|
if (bundle_config.src) {
|
|
|
|
bundle = bundle
|
|
|
|
.src(bundle_config.src)
|
|
|
|
.pipe(rename(application + path.sep + entry_path));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bundle = bundle
|
|
|
|
.src(bundle_path);
|
|
|
|
}
|
|
|
|
}
|
2015-07-19 00:13:51 +00:00
|
|
|
|
2015-08-24 08:35:13 +00:00
|
|
|
return bundle;
|
|
|
|
});
|
2015-07-19 00:13:51 +00:00
|
|
|
|
2015-08-24 08:35:13 +00:00
|
|
|
return es.merge(bundles)
|
2015-07-19 00:13:51 +00:00
|
|
|
.pipe(gulp.dest(path.join(pkg_config.name, application, 'static')));
|
|
|
|
}
|
|
|
|
|
2015-07-20 08:06:32 +00:00
|
|
|
// Browserify build
|
2015-08-24 08:35:13 +00:00
|
|
|
function browserify_stream (file, config, cb_output) {
|
2015-07-19 00:13:51 +00:00
|
|
|
bower_resolve.offline = true;
|
|
|
|
bower_resolve.init(function () {
|
2015-09-28 17:03:53 +00:00
|
|
|
var bundle_stream = browserify({
|
|
|
|
paths: ['./']
|
|
|
|
});
|
2015-07-19 00:13:51 +00:00
|
|
|
|
2015-08-25 05:59:39 +00:00
|
|
|
Object.keys(standalone).map(function (module) {
|
2015-07-19 00:13:51 +00:00
|
|
|
bundle_stream = bundle_stream.external(module);
|
|
|
|
});
|
|
|
|
|
2015-08-26 19:22:17 +00:00
|
|
|
if (typeof(config.expose) == 'undefined') {
|
|
|
|
bundle_stream.add(file.path);
|
2015-08-24 08:35:13 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
bundle_stream = bundle_stream.require(
|
2015-08-26 19:22:17 +00:00
|
|
|
file.path, {expose: config.expose}
|
|
|
|
);
|
2015-08-24 08:35:13 +00:00
|
|
|
}
|
|
|
|
|
2015-07-19 00:13:51 +00:00
|
|
|
bundle_stream
|
2015-08-25 05:59:39 +00:00
|
|
|
.transform('debowerify', {ignoreModules: Object.keys(standalone)})
|
2015-07-19 00:13:51 +00:00
|
|
|
.bundle()
|
|
|
|
.on('error', function (ev) {
|
|
|
|
gulp_util.beep();
|
|
|
|
gulp_util.log('Browserify error:', ev.message);
|
2015-02-26 20:02:32 +00:00
|
|
|
})
|
2017-11-04 07:15:03 +00:00
|
|
|
.pipe(vinyl_source(path.basename(file.path)))
|
2015-07-19 00:13:51 +00:00
|
|
|
.pipe(es.map(function (data, cb_inner) {
|
|
|
|
cb_output(null, data);
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
}
|
2015-02-06 09:43:06 +00:00
|
|
|
|
2015-07-19 00:13:51 +00:00
|
|
|
// Build standalone vendor modules
|
|
|
|
function build_vendor_sources(data, cb_output) {
|
|
|
|
bower_resolve.offline = true;
|
|
|
|
bower_resolve.init(function () {
|
2015-08-25 05:59:39 +00:00
|
|
|
var standalone_modules = Object.keys(standalone).map(function (module) {
|
|
|
|
var vendor_options = standalone[module] || {},
|
|
|
|
vendor_bundles = [];
|
|
|
|
|
|
|
|
// Bundle vendor libs for import via require()
|
|
|
|
vendor_bundles.push(
|
|
|
|
browserify()
|
2015-07-19 00:13:51 +00:00
|
|
|
.require(bower_resolve(module), {expose: module})
|
|
|
|
.bundle()
|
|
|
|
.pipe(vinyl_source(module + '.js'))
|
|
|
|
.pipe(vinyl_buffer())
|
|
|
|
.pipe(uglify())
|
2015-08-25 05:59:39 +00:00
|
|
|
.pipe(gulp.dest(
|
|
|
|
path.join(pkg_config.name, 'static', 'vendor')
|
|
|
|
))
|
|
|
|
);
|
|
|
|
|
|
|
|
// Bundle standalone for legacy use. These should only be used on
|
|
|
|
// old documentation that does not yet use the new bundles
|
|
|
|
if (typeof(vendor_options.standalone) != 'undefined') {
|
|
|
|
vendor_bundles.push(
|
|
|
|
browserify({standalone: vendor_options.standalone})
|
|
|
|
.require(bower_resolve(module))
|
|
|
|
.bundle()
|
|
|
|
.pipe(vinyl_source(module + '-standalone.js'))
|
|
|
|
.pipe(vinyl_buffer())
|
|
|
|
.pipe(uglify())
|
|
|
|
.pipe(gulp.dest(
|
|
|
|
path.join(pkg_config.name, 'static', 'vendor')
|
|
|
|
))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return es.merge(vendor_bundles);
|
2015-07-19 00:13:51 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
es
|
|
|
|
.merge(standalone_modules)
|
|
|
|
.pipe(es.wait(function (err, body) {
|
|
|
|
cb_output(null, data);
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
}
|
2015-02-06 09:43:06 +00:00
|
|
|
|
|
|
|
/* Tasks */
|
2015-07-19 00:13:51 +00:00
|
|
|
gulp.task('build', function (done) {
|
|
|
|
gulp_util.log('Building source files');
|
|
|
|
|
|
|
|
es
|
|
|
|
.merge(Object.keys(sources).map(function (n) {
|
|
|
|
return build_app_sources(n, true);
|
|
|
|
}))
|
|
|
|
.pipe(es.wait(function (err, body) {
|
|
|
|
gulp_util.log('Collecting static files');
|
2015-07-30 22:46:20 +00:00
|
|
|
run('./manage.py collectstatic --noinput')
|
2015-07-19 00:13:51 +00:00
|
|
|
.exec('', function (err) { done(err); });
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
gulp.task('vendor', function (done) {
|
|
|
|
build_vendor_sources(null, done);
|
|
|
|
});
|
2015-02-06 09:43:06 +00:00
|
|
|
|
2015-07-19 00:13:51 +00:00
|
|
|
gulp.task('dev', function (done) {
|
|
|
|
gulp_util.log('Continually building source files');
|
2015-02-06 09:43:06 +00:00
|
|
|
|
2015-07-19 00:13:51 +00:00
|
|
|
es
|
|
|
|
.merge(Object.keys(sources).map(function (application) {
|
2015-07-30 21:07:51 +00:00
|
|
|
var files = [
|
|
|
|
path.join(pkg_config.name, application, 'static-src', '**', '*.js'),
|
2015-08-25 18:55:40 +00:00
|
|
|
path.join(pkg_config.name, application, 'static-src', '**', '*.less')
|
2015-07-30 21:07:51 +00:00
|
|
|
];
|
2015-07-19 00:13:51 +00:00
|
|
|
return watch(files, {verbose: true, name: 'dev'}, function () {
|
|
|
|
build_app_sources(application, false)
|
|
|
|
.pipe(es.wait(function (err, body) {
|
|
|
|
gulp_util.log('Collecting static files');
|
2015-07-30 22:46:20 +00:00
|
|
|
run('./manage.py collectstatic --noinput').exec('');
|
2015-07-19 00:13:51 +00:00
|
|
|
}));
|
|
|
|
});
|
|
|
|
}))
|
|
|
|
.pipe(es.wait(function (err, body) {
|
|
|
|
done(null);
|
|
|
|
}));
|
2015-02-06 09:43:06 +00:00
|
|
|
});
|
|
|
|
|
Add eslint using the airbnb config. (#2905)
* Add eslint using the airbnb config.
In an effort to make the JS consistent, this adds an ESLint gulp task. ESLint
is *very* configurable, and has no defaults. Instead, this reaches for
airbnb's legacy config (which covers ES5), which is one of the most popular
configurations. As a last step, it turns off all of the rules which currently
fail. We can turn them on piecemeal, or override the airbnb style to use a
different format.
Rules to prioritize (as they likely indicate bugs):
* "array-callback-return": "off",
* "eqeqeq": "off",
* "guard-for-in": "off",
* "no-inner-declarations": "off",
* "no-loop-func": "off",
* "no-mixed-operators": "off",
* "no-undef": "off",
* "no-use-before-define": "off",
* "one-var": "off",
* Lint frontend in Travis.
This adds an ESLint step to the CI service so we prevent unlinted code from
making its way in.
* Create an ESLint tox env.
By adding a tox env for eslint, we allow users to run it locally as part of
tox runs.
Thanks for the suggestion @ericholscher!
* Fix tox call to gulp lint task
2017-05-24 23:12:33 +00:00
|
|
|
gulp.task('lint', function (done) {
|
|
|
|
var paths = Object.keys(sources).map(function(application) {
|
|
|
|
return path.join(pkg_config.name, application, 'static-src', '**', '*.js');
|
|
|
|
});
|
|
|
|
return gulp
|
|
|
|
.src(paths)
|
|
|
|
.pipe(eslint())
|
|
|
|
.pipe(eslint.format())
|
|
|
|
.pipe(eslint.failAfterError());
|
|
|
|
});
|
|
|
|
|
2015-02-06 09:43:06 +00:00
|
|
|
gulp.task('default', ['build']);
|