Skin Extension Plugin

Last modified by Thomas Mortagne on 2023/10/10 17:11

cogAllows the interface components to pull the CSS and JavaScript they need
TypePlugin
Category
Developed byUnknown
Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Description

Skin extensions provide a way to customize the XWiki look & feel (CSS) and behavior (JavaScript) either on specific wiki pages (on demand) or on the entire wiki. Check the design page for more information.

Usage

For a complete documentation on what you can do with the Skin Extensions plugin, you can read the Skin Extensions tutorial.

  • $xwiki.jsx.use('Space.Page') pulls a JavaScript skin extension located in the wiki.
  • $xwiki.ssx.use('Space.Page') pulls a style sheet skin extension located in the wiki.
  • $xwiki.jsfx.use('path/to/file.js') pulls a JavaScript file located in the current skin, or on the filesystem, in the resources folder.
  • $xwiki.ssfx.use('path/to/file.css') pulls a style sheet file located in the current skin, or on the filesystem, in the resources folder.
  • $xwiki.jsrx.use('path/to/file.js') pulls a JavaScript file located in a JAR (located either in WEB-INF/lib or added through an Extension).
  • $xwiki.ssrx.use('path/to/file.css') pulls a style sheet file located in a JAR (located either in WEB-INF/lib or added through an Extension).
  • All the above versions accept as a second parameter a map of parameters, as in $xwiki.jsx.use('Document.Name', {'minify' : false, 'language': $context.language})
  • jsfx and ssfx have an optional second boolean parameter, which allows to specify whether the URL of the pulled file extension should always pass through the skin action: $xwiki.jsfx.use('path/to/file.js', true); for enabling this behavior with the generic parameter map, use $xwiki.jsfx.use('file.js', {'forceSkinAction': true})
  • $xwiki.linkx.use('url/to/file.css', {'type': 'text/css', 'rel': 'stylesheet'}) pulls a style sheet from any URL, this could be very useful in combination with the webjar module, where you can use $xwiki.linkx.use($services.webjars.url('artifact-id','path/to/file.css'), {'type': 'text/css', 'rel': 'stylesheet'})

Important parameters:

  • language is used by default for JavaScript extensions, set to the current context language, so that messages can be correctly translated with $msg.get
  • minify allows to prevent minifying the JavaScript and css code, for debug purposes; defaults to true
  • forceSkinAction, used only for skin resources, forces to construct URLs which pass through the skin action, which enables velocity parsing of the file; defaults to false
  • defer, used only for JavaScript extension, which can be used to prevent scripts from being defered; defaults to true
  • colorTheme allows to render a ssx extension using a specific color theme (including color themes from other wikis on a XEM)

Creating a skin extension

A skin extension is a wiki document which contains an instance of XWiki.StyleSheetExtention class or XWiki.JavaScriptExtention class. These objects
hold the actual code (CSS or JavaScript, respectively), caching policy, and whether this code should be parsed (if it is generated by Velocity or Groovy code).

Skin extension pulling

Skin extensions can be loaded automatically on every page or on demand (recommended) on specific wiki pages. The later has to be done programmatically from a wiki page or a Velocity template using a script like this:

$xwiki.ssx.use('My.CSS')
$xwiki.jsx.use('My.JavaScript')

Here, 'My.CSS' and 'My.JavaScript' are the references of the wiki pages that contain the StyleSheetExtension / JavaScriptExtension objects.

Limitations

If you use several Skin Extension objects of the same type in the same page (e.g. several SSX xobjects), they all have to use the same scope. You need separate pages if you need different scopes (e.g. on demand vs. wiki). Note that you may want to use several objects of the same scope if you want to separate your code in multiple modules for example.

Configuration

Skin extensions defined in wiki pages can be configured through the corresponding skin extension objects. The following list of options are shared between CSS and JavaScript extensions:

  • Use this extension: controls whether the skin extension is loaded automatically on every page or on demand (on a limited set of pages)
    • on this page or on demand: requires Script rights to activate it
    • on demand only: requires Script rights to activate it
    • on this wiki: requires Programming rights to activate it
  • Parse content: whether to parse the skin extension content for Velocity code before minifying it
  • Caching policy: How long the browser should keep using the result before asking for a refresh. Caching skin extensions is recommended to improve page load time. However, when used together with the Parse content option set to Yes, the outcome might get fixed on one of the possible results of the contained Velocity code and not re-evaluated until the browser ask for a new version.

    CachingPolicy.png

Note that if multiple skin extension objects of the same type are present on a wiki page then their content is aggregated and the configuration options of the first object are used (e.g. if the first sets "Parse content" to "Yes" and the second to "No", both will be parsed).

Style sheet configuration

Style sheet extensions have additional configuration options:

  • Content Type: you can choose between plain CSS and LESS

JavaScript configuration

12.7.1+, 12.8+ 

JavaScript extensions can be configured to run in strict mode by setting skinx.jsStrictModeEnabled to true in xwiki.properties. The effect of this is that:

  • the content of the JavaScript extension is parsed expecting strict code; XWiki falls-back on the unminified source if parsing fails, and logs the parsing errors
  • the minifier emits the "use strict;" statement that enables the strict mode

Note that while strict mode improves performance and security, it can also make XWiki extensions fail if they don't support it.

Tip: How to refer a file from a skin extension

Referring files from the code of a skin extensions is useful, for example, in StyleSheetExtensions, when images are needed for styling. The StyleSheetExtension can use images that are 1) in the XWiki skin directory or 2) attached to a wiki document.

  1. The $xwiki.getSkinFile() function obtains a file located on the disk. The file will be looked for in the configured skins (first in the current skin, then in the base skin, then in the default skin, and finaly, in the templates directory; see the skin documentation for details about skin structure). Example:
    background-image: url($xwiki.getSkinFile("path/to/the/image.png"));
  2. For using images that are attached to a document in the wiki:
    • If the image is attached to the wiki document containing the refering StyleSheetExtension, it can be accessed as shown in the following example:
      background-image: url($doc.getAttachmentURL("image.png"));
    • An image attached to another wiki document can be accessed this way:
      background-image: url($xwiki.getDocument("Some.Document").getAttachmentURL("image.png"));

In all cases, the "Parse content" property of the StyleSheetExtension object must be set to "yes", so the code that obtains the actual url can be evaluated.

Using LESS

Since XWiki 6.4M2, you can write LESS code thanks to the LESS Module, inside a Skin Extension.

For that, you just need to set the field "Content Type" to "LESS":

contentTypeLESS.png

You will be able to use every Flamingo Theme variables and every mix-ins defined in your skin. For example, for Flamingo, you can use all bootstrap's mixins.

Example:

.myClass {
 color: @brand-primary;
 .make-xs-column(12);
 .make-sm-column(6);
}

Of course, the LESS compilation result is cached so that it is not re-computed for every request.

14.7+ The SSX request parameters are taken into account when caching the result of the LESS compilation. This allows to use request parameters in Velocity for customizing a LESS stylesheet without the need to recompile the stylesheet for every request, only for the ones with parameter values for which the compilation output has not been cached yet.

Compatibility issue

You cannot use LESS in a SSX with a skin that does not have a less directory. For example, it will not work with Colibri.

So a good practice is to have 2 SSX objects: a first one containing pure CSS and a second one containing LESS code that overwrites the first's CSS rules. Example:

A first SSX object containing CSS code:

.myClass {
 color: blue; // for skins that does not support LESS
}

A second one containing LESS code:

.myClass {
 color: @brand-primary; // for skins that support LESS
}

Note that because of some bugs in the LESS Compiler, you are not able to use the 'extend' function to use a selector defined in the skin. But you can still use them as mix-ins. In other words, you can do:

.myClass {
 // .alert is defined in the skin
 .alert();
}

but you cannot do:

.myClass {
 // .alert is defined in the skin
 &:extend(.alert);
}

Debugging

The LESS compilation can fail if you have some mistakes in your code. As a result, by default, you will not see anything. But the error message is displayed inside a CSS comment if you disable the minification.

For example: you have a problem in a SSX stored in the Test.SSX document. Go to the following url:
/xwiki/bin/ssx/Test/SSX. You won't see anything. But now go to /xwiki/bin/ssx/Test/SSX?minify=false and you will see the LESS Error. Example:

/* LESS errors while parsing skin extension [LESS]. */
/* LESSCompilerException: The path [/skins/colibri/less] is not a directory or does not exist. */

See also

Tags: obsolete
    

Get Connected