0

I want to create a JS Preprocessor, this is just something to display data from js variables, I currently got:

var ____Code = fs.readFileSync(__resources + '/help.txt').toString();
    ____Code.split('{%').forEach((i,ii) => {
      var _Code = i.split('%}')[0];
      ____Code.split('{%' + _Code + '%}').join(`${_Code}`);
    });

The point of this code was basically if I had a js file looking like this:

var obj = {
  hello: 'world',
  language: 'javascript',
  filetype: 'text',
  test: {
    successfull: 'Yes!'
  }
}
var ____Code = fs.readFileSync(__resources + '/help.txt').toString();
    ____Code.split('{%').forEach((i,ii) => {
      var _Code = i.split('%}')[0];
      ____Code.split('{%' + _Code + '%}').join(`${_Code}`);
    });

And the help.txt looks like this:

Is this successfull? {%obj.test.successfull%}
I am a {%obj.filetype%} file, that is has been read by {%obj.language%}.
The default example for {%obj.language%} is: "Hello {%obj.hello%}"

Then I'd want the output to be:

Is this successfull? Yes!
I am a text file, that is has been read by javascript.
The default example for javascript is: "Hello world"

But the actual outcome is the exact same as help.txt, how may i make it replace {%variable%} to the actual js variable?

Alliator
  • 73
  • 1
  • 10
  • May I suggest a different approach? Preprocessing code using regular expressions and what not is hard, and there's no need to reinvent the wheel. You could use existing tools like [Acorn](https://github.com/ternjs/acorn) to create an abstract syntax tree (AST) which you can use for your preprocessor. – Patrick Hund Mar 19 '17 at 16:47
  • You are not changing the `___Code` variable anywhere? You need to use an assignment somehow (and probably want to avoid `forEach`) – Bergi Mar 19 '17 at 16:50

2 Answers2

0

You should use a combination of String#replace and Array#reduce instead of eval (which is generally less performant and always less secure).

var data = {
  obj: {
    hello: 'world',
    language: 'javascript',
    filetype: 'text',
    test: {
      successful: 'Yes!'
    }
  }
}

var ____Code = // fs.readFileSync(__resources + '/help.txt').toString()
`
Is this successfull? {%obj.test.successful%}
I am a {%obj.filetype%} file, that is has been read by {%obj.language%}.
The default example for {%obj.language%} is: "Hello {%obj.hello%}"
`

var result = ____Code.replace(/\{%(.*?)%\}/g, function(_, path) {
  return path.split('.').reduce(function(o, k) {
    return o[k]
  }, data)
})

console.log(result)
gyre
  • 16,369
  • 3
  • 37
  • 47
  • It breaks easily when OP writes some login into it or uses "obj[a]" style to get the value. – blackmiaool Mar 20 '17 at 01:12
  • @blackmiaool Anything is better than `eval` ;) – gyre Mar 20 '17 at 01:14
  • What if the tamplate is provided by OP and he/she doesn't care about the performance? – blackmiaool Mar 20 '17 at 01:15
  • Then I would suggest you put a massive disclaimer explaining the situations for which your answer is recommended. `eval` has its uses, but in production code these are few and far between. – gyre Mar 20 '17 at 01:19
  • The fastest tamplate engine is using "new Function" to get values. https://github.com/olado/doT/blob/master/doT.js#L133 – blackmiaool Mar 20 '17 at 01:25
-1

Try this:

var a = `
Is this successfull? {%obj.test.successfull%}
I am a {%obj.filetype%} file, that is has been read by {%obj.language%}.
The default example for {%obj.language%} is: "Hello {%obj.hello%}"
`;
var obj = {
  hello: 'world',
  language: 'javascript',
  filetype: 'text',
  test: {
    successfull: 'Yes!'
  }
}
var ____Code = a;
var b=____Code.split('{%').forEach((i, ii) => {
  if(ii===0)
  return;
  var _Code = i.split('%}')[0];
  var _text;
  eval(`_text=${_Code}`);
  console.log(_text);
  console.log(_Code)
  ____Code=____Code.replace('{%' + _Code + '%}',`${_text}`);
});
console.log(____Code)

Why

The "eval" function is what u want.

PS: theres are many templates engines like this written with js, u can just find one and use it if u don't mind. (underscore's template for example).

PPS: Why is using the JavaScript eval function a bad idea?

Community
  • 1
  • 1
blackmiaool
  • 5,234
  • 2
  • 22
  • 39