-
Notifications
You must be signed in to change notification settings - Fork 4
Rulers: Overview
Rulers are what dictate the html output of a tag. The parser will automatically tokenize any content with an opening tag [tag]
and a closing tag [/tag]
, before passing it to the ruler.
Rulers in the markdown-it extension are split into two general types: Inline and Block level. The order of parsing is Block Level > Inline Level. This leaves the engine with the annoying quirks of not being able to put block level tags inside inline level. Overall, these rulers function the same way.
Here is an example of a tag and its ruler, specifically a block level ruler with replace
:
[print=line]
text
[/print]
md.block.bbcode.ruler.push("print", {
tag: "print",
replace: function (state, tagInfo, content) {
let printOption = tagInfo.attrs['_default'];
let token = state.push("div_open", "div", 1);
if (!printOption) {
token.attrs = [["class", "bbcode-print"]];
} else {
token.attrs = [["class", "bbcode-print-" + printOption]];
}
token = state.push("inline", "", 0);
token.content = content;
token.children = [];
state.push("div_close", "div", -1);
return true;
}
});
It defines the name of the tag, in this case [print]
, and picks up it's components, the tagInfo
and the content
.
tagInfo
is the arguments given inside the tag, creating a dictionary. In this case [print=line] -> {_default: "line"}
.
It passes this, along with content
, into a function that determines the html output by pushing attributes into the token.
This is a brief example. The following sections will go into further detail. But first, let us start with the tag itself
As briefly touched upon above, a tag is composed of three parts: tag
, tagInfo
, content
. This comes together like so:
[tag tagInfo]content[/tag]
tag
and content
are self-explanatory (Note: content
can be manipulated inside the ruler). tagInfo
on the other hand is more interesting, as it is completely optional. tagInfo
comes in two types, a single argument, and a multi-argument.
[tag=value]
Here, the value is stored as a string in the key _default
, accessible via tagInfo.attrs
. If no value is provided, tagInfo.attrs['_default']
returns NULL
. This happens when the tag is [tag]
or [tag arg1=value1 ...]
.
[tag arg1=value1 arg2=value2 ...]
Any number of arguments can be provided. Similar to the single argument, every value is optional, and if missing, returns a NULL
. Each one creates a key/value pair in tagInfo.attrs
under their respective names.
{arg1: "value1", arg2: "value2", ...}
It is up to the ruler's code to determine how to process a tag when given its arguments. The best example of this is the [font]
tag.
It should be noted that it is illegal to create a combined tag structure [tag=value1 arg=value2]
, as _default
will have the value "value1 arg=value2"
Let us discuss the structure of a ruler. Here is the basic outline for creating a ruler:
function setupMarkdownIt(md) {
md.inline.bbcode.ruler.push("tagname", {
tag: "tagname",
method: "method function/value"
});
md.block.bbcode.ruler.push("secondtagname", {
tag: "secondtagname",
method: "method function/value"
});
}
All rulers are created inside the setupMarkdownIt(md)
function, where an array is pushed into either the block or inline level, containing the name of the tag and the method for handling it. Block and Inline levels will be discussed in a later section. For simplicity in the rest of this discussion, we'll refer to both md.inline.bbcode.ruler
and md.block.bbcode.ruler
as ruler
.
ruler
is made up of the tag
and the method
. tag
defines the name of the tag and seems to be case-insensitive, but as a standard, we keep it lowercase. method
determines the html to be outputted.