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.

We need two new functions (please note that Drupal best practices are to include functions in template.php or a custom module; logic should not be placed in *.tpl.php).

function bb2html($text) {
  $bbcode = array(
                  "[strong]", "[/strong]",
                  "[b]",  "[/b]",
                  "[u]",  "[/u]",
                  "[i]",  "[/i]",
                  "[em]", "[/em]"
                );
  $htmlcode = array(
                "<strong>", "</strong>",
                "<strong>", "</strong>",
                "<u>", "</u>",
                "<i>", "</i>",
                "<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

Comments

wholcomb’s picture

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

function bb2html($text) {
  $bbcode_regex = '/\[(strong|cite|em)\](.*)\[\/\1\]/';
  return preg_replace($bbcode_regex, '<$1>$2</$1>', $text);
}
sander-martijn’s picture

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.

redhatmatt’s picture

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

Bummer, maybe not...

felipensp’s picture

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

r00lnyi’s picture

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;

}

christefano’s picture

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



Christefano  
Founder, CEO
Large Robot
954-247-4786
http://www.largerobot.com
redhatmatt’s picture

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:



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

 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...

gnerdalot’s picture

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!!!

dupls’s picture

you mention render the html link in the title.
If I understand correctly I have entered the
"[a]", "[amiddle]", "[/a]"
although I fail to understand the significance of "[amiddle]"
Regardless then I tried editing the title.
[a href=/gosomeplace]Place I want to go[/a]
But I'm seeing the entire code in the title.

By the way all the other codes work so I know I'm close! ;o)

chris.mccreery’s picture

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.

chris.mccreery’s picture

Sorry I was inserting < instead of [

nicobo’s picture

Thanks for this very usefull hack.

For info, I've found that block.tpl.php and node.tpl.php also had references to $title, so I had to apply the bb2html function there also.

I'm working with the Zen theme on Acquia (Drupal 6.15), but I didn't check if that was Zen-specific or not.

Cheers.

laraz’s picture

Hi.
The function bb2html() works perfect for me. But in my page.tpl.php I haven't got the variable $head_title for use the function bb_strip($head_title);

Therefore, in the title of the head appears [strong][/strong]. My theme is zen. I use the version for Drupal 7.

thanks.

drum5ormore’s picture

In Drupal 7 you have to use html.tpl.php to modify the page title. http://api.drupal.org/api/drupal/modules!system!html.tpl.php/7

ambientdrup’s picture

I'd be interested in seeing the final code you ended up with for Drupal 7? Especially for including scientific characters. I tried the code in your example in D7 and it did not work. Has anything changed since your original post?

-Trevor

jeffreyd’s picture

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.

designguru’s picture

Hey all,

I know this is an old thread but anyone stumbling upon it may enjoy a post I just wrote on how to have html titles on nodes using Drupal 6.x:

http://designguru.org/blog/031110/how-use-html-alternative-titles-drupal...

Cheers,

Qasim

Qasim Virjee
Principal, http://designguru.org
qasim@designguru.org
1.416.777-1864

lizac’s picture

Just like everyone else, I've been scouring the web to find answer for this need and I'm so glad that I found this one! However, I just notice something while applying the fix.

I actually used the search function of our site in finding other content with & in title and realized that the result seems unusual which I also happened to find in drupal.org. See http://min.us/mRCl4d1nunc7B. When searching with & only, it appears that the result has "&_a_m_p_;". same goes when you include in your search "&_a_m_p_;" Any idea on how to fix it?

Also, how do we apply this on title that is produced by Views?

hooface’s picture

Just solved my problem.Thanks!

lizac’s picture

@hooface. did it solve your problem on search result as well? Thanks!

prabhatjn’s picture

Here is another easy solution that worked for me.
http://stackoverflow.com/questions/1535878/html-rich-text-in-drupals-nod...

Perry.

tarzadon’s picture

The bb2html and bb_strip functions worked for me.

I tried the preprocess_node function in the previous comment, but I couldn't get it to work.

subu.purohit’s picture

I have successfully added html tags in node title, but bbcode text is coming in url alias.
ie. if my node title is "My [em]blog[/em] title", then my url is coming as :

content/my-emblogem-title.

Is there any way so that I can exclude these text from url ?

Thanks in advance.

subu.purohit’s picture

I have got a temporarily solution . what I did :

I added a new line :
$node->title = bb_strip($node->title);
Just before :
$placeholders = pathauto_get_placeholders('node', $node);

In pathauto_nodeapi() function in pathauto.module

And added same line after
node_save($node);
in node.pages.inc to avoid bb codes in successful message after node creation.

Please let me know a better way if any.

Thanks

TravisJohnston’s picture

Looks like a lot of people have been asking about using this with views and there are never any responses. The one towards the top doesn't really have anything to do with it.

So if you want to allow HTML in your view fields, such as a Node Title, here's what you do:

  1. Insert the original Function code into your template.php file like normal
  2. Create a view template file for the field you want to edit, such as the Title field in a Billboard view views-view-field--billboards--block--title.tpl.php. You will want to use the one with just the print $output field
    (If you have never made template files for views, I have included some basic instructions below for this to help you out)
  3. Now do the same wrap as suggested in the page.tpl.php, you will want to wrap the $output variable so it looks like this:
    print bb2html($output); 
    
  4. Now save, clear caches, and your good to go. Just remember that the way the function is setup, you need to use the [tag here] format in your title in order for it to work

So real quick for creating view template files since there is always a chance that someone will ask.

  1. Open the view then go to the specific block/page/etc that you want
  2. Click Theme Information
  3. Look for the field you want to work with, for the HTML in node title, I am using the Title field.
  4. It shows you a bunch of suggested names for the template file, for good practice, take the last one as this is the most granular and specific template file for the view you are in. If you want to apply the changes to all node titles in views, you can just look closer to the top and grab the second one in's name.
  5. What I like to do here is copy the name of the template file, then create a new PHP document in your editor. Replace the name of the file with the one you copied (make sure to remove the extra .php at the end :) )
  6. Then go back to the view (still in the theme information) and click the field link that is provided, such as Field Node: Title (ID: title):. You should now see some code, copy all of it and place it into your newly created template file.
  7. lastly, save the file, clear caches and your all set. You can now follow the directions that I included above

Thank you kindly,

Travis Johnston

Creo Coding - Let's Start Our Journey!
Owner and Web Developer
http://www.creocoding.com

Facebook - Facebook.com/CreoCoding
LinkedIn - http://lnkd.in/rQrdS7

ryan.gibson’s picture

many thanks amigo.

RdeBoer’s picture

karthikkumarbodu’s picture

Yes we can achieve HTML in page titles just like below
drupal_set_title('This is emphasised format of my page title', PASS_THROUGH);

Karthik Kumar Bodu