View source
<?php
use Drupal\Core\Url;
function xbbcode_basic_init() {
drupal_add_css(drupal_get_path('module', 'xbbcode_basic') . '/xbbcode_basic.css');
}
function xbbcode_basic_xbbcode_info() {
$tags['i'] = [
'markup' => '<em>{content}</em>',
'description' => t('Italic text'),
'sample' => t('[i]italic[/i]'),
];
$tags['b'] = [
'markup' => '<strong>{content}</strong>',
'description' => t('Bold text'),
'sample' => t('[b]bold[/b]'),
];
$tags['u'] = [
'markup' => '<span style="text-decoration:underline">{content}</span>',
'description' => t('Underlined text'),
'sample' => t('[u]underlined[/u]'),
];
$tags['s'] = [
'markup' => '<del>{content}</del>',
'description' => t('Stricken-through text'),
'sample' => t('[s]this sentence is false[/s]'),
];
$tags['font'] = [
'markup' => '<span style="font-family:{option}">{content}</span>',
'description' => t('Changes the font of the text.'),
'sample' => t('[font=arial]Text[/font]'),
];
$tags['size'] = [
'markup' => '<span style="font-size:{option}">{content}</span>',
'description' => t('Changes the text size. This requires the <em>unit</em> (pt, px, em) of the size.'),
'sample' => t('[size=16pt]Text[/size]'),
];
$tags['color'] = [
'markup' => '<span style="color:{option}">{content}</span>',
'description' => t('Changes the color. You may enter a color word (red) or a hex code <em>with hash sign</em> (#ff0)'),
'sample' => t('[color=#f80]Orange text[/color]'),
];
$tags['sup'] = [
'markup' => '<sup>{content}</sup>',
'sample' => 'x[sup]2[/sup]',
'description' => t('Sets text to be set smaller and above the line.'),
];
$tags['sub'] = [
'markup' => '<sub>{content}</sub>',
'sample' => 'a[sub]i,j[/sub]',
'description' => t('Sets text to be smaller and below the line.'),
];
$tags['left'] = [
'markup' => '<object><p style="text-align:left">{content}</p></object>',
'description' => t('Aligns text on the left side.'),
'sample' => t('[left]Left-aligned text[/left]'),
];
$tags['right'] = [
'markup' => '<object><p style="text-align:right">{content}</p></object>',
'description' => t('Aligns text on the right side.'),
'sample' => t('[right]Right-aligned text[/right]'),
];
$tags['center'] = [
'markup' => '<object><p style="text-align:center">{content}</p></object>',
'description' => t('Aligns text in the center.'),
'sample' => t('[center]Centered text[/center]'),
];
$tags['justify'] = [
'markup' => '<object><p style="text-align:justify">{content}</p></object>',
'description' => t('Aligns text as a justified block.'),
'sample' => '[justify]Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.[/justify]',
];
$tags['url'] = [
'markup' => '<a href="{option}" title="{option}">{content}</a>',
'description' => t('Formats a Hyperlink.'),
'sample' => t('[url=http://drupal.org]Drupal.org[/url]'),
];
$tags['img'] = [
'callback' => 'xbbcode_basic_render_img',
'sample' => t('[img=65x73]
@url
[/img]', [
'@url' => Url::fromUri('base:core/themes/bartik/logo.png')
->toString(),
]),
'description' => t('Displays a picture. The size may be set by entering widthxheight as the only option.'),
];
$tags['node'] = [
'callback' => 'xbbcode_basic_render_nodelink',
'sample' => t('[node=1]Node #1[/node]'),
'description' => t('Links to a certain node. Unlike a [url] tag, this is passed through the linking function and returns the alias of the node.'),
];
$tags['wikipedia'] = [
'markup' => '<a title="{content} on Wikipedia" href="http://www.wikipedia.org/wiki/{content}">{content}</a>',
'sample' => t('[wikipedia]Drupal[/wikipedia]'),
'description' => t('Formats a link to Wikipedia, the free encyclopedia.'),
];
$tags['youtube'] = [
'callback' => 'xbbcode_basic_render_youtube',
'sample' => '[youtube=224x126]rF1X12PE6PY[/youtube]',
'description' => t('Embed a Youtube video.'),
];
$tags['h1'] = [
'markup' => '<h1>{content}</h1>',
'description' => t('Level 1 heading. <em>You may want to restrict access to the level 1 and level 2 headings for ordinary users.</em>'),
'sample' => t('[h1]Title[/h1]'),
];
$tags['h2'] = [
'markup' => '<h2>{content}</h2>',
'description' => t('Level 2 heading. Use this as the top level on non-node content, as level 1 is used by the site header.'),
'sample' => t('[h2]Volume[/h2]'),
];
$tags['h3'] = [
'markup' => '<h3>{content}</h3>',
'description' => t('Level 3 heading. Use this as the top level within nodes as levels 1 and 2 are used by the site and node title.'),
'sample' => t('[h3]Chapter[/h3]'),
];
$tags['h4'] = [
'markup' => '<h4>{content}</h4>',
'description' => t('Level 4 heading.'),
'sample' => t('[h4]Section[/h4]'),
];
$tags['h5'] = [
'markup' => '<h5>{content}</h5>',
'description' => t('Level 5 heading.'),
'sample' => t('[h5]Sub-section[/h5]'),
];
$tags['h6'] = [
'markup' => '<h6>{content}</h6>',
'description' => t('Level 6 heading.'),
'sample' => t('[h6]Sub-sub-section[/h6]'),
];
$tags['hr'] = [
'markup' => '<hr />',
'description' => t('Horizontal divider.'),
'sample' => '[hr]',
'options' => [
'selfclosing' => TRUE,
],
];
$tags['code'] = [
'callback' => 'xbbcode_basic_render_code',
'description' => t('Formats the content text as code, in Monospace and with a grey box around it. BBCode tags within this tag will <em>not</em> be parsed.'),
'sample' => t("[code]def fib (n):\n a, b = 0, 1\n for i in xrange(n):\n a, b = b, a + 1\n return a[/code]"),
];
$tags['php'] = [
'callback' => 'xbbcode_basic_render_code',
'description' => t('This colors the syntax of PHP code using the in-built PHP highlighting library.'),
'sample' => t("[php]<?php\n echo 'Hello World' . 5 . \$variable;\n?>[/php]"),
];
$tags['quote'] = [
'markup' => '<blockquote class="xbbcode">{content}</blockquote>',
'description' => t('Formats a quote.'),
'sample' => t('[quote]This text is quoted.[/quote]'),
];
$tags['list'] = [
'callback' => 'xbbcode_basic_render_list',
'description' => t('Formats a list. The CSS list style type or "n" may be set as an option.'),
'sample' => t("[list=lower-roman]\n [*]Apples\n [*]Oranges\n [*]Bananas\n [/list]"),
];
$tags['define'] = [
'callback' => 'xbbcode_basic_render_define',
'description' => t("Formats a definition list."),
'sample' => t("[define]\n --verbose:This will start the program with full debug messages.\n --in=IN:This will set the input file to IN.\n --out=OUT:This will write output to OUT.\n[/define]"),
];
$tags['table'] = [
'callback' => 'xbbcode_basic_render_table',
'description' => t('Create a table from comma-separated data. The tag option contains an optional caption and column headers; a prefix of ! or # aligns the column to the center or the right, respectively.'),
'sample' => t("[table=Caption;!Item,Color,#Amount]\nFish,Red,1\nFish,Blue,2\n[/table]"),
];
$tags['acronym'] = [
'markup' => '<acronym title="{option}">{content}</acronym>',
'sample' => t('[acronym=PHP: Hypertext Preprocessor]PHP[/acronym]'),
'description' => t('Puts a tooltip over the contained text, which displays the full meaning of the acronym.'),
];
$tags['abbr'] = [
'markup' => '<abbr title="{option}">{content}</abbr>',
'sample' => t('[abbr=et cetera]etc.[/abbr]'),
'description' => t('Identifies the content as an abbreviation and displays the full meaning in a tooltip.'),
];
return $tags;
}
function xbbcode_basic_render_img($tag) {
if ($tag->option) {
list($width, $height) = explode('x', $tag->option);
}
elseif (isset($tag->args['width'], $tag->args['height'])) {
list($width, $height) = [
$tag->args['width'],
$tag->args['height'],
];
}
else {
list($width, $height) = [
0,
0,
];
}
$scale = $width && $height ? "style='width:{$width}px;height:{$height}px;'" : '';
$alt = isset($tag->args['alt']) ? $tag->args['alt'] : "IMAGE({$tag->content})";
return "<img {$scale} src='{$tag->content}' alt='{$alt}' />";
}
function xbbcode_basic_render_youtube($tag) {
list($width, $height) = [
560,
315,
];
if (preg_match('/^(\\d+)x(\\d+)$/', $tag->option, $match)) {
list($width, $height) = [
$match[1],
$match[2],
];
}
else {
$width = $tag
->attr('width') ? $tag
->attr('width') : $width;
$height = $tag
->attr('height') ? $tag
->attr('height') : $height;
}
if (preg_match('/(\\/v\\/|((\\?|&|&)v=))(?<id>.*?)(&|$)/', $tag->content, $match)) {
$id = $match['id'];
}
else {
$id = $tag->content;
}
return "<iframe width=\"{$width}\" height=\"{$height}\" src=\"http://www.youtube.com/embed/{$id}\" frameborder=\"0\" allowfullscreen></iframe>";
}
function xbbcode_basic_render_nodelink($tag) {
return Drupal::l($tag->content, new Url('entity.node.canonical', [
'node' => $tag->option,
]), [
'html' => TRUE,
]);
}
function xbbcode_basic_render_list($tag) {
$items = preg_split('/\\s*\\[\\*\\]\\s*/', trim($tag->content));
array_shift($items);
$text = '<li>' . implode('</li><li>', $items) . '</li>';
$style = '';
if ($tag->option == 'n') {
$element = 'ol';
}
else {
$element = 'ul';
if (preg_match('/^[a-z-]*$/', $tag->option, $match)) {
$style = ' style="list-style-type:' . $match[0] . '"';
}
}
return "<{$element}{$style}>{$text}</{$element}>";
}
function xbbcode_basic_render_code($tag) {
$text = $tag->source;
if ($tag->name == 'code' && !strpos("-{$text}-", "\n") && !strpos("-{$text}-", "<br")) {
return "<code>{$text}</code>";
}
$text = trim($text);
if ($tag->name == 'php') {
$text = preg_replace('/<\\/?code>/', '', highlight_string(html_entity_decode($text), TRUE));
}
$text = '<object><div class="codeblock xbbcode">' . trim($text) . '</div></object>';
return $text;
}
function xbbcode_basic_render_define($tag) {
$items = explode("\n", $tag->content);
$out = '<dl>';
foreach ($items as $item) {
preg_match('/^((.*?):)?(.*)$/', $item, $match);
if ($match[1]) {
$out .= "<dt>{$match[2]}</dt>";
}
$out .= "<dd>{$match[3]}</dd>";
}
$out .= '</dl>';
return $out;
}
function xbbcode_basic_render_table($tag) {
$alignment = [
'' => 'left',
'#' => 'right',
'!' => 'center',
];
$table = [
'#type' => 'table',
'#rows' => [],
];
if ($tag->option) {
preg_match('/^(?:(.*);)?(.*)$/', $tag->option, $match);
list($_, $table['#caption'], $headers) = $match;
}
else {
$table['#caption'] = $tag
->attr('caption');
$headers = $tag
->attr('headers');
}
if ($headers) {
$headers = explode(',', $headers);
$table['#header'] = [];
foreach ($headers as $i => $header) {
preg_match('/^([#!]?)(.+)$/', $header, $match);
$table['#header'][$i] = $match[2];
$align[$i] = $alignment[$match[1]];
}
}
$rows = explode("\n", trim($tag->content));
foreach ($rows as $i => $row) {
$row = preg_split('/(?<!\\\\),/', $row);
if ($headers) {
foreach ($row as $j => $cell) {
$row[$j] = [
'#markup' => trim(str_replace('\\,', ',', $cell)),
'#wrapper_attributes' => [
'style' => 'text-align:' . $align[$j],
],
];
}
$table["row-{$i}"] = $row;
}
else {
$table['#rows'][] = $row;
}
}
return preg_replace('/(>)\\s+|\\s+(<)/', '\\1\\2', drupal_render($table));
}