mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-08-26 20:45:47 +02:00
225 lines
7.3 KiB
Markdown
225 lines
7.3 KiB
Markdown
title: Shortcodes
|
|
summary: Flexible content embedding
|
|
|
|
# Shortcodes
|
|
|
|
The [api:ShortcodeParser] API is simple parser that allows you to map specifically formatted content to a callback to
|
|
transform them into something else. You might know this concept from forum software which don't allow you to insert
|
|
direct HTML, instead resorting to a custom syntax.
|
|
|
|
In the CMS, authors often want to insert content elements which go beyond standard formatting, at an arbitrary position
|
|
in their WYSIWYG editor. Shortcodes are a semi-technical solution for this. A good example would be embedding a 3D file
|
|
viewer or a Google Map at a certain location.
|
|
|
|
|
|
:::php
|
|
$text = "<h1>My Map</h1>[map]"
|
|
|
|
// Will output
|
|
// <h1>My Map</h1><iframe ..></iframe>
|
|
|
|
|
|
Here's some syntax variations:
|
|
|
|
|
|
:::php
|
|
[my_shortcode]
|
|
#
|
|
[my_shortcode /]
|
|
#
|
|
[my_shortcode,myparameter="value"]
|
|
#
|
|
[my_shortcode,myparameter="value"]Enclosed Content[/my_shortcode]
|
|
|
|
Shortcodes are automatically parsed on any database field which is declared as [api:HTMLValue] or [api:HTMLText],
|
|
when rendered into a template. This means you can use shortcodes on common fields like `SiteTree.Content`, and any
|
|
other `[api:DataObject::$db]` definitions of these types.
|
|
|
|
Other fields can be manually parsed with shortcodes through the `parse` method.
|
|
|
|
:::php
|
|
$text = "My awesome [my_shortcode] is here.";
|
|
ShortcodeParser::get_active()->parse($text);
|
|
|
|
## Defining Custom Shortcodes
|
|
|
|
First we need to define a callback for the shortcode.
|
|
|
|
**mysite/code/Page.php**
|
|
|
|
:::php
|
|
<?php
|
|
|
|
class Page extends SiteTree {
|
|
|
|
private static $casting = array(
|
|
'MyShortCodeMethod' => 'HTMLText'
|
|
);
|
|
|
|
public function MyShortCodeMethod($arguments, $content = null, $parser = null, $tagName) {
|
|
return str_replace($content, "<em>$content</em>", $this->Content);
|
|
}
|
|
}
|
|
|
|
These parameters are passed to the `MyShortCodeMethod` callback:
|
|
|
|
- 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.
|
|
- An associative array of extra information about the shortcode being parsed. For example, if the shortcode is
|
|
is inside an attribute, the `element` key contains a reference to the parent `DOMElement`, and the `node`
|
|
key the attribute's `DOMNode`.
|
|
|
|
|
|
To register a shortcode you call the following.
|
|
|
|
**mysite/_config.php**
|
|
|
|
:::php
|
|
// ShortcodeParser::get('default')->register($shortcode, $callback);
|
|
|
|
ShortcodeParser::get('default')->register('my_shortcode', array('Page', 'MyShortCodeMethod'));
|
|
|
|
|
|
## Built-in Shortcodes
|
|
|
|
SilverStripe comes with several shortcode parsers already.
|
|
|
|
### Links
|
|
|
|
Internal page links keep references to their database IDs rather than the URL, in order to make these links resilient
|
|
against moving the target page to a different location in the page tree. This is done through the `[sitetree_link]`
|
|
shortcode, which takes an `id` parameter.
|
|
|
|
:::php
|
|
<a href="[sitetree_link,id=99]">
|
|
|
|
Links to internal `File` database records work exactly the same, but with the `[file_link]` shortcode.
|
|
|
|
:::php
|
|
<a href="[file_link,id=99]">
|
|
|
|
### Media (Photo, Video and Rich Content)
|
|
|
|
Many media formats can be embedded into websites through the `<object>` tag, but some require plugins like Flash or
|
|
special markup and attributes. OEmbed is a standard to discover these formats based on a simple URL, for example a
|
|
Youtube link pasted into the "Insert Media" form of the CMS.
|
|
|
|
Since TinyMCE can't represent all these variations, we're showing a placeholder instead, and storing the URL with a
|
|
custom `[embed]` shortcode.
|
|
|
|
|
|
[embed width=480 height=270 class=left thumbnail=http://i1.ytimg.com/vi/lmWeD-vZAMY/hqdefault.jpg?r=8767]
|
|
http://www.youtube.com/watch?v=lmWeD-vZAMY
|
|
[/embed]
|
|
|
|
|
|
### 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>
|
|
|
|
You may need to escape text inside attributes `>` becomes `>`, 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.
|
|
|
|
:::ss
|
|
<!-- Good -->
|
|
<div>
|
|
[shortcode]
|
|
<p>Caption</p>
|
|
[/shortcode]
|
|
</div>
|
|
|
|
<!-- 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>
|
|
|
|
### Parameter values
|
|
|
|
Here is a summary of the callback parameter values based on some example shortcodes.
|
|
|
|
:::php
|
|
public function MyCustomShortCode($arguments, $content = null, $parser = null, $tagName) {
|
|
// ..
|
|
}
|
|
|
|
[my_shortcode]
|
|
$attributes => array();
|
|
$content => null;
|
|
$parser => ShortcodeParser instance,
|
|
$tagName => 'myshortcode')
|
|
|
|
[my_shortcode,attribute="foo",other="bar"]
|
|
|
|
$attributes => array ('attribute' => 'foo', 'other' => 'bar')
|
|
$enclosedContent => null
|
|
$parser => ShortcodeParser instance
|
|
$tagName => 'my_shortcode'
|
|
|
|
[my_shortcode,attribute="foo"]content[/my_shortcode]
|
|
|
|
$attributes => array('attribute' => 'foo')
|
|
$enclosedContent => 'content'
|
|
$parser => ShortcodeParser instance
|
|
$tagName => 'my_shortcode'
|
|
|
|
## 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]
|
|
|
|
The parser will raise an error if it can not find a matching opening tag for any particular closing tag
|
|
|
|
## Related Documentation
|
|
|
|
* [Wordpress Implementation](http://codex.wordpress.org/Shortcode_API)
|
|
* [How to Create a Google Maps Shortcode](how_tos/create_a_google_maps_shortcode)
|
|
|
|
## API Documentation
|
|
|
|
* [api:ShortcodeParser]
|