J'ai un modèle de message dans une chaîne et j'essaie de prévisualiser un exemple de message pour l'utilisateur. Dans l'aperçu, je souhaite mettre en évidence les signes dollar $ sans échappement qui ne font pas partie d'un jeton de publipostage approuvé.

Exemple de modèle de message

<h1>Title</h1>

Good Dollar --> A new card costs (\$13.00)<br/>
Bad Dollar --> A new card costs ($13.00)<br/>
Good Dollar --> A new card costs \$13.00<br/>
Bad Dollar --> A new card costs $13.00<br/>
badDollar$ goodDollar\$
<br/>
Email Address: ${msg.from}<br/>
Reply-To Address: ${msg.replyTo}<br/>
Email Address: ${msg.address}<br/>

Résultat de l'aperçu souhaité

enter image description here

Je l'ai fait fonctionner avec le code suivant, mais cela semble vraiment maladroit. Il doit y avoir un meilleur moyen que cela.

    preview(string) {
        let msg = {
            from: 'noreply@company.com',
            replyTo: 'reply@company.com',
            address: 'customer@gmail.com'
        }

        this.user.organization.customFields.forEach((cf) => msg[`cf_${cf.name}`] = this.user.customFields[cf.name].value)

        let slashDollar = 'SLASHDOLLAR';
        string = string.replace(new RegExp(/\\\$/, "g"), slashDollar)
        string = eval('`' + string + '`')
        let pattern = new RegExp(/\$/, "g")
        if (pattern.test(string)) {
            this.MessageService.alert('You need to prefix every dollar sign "$" with a backslash "\\" unless the dollar sign is part of a mail merge token', true)
            string = string.replace(pattern, (match) => `<span style="color:#ef2160">${match}</span>`)
        }
        string = string.replace(new RegExp(slashDollar, "g"), '$')
        return string
    }

Après avoir appelé eval, tout $ restant qui n'est pas échappé doit être indiqué comme une erreur. Je voudrais simplement utiliser un seul replace (au lieu de le remplacer 3 fois), mais je n'arrivais pas à faire correspondre $ sans un \ précédent. J'ai essayé plusieurs variantes de ce qui suit, mais sans succès. Alors est-il possible de faire cela sans remplacer chaque \$ par un jeton intermédiaire puis remplacer chaque $ puis remplacer les jetons intermédiaires par $?

string = string.replace(new RegExp(/[^\\]\$/, "g"), (match) => `${match[0]}<span style="color:#ef2160">${match[1]}</span>`)
0
10GritSandpaper 7 oct. 2020 à 18:34

2 réponses

Meilleure réponse

Merci à @PeterSeliger pour son commentaire sur l'utilisation d'un regard négatif derrière. Le problème était un peu plus compliqué que cela, mais c'était la pièce manquante dont j'avais besoin.

Mon principal problème est que l'appel eval(...) a enlevé les \ de chaque \$, donc après avoir appelé eval(...), il n'y avait aucun moyen de différencier les $ qui étaient à l'origine échappé.

Cependant, j'ai pu combiner un lookbehind négatif avec un lookahead négatif pour trouver chaque $ qui n'était pas précédé d'un \ et n'était pas suivi d'un {. Cela m'a permis d'identifier les signes dollar erronés avant d'appeler eval.

Solution finale:

    preview(string) {
        let msg = {
            from: 'noreply@company.com',
            replyTo: 'reply@company.com',
            address: 'customer@gmail.com'
        }

        let erroneousDollarSigns = new RegExp("(?<!\\\\)\\$(?!{)", "g");
        if (erroneousDollarSigns.test(string)) {
            this.MessageService.alert('You need to prefix every dollar sign "$" with a backslash "\\" unless the dollar sign is part of a mail merge token', true)
            string = string.replace(erroneousDollarSigns, (match) => `<span style="color:#ef2160">${match}</span>`)
        }

        return eval('`' + string + '`')
    }
0
10GritSandpaper 7 oct. 2020 à 16:40

... utilisez un lookbehind négatif comme avec cet exemple de regex ... (?<!\\)\$.

Et bien sûr, dans une chaîne (modèle), la barre oblique inverse d'échappement du dollar doit également être échappée. L'expression régulière fournie échoue pour une seule barre oblique inverse dans la chaîne.

const msg = {
  from: 'noreply@company.com',
  replyTo: 'reply@company.com',
  address: 'customer@gmail.com'
}
const htmlTemplate = `<h1>Title</h1>

Good Dollar --> A new card costs (\\$13.00)<br/>
Bad Dollar --> A new card costs ($13.00)<br/>
Good Dollar --> A new card costs \\$13.00<br/>
Bad Dollar --> A new card costs \$13.00<br/>
badDollar\$ goodDollar\\$

<br/>
<br/>

Email Address: ${msg.from}<br/>
Reply-To Address: ${msg.replyTo}<br/>
Email Address: ${msg.address}<br/>`;


const regXUnescapedDollar = (/(?<!\\)\$/g);

document.body.innerHTML = htmlTemplate
  .replace(regXUnescapedDollar, '<span style="color:#ef2160">$</span>')
  .replace(/\\/g, ''); // replace backslash within text content output.
1
Peter Seliger 7 oct. 2020 à 16:28