mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merged existing shortcode docs with new topics docs from 3.0
This commit is contained in:
parent
4c7c40e8b9
commit
306d3b0c7e
@ -1,32 +1,143 @@
|
||||
# Shortcodes
|
||||
# Shortcodes: Flexible Content Embedding
|
||||
|
||||
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.
|
||||
## Overview
|
||||
|
||||
A guide to syntax
|
||||
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.
|
||||
|
||||
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]]
|
||||
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.
|
||||
|
||||
Shortcode parsing is already hooked into HTMLText and HTMLVarchar fields when rendered into a template
|
||||
Here's some syntax variations:
|
||||
|
||||
## Attribute and element scope
|
||||
[my_shortcode]
|
||||
[my_shortcode /]
|
||||
[my_shortcode,myparameter="value"]
|
||||
[my_shortcode,myparameter="value"]Enclosed Content[/my_shortcode]
|
||||
|
||||
## Usage
|
||||
|
||||
In its most basic form, you can invoke the `[api:ShortcodeParser]` directly:
|
||||
|
||||
:::php
|
||||
ShortcodeParser::get_active()->parse($myvalue);
|
||||
|
||||
In addition, 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.
|
||||
|
||||
In order to allow shortcodes in your own template placeholders,
|
||||
ensure they're casted correctly:
|
||||
|
||||
:::php
|
||||
class MyObject extends DataObject {
|
||||
static $db = array('Content' => 'HTMLText');
|
||||
static $casting = array('ContentHighlighted' => 'HTMLText');
|
||||
public function ContentHighlighted($term) {
|
||||
return str_replace($term, "<em>$term</em>", $this->Content);
|
||||
}
|
||||
}
|
||||
|
||||
There is currently no way to allow shortcodes directly in template markup
|
||||
(as opposed to return values of template placeholders).
|
||||
|
||||
## 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.
|
||||
If the shortcode is used for template placeholders of type `HTMLText` or `HTMLVarchar`,
|
||||
the returned value should be valid HTML
|
||||
|
||||
To register a shortcode you call:
|
||||
|
||||
ShortcodeParser::get('default')->register('my_shortcode', <callback>);
|
||||
|
||||
These parameters are passed to the 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.
|
||||
|
||||
## Example: Google Maps Iframe by Address
|
||||
|
||||
To demonstrate how easy it is to build custom shortcodes, we'll build one to display
|
||||
a Google Map based on a provided address. Format:
|
||||
|
||||
[googlemap,width=500,height=300]97-99 Courtenay Place, Wellington, New Zealand[/googlemap]
|
||||
|
||||
So we've got the address as "content" of our new `googlemap` shortcode tags,
|
||||
plus some `width` and `height` arguments. We'll add defaults to those in our shortcode parser so they're optional.
|
||||
|
||||
:::php
|
||||
ShortcodeParser::get('default')->register('googlemap', function($arguments, $address, $parser, $shortcode) {
|
||||
$iframeUrl = sprintf(
|
||||
'http://maps.google.com/maps?q=%s&hnear=%s&ie=UTF8&hq=&t=m&z=14&output=embed',
|
||||
urlencode($address),
|
||||
urlencode($address)
|
||||
);
|
||||
$width = (isset($args['width']) && $args['width']) ? $args['width'] : 400;
|
||||
$height = (isset($args['height']) && $args['height']) ? $args['height'] : 300;
|
||||
return sprintf(
|
||||
'<iframe width="%d" height="%d" src="%s" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>',
|
||||
$width,
|
||||
$height,
|
||||
$iframeUrl
|
||||
);
|
||||
});
|
||||
|
||||
The hard bits are taken care of (parsing out the shortcodes), everything we need to do is a bit of string replacement.
|
||||
CMS users still need to remember the specific syntax, but these shortcodes can form the basis
|
||||
for more advanced editing interfaces (with visual placeholders). See the built-in `[embed]` shortcode as an example
|
||||
for coupling shortcodes with a form to create and edit placeholders.
|
||||
|
||||
## 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. Example: `<a href="[sitetree_link,id=99]">`
|
||||
|
||||
Links to internal `File` database records work exactly the same, but with the `[file_link]` shortcode.
|
||||
|
||||
### 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 varations, we're showing a placeholder
|
||||
instead, and storing the URL with a custom `[embed]` shortcode.
|
||||
|
||||
Example: `.[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]`
|
||||
|
||||
|
||||
## Syntax
|
||||
|
||||
* 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]]`
|
||||
|
||||
### 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>
|
||||
- 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"
|
||||
|
||||
@ -37,11 +148,8 @@ change the name of a tag. These usages are forbidden:
|
||||
|
||||
<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
|
||||
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
|
||||
|
||||
Good:
|
||||
@ -61,12 +169,12 @@ Bad:
|
||||
[/shortcode]
|
||||
</p>
|
||||
|
||||
## Location
|
||||
### 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>
|
||||
<p><a href="#">Head [figure,src="assets/a.jpg",caption="caption"] Tail</a></p>
|
||||
|
||||
When converted naively would become
|
||||
|
||||
@ -83,43 +191,11 @@ When the location attribute is "leftAlone" or "center" then the DOM is split aro
|
||||
|
||||
<p><a href="#">Head </a></p><figure><img src="assets/a.jpg" /><figcaption>caption</figcaption></figure><p><a href="#"> Tail</a></p>
|
||||
|
||||
## 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.
|
||||
|
||||
For the shortcode to work, you need to register it with the `ShortcodeParser`. Assuming you've placed the
|
||||
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
|
||||
Short
|
||||
|
||||
[my_shortcodes]
|
||||
|
||||
@ -128,7 +204,7 @@ Here is a summary of the callback parameter values based on some example shortco
|
||||
$parser => ShortcodeParser instance
|
||||
$tagName => 'my_shortcode'
|
||||
|
||||
#### Short with attributes
|
||||
Short with attributes
|
||||
|
||||
[my_shortcode,attribute="foo",other="bar"]
|
||||
|
||||
@ -137,7 +213,7 @@ Here is a summary of the callback parameter values based on some example shortco
|
||||
$parser => ShortcodeParser instance
|
||||
$tagName => 'my_shortcode'
|
||||
|
||||
#### Long with attributes
|
||||
Long with attributes
|
||||
|
||||
[my_shortcode,attribute="foo"]content[/my_shortcode]
|
||||
|
||||
@ -146,11 +222,6 @@ Here is a summary of the callback parameter values based on some example shortco
|
||||
$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
|
||||
@ -161,3 +232,7 @@ example the below code will not work as expected:
|
||||
[/shortcode]
|
||||
|
||||
The parser will raise an error if it can not find a matching opening tag for any particular closing tag
|
||||
|
||||
## Related
|
||||
|
||||
* [Wordpress implementation](http://codex.wordpress.org/Shortcode_API)
|
@ -1,143 +0,0 @@
|
||||
# Shortcodes: Flexible Content Embedding
|
||||
|
||||
## Overview
|
||||
|
||||
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.
|
||||
|
||||
Here's some syntax variations:
|
||||
|
||||
[myshortcode]
|
||||
[myshortcode /]
|
||||
[myshortcode,myparameter="value"]
|
||||
[myshortcode,myparameter="value"]Enclosed Content[/myshortcode]
|
||||
|
||||
## Usage
|
||||
|
||||
In its most basic form, you can invoke the `[api:ShortcodeParser]` directly:
|
||||
|
||||
:::php
|
||||
ShortcodeParser::get_active()->parse($myvalue);
|
||||
|
||||
In addition, 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.
|
||||
|
||||
In order to allow shortcodes in your own template placeholders,
|
||||
ensure they're casted correctly:
|
||||
|
||||
:::php
|
||||
class MyObject extends DataObject {
|
||||
static $db = array('Content' => 'HTMLText');
|
||||
static $casting = array('ContentHighlighted' => 'HTMLText');
|
||||
public function ContentHighlighted($term) {
|
||||
return str_replace($term, "<em>$term</em>", $this->Content);
|
||||
}
|
||||
}
|
||||
|
||||
There is currently no way to allow shortcodes directly in template markup
|
||||
(as opposed to return values of template placeholders).
|
||||
|
||||
## 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.
|
||||
If the shortcode is used for template placeholders of type `HTMLText` or `HTMLVarchar`,
|
||||
the returned value should be valid HTML
|
||||
|
||||
To register a shortcode you call:
|
||||
|
||||
ShortcodeParser::get('default')->register('myshortcode', <callback>);
|
||||
|
||||
These parameters are passed to the 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.
|
||||
|
||||
## Example: Google Maps Iframe by Address
|
||||
|
||||
To demonstrate how easy it is to build custom shortcodes, we'll build one to display
|
||||
a Google Map based on a provided address. Format:
|
||||
|
||||
[googlemap,width=500,height=300]97-99 Courtenay Place, Wellington, New Zealand[/googlemap]
|
||||
|
||||
So we've got the address as "content" of our new `googlemap` shortcode tags,
|
||||
plus some `width` and `height` arguments. We'll add defaults to those in our shortcode parser so they're optional.
|
||||
|
||||
:::php
|
||||
ShortcodeParser::get('default')->register('googlemap', function($arguments, $address, $parser, $shortcode) {
|
||||
$iframeUrl = sprintf(
|
||||
'http://maps.google.com/maps?q=%s&hnear=%s&ie=UTF8&hq=&t=m&z=14&output=embed',
|
||||
urlencode($address),
|
||||
urlencode($address)
|
||||
);
|
||||
$width = (isset($args['width']) && $args['width']) ? $args['width'] : 400;
|
||||
$height = (isset($args['height']) && $args['height']) ? $args['height'] : 300;
|
||||
return sprintf(
|
||||
'<iframe width="%d" height="%d" src="%s" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>',
|
||||
$width,
|
||||
$height,
|
||||
$iframeUrl
|
||||
);
|
||||
});
|
||||
|
||||
The hard bits are taken care of (parsing out the shortcodes), everything we need to do is a bit of string replacement.
|
||||
CMS users still need to remember the specific syntax, but these shortcodes can form the basis
|
||||
for more advanced editing interfaces (with visual placeholders). See the built-in `[embed]` shortcode as an example
|
||||
for coupling shortcodes with a form to create and edit placeholders.
|
||||
|
||||
## 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. Example: `<a href="[sitetree_link,id=99]">`
|
||||
|
||||
Links to internal `File` database records work exactly the same, but with the `[file_link]` shortcode.
|
||||
|
||||
### 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 varations, we're showing a placeholder
|
||||
instead, and storing the URL with a custom `[embed]` shortcode.
|
||||
|
||||
Example: `.[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]`
|
||||
|
||||
|
||||
## 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 recognise this as:
|
||||
|
||||
[shortcode]
|
||||
[shortcode]
|
||||
[/shortcode]
|
||||
|
||||
## Related
|
||||
|
||||
* [Wordpress implementation](http://codex.wordpress.org/Shortcode_API)
|
Loading…
Reference in New Issue
Block a user