javascript - obtener - Ejecute parcialmente el código como html y como texto
llamar archivo javascript desde html (5)
Resumen del problema
Para analizar HTML en javascript, generalmente usa un objeto DOMParser (compatible con IE10 +).
Como usted dijo, el análisis falla dentro de la sección data-type="code"
, porque no sabe cómo manejar las etiquetas </#...>
...
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
);
Encontrando un camino alrededor
Ahora, puede parecer una buena idea intentar y reemplazar rápidamente los caracteres que necesitan ser escapados, pero no lo recomendaría ...
Que yo sepa, no hay manera de "entrar" en el proceso de análisis o pasar una estrategia para ciertos tipos de elementos ...
Yo diría que esto te deja con dos opciones. Ya sea:
- No use la sintaxis no analizable dentro de la sección de códigos, como lo sugirió el usuario Eduardo Poço en su respuesta
o, (mi dirección preferida), trate de
- Modifique la plantilla en sí para dejar de analizar el contenido de las secciones del código todas juntas
Usando una plantilla modificada
¡Hay una etiqueta para "script" como contenido en HTML! Es, como era de esperar, la etiqueta <script>
. Inyectémoslo en nuestra sección de code
:
<section data-type="code">
<script type="text">
<#code></#code>
</script>
</section>
El DOMParser
no tocará esta etiqueta, dejándola exactamente como está:
const templ = ''<section><div class="row"><div class="col-sm-12"><section data-type="code"><script type="text"><#code></#code></'' + ''script></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(
"Now, there''s a <script> tag:/n",
doc.querySelector("[data-type=''code'']").innerHTML
);
Tenga en cuenta que tuve que unir la cadena de la plantilla desde dos partes para asegurarme de que el fragmento de código de stackoverflow no se rompa. ¿Están experimentando un problema similar? : -o
Ahora, todo lo que tenemos que hacer es usar los métodos generales de DOM, incluido innerText
( no innerHTML
) para volver a innerText
el contenido interno del script en la parte visible del DOM:
var templ = ''<section><div class="row"><div class="col-sm-12"><section data-type="code"><script type="text"><#code></#code></'' + ''script></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>`;''
var parser = new DOMParser();
var doc = parser.parseFromString(templ, "text/html");
Array
.from(doc.querySelectorAll(
"[data-type=''code''] > script")
)
.forEach(script => {
const codeTag = document.createElement("code");
codeTag.innerText = script.innerHTML;
script.replaceWith(codeTag);
});
document.getElementById("wrapper").appendChild(doc.body.firstChild);
code { background: #efefef; }
<div id="wrapper"></div>
Introducción
Actualmente estoy creando un creador de plantillas donde los usuarios pueden crear una plantilla para una aplicación. El usuario puede arrastrar y soltar varios bloques, como bloques de texto y bloques de ''código personalizado''. La plantilla será analizada dentro de una aplicación. En este momento, una plantilla podría verse así:
<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>
Entonces, esta plantilla contiene dos elementos (vea el atributo de data-type
): una parte es un código escrito personalizado. Aquí, el usuario escribió un código personalizado, incluido el código de Apache Freemarker. La segunda parte es texto escrito personalizado.
Situación
El código anterior se utilizará de dos maneras diferentes.
- Exactamente este código se usará dentro de una aplicación que usa la plantilla (por eso es por lo que deberían poder escribir el código de Freemarker, porque se analizará).
- En mi sitio web, el usuario debe poder editar esta plantilla. Debido a que el código se almacena en la base de datos como se escribió anteriormente, existe un problema:
Problema
Cuando represento directamente la plantilla en la interfaz web, la parte de text
se procesará correctamente con las etiquetas <u></u>
, pero la parte del code
también se procesará como html, lo que podría causar un comportamiento extraño (como el marcador de acceso gratuito). la notación </#list>
se convierte automáticamente a <!--#list-->
).
Pero, si represento la plantilla completa solo como texto, la parte de text
con las etiquetas <u></u>
tampoco se representará.
Gastos esperados
Quiero leer la variable de plantilla con JavaScript / jQuery y luego analizar cada data-type
con text
como html y con code
como texto.
¿Cómo puedo recorrer la plantilla y hacer esto?
¿Qué pasa con algo como esto?
// https://.com/questions/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>
Hay una sintaxis alternativa que utiliza corchetes en lugar de corchetes angulares.
Compruebe si soluciona su etiqueta identificando el problema sin alterar ninguna otra característica.
https://freemarker.apache.org/docs/dgui_misc_alternativesyntax.html
EDITAR 1
Para mostrar el código fuente dentro de las etiquetas <#code> cuando se analiza el HTML, puede escapar de él en su base de datos (escape html caracteres especiales como <,> y & a & lt; & gt; y & amp;). Por lo tanto, cuando se procesa, no se crearán etiquetas html en el contenido del código y el documento no se desordenará.
Luego, puede procesar todo el contenido de la base de datos directamente como HTML: el texto mantendrá el marcado y el código será el texto.
Para hacer esa modificación, puede usar expresiones regulares para encontrar lo que está encerrado por las etiquetas <#code> y reemplazarlo con el equivalente de escape de HTML. La forma exacta de hacerlo depende del idioma que usará para el trabajo, ya que hay algunas diferencias en RegExes y en las funciones de escape disponibles.
Editar 2
Si está cargando el contenido utilizando AJAX, tiene la posibilidad de aplicar el reemplazo en javascript, DESPUÉS de que el contenido se haya obtenido del servidor, manteniendo su base de datos tal como está.
Podría usar códigos de juego de caracteres, por lo que no se ejecuta antes de enviar. Referencia de conjunto de caracteres HTML
Pueden editarlo, ya que parece normal y enviarlo a usted o al servidor. Asegúrese de incluir su referencia de juego de caracteres en la cabeza.
<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>
Si no lo entendí mal, puede usar la etiqueta <plaintext>
para representar el bloque como texto en la página.
<plaintext>
<#code></#code>
</plaintext>