1

I've found the perfect JavaScript templating engine, built by Krasimir, it is just what I needed.
The templating engine works great but naturally I couldn't resist the urge to hack at it a bit and maybe even add a couple of features.
Unfortunately I am having trouble understanding some of the code.

Here is the code:

var TemplateEngine = function(html, options) {
  var re = /<%([^%>]+)?%>/g,
    reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
    code = 'var r=[];\n',
    cursor = 0,
    match;
  var add = function(line, js) {
    /* --begin problem  */
    js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') : (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
    /* --end problem    */
    return add;
  };
  while (match = re.exec(html)) {
    add(html.slice(cursor, match.index))(match[1], true);
    cursor = match.index + match[0].length;
  }
  add(html.substr(cursor, html.length - cursor));
  code += 'return r.join("");';
  return new Function(code.replace(/[\r\t\n]/g, '')).apply(options);
};

Here is the line I don't understand:

js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') : (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');

I'm not new to JavaScript but that's some weird looking code and from what I know it is a ternary operator without a left hand assignment (correct me if I'm wrong)

So in order to get a better understanding of what the author was doing I have attempted to convert the ternary operator into conditional statements.

This is what I have so far:

if(js) {
  if(code += line.match(reExp)) {
    line += '\n';
  } else {
    line += 'r.push(' + line + ');\n';
  }
} else {
  if(code += line !== '') {
    line += 'r.push("' + line.replace(/"/g, '\\"') + '");\n';
  } else {
    line += "";
  }
}

This failed and threw the error "Uncaught SyntaxError: Unexpected token if"

Can anybody help me convert this code into conditional statements and maybe even give me an explanation as to what the code does?

Also out of curiosity could anybody tell me if IE8 supports this code?
NOTE: I don't mind IE8 support I would just like to know if this templating engine supports IE8.

You can find the templating engine on Krasimir's Website or Krasimir's Github

  • 1
    Your alternate code does not have a syntax error. If you're getting that error, it's coming from somewhere else. – Pointy Mar 28 '16 at 20:30
  • @Pointy Yes that is what I was thinking and I'm also 100% positive that the template code does not have syntax error as well because I used the same code from the example, maybe I've gotten something wrong in the statement? –  Mar 28 '16 at 20:33

3 Answers3

1

You are not supposed to append code to line you must append to code, try this:

if (js && type(js) !== "undefined") {
  if (line.match(reExp)) {
    code += line;
  } else {
    code += "r.push(" + line + ");";
  }
} else if (line !== "") {
  code = code + "r.push(\"" + line.replace(/"/g, '\\"') + "\");";
}
0

The ternary operator ?: works in JavaScript just like in C. In this case, we can format the expression as

js? (code += (line.match(reExp)? line + '\n' : 'r.push(' + line + ');\n')
  : (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');

and it looks just like an if-else block. The whole expression evaluates to one of two compound assignment expressions, depending on the value of js. The value of this expression is ignored, but we can still get side-effects out of it. The author simply chose to write this instead of if (js) { code += ...; } else { code += ...; }.

Evelyn Kokemoor
  • 326
  • 1
  • 9
  • Evelyn, it appears the poster of origonal answer has been banned, so I've accepted your answer, the rep's gotta go to someone :) Once again thank you so very much for the answer, cheers. –  May 24 '16 at 03:28
0

I know this question has not gotten a lot of attention but I thought I'd post this answer anyways in hopes that it would help someone who is facing this problem.
With some effort and a ton of help from JSHint I have figured out the solution to my question.
I was appending the current compiled line to the "line" variable and not the "code" variable.
This resulted with the "line" variable containing the last line of the template and the rest of the compiled code, meaning that the "code" variable had no code :D and was therefor equivalent to null.

Here is the code I had before I figured out what I was doing wrong:

var add = function(line, js) {
  if(js) {
    if(code += line.match(reExp)) {
      line += '\n';
    } else {
      line += 'r.push(' + line + ');\n';
    }
  } else {
    if(code += line !== '') {
      line += 'r.push("' + line.replace(/"/g, '\\"') + '");\n';
    } else {
      line += "";
    }
  }
};

After replacing the "line" variable with the "code" variable here and there and making a couple of optimisations here is the final working answer:

var add = function(line, js) {
  if(js && typeof js !== "undefined") {
    if(line.match(reExp)) {
      code += line;
    } else {
      code += "r.push(" + line + ");";
    }
  } else if(line !== "") {
    code += "r.push(\"" + line.replace(/"/g, '\\"') + "\");";
  }
};