A tiny library allowing to compose website components being used repeatedly by wrapping them in the callbacks that produce respective HTML markup.
First of all, you need to include ShortcodeJS library. When you're done with the former, new shortcodes are meant to be registered with
the Shortcode.register()
method. Finally, sources can be parsed by the Shortcode.parse()
method.
There are two kinds of shortcode:
- empty shortcode being standalone shortcode with no content surrounded, e.g.
[shortcode/]
- content shortcode being shortcode that surrounds a content, e.g.
[shortcode]Content.[/shortcode]
In addition, both can have attributes assigned, e.g. [shortcode attr="val"/]
.
Shortcode.register(name, cb)
Registers new shortcode.
Returns: undefined
.
Parameters:
name
- astring
that represents the name of the shortcodecb
- a callbackfunction
that returns HTML markup, having taken up to 2 parameters:attr
- anobject
containing attributes assigned to a shortcodecontent
- astring
representing the content of a shortcode
Shortcode.parse(source[, variables])
Parses a source turning registered shortcodes into respecitve HTML markup.
Returns: string
being HTML markup.
Parameters:
source
- astring
that holds the content to be parsedvariables
- aobject
that holds variables that can be interpolated in the content (consult Interpolating variables for details)
Shortcode.set(option, value)
Sets a particular option using given value.
Returns: undefined
.
Parameters:
option
- astring
representing a name of the option being setvalue
- astring
representing a value to set
The table below shows available options to set.
Option | Default value | Description |
---|---|---|
attributeNameToCamelCase |
true |
Whether to turn dash-case attribute name into camelCase, for example sc-attr into scAttr . |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ShortcodeJS</title>
</head>
<body>
<blockquote id="quotation">
<p>We don't need another JavaScript framework. We need stuff like the [b]ShortcodeJS[/b] library.</p>
<cite>~ @:author</cite>
</blockquote>
<script src="shortcode.js"></script>
<script>
Shortcode.register('b', function (attr, content) {
return `<b>${content}</b>`;
});
var quotation = document.getElementById('quotation');
quotation.innerHTML = Shortcode.parse(quotation.innerHTML, {author: 'A. Lincoln'});
</script>
</body>
</html>
Note that the name of a shortcode is passed as first argument of the Shortcode.register()
method, then this name is used within
a content that will be processed.
Simplest component only consists of name.
Neither component's attributes nor its content is involved, therefore no parameters are used with the callback composing HTML markup.
Shortcode.register('separator', function () {
return '<hr />';
});
/*
given input:
[separator/]
expected output:
<hr />
*/
Right beside the name, a shortcode can have attributes assigned.
It can be done the same way as if it were regular HTML element.
Shortcode.register('separator', function (attr) {
return `<hr style="width: ${attr.width}" />`;
});
/*
given input:
[separator width="50%"/]
expected output:
<hr style="width: 50%" />
*/
As well, the shortcodes are able to hold content, including another nested shortcodes.
Though the example below does not use attributes, passing attr
parameter is essential as it precedes the content
parameter that we make use of.
Shortcode.register('frame', function (attr, content) {
return `<div style="border: solid 1px #333">${content}</div>`;
});
/*
given input:
[frame]This content is important.[/frame]
expected output:
<div style="border: solid 1px #333">This content is important.</div>
*/
Content shortcodes are any less different when it comes to assigning attributes.
Shortcode.register('cite', function (attr, content) {
return `@${attr.user}: ${content}`;
});
/*
given input:
[cite user="damianc"]I hope you will make good use of it.[/cite]
expected output:
@damianc: I hope you will make good use of it.
*/
An input string can have assigned variables whose values will be inserted when parsing.
To indicate placeholder for a variable, it's necessary to use @:name
or @@:name
syntax.
There are two kinds of such variables:
- pre-parsing - these variables will be interpolated before processing shortcodes (use
@@:name
syntax) - post-parsing - these variables will be interpolated after processing shortcodes (use
@:name
syntax)
Values of variables are being received from an object passed as a second parameter of the parse()
method call.
The keys of the object are mapped to variable names used within an input string while while their values correspond to the
values of the object's properties with identical names.
In the code below, following steps are being done:
@@:textDecoration
is replaced withb
string- the input string with shortcodes embedded is processed
@:languageName
is replaced withJavaScript
,@:libraryName
is replaced withShortcodeJS
<p id="frame">
Among @:languageName libraries worth to discover is [@@:textDecoration]@:libraryName[/@@:textDecoration].
</p>
var frame = document.getElementById('frame');
frame.innerHTML = Shortcode.parse(frame.innerHTML, {
textDecoration: 'bold' ? 'b' : 'u',
languageName: 'JavaScript',
libraryName: 'ShortcodeJS'
});
/*
expected output:
Among JavaScript libraries worth to discover is <b>ShortcodeJS</b>.
*/
As done in the code above, using pre-parsing variables is recommended mostly for things that can affect process of parsing a shortcode, i.e., name of a shortcode or values that its attributes have assigned. Other values can be inserted after the shortcode parsing is perfrormed; this is what post-parsing variables are meant to.
It may happen that your shortcode is to take a multiple of attributes of which not all are required. In the case, default values should be guaranteed to be delivered.
Note that attribute names must not contain uppercase characters as they will not be preserved.
Even if you use a shortcode like[frame borderColor="red"]
, theattr
object is to containbordercolor
property rather thanborderColor
.
Still, you could use dash-case name, e.g.[frame border-color="red"]
, in which case the respective property name can remain the same, i.e.border-color
(keep in mind that such a name is required to be surrounded with quotes when accessed). See Combined attribute names for details.
Shortcode.register('frame', function (attr, content) {
var settings = Object.assign({
borderwidth: '1px',
bordercolor: '#333'
}, attr);
return `<div style="border: solid ${settings.borderwidth} ${settings.bordercolor}">
${content}
</div>`;
});
/*
given input:
[frame bordercolor="red"]This message is very important![/frame]
expected output:
<div style="border: solid 1px red">This message is very important!</div>
*/
By default, attribute names consisting of the words separated by dash are turning into the camelCase form to be accessed with the attr
object in the shortcode callback (e.g. sc-attr
-> scAttr
). Why that happens is because the attributeNameToCamelCase
setting is set to true
by default. To keep attribute names dash-case set this option to false
with Shortcode.set()
method.
Shortcode.set('attributeNameToCamelCase', false);
ShortcodeJS is supposed to run in browser environment that delivers the window.document
object.
For environments like Node.js (without the document
object by default), function returning ShortcodeJS API is provided - this function takes appropriate document
object that can be derived from an external library like jsdom.
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<!DOCTYPE html></html>');
const { document } = dom.window;
const Shortcode = require('./shortcode')(document);
// ...