javascript - parser - ¿Cómo evitar que Markdown envuelva el HTML generado en un elemento<p>?
marked npm (4)
¿Sería jQuery una opción? Esto funcionaría en caso de que:
var $text = $(new Showdown.converter().makeHtml( ''*foo*'' ) );
console.log( $text.html() );
Actualización: la recompensa es por una solución que utiliza la biblioteca "marcada".
Este código Markdown:
*foo*
producirá este código HTML:
<p><em>foo</em></p>
Demostración en vivo: https://jsbin.com/luganot/edit?js,console
Sin embargo, ya estoy inyectando el código HTML generado en un contexto en línea, así:
<p> text [inject generated HTML here] text </p>
así que no quiero que el elemento <p>
ajuste al código HTML generado. Solo quiero que los delimitadores *
se conviertan en un elemento <em>
, y así sucesivamente.
¿Hay alguna manera de decirle al convertidor de Markdown que no produzca el envoltorio <p>
? Actualmente, estoy haciendo un .slice(3,-4)
en la cadena HTML generada, que elimina las etiquetas <p>
y </p>
, pero obviamente esta no es una solución que me gustaría mantener. A largo plazo.
Puede omitir la parte de bloqueo de bloques y usar inlineLexer en su lugar.
html = marked.inlineLexer(markdown, [], options);
//example
marked.inlineLexer(''*foo*'', []) // will output ''<em>foo</em>''
Si sigue el estándar de Commonmark , no hay una forma oficial de eliminar elementos no deseados del marcado que de lo contrario se generaría. En 2014 pregunté sobre la posibilidad de un modo en línea , pero eso no generó mucha actividad y nunca lo seguí para hacerlo realidad.
Dicho esto, la solución más sencilla que conozco para desinfectar la reducción es ejecutarla a través de una lista blanca como un paso posterior al procesamiento.
h1-6
etiquetas <p>
probablemente no sea suficiente porque sería relativamente fácil agregar #
caracteres y terminar con etiquetas h1-6
extraviadas, o tener elementos <div>
línea que no están permitidos en los elementos <p>
.
La lista blanca es bastante sencilla en JS, siempre que esté en el contexto de un navegador o utilice una API DOM similar.
Este ejemplo toma el resultado de marked
y genera un fragmento de documento. Los nodos en el fragmento luego se filtran en función de si están expresando contenido (que son los únicos nodos que pueden contener <p>
elementos). Después del filtrado, los nodos resultantes se devuelven para que se puedan usar en el DOM.
const phrasingContent = [
''#text'', ''a'', ''abbr'', ''area'', ''audio'', ''b'', ''bdi'', ''bdo'', ''br'', ''button'',
''canvas'', ''cite'', ''code'', ''data'', ''datalist'', ''del'', ''dfn'', ''em'', ''embed'',
''i'', ''iframe'', ''img'', ''input'', ''ins'', ''kbd'', ''keygen'', ''label'', ''map'', ''mark'',
''math'', ''meter'', ''noscript'', ''object'', ''output'', ''picture'', ''progress'', ''q'',
''ruby'', ''s'', ''samp'', ''script'', ''select'', ''small'', ''span'', ''strong'', ''sub'',
''sup'', ''svg'', ''template'', ''textarea'', ''time'', ''u'', ''var'', ''video'', ''wbr''
]
function sanitize(text) {
const t = document.createElement(''template'')
t.innerHTML = text
whitelist(t.content, phrasingContent)
return t.content
}
function whitelist(parent, names) {
for (const node of parent.childNodes) {
whitelist(node, names)
if (!names.includes(node.nodeName.toLowerCase())) {
unwrap(node)
}
}
}
function unwrap(node) {
const parent = node.parentNode
while (node.firstChild) {
parent.insertBefore(node.firstChild, node)
}
parent.removeChild(node)
}
function empty(node) {
while (node.firstChild) {
node.removeChild(node.firstChild)
}
}
const form = document.querySelector(''form'')
const input = document.querySelector(''textarea'')
const output = document.querySelector(''output'')
form.addEventListener(''submit'', e => {
e.preventDefault()
empty(output)
output.appendChild(sanitize(marked(input.value)))
}, false)
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.6/marked.min.js"></script>
<form>
<p>
<textarea name="input" cols="30" rows="10">*foo*</textarea>
</p>
<button type="submit">Test</button>
</form>
<p> text <output></output> text </p>
Por supuesto, todo esto supone un entorno de navegador, y esa lista blanca puede manejarse después de que la entrada se procesa a través de la biblioteca marked
.
También estaba buscando una solución para esto cuando encontré este hilo SO. No encontré ninguna buena solución todavía aquí, así que he escrito la mía propia.
var markdown = new Showdown.converter().makeHtml( ''*foo*'' );
console.log(markdown.replace(/^<p>|<//p>$/g, ''''));