I have a simple CRUD webapp that's built upon populating template literals based on user input. The issue is that if the user inputs something like <b>Hey</b>
then it's rendered as bold on the page:
const element = (name) => {
const elementHTML=
`<div>
<ul>
<li>${name}</li>
</ul>
</div>`
const element = document.createElement('div')
element.innerHTML = elementHTML
return element.firstChild
}
const userInput = '<b>foo</b>'
document.body.appendChild(element(userInput)) //
How can I stop this interaction? My guess is to use some invisible character around the ${embedded expression}
to stop what's inside from being interpreted as HTML, so something like:
const elementhtml = `<div>|${name}|</div>`
Where |
would be the invisible character.
Is there a best practice to draw the expressions as text instead of HTML? I understand that this is a product of using innerHTML to create the element, but isn't that necessary to make use of template literals?
CodePudding user response:
Don't interpolate input from the user into HTML markup directly. Either escape the entities so they're interpreted as plain text instead of HTML tags, or assign to the .textContent
of the element instead.
const element = (name) => {
const elementHTML=
`<div>
<ul>
<li></li>
</ul>
</div>`
const element = document.createElement('div')
element.innerHTML = elementHTML
element.querySelector('li').textContent = name;
return element.firstChild
}
const userInput = '<b>foo</b>'
document.body.appendChild(element(userInput))
CodePudding user response:
You can .replace()
<
and >
with unicode HTML entities <
and >
, respectively.
const element = (name) => {
const elementHTML =
`<div>
<ul>
<li>${name}</li>
</ul>
</div>`;
const element = document.createElement('div');
element.innerHTML = elementHTML;
return element.firstChild;
}
const userInput = (data) => data.replace(/</g, '<').replace(/>/g, '>');
document.body.appendChild(element(userInput(`<b>foo</b>`)));
CodePudding user response:
Do the same you did but don't mention it directly in the li tag. Do it this way: document.getElementById("li").innerText=name
CodePudding user response:
I see you are getting name
from the user. You can validate the name
to be a real name first, so you don't need to think of the HTML
. This Regular Expression
can be used to validate a name.
/^[a-z ] $/i
characters from a-z case insensitive, and spaces are allowed. Meaning the user cannot put html tags in there.
Even if you have validated user input, you should still not use innerHTML
as it will take the name
or text
as html
. You should instead use innerText
or textContent
to prevent that.
You can also you replace()
and replaceAll()
methods to remove parts of the text, this could be the html
or any other tags inside the text