1

Suppose there is a large paragraph of text, the conversion rules are:

  • **title** to <h1>title</h1>

  • :blush: to <img class="emoji" title="blush" src="/img/blush.png"/>

How can I do the conversion in one traversal?

Nicolas S.Xu
  • 13,794
  • 31
  • 84
  • 129
  • 5
    Have you tried anything yet? – sp00m Nov 05 '14 at 08:57
  • @sp00m I tried to look at marked.js, but it is too complex for me to understand... – Nicolas S.Xu Nov 05 '14 at 09:10
  • This is a good question, doing string or regex replaces in parallel is different from doing them in sequence (think `.replace('+', '-').replace('-', '+')`. I haven't found a well-answered duplicate on SO – Kos Nov 05 '14 at 09:19
  • Okay, found one: http://stackoverflow.com/questions/15604140/replace-multiple-strings-with-multiple-other-strings It uses the fact that you can give a function as second argument to `.replace`. – Kos Nov 05 '14 at 09:25

5 Answers5

1

The best way to do such things is regex - it is very optimized mechanism for such tasks in every language.

in javascript according to your examples:

>>> "**title** qweqwe **foo** ololo **bar**".replace(/(\*\*(\w+)\*\*)/g, "<h1>$2</h1>")
"<h1>title</h1> qweqwe <h1>foo</h1> ololo <h1>bar</h1>"

and

":blush: qweqwe :tongue: ololo :smile:".replace(/(\:(\w+)\:)/g, '<img class="emoji" title="$2" src:="/img/$2.png"/>')
"<img class="emoji" title="blush" src:="/img/blush.png"/> qweqwe <img class="emoji" title="tongue" src:="/img/tongue.png"/> ololo <img class="emoji" title="smile" src:="/img/smile.png"/>"

tada!

scythargon
  • 3,363
  • 3
  • 32
  • 62
  • That's two traversals, one for headers and one for emojis. – Kos Nov 05 '14 at 09:11
  • 1
    well there ARE `x|y` syntax in js regexps but no named groups syntax... so we can not distinguish which is where. Or you can use this crossbrowser js library for extended regexp syntax - http://xregexp.com/syntax/#namedCapture but I'd suggest you to not do that and use only plain one. – scythargon Nov 05 '14 at 09:20
1

you can try this :

<div id="replace">**title**some text :blush: some link </div>
var str= $("#replace").html();    
str = str.replace("**title**", "<h1>title</h1>");     
str = str.replace(":blush:", "<img class="emoji" title="blush" src:"/img/blush.png"/>");     
$("#replace").html(str);    
1

Capture the different patterns in 1 regex with different capture groups and have a replace-function inspect the different capture groups:

var input = '**Hey** Oh you! :blush:';
document.write(input.replace(/\*\*([^*]*)\*\*|:(happy|blush):/ig, function(match, title, smiley) {
  if (title != undefined) {
    return '<h2>' + title + '</h2>';
  } else if (smiley != undefined) {
    return '<img class="emoji" title="blush" src="/img/' + smiley + '.png" />';
  }
}));

This is the only answer with just one traversal on this page. Note though that it won't catch this:

var text = '**title with :blush: smiley** gotcha!';
asontu
  • 4,548
  • 1
  • 21
  • 29
0

You can use a regex for this problem.

var mystring = 'some text **title** some other text';
var re = /\*{2}(\w*)\*{2}/g;
mystring.replace(re, "<h1>$1</h1>");

Here the regex searches for any pattern starting with two * and ending with two *. The middle part is captured and used in the replace method.

tune2fs
  • 7,605
  • 5
  • 41
  • 57
0

Title

var re_title = /\*\*(.+)\*\*/g;
str.replace(re_title, '<h1>$1</h1>')

Emoji

var re_emoji = /:(.+):/g;
str.replace(re_emoji, '<img class="emoji" title="$1" src="/img/$1.png"/>')

You can club them together by running one replace after the other.

str.replace(re_title, '<h1>$1</h1>').replace(re_emoji, '<img class="emoji" title="$1" src="/img/$1.png"/>')

Sample

var str = '**title** :some_emoji:'
str.replace(re_title, '<h1>$1</h1>').replace(re_emoji, '<img class="emoji" title="$1" src="/img/$1.png"/>')
// output = "<h1>title</h1> <img class="emoji" title="some_emoji" src="/img/some_emoji.png"/>"

var str = '**:some_emoji: **'
str.replace(re_title, '<h1>$1</h1>').replace(re_emoji, '<img class="emoji" title="$1" src="/img/$1.png"/>')
// output = "<h1><img class="emoji" title="some_emoji" src="/img/some_emoji.png"/></h1>"

Since the capture groups cannot be named, the 'a|b' regex syntax cannot be used for replacement.

Aniket
  • 9,622
  • 5
  • 40
  • 62