Экранированный html снова не экранируется в методе jquery html

Я хочу избежать текста заголовка в div. Но при подаче экранированного текста в вызов html() он снова не экранируется. Вот код

const title = $('<div/>').text('test <script>').html(); // test &amp;lt;script&amp;gt;
const span = `<span title="${title}">Hello world</span>`; // still correct
$('#test').html(span); 

но теперь сгенерированный html внутри #span снова имеет 'test ‹script'; проверьте демо здесь:

// find elements
var banner = $("#banner-message")
var button = $("button")

// handle click and add class
button.on("click", () => {
  const title = $('<div/>').text('test <script>').html();
  const span = `<span title="${title}">Hello world</span>`;
  $('#test').html(span);
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#banner-message {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  font-size: 25px;
  text-align: center;
  transition: all 0.2s;
  margin: 0 auto;
  width: 300px;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
}

#banner-message.alt {
  background: #0084ff;
  color: #fff;
  margin-top: 40px;
  width: 200px;
}

#banner-message.alt button {
  background: #fff;
  color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="banner-message">
  <p id="test">Hello World</p>
  <button>Add title</button>
</div>

  1. Нажмите кнопку добавить заголовок
  2. Наведите курсор на элемент, чтобы проверить заголовок

Ожидается: показывать заголовок как тестовый скрипт.

Фактически: заголовок отображается как тест


person coure2011    schedule 11.08.2020    source источник
comment
каков именно результат, который вы пытаетесь произвести?   -  person Lal    schedule 11.08.2020
comment
хотите заголовок как: test lt;scriptgt;   -  person coure2011    schedule 11.08.2020
comment
Он отлично работает в хроме.. в каком браузере вы пытаетесь это сделать?   -  person Lal    schedule 11.08.2020
comment
Пробовал в хроме и FF, хочу показать текстовый тест lt;scriptgt; при наведении показывает тестовый ‹скрипт›   -  person coure2011    schedule 11.08.2020


Ответы (2)


Экранируйте строку во второй раз.

function escape_html(str) {
    return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') ;
}

// find elements
var banner = $("#banner-message")
var button = $("button")

// handle click and add class
button.on("click", () => {
  let title = escape_html(escape_html('test <script>'));
  const span = `<span title="${title}">Hello world</span>`;
  $('#test').html(span);
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#banner-message {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  font-size: 25px;
  text-align: center;
  transition: all 0.2s;
  margin: 0 auto;
  width: 300px;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
}

#banner-message.alt {
  background: #0084ff;
  color: #fff;
  margin-top: 40px;
  width: 200px;
}

#banner-message.alt button {
  background: #fff;
  color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="banner-message">
  <p id="test">Hello World</p>
  <button>Add title</button>
</div>

person LeGEC    schedule 11.08.2020
comment
Этот код не будет выполнен, если отображаемый тег равен </script>, если скрипт не является внешним по отношению к странице. - person mplungjan; 11.08.2020

Если вы не можете сломать тег скрипта, вы можете экранировать тег на сервере или в теге

Обратите внимание, что код здесь злоупотребляет устаревшим тегом xmp, чтобы показать проблему, потому что вы НЕ МОЖЕТЕ иметь </script> где-либо в своем скрипте, если скрипт не является внешним по отношению к странице, поэтому, если вы планируете показывать

<script>alert('Hello')</script>

тогда страница не будет загружаться правильно, если указанная выше строка не находится в тегах xmp

Я дал ДВА решения на основе исходного вопроса и последующего комментария.

$("button").on("click", function() {
  const $converter = $("<div/>").text($("#textFromServer").text())

  // Expected: Show title as "test &lt;script&gt;"

  $("#test1").prop("title", $converter.html())

  // want the title as: "test &amp;lt;script&amp;gt;" 

  $("#test2").prop("title", $converter.html().replace(/&/g, "&amp;"))
});
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#banner-message {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  font-size: 25px;
  text-align: center;
  transition: all 0.2s;
  margin: 0 auto;
  width: 300px;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
}

#banner-message.alt {
  background: #0084ff;
  color: #fff;
  margin-top: 40px;
  width: 200px;
}

#banner-message.alt button {
  background: #fff;
  color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<div id="banner-message">
  <p id="test1">Hello World</p>
  <p id="test2">Hello World</p>
  <button>Add title</button>
</div>

<xmp style="display:none" id="textFromServer">test <script></xmp>

person mplungjan    schedule 11.08.2020