Skin:Lift/Development guide

The Lift skin was developed using the SkinMustache class, available in Mediawiki 1.36 and above. This is a development guide to show how it was made so that other skin developers will have an idea as to what they can do when developing skins using the SkinMustache class.

Goals
This development guide will show how to:


 * Set up the initial folder for a skin using SkinMustache
 * Set up SkinJSON to aid in developing and troubleshooting
 * Easily incorporate frameworks, such as Bootstrap, Hover, Animate, and Font Awesome, in addition to incorporate the Google Roboto font
 * Easily incorporate custom css and js files
 * Create a fixed-top header and search bar using Bootstrap
 * Extend the SkinMustache method to provide html-free menus so that the Mustache template will have fuller control over the html displayed
 * Clean up skin.json
 * Show how extensions can pass additional information to the skin
 * Show how to incorporate that additional information in the mustache templates

Set up the initial folder for a skin using SkinMustache
Although a skin folder can have a variety of structures, the Example skin provides a starting point. I personally had difficulties downloading and installing the files from the Github repository, so I recommend downloading from the Mediawiki Skin:Example page.

Install the skin per the directions and in the wiki under Preferences change the skin to Example. For a new wiki installation, the Main Page should now look something like this:

To convert this to our new skin:
 * 1) Rename the "Example" folder to "Lift"
 * 2) Now in the "Lift" folder, delete the .phan folder and all files in the root EXCEPT skin.json
 * 3) Open skin.json and change all instances of "Example" to "Lift" being careful to maintain case sensitivity
 * 4) In LocalSettings.php change wfLoadSkin( 'Example' ); to wfLoadSkin( 'Lift' );
 * 5) In the wiki under Preferences change the skin to Lift

Checking our wiki, the Main Page should look the same as it did when the skin was named Example.

Finally, edit skin.json to update the other information for your new skin (i.e., "version", "author", etc.).

Set up SkinJSON to aid in developing and troubleshooting
SkinJSON is a useful tool to allow us to see the data returned by SkinMustache. Download the files from the SkinJSON Github repository into a SkinJSON folder under our Skins directory and enter wfLoadSkin( 'SkinJson' ); in LocalSetting.php.

You will see SkinJSON now available as a skin under your preferences as jsonskin but DO NOT UPDATE YOUR PREFERENCES TO USE jsonskin. We will access the json returned by SkinMustache class indirectly through the following url:

basewikiurl/Main_Page?useskin=lift&useformat=json

This will show all the data that is passed to the Lift skin in a json format.

When viewing the wiki normally, the SkinMustache class is merging this json data with the mustache files inside the templates folder to form the HTML to render the page.

Of interest here are the various items under "data-portlets", for example the "data-user-menu":

Data-portlets are used to form our menus, with each portlet being an individual menu. For the data-user-menu, the core Mediawiki software determines what menu options will be available to the user on each page, the SkinMustache class converts those options into json data (shown as html-items here), and the mustache files in the templates directory form it into html to display on the wiki.

Easily incorporate frameworks
To incorporate other frameworks, in this case Bootstrap, Animate, Hover, and Font Awesome, download the folders and files of those frameworks into the resources folder:

To incorporate the Roboto front from Google, create a font_roboto.css file and place it in the resources folder:

The resources folder:

Next, the location of these resources need to be identified to the skin using ResourcesModules in skin.json (note that I have only kept two of the original four style sheets, screen-common.less and screen-desktop.less, and I am no longer using conditional loading; later we'll also be deleting those two style sheets as we move toward using Bootstrap for the skin):

At this point all of our resources are located in the "resources" directory, so we can simplify our skin.json file by updating the localBasePath under ResourceFileModulePaths to point to the "resources" folder (and remember to remove the leading "resources/" fragment from the styles and scripts themselves):

Easily incorporate custom css and js files
We can also use the ResourceModules to load our own css and js files.

For now, create two files, lift.css and lift.js in the resources root directory:

Now edit skin.json to identify the two custom files under ResourceModules:

Finally, edit the lift.css file to specify Roboto should be used as the font for the entire body element:

At this point, we have added all the resources we'll use and reserve the ability to edit lift.css and lift.js more later. However, looking at our wiki's Main page it will show that the font is now Roboto because it was loaded under font_roboto.css and the font for the body element was specified in lift.css (compare this to the screenshot above for the Example skin without any modifications to see the difference in fonts):



Create a fixed-top header with the site logo and search bar
Now that all the resources are loaded, let's create a fixed-top header with the site logo and search bar for the site.

First, let's use the SkinJSON skin to look at the relevant JSON returned from the SkinMustache class by navigating to the url:

yourwikibaseurl/wiki/Main_Page?useskin=lift&useformat=json

For my test wiki this shows:

Next, let's look in the templates folder at the skin.mustache file. The SkinMustache class uses to template construct the HTML from the above JSON. If you're not familiar with Mustache, then it would be worth reviewing a good tutorial first. It would also be worth quickly comparing the JSON and the template with the actual html generated for the main page to see how the page is constructed.

At the very top of the skin.mustache template, add to include header.mustache as a partial template. Also, start to introduce Boostrap classes into the templates by adding the classes "container-xxl", "pt5", "mt-5" to the mw-wrapper div. This will help keep the size of the main content consistent while also adding some space at the top for our header: Now create the file header.mustache in the templates directory and enter this code. Your templates folder should now look like this: Now refresh the wiki and the main page should look like this: We were able to previously change the site to the Roboto font, and now, using Boostrap classes, we are able to easily make the new header in a fixed position at the top of the page. It has the site logo and a fully functional search bar using Bootstrap's floating labels. The search bar as a button, but in the template we added the class "d-none", so while it is operational it does not display. Additionally, we've taken the first steps to move fully toward a Bootstrap skin by adding the "container-xxl" class to the mw-wrapper div, although it didn't change the appearance.

Take a moment to navigate around the site to see how various pages look with the header at the top and the Roboto font.

Next we'll tackle the menu items.

Extend SkinMustache method to provide html-free menu links
Currently the menus are returned in data-portlets and data-portlets-sidebar:

A closer look at one of the menu items, data-user-menu, shows that the JSON returned from SkinMustache already forms the html for us under the member html-items:

This preformmated html from SkinMustache prevents us from templating the JSON to take advantage of Bootstrap classes to style our own menus.

To fix this, we must make our own skin class, in this case SkinLift, that will extend SkinMustache so that we have control over the JSON that is returned.

First, create a new folder called includes, and inside that folder create a file called SkinLift.php:

For now, enter this into the SkinLift.php file: Update the json.skin file to 1) autoload the SkinLift class from "includes/SkinLift.php" and 2) change the class under "ValidSkinNames"."lift" from "SkinMustache" to "SkinLift":

Now refresh the wiki to ensure everything works. The page should be the same although the class returning the JSON is now SkinLift.

To get our new class to return an array of html attributes rather than fully formed html, we need to overwrite SkinMustache's getPortletData function to the following: Save SkinLift.php and now look at the JSON returned from SkinLift using SkinJSON: The new function in SkinLift has added a new member to each data-portlet called array-links, which holds the html attributes to make links rather than the html itself.

With this new JSON available we can return to header.mustache to add our menus to the header as well: