fix: render code block without language (#276)

This commit is contained in:
三咲智子 Kevin Deng 2022-12-02 10:19:31 +08:00 committed by GitHub
parent 18d5fd4804
commit 0f06653636
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 7 deletions

View file

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
const props = defineProps<{ const props = defineProps<{
code: string code: string
lang: string lang?: string
}>() }>()
const raw = $computed(() => decodeURIComponent(props.code).replace(/&#39;/g, '\'')) const raw = $computed(() => decodeURIComponent(props.code).replace(/&#39;/g, '\''))
@ -13,7 +13,7 @@ const langMap: Record<string, string> = {
} }
const highlighted = computed(() => { const highlighted = computed(() => {
return props.lang ? highlightCode(raw, langMap[props.lang] || props.lang as any) : raw return props.lang ? highlightCode(raw, (langMap[props.lang] || props.lang) as any) : raw
}) })
</script> </script>

View file

@ -38,7 +38,7 @@ function handleCodeBlock(el: Element) {
const codeEl = el.childNodes[0] as Element const codeEl = el.childNodes[0] as Element
const classes = codeEl.attrs.find(i => i.name === 'class')?.value const classes = codeEl.attrs.find(i => i.name === 'class')?.value
const lang = classes?.split(/\s/g).find(i => i.startsWith('language-'))?.replace('language-', '') const lang = classes?.split(/\s/g).find(i => i.startsWith('language-'))?.replace('language-', '')
const code = treeToText(codeEl.childNodes[0]) const code = codeEl.childNodes[0] ? treeToText(codeEl.childNodes[0]) : ''
return h(ContentCode, { lang, code: encodeURIComponent(code) }) return h(ContentCode, { lang, code: encodeURIComponent(code) })
} }
} }
@ -61,11 +61,10 @@ export function parseMastodonHTML(html: string, customEmojis: Record<string, Emo
return `:${name}:` return `:${name}:`
}) })
// handle code blocks // handle code blocks
.replace(/>(```|~~~)([\s\S]+?)\1/g, (_1, _2, raw) => { .replace(/>(```|~~~)(\w*)([\s\S]+?)\1/g, (_1, _2, lang, raw) => {
const plain = htmlToText(raw) const code = htmlToText(raw)
const [lang, ...code] = plain.split('\n')
const classes = lang ? ` class="language-${lang}"` : '' const classes = lang ? ` class="language-${lang}"` : ''
return `><pre><code${classes}>${code.join('\n')}</code></pre>` return `><pre><code${classes}>${code}</code></pre>`
}) })
const tree = parseFragment(processed) const tree = parseFragment(processed)

View file

@ -25,6 +25,22 @@ exports[`content-rich > code frame 2 1`] = `
" "
`; `;
exports[`content-rich > code frame empty 1`] = `
"<p></p>
<pre></pre>
<br />
<p></p>
"
`;
exports[`content-rich > code frame no lang 1`] = `
"<p></p>
<pre>hello world</pre>
<br />no lang
<p></p>
"
`;
exports[`content-rich > custom emoji 1`] = ` exports[`content-rich > custom emoji 1`] = `
"Daniel Roe "Daniel Roe
<img <img

View file

@ -39,6 +39,16 @@ describe('content-rich', () => {
const { formatted } = await render('<p><span class=\"h-card\"><a href=\"https://mas.to/@antfu\" class=\"u-url mention\">@<span>antfu</span></a></span> Testing<br />```ts<br />const a = hello<br />```</p>') const { formatted } = await render('<p><span class=\"h-card\"><a href=\"https://mas.to/@antfu\" class=\"u-url mention\">@<span>antfu</span></a></span> Testing<br />```ts<br />const a = hello<br />```</p>')
expect(formatted).toMatchSnapshot() expect(formatted).toMatchSnapshot()
}) })
it('code frame no lang', async () => {
const { formatted } = await render('<p>```<br />hello world<br />```<br />no lang</p>')
expect(formatted).toMatchSnapshot()
})
it('code frame empty', async () => {
const { formatted } = await render('<p>```<br /><br />```<br /></p>')
expect(formatted).toMatchSnapshot()
})
}) })
async function render(content: string, emojis?: Record<string, Emoji>) { async function render(content: string, emojis?: Record<string, Emoji>) {