2013-02-04 21:27:22 +01:00
|
|
|
# Shortcodes
|
|
|
|
|
2013-02-14 03:11:10 +01:00
|
|
|
The Shortcode API is a way to replace simple bbcode-like tags within HTML. It is inspired by and very similar to
|
|
|
|
the [Wordpress implementation](http://codex.wordpress.org/Shortcode_API) of shortcodes.
|
2013-02-04 21:27:22 +01:00
|
|
|
|
2013-02-14 03:11:10 +01:00
|
|
|
A guide to syntax
|
2013-02-04 21:27:22 +01:00
|
|
|
|
2013-02-14 03:11:10 +01:00
|
|
|
Unclosed - [shortcode]
|
|
|
|
Explicitly closed - [shortcode/]
|
|
|
|
With parameters, mixed quoting - [shortcode parameter=value parameter2='value2' parameter3="value3"]
|
|
|
|
Old style parameter separation - [shortcode,parameter=value,parameter2='value2',parameter3="value3"]
|
|
|
|
With contained content & closing tag - [shortcode]Enclosed Content[/shortcode]
|
|
|
|
Escaped (will output [just] [text] in response) - [[just] [[text]]
|
|
|
|
|
|
|
|
Shortcode parsing is already hooked into HTMLText and HTMLVarchar fields when rendered into a template
|
|
|
|
|
|
|
|
## Attribute and element scope
|
|
|
|
|
|
|
|
HTML with unprocessed shortcodes in it is still valid HTML. As a result, shortcodes can be in two places in HTML:
|
|
|
|
|
|
|
|
- In an attribute value, like so:
|
|
|
|
|
|
|
|
<a title="[title]">link</a>
|
|
|
|
|
|
|
|
- In an element's text, like so:
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Some text [shortcode] more text
|
|
|
|
</p>
|
|
|
|
|
|
|
|
The first is called "element scope" use, the second "attribute scope"
|
|
|
|
|
|
|
|
You may not use shortcodes in any other location. Specifically, you can not use shortcodes to generate attributes or
|
|
|
|
change the name of a tag. These usages are forbidden:
|
|
|
|
|
|
|
|
<[paragraph]>Some test</[paragraph]>
|
|
|
|
|
|
|
|
<a [titleattribute]>link</a>
|
|
|
|
|
|
|
|
Also note:
|
|
|
|
|
|
|
|
- you may need to escape text inside attributes `>` becomes `>` etc
|
|
|
|
|
|
|
|
- you can include HTML tags inside a shortcode tag, but you need to be careful of nesting to ensure you don't
|
|
|
|
break the output
|
|
|
|
|
|
|
|
Good:
|
|
|
|
|
|
|
|
<div>
|
|
|
|
[shortcode]
|
|
|
|
<p>Caption</p>
|
|
|
|
[/shortcode]
|
|
|
|
</div>
|
2013-02-04 21:27:22 +01:00
|
|
|
|
2013-02-14 03:11:10 +01:00
|
|
|
Bad:
|
|
|
|
|
|
|
|
<div>
|
|
|
|
[shortcode]
|
|
|
|
</div>
|
|
|
|
<p>
|
|
|
|
[/shortcode]
|
|
|
|
</p>
|
|
|
|
|
|
|
|
## Location
|
|
|
|
|
|
|
|
Element scoped shortcodes have a special ability to move the location they are inserted at to comply with
|
|
|
|
HTML lexical rules. Take for example this basic paragraph tag:
|
|
|
|
|
|
|
|
<p><a href="#">Head [figure src="assets/a.jpg" caption="caption"] Tail</a></p>
|
|
|
|
|
|
|
|
When converted naively would become
|
|
|
|
|
|
|
|
<p><a href="#">Head <figure><img src="assets/a.jpg" /><figcaption>caption</figcaption></figure> Tail</a></p>
|
|
|
|
|
|
|
|
However this is not valid HTML - P elements can not contain other block level elements.
|
|
|
|
|
|
|
|
To fix this you can specify a "location" attribute on a shortcode. When the location attribute is "left" or "right"
|
|
|
|
the inserted content will be moved to immediately before the block tag. The result is this:
|
|
|
|
|
|
|
|
<figure><img src="assets/a.jpg" /><figcaption>caption</figcaption></figure><p><a href="#">Head Tail</a></p>
|
|
|
|
|
|
|
|
When the location attribute is "leftAlone" or "center" then the DOM is split around the element. The result is this:
|
|
|
|
|
|
|
|
<p><a href="#">Head </a></p><figure><img src="assets/a.jpg" /><figcaption>caption</figcaption></figure><p><a href="#"> Tail</a></p>
|
2013-02-04 21:27:22 +01:00
|
|
|
|
|
|
|
## Defining Custom Shortcodes
|
|
|
|
|
|
|
|
All you need to do to define a shortcode is to register a callback with the parser that will be called whenever a
|
|
|
|
shortcode is encountered. This callback will return a string to replace the shortcode with.
|
|
|
|
|
|
|
|
:::php
|
|
|
|
public static function my_shortcode_handler($attributes, $enclosedContent, $parser, $tagName) {
|
|
|
|
// This simple callback simply converts the shortcode to a span.
|
|
|
|
return "<span class=\"$tagName\">$enclosedContent</span>";
|
|
|
|
}
|
|
|
|
|
|
|
|
The parameters passed to the callback are, in order:
|
|
|
|
|
|
|
|
* Any parameters attached to the shortcode as an associative array (keys are lower-case).
|
|
|
|
* Any content enclosed within the shortcode (if it is an enclosing shortcode). Note that any content within this will
|
|
|
|
not have been parsed, and can optionally be fed back into the parser.
|
|
|
|
* The ShortcodeParser instance used to parse the content.
|
|
|
|
* The shortcode tag name that was matched within the parsed content.
|
|
|
|
|
2013-02-04 22:43:01 +01:00
|
|
|
For the shortcode to work, you need to register it with the `ShortcodeParser`. Assuming you've placed the
|
2013-02-04 21:27:22 +01:00
|
|
|
callback function in the `Page` class, you would need to make the following call from `_config.php`:
|
|
|
|
|
|
|
|
:::php
|
|
|
|
ShortcodeParser::get('default')->register(
|
|
|
|
'shortcode_tag_name',
|
|
|
|
array('Page', 'my_shortcode_handler')
|
|
|
|
);
|
|
|
|
|
|
|
|
An example result of installing such a shortcode would be that the string `[shortcode_tag_name]Testing
|
|
|
|
testing[/shortcode_tag_name]` in the page *Content* would be replaced with the `<span class="shortcode_tag_name">Testing
|
|
|
|
testing</span>`.
|
|
|
|
|
|
|
|
### Parameter values
|
|
|
|
|
|
|
|
Here is a summary of the callback parameter values based on some example shortcodes.
|
|
|
|
|
|
|
|
#### Short
|
|
|
|
|
|
|
|
[my_shortcodes]
|
|
|
|
|
|
|
|
$attributes => array()
|
|
|
|
$enclosedContent => null
|
|
|
|
$parser => ShortcodeParser instance
|
|
|
|
$tagName => 'my_shortcode'
|
|
|
|
|
|
|
|
#### Short with attributes
|
|
|
|
|
|
|
|
[my_shortcode,attribute="foo",other="bar"]
|
|
|
|
|
|
|
|
$attributes => array ('attribute' => 'foo', 'other' => 'bar')
|
|
|
|
$enclosedContent => null
|
|
|
|
$parser => ShortcodeParser instance
|
|
|
|
$tagName => 'my_shortcode'
|
|
|
|
|
|
|
|
#### Long with attributes
|
|
|
|
|
|
|
|
[my_shortcode,attribute="foo"]content[/my_shortcode]
|
|
|
|
|
|
|
|
$attributes => array('attribute' => 'foo')
|
|
|
|
$enclosedContent => 'content'
|
|
|
|
$parser => ShortcodeParser instance
|
|
|
|
$tagName => 'my_shortcode'
|
|
|
|
|
|
|
|
## Inbuilt Shortcodes
|
|
|
|
|
|
|
|
All internal links inserted via the CMS into a content field are in the form `<a href="[sitetree_link,id=n]">`. At
|
|
|
|
runtime this is replaced by a plain link to the page with the ID in question.
|
|
|
|
|
|
|
|
## Limitations
|
|
|
|
|
|
|
|
Since the shortcode parser is based on a simple regular expression it cannot properly handle nested shortcodes. For
|
|
|
|
example the below code will not work as expected:
|
|
|
|
|
|
|
|
[shortcode]
|
|
|
|
[shortcode][/shortcode]
|
|
|
|
[/shortcode]
|
|
|
|
|
2013-02-14 03:11:10 +01:00
|
|
|
The parser will raise an error if it can not find a matching opening tag for any particular closing tag
|