Inserting HTML into node titles

Last modified: August 26, 2009 - 23:55

Drupal strips all HTML from node titles when they're displayed to prevent XSS exploits. However, there are some cases where inline HTML elements are needed, such as when titles contain scientific names.

To work around this, we will use pseudotags like [i] and [/i] which Drupal will safely translate into real HTML tags when the page is displayed.

The PHPTemplate file page.tpl.php will need to be edited in order to make this trick work. Specifically, we need to add two new functions.

<?php
function bb2html($text) {
 
$bbcode = array(
                 
"[strong]", "[/strong]",
                 
"[b]""[/b]",
                 
"[u]""[/u]",
                 
"[i]""[/i]",
                 
"[em]", "[/em]"
               
);
 
$htmlcode = array(
               
"<strong>", "</strong>",
               
"<strong>", "</strong>",
               
"<u>", "</u>",
               
"<em>", "</em>",
               
"<em>", "</em>"
             
);
  return
str_replace($bbcode, $htmlcode, $text);
}

function
bb_strip($text) {
 
$bbcode = array(
                 
"[strong]", "[/strong]",
                 
"[b]""[/b]",
                 
"[u]""[/u]",
                 
"[i]""[/i]",
                 
"[em]", "[/em]"
               
);
  return
str_replace($bbcode, '', $text);
}
?>

This is how you make a phrase in the title italicized:

My title [em]rocks[/em]!

One problem with this approach is that node title also shows up in the page titles, and page titles are not allowed to have any markup. That's where the above bb_strip function comes in. Between the HTML title tags in page.tpl.php, add the following:

<?php print bb_strip($head_title); ?>

And whenever you reference the node title in your template use this:

<?php print bb2html($title); ?>

NOTE: If you use books, this mechanism has a problem unless you are willing to patch book.module. book.module, in the function book_tree_recurse, creates links to nodes by their title, and of course doesn't know to use your code

regexes

wholcomb - August 21, 2006 - 05:59

If you want to guarantee that tags are closed, you can use the clichéd regex with a backreference:

<?php
function bb2html($text) {
 
$bbcode_regex = '/\[(strong|cite|em)\](.*)\[\/\1\]/';
  return
preg_replace($bbcode_regex, '<$1>$2</$1>', $text);
}
?>

One correction

sander-martijn - August 21, 2007 - 20:04

If you want/need to access these functions from node.tpl.php or any other file you will need the function to live in template.php. Even if you are only calling it in page.tpl.php it's probably a better idea to keep it in template.php for the sake of code separation. Other than that, great fix for an annoying problem. Now if only we can find a solution for special characters.

so no one ever got the special characters in node title solved..

redhatmatt - February 5, 2009 - 05:20

almost seems like replacing say [amp] with & would maybe kinda work???

Bummer, maybe not...

Newlines

felipensp - September 4, 2007 - 11:00

Use the modifier 's' in regex to match newline inside of tags.

Using Views...

r00lnyi - March 6, 2008 - 14:31

If you-re using views and want do highlight one or some titles in views-result page or block .....

1. First of all you need edit view.module
Take this function

function theme_views_view_list($view, $nodes, $type) {
  $fields = _views_get_fields();

  foreach ($nodes as $node) {
    $item = '';
    foreach ($view->field as $field) {
      if (!isset($fields[$field['id']]['visible']) && $fields[$field['id']]['visible'] !== FALSE) {
        if ($field['label']) {
          $item .= "<div class='view-label ". views_css_safe('view-label-'. $field['queryname']) ."'>" . $field['label'] . "</div>";
        }
        $item .= "<div class='view-field ". views_css_safe('view-data-'. $field['queryname']) . views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view) . "</div>";
      }
    }
    $items[] = "<div class='view-item ". views_css_safe('view-item-'. $view->name) ."'>$item</div>\n"; // l($node->title, "node/$node->nid");
  }
  if ($items) {
    return theme('item_list', $items);
  }
}

and replace by this

function theme_views_view_list($view, $nodes, $type) {
  $fields = _views_get_fields();

  foreach ($nodes as $node) {
    $item = '';
    foreach ($view->field as $field) {
      if (!isset($fields[$field['id']]['visible']) && $fields[$field['id']]['visible'] !== FALSE) {
        if ($field['label']) {
          $item .= "<div class='view-label ". views_css_safe('view-label-'. $field['queryname']) ."'>" . $field['label'] . "</div>";
        }
        $item .= "<div class='view-field ". views_css_safe('view-data-'. $field['queryname']) ."' id='v".$node->nid."'>" . views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view) . "</div>";
      }
    }
    $items[] = "<div class='view-item ". views_css_safe('view-item-'. $view->name) ."'>$item</div>\n"; // l($node->title, "node/$node->nid");
  }
  if ($items) {
    return theme('item_list', $items);
  }
}

So every view element item has id="number of node" anywhere. Do not forget you cant use digits only in css id's so i added "v" as prefix.

Then just css. For example ...

#v3640 a:link, #v3640 a:visited  {
color: red;
font-weight: bold;

}

submitted as a patch

christefano - May 1, 2008 - 21:28

This proposed modification has been submitted as a patch. Please review it at http://drupal.org/node/253686 when you have a chance.

Special Characters in Node Title solved / example

redhatmatt - February 5, 2009 - 08:46

Ok so here is a little clearer instructions on implementing the previous snippet AND how to add special characters for those of you who did not follow what was here:

Go to your template.php file in your themes folder for the them you are using and open it... right after the initial php opening tag line 1:

<?php
function bb2html($text) {
$bbcode = array(
"[strong]", "[/strong]",
"[b]", "[/b]",
"[u]", "[/u]",
"[i]", "[/i]",
"[em]", "[/em]",
"[amp]", "[theta]", "[degree]", "[prime]", "[doubleprime]", "[squareroot]"
);
$htmlcode = array(
"<strong>", "</strong>",
"<strong>", "</strong>",
"<u>", "</u>",
"<em>", "</em>",
"<em>", "</em>",
"&amp;", "&theta;", "&#176;", "&prime;", "&Prime;", "&radic;"
);
return
str_replace($bbcode, $htmlcode, $text);
}

function
bb_strip($text) {
$bbcode = array(
"[strong]", "[/strong]",
"[b]", "[/b]",
"[u]", "[/u]",
"[i]", "[/i]",
"[em]", "[/em]",
"&amp;", "&theta;", "&#176;", "&prime;", "&Prime;", "&radic;"
);
return
str_replace($bbcode, '', $text);
}

Save it...

then open up page.tpl.php and find the lines that mention $title... basically we want to slip in

<?php print bb2html($title);
?>
there but modify what is actually in YOUR page.tpl.php file... in my instance I was using plain old Garland (yippee!)

so I found:

<?php
if ($title): print '<h2'. ($tabs ? ' class="with-tabs"' : '') .'>'. $title .'</h2>'; endif;
?>

around line 68
and replaced it with:
<?php
if ($title): print '<h2'. ($tabs ? ' class="with-tabs"' : '') .'>'. bb2html($title) .'</h2>'; endif;

Finally put this (as he said before) between the title tags at the top to strip the [whatever] items out of your title...

<?
php print bb_strip($head_title);
?>

Ok so that's it, hopefully you can get through the patterns now... if you still have issues I will subscribe to this thread or just contact me, for my instance I needed only scientific special characters... so I am going to make a completed list of characters and post the whole thing here when I am done, so whomever will not have to do the same work again...

Added this to allow hyperlinks in titles

gnerdalot - July 20, 2009 - 07:56

In Salamander skins theme changed block.tpl.php:

  <div class="block block-<?php print $block->module ?>" id="block-<?php print $block->module ?>-<?php print $block->delta ?>">
    <h2 class="title"><?php print bb2html($block->subject) ?></h2>
    <div class="content"><?php print $block->content ?></div>
</div>

then in template.php added this to the lines for links

"[a]", "[amiddle]", "[/a]",

.. so that a block title when edited now looks like:

[a]about[amiddle]About Us[/a]

and render the html link in the title.

Thanks for posting this - elegant solution to adding html to the block titles!!!

Not working

chris.mccreery - August 31, 2009 - 16:32

I am trying to implement this on a site but am having no luck. I followed the directions above exactly(or so I think) but nothing is being converted to html. I just get Title of Page. Any ideas of what I might be missing? I'm using the Basic theme, on Drupal 6.13

Thanks.

Resolved

chris.mccreery - August 31, 2009 - 17:35

Sorry I was inserting < instead of [

Why Is Filtering Not Applicable?

jeffreyd - October 7, 2009 - 21:40

Why is content filtering not used to control tags in titles, like it is on body content? Wouldn't that remove the risk of XSS? Is there a performance problem?

Further reading of other discussions points out that the Title field is overloaded with competing purposes. Plain text is the only answer with our current architecture (in D6). There is also some discussion on a real fix for this issue at 82751 (Enable HTML in titles). D7 will help us along nicely.

There is also a module (Page Title, for D5 & D6) for splitting out the two main purposes of the Title field, as a content title, and as a web page title.

Incidentally, menus suffer from a similar plain text issue. I want select HTML tags to work there too.

 
 

Drupal is a registered trademark of Dries Buytaert.