Theme extensions

map.apps allows you to create a bundle that extends an existing theme. This can be helpful in multiple circumstances:

  • You want to use a map.apps default theme but your custom bundles require custom styling.

  • You develop a custom main theme but your bundles are developed separately.

Although it is possible to provide custom CSS with each bundle, it makes sense to package all needed styles for a set of bundles in a themes extension bundle for the following reasons:

  • Less CSS is easier to use.

  • Files are compressed and packed into a single file during the build process. This results in fewer server requests in production.

The purpose of a theme extension is not to customize the overall look and feel of map.apps but to provide compulsory style declarations for custom bundles.

The setup consists of a few steps which are described below and require map.apps for Developers as base project.

Creating a theme extension for a single theme

In the following guide we’ll provide additional styles for two fictional bundles called earth-shadow-viewer and map-locate. The theme extension will extend the map.apps default theme everlasting.

Step 1: Scaffolding the bundle

Create a folder called src/main/js/bundles/custom-theme-extension with a manifest.json and the following content inside:

src/main/js/bundles/custom-theme-extension/manifest.json
{
    "name": "custom-theme-extension",
    "version": "1.0.0",
    "description": "This bundle provides additional styling rules, applied when the active theme is everlasting",
    "i18n": [],
    "layer": "",
    "main": "",
    "startLevel": 1,
    "cssThemesExtension": [
        {
            "name": "everlasting"
        }
    ]
}

Create the following files at the given locations with the displayed content:

src/main/js/bundles/custom-theme-extension/everlasting/everlasting.less
@import url("styles/bundles/bundles.css");
src/main/js/bundles/custom-theme-extension/everlasting/styles/bundles/bundles.css
@import url("earth-shadow-viewer.css");
@import url("map-locate.css");
src/main/js/bundles/custom-theme-extension/everlasting/styles/bundles/earth-shadow-viewer.less
@import "../themeSettings.less";
.@{themeName} {
  /*additional styling for custom bundle can be placed here*/
}
src/main/js/bundles/custom-theme-extension/everlasting/styles/bundles/map-locate.less
@import "../themeSettings.less";
.@{themeName} {
/*additional styling for custom bundle can be placed here*/
}

Delete the folder theme-custom from src/main/js/bundles as it is not possible to develop a custom theme and a theme extension in the same map.apps project.

Step 2: Configuring the gulpfile

Open gulpfile.js inside the project’s root folder and replace the complete call of mapapps.registerTasks(…​) with the following:

pom.xml
mapapps.registerTasks({
    /* A detailed description of available settings is available at https://www.npmjs.com/package/ct-mapapps-gulp-js */
    themes: ['everlasting'],
    themesSrcLocation: "./src/main/js/bundles/custom-theme-extension",
    themesDestLocation: "./target/webapp/js/bundles/custom-theme-extension"
});

Step 3: Adjusting the pom.xml

To use Less variables from the base theme (e.g. the @themeName or colors) you must copy the theme’s themeSettings.less file before compiling. Add the following <resources> element to the pom.xml inside the project’s root folder.

pom.xml
    <sourceDirectory>src/main/js</sourceDirectory>
    <!-- Add this element: -->
    <resources>
        <resource>
            <directory>${project.build.directory}/unpacked/layout/theme-common/styles</directory>
            <includes>
                <include>**/*</include>
            </includes>
            <targetPath>${js.build.outputPath}/bundles/custom-theme-extension/theme-common/styles/</targetPath>
            <filtering>false</filtering>
        </resource>
        <!-- Copy Theme Resources -->
        <resource>
            <directory>${project.build.directory}/unpacked/layout/theme-everlasting/styles</directory>
            <includes>
                <include>themeSettings.less</include>
            </includes>
            <targetPath>${js.build.outputPath}/bundles/custom-theme-extension/everlasting/styles</targetPath>
            <filtering>false</filtering>
        </resource>
    </resources>
    <testResources>

You must also change the execution phase of the frontend-maven-plugin to process-resources:

pom.xml
 <execution>
    <id>run gulp ${gulp.task}</id>
    <goals>
        <goal>gulp</goal>
    </goals>
    <configuration>
        <arguments>${gulp.task}</arguments>
    </configuration>
    <!-- add this element: -->
    <phase>process-resources</phase>
</execution>

After that, everything is set up and the development server can be started as usual.

Step 4: Testing the setup

To test your setup add the custom-theme-extension bundle from step 1 to the app.json of src/main/js/apps/ and load the app inside the browser. Use the browser’s developer tools to check that the files map-locate.css and earth-shadow-viewer.css get loaded.