2

I want to render a text as common HTML and parse occurrences of [code] tags that should be output unrendered - with the tags left untouched.

So input like this gets processed accordingly:

<p>render as HTML here</p>
[code]<p>keep tags visible here</p>[/code]
<p>more unescaped text</p>

I've regexed all code-tags but I have no idea how to properly set the text of the element afterwards. If I use jQuery's text() method nothing gets escaped, if I set it with the html() method everything gets rendered and I gained nothing. Can anybody give me a hint here?

beast.caged
  • 65
  • 12

4 Answers4

2

Try replacing [code] with <xmp> and [/code] with </xmp> using regex or alike, and then use the jQuery html() function.

Note that <xmp> is technically deprecated in HTML5, but it still seems to work in most browsers. For more information see How to display raw html code in PRE or something like it but without escaping it.

Community
  • 1
  • 1
Andreas
  • 662
  • 1
  • 6
  • 13
1

You could replace the [code] and [/code] tags by <pre> and </pre> tags respectively, and then replace the < within the <pre> tags by & lt;
A programmatic solution based on Javascript is as follows

function myfunction(){
  //the string 's' probably would be passed as a parameter

  var s = "<p>render as HTML here</p>\
  [code]<p>keep tags visible here</p>[/code]\
  <p>more unescaped text</p>";

  //keep everything before [code] as it is
  var pre = s.substring(0, s.indexOf('[code]'));

  //replace < within code-tags by &lt;
  pre += s.substring(s.indexOf('[code]'), s.indexOf('[/code]'))
           .replace(new RegExp('<', 'g'),'&lt;');

  //concatenate the remaining text
  pre += s.substring(s.indexOf('[/code]'), s.length);

  pre = pre.replace('[code]', '<pre>');
  pre = pre.replace('[/code]', '</pre>');

  //pre can be set as some element's innerHTML
  return pre;
}
S Raghav
  • 1,386
  • 1
  • 16
  • 26
1

I would NOT recommend the accepted answer by Andreas at all, because the <xmp> tag has been deprecated and browser support is totally unreliable.

It's much better to replace the [code] and [/code] tags by <pre> and </pre> tags respectively, as raghav710 suggested.

He's also right about replacing the < character with &lt;, but that's actually not the only character you should replace. In fact, you should replace character that's a special character in HTML with corresponding HTML entities.

Here's how you replace a character with its corresponding HTML entity :

var chr = ['&#', chr.charCodeAt(), ';'].join('');
Community
  • 1
  • 1
John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • In addition to not using ``, I would also avoid trying to escape the inserted text. Instead, I suggest using `node.textContent/jQuery.text`, to avoid XSS and for better performance with larger strings. `textContent` passes the text to be inserted directly to the browser, avoiding fiddly HTML entity escaping step. – Lie Ryan Mar 02 '16 at 13:13
1

You can replace the [code]...[/code] with a placeholder element. And then $.parseHTML() the string with the placeholders. Then you can insert the code into the placeholder using .text(). The entire thing can then be inserted to the document (run below or in JSFiddle).

var str = "<div><b>parsed</b>[code]<b>not parsed</b>[/code]</div>";
var placeholder = "<div id='code-placeholder-1' style='background-color: gray'></div>";
var codepat = /\[code\](.*)\[\/code\]/;
var code = codepat.exec(str)[1];
var s = str.replace(codepat, placeholder);
s = $.parseHTML(s);
$(s).find("#code-placeholder-1").text(code);
$("#blah").html(s);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Text
<div id="blah">place holder</div>
Around

The code above will need some modifications if you have multiple [code] blocks, you will need to generate a unique placeholder id for each code block.

If you may be inserting untrusted structure code, would highly recommend using large random number for the placeholder id to prevent a malicious user from hijacking the placeholder id.

Lie Ryan
  • 62,238
  • 13
  • 100
  • 144