diff --git a/composables/content.ts b/composables/content.ts
index a5c3246c..3aa9d502 100644
--- a/composables/content.ts
+++ b/composables/content.ts
@@ -1,7 +1,7 @@
import type { Emoji } from 'masto'
import type { DefaultTreeAdapterMap } from 'parse5'
-import { parseFragment } from 'parse5'
-import type { Component, VNode } from 'vue'
+import { parseFragment, serialize } from 'parse5'
+import type { VNode } from 'vue'
import { Fragment, h, isVNode } from 'vue'
import { RouterLink } from 'vue-router'
import ContentCode from '~/components/content/ContentCode.vue'
@@ -9,10 +9,6 @@ import ContentCode from '~/components/content/ContentCode.vue'
type Node = DefaultTreeAdapterMap['childNode']
type Element = DefaultTreeAdapterMap['element']
-const CUSTOM_BLOCKS: Record Testing code block Testing code block
`
})
- const tree = parseFragment(content)
+ const tree = parseFragment(processed)
+
+ function walk(node: Node) {
+ if ('childNodes' in node)
+ node.childNodes = node.childNodes.flatMap(n => walk(n))
+
+ if (node.nodeName === '#text') {
+ // @ts-expect-error casing
+ const text = node.value as string
+ const converted = text
+ .replace(/\*\*(.*?)\*\*/g, '$1')
+ .replace(/\*(.*?)\*/g, '$1')
+ .replace(/~~(.*?)~~/g, '${code.join('\n')}
$1')
+ .replace(/__(.*?)__/g, '$1')
+ .replace(/`([^`]+?)`/g, '$1
')
+
+ if (converted !== text)
+ return parseFragment(converted).childNodes
+ }
+ return [node]
+ }
+
+ tree.childNodes = tree.childNodes.flatMap(n => walk(n))
+
+ return tree
+}
+
+export function convertMastodonHTML(html: string, customEmojis: Recordimport { useMouse, usePreferredDark } from '@vueuse/core'
+"
+import { useMouse, usePreferredDark } from '@vueuse/core'
// tracks mouse position
const { x, y } = useMouse()
// is the user prefers dark theme
-const isDark = usePreferredDark()
const a = hello
+const a = hello
+
"
`;
diff --git a/tests/__snapshots__/html-parse.test.ts.snap b/tests/__snapshots__/html-parse.test.ts.snap
new file mode 100644
index 00000000..9955b476
--- /dev/null
+++ b/tests/__snapshots__/html-parse.test.ts.snap
@@ -0,0 +1,73 @@
+// Vitest Snapshot v1
+
+exports[`html-parse > code frame 1`] = `
+"Testing code block
+ +import { useMouse, usePreferredDark } from '@vueuse/core'
+
+// tracks mouse position
+const { x, y } = useMouse()
+// is the user prefers dark theme
+const isDark = usePreferredDark()
+
+"
+`;
+
+exports[`html-parse > code frame 2 1`] = `
+"
+ @antfu
+ Testing
+
const a = hello
+
+"
+`;
+
+exports[`html-parse > custom emoji 1`] = `
+"Daniel Roe
+
+"
+`;
+
+exports[`html-parse > empty 1`] = `""`;
+
+exports[`html-parse > inline markdown 1`] = `
+"text code
bold italic
code block
+
+"
+`;
+
+exports[`html-parse > link + mention 1`] = `
+"+ Happy 🤗 we’re now using + @vitest + (migrated from chai+mocha) + https://github.com/ayoayco/astro-reactive-library/pull/203 +
+" +`; diff --git a/tests/html-parse.test.ts b/tests/html-parse.test.ts new file mode 100644 index 00000000..306fbc86 --- /dev/null +++ b/tests/html-parse.test.ts @@ -0,0 +1,66 @@ +import type { Emoji } from 'masto' +import { describe, expect, it } from 'vitest' +import { format } from 'prettier' +import { serialize } from 'parse5' +import { parseMastodonHTML } from '~/composables/content' + +describe('html-parse', () => { + it('empty', async () => { + const { formatted } = await render('') + expect(formatted).toMatchSnapshot() + }) + + it('link + mention', async () => { + // https://fosstodon.org/@ayo/109383002937620723 + const { formatted } = await render('Happy 🤗 we’re now using @vitest (migrated from chai+mocha) https://github.com/ayoayco/astro-reactive-library/pull/203
') + expect(formatted).toMatchSnapshot() + }) + + it('custom emoji', async () => { + const { formatted } = await render('Daniel Roe :nuxt:', { + nuxt: { + shortcode: 'nuxt', + url: 'https://media.mas.to/masto-public/cache/custom_emojis/images/000/288/667/original/c96ba3cb0e0e1eac.png', + staticUrl: 'https://media.mas.to/masto-public/cache/custom_emojis/images/000/288/667/static/c96ba3cb0e0e1eac.png', + visibleInPicker: true, + }, + }) + expect(formatted).toMatchSnapshot() + }) + + it('code frame', async () => { + // https://mas.to/@antfu/109396489827394721 + const { formatted } = await render('Testing code block
```ts
import { useMouse, usePreferredDark } from '@vueuse/core'
// tracks mouse position
const { x, y } = useMouse()
// is the user prefers dark theme
const isDark = usePreferredDark()
```
@antfu Testing
```ts
const a = hello
```
text `code` **bold** *italic*
```js
code block
```