Mecha CMS

Mecha CMS blog and documentation.

Shortcode

Updated: Sunday, 07 August 2016

Definition, standard and methods for creating the shortcode parser.

Shortcode is a special code which can be used as shortcut to quickly insert particular object repeatedly. To make a simple shortcode, go to the Shortcode manager page and add your desired shortcode patterns there.

Shortcode Standard

Simple Shortcode

A simple shortcode can be expressed as follows:

{{key}}

key is a phrase, it used to differentiate between shortcodes.

Shortcode with Variable Value

There are two options you can choose to add the shortcode value, that is through the attributes or through the key itself. Values that preppended directly to the shortcode key only applicable for shortcode that only has a single value:

{{key:value}}
{{key=value}}
{{key attribute-1:value-1 attribute-2:value-2}}
{{key attribute-1=value-1 attribute-2=value-2}}

Value Contains Space Characters

Wrap each value with quote symbol to avoid misinterpretation of the shortcode parser:

{{example text="lorem ipsum dolor sit amet" size="1000"}}

Usage of Underscore and Dot Notation

Mecha has its own standard about the shortcode key patterns. A shortcode key cannot contains any white-space characters and only allowed to be written with alphabetic and numeric characters. To write a key phrase contained with space character in it, you have to replace the space character with a _:

{{example_of_a_valid_shortcode}}

Dot notation can be used to describes about “descendant”, or to connects between shortcodes with single parent key phrase, for example:

{{data}}
{{data.post}}
{{data.post.title}}

Here, data is the parent key phrase. post describes about ‘child of data’ or ‘branch of data’ or ‘part of data’ or ‘member of data’. title describes about ‘member of post that is a member of data’. There will be no special thing that will happen after you write the pattern above. This is only intended for readability of the code.

Disabling the Shortcode

To write a plain shortcode inside the post editor without having to make them translated by the shortcode parser, you can wrap the shortcode with a backtick character like so:

`{{disabled_shortcode}}`

Making a Shortcode Parser

Mecha already has its own simple shortcode parser that can recognizes and handles the inputs you provide in the Shortcode manager page. However, in some more complicated cases you will have to create your own shortcode parser.

Here we will work with filters. We will use the content of the post as the target of manipulation, so we will need these filters:

shortcode
article:shortcode
page:shortcode

More information about the filters above can be learned here.

Using str_replace

A simple parser can be created with PHP str_replace:

Filter::add('shortcode', function($content) {
    return str_replace('{{foo}}', '<mark>test</mark>', $content);
});

It will automatically replaces all {{foo}} in the article and page content with <mark>test</mark>. The advantage of this method is that it is easy to be created and it has a better performance. The drawback is that you cannot disable this shortcode although you’ve wrap the shortcode pattern with backtick character(s). To overcome this limitation, switch str_replace to preg_replace.

Using preg_replace

// “(?<!`)” means “not preceded by a `”
// “(?!`)” means “not followed by a `”
Filter::add('shortcode', function($content) {
    return preg_replace('#(?<!`)\{\{foo\}\}(?!`)#', '<mark>test</mark>', $content);
});

The disadvantage of this method is that it has worse performance than str_replace. However, this method has other several advantages, one of them is that, this method can extracts the value of the variable inside the shortcode:

Filter::add('shortcode', function($content) {
    if(strpos($content, '{{foo:') === false) return $content;
    return preg_replace('#(?<!`)\{\{foo\:(.*?)\}\}(?!`)#', 'Price: $1', $content);
});

The parser above will replaces all {{foo:5}} in the article and page content with Price: 5, {{foo:100}} with Price: 100, and so on.

Using Converter::attr()

You can use preg_replace to extract all the values that is available inside the shortcode attributes, but you can’t make the shortcode works if user writes the shortcode attributes in random order:

Filter::add('shortcode', function($content) {
    if(strpos($content, '{{foo ') === false) return $content;
    return preg_replace(
        '#(?<!`)\{\{foo +id="(.*?)" +class="(.*?)"\}\}(?!`)#',
        '<div id="$1" class="$2">FOO</div>',
    $content);
});

// Works: `{{foo id="bar" class="baz"}}`
// Fails: `{{foo class="baz" id="bar"}}`

To overcome these limitations, use the Converter::attr() method to extracts all of the attributes and their values before doing the shortcode translation:

Filter::add('shortcode', function($content) {
    if(strpos($content, '{{foo ') === false) return $content;
    return preg_replace_callback('#(?<!`)\{\{foo *.*?\}\}(?!`)#', function($matches) {
            $data = Converter::attr(
                $matches[0],
                array('{{', '}}', ' '),
                array('"', '"', '=')
            );
            return '<div id="' . $data['attributes']['id'] . '" class="' . $data['attributes']['class'] . '">FOO</div>';
        },
    $content);
});
Donation and Email Subscription