I'm looking for a part-time remote job.

Hire me


I'm the author of:

Mastering Redmine is a comprehensive guide with tips, tricks and best practices, and an easy-to-learn structure.

Check the book's project or

Buy the book

Social pages of the book:

By buying this book you also donate to Redmine (see this page).


Follow me:

Inline hook for Wiki content

Besides supporting native Redmine hooks Hooks Manager provides its own one – view_wiki_inline_content. This hook differs from other hooks in that it is not triggered automatically. Instead to trigger it you need to do this manually inside the Wiki content.

To let you use the view_wiki_inline_content hook the Hooks Manager provides the special Wiki macro {{inline_hook}}, which you need to insert into your Wiki text to trigger this hook, and, therefore, to put your custom HTML content in place of the macro.

In Hooks Manager you can find this hook on the “Wiki page” and in “Content” location. To be able to see the hook you need to enable the “Show all hooks” checkbox.

Macro arguments

Like many other Redmine macros the {{inline_hook}} macro can accept arguments. But all its arguments must be in the following format: name=value. Arguments must be separated using commas.

Check this sample:

{{inline_hook(mysite_align=right,mysite_content_id=sitenav)}}

But the point is, how do we use such argumets in HTML, that we can specify using the Hooks Manager?.. Pure HTML does not support any variable concept. But JavaScript does!

Thus, arguments, which you specify for the {{inline_hook}} macro, get automatically and transparently converted into JavaScript variables, which you do can use in your custom HTML code! Of course, this means, that in such cases you must use JavaScript and not just pure HTML!

Check this sample:

<div id="custom-content"></div>
<script type="text/javascript">
//<![CDATA[
if (mysite_content_id = 'sitenav') {
  $('#custom-content').html('Your custom HTML here!');
}
//]]>
</script>

By the way, this sample demonstrates, how to generate different HTML content depending on macro's arguments.

Best practices

Some best practices for macro's arguments and defining the HTML content for the hook include:

  • Use argument names prepended with some unique idenitifier (e.g., mysite_) to avoid overriding existing JavaScript variables.
  • Use and check some special argument/variable, which will indicate, that the macro was not added accidentally, e.g.:
    if (mysite_i_know_what_i_do === true) { ... }
    
  • Additionally check the URL of the page, where you want your custom HTML code to appear:
    if (window.location.href.indexOf('/path/to/the/page') != -1) { ... }
    
  • Additionally check the parent element(s) of the HTML elements, which were inserted with the {{inline_hook}} macro, e.g.:
    var scriptTags = document.getElementsByTagName('script');
    if (scriptTags[scriptTags.length - 1].parentNode.id == 'the_unique_id') { ... }
    

Example for Google ads

Well, the way I use the plugin is still for Google ads. Still Google ads were the initial reason for creating this plugin. So let’s see, how can we add inline Google ads using the {{inline_hook}} macro.

This is a real life example, which is used on this site.

As you might know Google ads use four JavaScript variables: google_ad_client, google_ad_slot, google_ad_width and google_ad_height. The google_ad_client variable contains the identifier of the client (i.e., me in this case), which I want to set in the HTML content to prevent overriding it in the {{inline_hook}} macro.

So in the text area I put:

<div style="padding: 0.5em 0 0.5em 1em; float: right;">
<script type="text/javascript">
<!--
google_ad_client = "ca-pub-2013328300146844";
//-->
</script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</div>

The rest variables I define in the {{inline_hook}} macro as follows:

{{inline_hook(google_ad_slot=6038760372,google_ad_width=160,google_ad_height=90)}}

Check the start of this page for the sample of Google ads generated this way.

I don't follow the best practices here.

Security

For now Redmine provides no means for restricting usage of specific macros to specific user roles. This means, that any user can insert the {{inline_hook}} macro into Wiki content (e.g., into issue, forum or news comments). This user will just need to have a create or edit permission for this Wiki content.

Thus, from this point of view the {{inline_hook}} macro can be extremely dangerous. You must always take this drawback into account!

Another security issue can be arguments for the {{inline_hook}} macro. When specified these arguments get automatically injected into your page as JavaScript variables. While it is not obvious for me (for now), what the danger is, this can become a huge issue for your site. Thus using this macro a bad guy can override value of some internal JS variable, what can make your site behave in an unexpected way.

Luckily it's easy to disable JavaScript arguments of the macro -- just do not define any content for the placeholder of the view_wiki_inline_content hook.

Check also Best practices.

Terms of use | Privacy policy