fix: escape/textify the contents of inline and block code (#954)

This commit is contained in:
Daniel Roe 2023-01-11 16:24:13 +00:00 committed by GitHub
parent 24d43699bb
commit f9509f8987
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 1 deletions

View file

@ -53,10 +53,13 @@ export function parseMastodonHTML(
// Handle code blocks // Handle code blocks
html = html html = html
.replace(/>(```|~~~)(\w*)([\s\S]+?)\1/g, (_1, _2, lang: string, raw: string) => { .replace(/>(```|~~~)(\w*)([\s\S]+?)\1/g, (_1, _2, lang: string, raw: string) => {
const code = htmlToText(raw) const code = htmlToText(raw).replace(/</g, '&lt;').replace(/>/g, '&gt;')
const classes = lang ? ` class="language-${lang}"` : '' const classes = lang ? ` class="language-${lang}"` : ''
return `><pre><code${classes}>${code}</code></pre>` return `><pre><code${classes}>${code}</code></pre>`
}) })
.replace(/`([^`\n]*)`/g, (_1, raw) => {
return raw ? `<code>${htmlToText(raw).replace(/</g, '&lt;').replace(/>/g, '&gt;')}</code>` : ''
})
} }
// Always sanitize the raw HTML data *after* it has been modified // Always sanitize the raw HTML data *after* it has been modified

View file

@ -40,6 +40,27 @@ exports[`content-rich > custom emoji 1`] = `
exports[`content-rich > empty 1`] = `""`; exports[`content-rich > empty 1`] = `""`;
exports[`content-rich > handles html within code blocks 1`] = `
"<p>
HTML block code:<br />
<pre lang=\\"html\\">
&lt;span class=&quot;icon--noto icon--noto--1st-place-medal&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;icon--noto icon--noto--2nd-place-medal-medal&quot;&gt;&lt;/span&gt;</pre
>
</p>
"
`;
exports[`content-rich > inline code with link 1`] = `
"<p>
Inline code with link:
<code
>https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal</code
>
</p>
"
`;
exports[`content-rich > link + mention 1`] = ` exports[`content-rich > link + mention 1`] = `
"<p> "<p>
Happy Happy

View file

@ -20,6 +20,16 @@ describe('content-rich', () => {
expect(formatted).toMatchSnapshot() expect(formatted).toMatchSnapshot()
}) })
it('inline code with link', async () => {
const { formatted } = await render('<p>Inline code with link: `<a href="https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal" target="_blank" rel="nofollow noopener noreferrer" class="status-link unhandled-link" title="https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal"><span class="invisible">https://</span><span class="ellipsis">api.iconify.design/noto.css?ic</span><span class="invisible">ons=1st-place-medal,2nd-place-medal</span></a>`</p>')
expect(formatted).toMatchSnapshot()
})
it('handles html within code blocks', async () => {
const { formatted } = await render('<p>HTML block code:<br>```html<br>&lt;span class="icon--noto icon--noto--1st-place-medal"&gt;&lt;/span&gt;<br>&lt;span class="icon--noto icon--noto--2nd-place-medal-medal"&gt;&lt;/span&gt;<br>```</p>')
expect(formatted).toMatchSnapshot()
})
it('custom emoji', async () => { it('custom emoji', async () => {
const { formatted } = await render('Daniel Roe :nuxt:', { const { formatted } = await render('Daniel Roe :nuxt:', {
nuxt: { nuxt: {