Edit on GitHub
Jump to docs navigation

Internals / The Bolt JS and CSS assets

Note: You are currently reading the documentation for Bolt 3.4. Looking for the documentation for Bolt 3.6 instead?

Bolt's backend has a lot of JavaScript and CSS, in order to make it look good, and work smoothly for the editors that use this environment. Meanwhile, it can be daunting to developers who need to either debug something in the Bolt backend, or who wish to use the available code to extend the backend in their extensions.

This page will give some insights into how it is structured, and how you can compile the assets in order to work with them.

For starters, Bolt's backend build process builds both the JavaScript as well as the CSS. Both of these consist of external packages we leverage, as well as our own code.

Quickstart

To get started, you'll need to have Node.js and Yarn on your system. The build process works best using Node 6+ and Yarn 1.0+.

To get the required modules, and pull in other dependencies, change into the app/src/ directory and run:

yarn install --strict-semver

You can then build or rebuild assets files by running:

yarn run grunt build

Alternatively, you can start the Grunt "watch" task that will update the built asset files while you're working on them by running:

yarn run grunt watch

CSS - Bootstrap and custom SCSS

The CSS is based on Bootstrap 3.3.7, with our own theming and custom styles added to that. It is built using sass. The main Bootstrap files are found at app/src/node_modules/bootstrap-sass. Our custom SCSS can be found at app/src/sass/

This folder contains the .scss files for the development of the back-end theme. The .scss files will be compiled into normal stylesheets in the app/view/css/ folder.

There is one main .scss file in the sass/ directory: app.scss

Folders

Within the modules/ folder you'll find all sass partials that should be included in the main app .scss files. In _base.scss we set all variables, mixins, extends and other sass statements that do not generate any styles in the final built file.

Media Query Handling

In _base.scss we have the Media Query handling. Here's the summary:

Put your code for a specific Media Query in this mixin:

@include respond-to('query_name') {}

For instance:

/* MQ for medium-screens and up ( min-width >=768 ) */
@include respond-to(medium-screens) {
    /*
     * some styles, e.g.
        color:$green; //gotta have greens!
     */
}

$medium-screens is coupled to a certain 'em' based width for the viewport.

As we develop 'mobile first' the base styles are not in a Media Query, so we set the following: (assuming our base em size of 1em is 16px)

  • $mid-mobile
  • $medium-screens
  • $large-screens
  • $wide-screens

See _base.scss for the current values.

JavaScript - Bootstrap, jQuery, CKEditor and more

Our JavaScript source files can be found in app/src/js. Some of the files are included in our git repository, others are pulled in using either NPM or our Grunt build process.

The final JavaScript files are built int app/view/js/.

Available Grunt tasks

  • grunt
    Starts the watch task that monitors the JavaScript and Sass source files and automatically rebuilds bolt.js, bolt.css and liveeditor.css when changes are detected.

  • grunt updateBolt
    Manually starts a rebuild of bolt.js, bolt.css and liveeditor.css.

  • grunt updateLib
    Updates everything that depends on external resources, either provided by npm or embedded in the lib folder. This command mainly builds lib.js and lib.css from external libraries, installs fonts, CKEditor and library locale files. It has to be run after any update to one of the external resources.

  • grunt prepareCkeditor
    Does some cleanup on CKEditor files in lib/ckeditor after updating it. Update process:

    • Get the latest version with URL extracted from lib/ckeditor/build-config.js.
    • Empty the folder lib/ckeditor and unpack the newer version there.
    • Run grunt prepareCkeditor to get files prepared.
    • Run grunt updateLib to get everything in place.
  • grunt docJs
    Generates documentation of Bolt's own JavaScript modules in the folder docs/js.

  • grunt docPhp
    Generates documentation of Bolt source files in the folder docs/php.

  • grunt lintHtml
    Downloads the Bolt backend pages defined in grunt-local/pages.js and checks them for html errors and problems.

  • grunt lintBoot
    Downloads Bolt backend pages defined in grunt-local/pages.js and checks them for Bootstrap errors and problems.

Local options

Add JS options files to the folder app/src/grunt-local/, in which you can put the options you want to overwrite. The content of these files look like:

    module.exports = {
        value: "The value"
    };

These files will automatically be ignored by git.

Sourcemaps

If it doesn't yet exist, create the file app/src/grunt-local/sourcemap.js.

A sample file to enable generation of sourcemaps looks like this:

    module.exports = {
        css: true,
        js: true
    };

Pages

For the linting tasks you have to define a list of pages to download to the tmp/pages folder. If it doesn't yet exist, create the file app/src/grunt-local/pages.js.

A sample file to enable this task looks like this:

    module.exports = {
        baseurl: "http://bolt.localhost/bolt/",
        requests: { … }
    };

The key of the requests part is the filename and the value defines the page to download.

  • If no extension is given on the request key .html is automatically appended.
  • If the value is a string it is handled as a GET request with that value a relative url.
  • If the value is an empty string the key is used as value.
  • If the value is an object it is used as request configuration (see https://github.com/request/request).
  • If the key is @login it is handled as not saved login request. The value has to be {u: "<username>", p: "<password>"} then.
  • If the key is @logout it is handled as not saved logout request. The value has to be {} then.

Example: Key handling

Three requests save the same page to file login.html.

    module.exports = {
        baseurl: "http://bolt.localhost/bolt/",
        requests: {
                "login": "",
                "login": "login",
                "login.html": "login"
            }
        }
    };

Example: POST request

Issue a manual login (same as @login, only page is saved as dashboard.html):

    module.exports = {
        baseurl: "http://bolt.localhost/bolt/",
        requests: {
            dashboard: {
                url: "login",
                method: "POST",
                form: {
                    username: "<enter username here>",
                    password: "<enter password here>",
                    action: "login"
                }
            }
        }
    };

Example: "Full" interface check

    module.exports = {
        baseurl: "http://bolt.localhost/bolt/",
        requests: {
            "login": "",
            "@login": {"u": "<enter username here>", "p": "<enter password here>"},

            // Dashboard
            "dashboard": "/",

            // Configuration: Users & Permissions
            "config-users": "users",
            "config-users-new": "users/edit",
            "config-users-edit": "users/edit/1",
            "config-roles": "roles",
            "config-permissions": "file/edit/config/permissions.yml",

            // Configuration: Main configuration
            "config-main": "file/edit/config/config.yml",

            // Configuration: Contenttypes
            "config-contenttypes": "file/edit/config/contenttypes.yml",

            // Configuration: Taxonomy
            "config-taxonomy": "file/edit/config/taxonomy.yml",

            // Configuration: Menu
            "config-menu": "file/edit/config/menu.yml",

            // Configuration: Routing
            "config-routing": "file/edit/config/routing.yml",

            // Configuration: Check database
            "config-dbcheck": "dbcheck",
            "config-prefill": "prefill",

            // Configuration: Clear the cache
            "config-clearcache": "clearcache",

            // Configuration: Change Log
            "config-changelog": "changelog",

            // Configuration: System Log
            "config-systemlog": "systemlog",

            // File Management
            "files-files": "files",
            "files-theme": "files/theme",

            // Translations
            "translations-messages": "tr",
            "translations-long-messages": "tr/infos",
            "translations-contenttypes": "tr/contenttypes",

            // Extras
            "extras-view-install": "extend",
            "extras-configure": "files/config/extensions",

            // Main Menu
            "profile": "profile",

            "@logout": {},
        }
    };

Bootlint

If it doesn't yet exist, create the file app/src/grunt-local/bootlint.js. You can override Bootlint options, e.g.:

    module.exports = {
        relaxerror: ["W012"],
        showallerrors: false,
        stoponerror: true,
        stoponwarning: false
    };

Htmllint

If it doesn't yet exist, create the file app/src/grunt-local/htmllint.js. You can override Htmllint options, e.g.:

    module.exports = {
        ignore: [
            "Element “link” is missing required attribute “property”.",
            /^Duplicate ID/
        ]
    };
Edit this page on GitHub
Couldn't find what you were looking for? We are happy to help you in the forum, on Slack or on IRC.