<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=344430429281371&amp;ev=PageView&amp;noscript=1">

The Safest Way To Inject CSS/HTML/Javascript to Confluence Pages

Posted by Foogie Sim on June 12, 2019

The conventional way of modifying Confluence pages via CSS/HTML/Javascript is usually via HTML Macros, Global Stylesheets, or Custom HTML as evident in the following posts:

While they do work, these options are not ideal, and in some cases (like the HTML Macro), should be avoided at all cost.

Let us look at the cons with each of these approaches:

HTML Macros

Screen Shot 2019-04-03 at 12.50.58 PM

HTML Macros are disabled by default in Confluence. And there is a really good reason for that. Once enabled, HTML macros will be available globally throughout a Confluence site, allowing anyone with Page edit capability to insert literally any Javascript/CSS imaginable. This leads to potential XSS (Cross-site scripting) attacks, allowing hackers to steal cookies from visitors to a page containing the macro.

Global/Space Stylesheets

Screen Shot 2019-04-03 at 12.49.45 PM

Global Stylesheets, available at Confluence Administration >> Look and Feel >> Stylesheet and Space Stylesheets, available at Space Administration >> Look and Feel >> Stylesheet allows Confluence Administrators or Space Administrators to insert specific CSS styles into Confluence globally, or within a specific space. This helps eliminate the security risk posed by HTML Macros, as:

  • It only renders CSS
  • It can only be modified/inserted by administrators

However, changes to stylesheets here have a space-wide or global impact to Confluence, and the stylesheet cannot be confined to just a single page. (Unlike HTML Macros that allow you to insert the script/stylesheet to just a single page)

Custom HTML

Unlike Global/Space Stylesheets, Custom HTML only has a global configuration, at Confluence Administration >> Look and Feel >> Custom HTML

So all changes made here will be applied globally. There is no way at all to confine this to a single page. 

Enter: User Macros

The safest alternative, I feel, to the 3 options above has got to be User Macros, which can be easily created via Confluence Administration >> User Macros

User Macros are:

  • Safer - Only Confluence Administrators can define User Macros in the Global Administration Settings
  • Confined to a Single Page - User Macros' CSS/Javascript/Markup will only render in the page(s) they are sitting on. It does not apply globally/space-wide
  • Configurable - Confluence Administrators can configure the user macro's visibility (in the macro browser) to be visible to all users, or only System Administrators 

I'll jump straight to the examples to give you an idea of what you can do with this:

Page Tree Macro with a CSS and Javascript Mod

Purpose

Allows users to search for child pages of the current page:

Screen Shot 2019-04-03 at 1.02.12 PM

It takes one argument: which is the Placeholder value (see the "Search Staffing" example above)

Macro Name searchchildpages
Visibility Visible to all users in the Macro Browser
Macro Title Search Child Pages
Categories Confluence Content
Macro Body Processing Rendered
Template
## Macro title: Search Child Pages
## Macro has a body: N
## Body processing: Rendered
## Output: XHTML
##
## Developed by: Foogie
## Date created: 03/04/2019
 
## @param placeholder:title=Placeholder Text|type=string|required=false|desc=Placeholder Text
 
 
     <script>
            AJS.toInit(function(){
               $('.medium-field').attr('placeholder''$!paramplaceholder');
              });
     </script>
 
 
<style>
input.medium-field { max-width: 400px !important; }
</style>
 
<ac:structured-macro ac:name="pagetreesearch" ac:schema-version="1" />

The example above shows a simple User Macro that allows us to style the default Page Tree Search macro (which doesn't fit our design sketch initially), with:

CSS

<style>
input.medium-field { max-width: 400px !important; }
</style>

Javascript

<script>
AJS.toInit(function(){
    $('.medium-field').attr('placeholder''$!paramplaceholder');
});
</script>

 

And in addition to that, the User Macro also takes in a parameter (or a set of parameters, if you desire) that users can add when inserting the macro. These parameters can be used to alter the final output, as in the example here where we determine the value of the Placeholder via the user's input.

And finally, User Macros are also able to render Confluence Macros, as you can see from this example:

<ac:structured-macro ac:name="pagetreesearch" ac:schema-version="1" />

(I actually use this to render virtually all macros imaginable on the Confluence sidebar - note that Confluence's sidebar usually only takes Wiki Markup macros - More on this in future blogs)

 

Conclusion

User Macros are infinitely more powerful, safe and configurable than the other 3 options I mentioned. It's a wonder why there aren't many discussions on this type of use case. I hope this article can start a shift towards more user-macro usage versus the conventional method, which isn't the best method at all for single-page applications of CSS/Javascript. 

Topics: Training, Software Training

Subscribe To
Our Newsletter

Interested in writing for the Software Adoption Blog?

We love connecting with software leaders and writers who can help us fulfill our mission to create entertaining AND educational resources that people can put to use.

Find Out How ➝

Recent Posts

Posts by Topic

see all