Extension Static Media Files¶
Static Media Bundles¶
Extensions can define sets of CSS and JavaScript files that should be packaged
and made available for use on a page. These are called “bundles,” and are
listed in the extension class’s Extension.css_bundles
and
Extension.js_bundles
attributes.
Each bundle has a name and a list of source files pertaining to that type of bundle. The format for a bundle is the same for CSS and JavaScript. Here’s an example:
class SampleExtension(Extension):
css_bundles = {
'default': {
'source_filenames': (
'css/common.less',
),
},
}
js_bundles = {
'default': {
'source_filenames': (
'js/extension.js',
'js/common.js',
),
},
'admin': {
'source_filenames': (
'js/admin.js',
),
}
}
A bundle can have any name. Bundle names will not conflict between extensions.
There’s one special bundle named “default”. If a “default” bundle is defined,
it will appear on all pages without having to be manually loaded. This is a
good place to put code you know will always need to execute, such as your
JavaScript JSExtension
subclass, or
to place CSS overrides you want to apply to all pages.
A bundle may also define an output_filename
, if it cares to specifically
name it. This is the name that will be used for the combined file during
packaging. If not provided, the file will be named based on the bundle name.
Usually, you will not need to provide your own name.
Packaging Bundles¶
Static bundles are packaged along with your extension automatically. You don’t have to do anything special. You will, however, need some node.js dependencies in order to package static media bundles.
If you’re running Review Board 2.5.7+, these dependencies will be installed for you when you begin to build the package.
If you’re running an older version, you will need to manually install them yourself. First, make sure you have a modern version of node.js installed and then run:
$ sudo npm install -g less uglifyjs
JavaScript File Types¶
Depending on the filename for your JavaScript code, the files will be run
through a compilation step. Files with a *.es6.js
or *.ts
extension will be compiled with Babel, as either ES6+ or TypeScript
respectively.
This allows you to use modern JavaScript features while still targeting your code to the same browsers as supported by Review Board. Using this is highly recommended if you expect to use features such as:
Changed in version 6.0: Support for TypeScript files was added in Review Board 6.0.
ES6 Modules¶
Starting with Review Board 6.0, you can additionally use ES6 modules to organize your code.
To use this, you’ll need to write a rollup.config.js
file with your
rollup configuration. This should live somewhere in your extension’s codebase
in a directory at or above the location of your javascript files.
This can be customized to your liking. At a minimum it will need to define the output module type, some common plugins, and the output namespace:
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
export default args => ({
external: [
'RB',
],
output: {
exports: 'named',
freeze: false,
sourcemap: true,
format: 'umd',
generatedCode: 'es2015',
// Put all code into window.MyExtension
name: 'MyExtension',
extend: true,
},
plugins: {
babel: babel({
babelHelpers: 'external',
extensions: extensions,
}),
commonjs: commonjs({
ignoreTryCatch: false,
transformMixedEsModules: true,
}),
resolve: resolve({
browser: true,
extensions: [
'.es6.js',
'.js',
'.ts',
],
}),
},
});
Any files with a basename of index (for example, index.ts or index.es6.js) will be compiled using rollup.js. You can then use the ES6 export and import keywords to manage your dependencies. Anything exported from your index file(s) will be made available in the bundle.
With the rollup.config.js
example above, the following view would be
available as MyExtension.MyView
within the runtime context.
export const MyView = Backbone.View.extend({
...
});
New in version 6.0.
Writing Static Media¶
CSS/Less¶
Files listed in Extension.css_bundles
can either be plain CSS
files, or less (*.less
) files.
Less is an extension of CSS that allows for variables, macros, calculations, conditionals, includes, and more. When used with your extension, these files will be automatically compiled to CSS for you.
We recommend using less over plain CSS files.
No matter which you use, you will want to take care to namespace your class names and IDs appropriately, in order to not conflict with rules from either Review Board or other extensions.
Including Review Board Styles¶
If you’re using less, you can reference definitions (variables and macros) from Review Board’s stylesheets by adding:
@import (reference) "@{STATIC_ROOT}rb/css/defs.less";
This will allow you to use any variable or macro we have defined. You can see the list by viewing the contents of reviewboard/static/rb/css/defs.less (and the contents of any files it includes) in the branch for the version you’re developing against.
JavaScript¶
JavaScript files have access to the Review Board JavaScript codebase, jQuery, Backbone.js, and other shipped libraries.
If you’re not using ES6 modules to structure your code, it is recommended that you namespace all the code in your JavaScript file, and wrap the file in a closure, as so:
(function() {
// Your code here.
})();
This will ensure that your variables do not leak and interfere with other extensions or the Review Board codebase.
Loading Static Media¶
When creating a template for a TemplateHook, you may need
to load one of your bundles. There are a couple of ways to do this: By using
the apply_to
option for a bundle, or by manually loading using template
tags.
Applying To Specific Pages¶
You can make a bundle apply to specific pages by listing their
URL names in the
apply_to
option in the bundle. This looks something like:
class SampleExtension(Extension):
css_bundles = {
'my-bundle': {
'source_filenames': (
'css/common.less',
),
'apply_to': [
'review-request-detail',
'my-custom-view',
],
},
}
There are a few useful predefined lists of URL names that might be useful to you:
reviewboard.urls.diffviewer_url_names
:URLs for all diff viewer pages.
reviewboard.urls.review_request_url_names
:URLs for the review request and diff viewer pages.
reviewboard.urls.reviewable_url_names
:URLs for the file attachment review and diff viewer pages.
Some other common URL names you might want to use include:
review-request-detail
:The review request page itself.
file-attachment
:The file attachment review UI pages (note that this will apply to all types of file attachments with review UIs!).
user-preferences
:The My Account page.
login
:The login page.
register
:The user registration page.
dashboard
:The Dashboard page.
You can look at the Review Board codebase reference for all the URL names (they’ll be listed in the
urls.py
files).