# Bespin Plugin Guide

## Themes

Bespin allows users to change themes (color schemes) and to create new theme plugins as well. This document describes how you can create your own themes and gives a basic overview about the theming techniques used in Bespin.

## The problem

Much of Bespin's UI (login form, command line) is themed using CSS. Imagine someone wants the whole UI background, including that of the command line, to be green. If you use CSS, this means you have to replace the entire CSS file only to change one variable - in this case the background color to green. If you could use variables in CSS, you could add a `background` variable and define a color in the theme data.

## LESS extends CSS

CSS has no way of dealing with variables, which is why Bespin uses LESS instead:

> LESS extends CSS with: variables, mixins, operations and nested rules. (Quoted from the LESS homepage.)

We use `themeVariables` to customize the CSS that LESS ultimately generates. You can't customize the UI 100%, because then every little bit has to be a themeVariable, but you can change most of the colors and a few more things. If that's not enough for your use case, you still can override the LESS file provided by a plugin with your own styles.

When you define a new theme, you have to create only a set of colors, fonts etc. that is then available to each plugin. We call these the `global themeVariables`. Plugins that provide user interface elements should use these variables to adjust their design. This ensures that whichever plugin a user installs looks right as they apply a theme.

## How this works

The `theme_manager` plugin is responsible to, surprise!, managing the themes. It loads all of the LESS files defined within the plugins and passes the plugin-specific `themeVariables` as well as the `global themeVariables` to it. The generated CSS code is then added to the page.

## Writing your own theme

If you want to create your own theme, create a new plugin - let's say 'demo_theme'. Themes have to be defined in the metadata of the plugin. The `package.json` file inside of the 'demo_theme' folder might look like this:

    {
        "description": "Provides a basic demo theme",
        "provides": [
            {
                "ep": "theme",
                "name": "demoTheme",
                "description": "Provides a basic demo theme",
                "pointer": "index#demoTheme"
           }
        ]
    }

The `name` provided in the metadata is what the user will type in when they're changing the theme. In this case, the user will type `set theme demoTheme`.

Create a new file `index.js` inside of the 'demo_theme' folder. This is the place where the `themeVariable` definitions will get stored. When the `theme_manager` plugin loads the demoTheme, it calls the function defined in the pointer property. This function has to return the `themeVariables`:

    // This goes in the index.js file.

    /**
     * Exports the demoTheme function that is called by the theme_manager plugin.
     */
    exports.demoTheme = function() {
        return {
            // Theme variables that are available to every plugin.
            global: {
                // Defines the color for links.
                link_color: 'blue',

                [...]
            },

            // Theme variables for the editor.
            text_editor: {
                // Theme of the gutter:
                gutter: {
                    [...]
                },

                editor: {
                    [...]
                },

                highlighter: {
                    [...]
                },

                scroller: {
                    [...]
                }
            },

            // Defines themeVariables for the command_line plugin.
            command_line: {
                // Defines the color for links.
                link_text: 'red';
            }
        };
    };

This is the basic structure of a theme definition. For a complete overview of all the adjustable `themeVariables` in the global and text_editor section, take a look at the whiteTheme.

In the example, we define the themeVariables for the `global themeVariables` (stored in `global`), the `text_editor` plugin and the `command_line` plugin. Within the `command_line`'s metadata the `link_text` is defined as:

        {
            "ep": "themevariable",
            "name": "link_text",
            "defaultValue": "@global_link_color"
        }

Every defined `themeVariable` has a `defaultValue`. This value is used if no other value is specified. In the case of the demoTheme, the value for the command_line's `link_text` will be red. If we hadn't declared this, the defaultValue will be used. As this value is equal to the global `link_color`, the value is then blue.

Note that it's generally a good idea to focus on the global variables as much as possible. There's no predicting which plugins a user is likely to have installed!

## Custom CSS

If adjusting the `themeVariables` is not enough for you, you can provide your own LESS file. The CSS rules from the LESS file will then override the CSS rules that are included inside of the plugins. The `theme_manager` has to know which LESS file you want to load with the theme, so you have to declare it inside of the themes metadata:

    {
        "description": "Provides a basic demo theme",
        "provides": [
            {
                "ep": "theme",
                "name": "demoTheme",
                "description": "Provides a basic demo theme",
                "url": [
                    "theme.less"
                ],
                "pointer": "index#demoTheme"
           }
        ]
    }

As the `demoTheme` gets activated, the `theme_manager` will handle the defined `themeVariables` and load up the files defined in the `url` property - in this case the theme.less file. This file has to be located in the resources folder which has to be inside of the plugin folder. You can use the whiteTheme as an example.