Частично запускать код как html и как текст
Введение
В настоящее время я создаю шаблон, в котором пользователи могут создавать шаблон для приложения. Пользователь может перетаскивать несколько блоков, таких как текстовые блоки и блоки "настраиваемого кода". Шаблон будет анализироваться в приложении. Сейчас шаблон может выглядеть так:
<section>
<div class="row">
<div class="col-sm-12">
<section data-type="code">
<#code></#code>
</section>
</div>
</div>
<div class="row">
<div class="col-sm-12" data-type="container-content">
<section data-type="text">
<u>Lorem</u> ipsum
</section>
</div>
</div>
</section>
Итак, этот шаблон содержит два элемента (см. атрибут data-type
): одна часть - это пользовательский письменный код. Здесь пользователь написал собственный код, включая код Apache Freemarker. Вторая часть - это индивидуальный письменный текст.
Ситуация
Приведенный выше код будет использоваться двумя разными способами.
- Именно этот код будет использоваться внутри приложения, используя
шаблон (так что почему они должны иметь возможность писать код Freemarker,
потому что это будет проанализировано).
- На моем веб-сайте пользователь должен уметь
для редактирования этого шаблона. Поскольку код хранится в базе данных как
написано выше, есть проблема:
Проблема
Когда я непосредственно обрабатываю шаблон в веб-интерфейсе, часть text
будет правильно отображаться с тегами <u></u>
, но часть code
будет отображаться как html, что может вызвать странное поведение (например, так как обозначение freemarker </#list>
автоматически преобразуется в <!--#list-->
).
Но если я сделаю полный шаблон только текстовым, часть text
с тегами <u></u>
также не будет отображаться.
Ожидаемый результат
Я хочу прочитать переменную шаблона с помощью JavaScript/jQuery, а затем проанализировать каждый data-type
с помощью text
как html и code
как текст.
Как я могу пропустить шаблон и сделать это?
Ответы
Ответ 1
Рекомендация
Для анализа HTML в javascript обычно используется объект DOMParser (поддерживается IE10 +).
Как вы сказали, синтаксический анализ не выполняется внутри раздела data-type="code"
, потому что он не знает, как обрабатывать теги </#...>
...
const templ = `<section><div class="row"><div class="col-sm-12"><section data-type="code"><#code></#code></section></div></div><div class="row"><div class="col-sm-12" data-type="container-content"><section data-type="text"><u>Lorem</u> ipsum</section></div></div></section>`;
const parser = new DOMParser();
const doc = parser.parseFromString(templ, "text/html");
console.log(
"Wrongly parsed </#code> tag:\n",
doc.querySelector("[data-type='code']").innerHTML
);
Ответ 2
Существует альтернативный синтаксис, который использует квадратные скобки вместо угловых скобок.
Проверьте, разрешает ли он проблему идентификации вашего тега, не испортив никакую другую функцию.
https://freemarker.apache.org/docs/dgui_misc_alternativesyntax.html
EDIT 1
Чтобы показать исходный код внутри тегов < #code при анализе HTML, вы можете избежать его в своей базе данных (выделите html специальные символы, такие как <, > и & to & lt; & gt; и &). Таким образом, когда он визуализируется, в содержимом кода не создаются теги html, и документ не будет испорчен.
Затем вы можете отобразить все содержимое базы данных напрямую как HTML: текст будет содержать разметку, а код будет текстовым.
Чтобы сделать эту модификацию, вы можете использовать регулярные выражения, чтобы найти то, что заключено в теги < #code > , и заменить эквивалент, экранированный HTML. Точный способ сделать это зависит от языка, который вы будете использовать для задания, так как есть некоторые отличия в RegExes и доступных функциях escape-функций.
EDIT 2
Если вы загружаете контент с помощью AJAX, у вас есть возможность применить замену в javascript, ПОСЛЕ того, как контент был получен с сервера, сохраняя вашу базу данных как есть.
Ответ 3
Вы можете использовать коды кодировки, поэтому он не выполняется перед выводом.
ссылка HTML charset
Они могут редактировать его, поскольку он выглядит нормально и отправляет его вам или серверу. Убедитесь, что вы включили ссылку на кодировку в голове.
<meta charset="UTF-8"> // HTML5
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"> // HTML4
<!-- @CHARSET / No execute -->
<section>
<div class="row">
<div class="col-sm-12">
<section data-type="code">
<#code> <!-- Run this --> </#code>
</section>
</div>
</div>
<div class="row">
<div class="col-sm-12" data-type="container-content">
<section data-type="text">
<u> <!-- Don't run --> </u>
</section>
</div>
</div>
</section>
Ответ 4
Если я не понял это неправильно, вы можете использовать тег <plaintext>
для отображения блока как текст на странице.
<plaintext>
<#code></#code>
</plaintext>
Ответ 5
Как насчет этого?
// https://stackoverflow.com/info/7477/autosizing-textarea-using-prototype
function FitToContent(id, maxHeight)
{
var text = id && id.style ? id : document.getElementById(id);
if (!text)
return;
/* Accounts for rows being deleted, pixel value may need adjusting */
if (text.clientHeight == text.scrollHeight) {
text.style.height = "30px";
}
var adjustedHeight = text.clientHeight;
if (!maxHeight || maxHeight > adjustedHeight)
{
adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
if (maxHeight)
adjustedHeight = Math.min(maxHeight, adjustedHeight);
if (adjustedHeight > text.clientHeight)
text.style.height = adjustedHeight + "px";
}
}
$('textarea').each(function(i,v){
FitToContent($(v)[0], document.documentElement.clientHeight)
});
textarea {
background: transparent;
border: 0;
font-family: 'Times New Roman';
font-size: 1em;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div class="row">
<div class="col-sm-12">
<h4>First code block</h4>
<section data-type="code">
<textarea class='code'><#code>
<h2>FreeMarker Spring MVC Hello World</h2>
<table class="datatable">
<tr>
<th>Make</th><th>Model</th>
</tr>
<#list model["carList"] as car>
<tr>
<td>${car.make}</td>
<td>${car.model}</td>
</tr>
</#list>
</table>
</#code></textarea>
</section>
</div>
</div>
<div class="row">
<div class="col-sm-12" data-type="container-content">
<h4>Regular HTML section</h4>
<section data-type="text">
<u>Lorem</u> ipsum
</section>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<h4>Second code block</h4>
<section data-type="code">
<textarea class='code'><#code>
<table class="datatable">
<tr>
<th>Name</th><th>Email</th>
</tr>
<#list model["personList"] as person>
<tr>
<td>${person.name}</td>
<td>${person.email}</td>
</tr>
</#list>
</table>
</#code></textarea>
</section>
</div>
</div>
</section>