3

Related to this question, but the answers don't solve my problem.

Backend (Node.js) receives some HTML from the frontend (React):

// this is merely an example
const price = '<strong>US$&nbsp;0.99</strong>';

The currency format is taken from Number.prototype.toLocaleString(). See this bit - $&? We'll come back to that later.

In the code below, #orderPrice# will be replaced with the product's price HTML and the string will be sent via e-mail, which comes from a template:

const template = `Your order has a total price of #orderPrice#.`.

const email = template.replace('#orderPrice#', price);

All fine and dandy, except it isn't. As seen here and in the aforementioned SO question, $& has special meaning when replacing strings - it inserts the matching string, despite being considered non-standard.

Let's say we have string1.replace(/pattern/g, string2). What caught me off guard is that neither string1 nor string2 can be sanitized/stripped off the $& bit, so I can't even sanitize the price html before inserting it into the template. The only way I can see it working is escaping the $ as $$ from the start, which is not possible due to the use of Number.toLocaleString(). We can always drop the .toLocaleString() and hardcode US$$ as a workaround, but that doesn't really address the question itself.

All that said, how can I sanitize a string having $&, assuming I can't escape it when it's being written?

gyohza
  • 736
  • 5
  • 18

2 Answers2

2

This works:

const email = template.replace('#orderPrice#', () => price); 
thorn0
  • 9,362
  • 3
  • 68
  • 96
1

You need to double any $ characters in price.

const price = '<strong>US$&nbsp;0.99</strong>';
const template = `Your order has a total price of #orderPrice#.`;
const email = template.replace('#orderPrice#', price.replace(/\$/g, '$$$$'));
console.log(email);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    Another option is `const email = template.replace('#orderPrice#', () => price);` – thorn0 Apr 22 '21 at 17:14
  • Thank you both for replying. @thorn0, can you post your comment as an answer? Both solutions work, but yours is a little more elegant and it's the one I'm picking. – gyohza Apr 22 '21 at 18:31