mirror of
https://github.com/elk-zone/elk.git
synced 2024-11-22 01:15:25 +03:00
feat: support codeblock
This commit is contained in:
parent
4885b165df
commit
0a8841f4f4
13 changed files with 201 additions and 52 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@ dist
|
||||||
.output
|
.output
|
||||||
.nuxt
|
.nuxt
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
public/shiki
|
||||||
|
|
|
@ -18,7 +18,7 @@ export default defineComponent({
|
||||||
return () => h(
|
return () => h(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'rich-content' },
|
{ class: 'rich-content' },
|
||||||
contentToVNode(props.content, undefined, emojiObject),
|
contentToVNode(props.content, emojiObject),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
22
components/content/ContentCode.vue
Normal file
22
components/content/ContentCode.vue
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
code: string
|
||||||
|
lang: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const raw = computed(() => decodeURIComponent(props.code).replace(/'/g, '\''))
|
||||||
|
|
||||||
|
const langMap: Record<string, string> = {
|
||||||
|
js: 'javascript',
|
||||||
|
ts: 'typescript',
|
||||||
|
vue: 'html',
|
||||||
|
}
|
||||||
|
|
||||||
|
const hightlighted = computed(() => {
|
||||||
|
return highlightCode(raw.value, langMap[props.lang] || props.lang as any)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<pre class="code-block" v-html="hightlighted" />
|
||||||
|
</template>
|
|
@ -1,14 +1,19 @@
|
||||||
import type { Emoji } from 'masto'
|
import type { Emoji } from 'masto'
|
||||||
import type { DefaultTreeAdapterMap } from 'parse5'
|
import type { DefaultTreeAdapterMap } from 'parse5'
|
||||||
import { parseFragment } from 'parse5'
|
import { parseFragment } from 'parse5'
|
||||||
import type { VNode } from 'vue'
|
import type { Component, VNode } from 'vue'
|
||||||
import { Fragment, h } from 'vue'
|
import { Fragment, h, isVNode } from 'vue'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
|
import ContentCode from '~/components/content/ContentCode.vue'
|
||||||
|
|
||||||
type Node = DefaultTreeAdapterMap['childNode']
|
type Node = DefaultTreeAdapterMap['childNode']
|
||||||
type Element = DefaultTreeAdapterMap['element']
|
type Element = DefaultTreeAdapterMap['element']
|
||||||
|
|
||||||
export function defaultHandle(el: Element) {
|
const CUSTOM_BLOCKS: Record<string, Component> = {
|
||||||
|
'custom-code': ContentCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMention(el: Element) {
|
||||||
// Redirect mentions to the user page
|
// Redirect mentions to the user page
|
||||||
if (el.tagName === 'a' && el.attrs.find(i => i.name === 'class' && i.value.includes('mention'))) {
|
if (el.tagName === 'a' && el.attrs.find(i => i.name === 'class' && i.value.includes('mention'))) {
|
||||||
const href = el.attrs.find(i => i.name === 'href')
|
const href = el.attrs.find(i => i.name === 'href')
|
||||||
|
@ -26,36 +31,58 @@ export function defaultHandle(el: Element) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return el
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBlocks(el: Element) {
|
||||||
|
if (el.tagName in CUSTOM_BLOCKS) {
|
||||||
|
const block = CUSTOM_BLOCKS[el.tagName]
|
||||||
|
const attrs = Object.fromEntries(el.attrs.map(i => [i.name, i.value]))
|
||||||
|
return h(block, attrs, () => el.childNodes.map(treeToVNode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleNode(el: Element) {
|
||||||
|
return handleBlocks(el) || handleMention(el) || el
|
||||||
}
|
}
|
||||||
|
|
||||||
export function contentToVNode(
|
export function contentToVNode(
|
||||||
content: string,
|
content: string,
|
||||||
handle: (node: Element) => Element | undefined | null | void = defaultHandle,
|
|
||||||
customEmojis: Record<string, Emoji> = {},
|
customEmojis: Record<string, Emoji> = {},
|
||||||
): VNode {
|
): VNode {
|
||||||
content = content.trim().replace(/:([\w-]+?):/g, (_, name) => {
|
content = content
|
||||||
const emoji = customEmojis[name]
|
.trim()
|
||||||
if (emoji)
|
// handle custom emojis
|
||||||
return `<img src="${emoji.url}" alt="${name}" class="custom-emoji" />`
|
.replace(/:([\w-]+?):/g, (_, name) => {
|
||||||
return `:${name}:`
|
const emoji = customEmojis[name]
|
||||||
})
|
if (emoji)
|
||||||
|
return `<img src="${emoji.url}" alt="${name}" class="custom-emoji" />`
|
||||||
|
return `:${name}:`
|
||||||
|
})
|
||||||
|
// handle codeblocks
|
||||||
|
.replace(/<p>(```|~~~)([\s\S]+?)\1(\s|<br\s?\/?>)*<\/p>/g, (_1, _2, raw) => {
|
||||||
|
const plain = htmlToText(`<p>${raw}</p>`).trim()
|
||||||
|
const [lang, ...rest] = plain.split(/\n/)
|
||||||
|
return `<custom-code lang="${lang || ''}" code="${encodeURIComponent(rest.join('\n'))}" />`
|
||||||
|
})
|
||||||
|
|
||||||
const tree = parseFragment(content)
|
const tree = parseFragment(content)
|
||||||
return h(Fragment, tree.childNodes.map(n => treeToVNode(n, handle)))
|
return h(Fragment, tree.childNodes.map(n => treeToVNode(n)))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function treeToVNode(
|
export function treeToVNode(
|
||||||
input: Node,
|
input: Node,
|
||||||
handle: (node: Element) => Element | undefined | null | void = defaultHandle,
|
|
||||||
): VNode | string | null {
|
): VNode | string | null {
|
||||||
if (input.nodeName === '#text')
|
if (input.nodeName === '#text')
|
||||||
// @ts-expect-error casing
|
// @ts-expect-error casing
|
||||||
return input.value
|
return input.value
|
||||||
|
|
||||||
if ('childNodes' in input) {
|
if ('childNodes' in input) {
|
||||||
const node = handle(input)
|
const node = handleNode(input)
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return null
|
return null
|
||||||
|
if (isVNode(node))
|
||||||
|
return node
|
||||||
|
|
||||||
const attrs = Object.fromEntries(node.attrs.map(i => [i.name, i.value]))
|
const attrs = Object.fromEntries(node.attrs.map(i => [i.name, i.value]))
|
||||||
if (node.nodeName === 'a' && (attrs.href?.startsWith('/') || attrs.href?.startsWith('.'))) {
|
if (node.nodeName === 'a' && (attrs.href?.startsWith('/') || attrs.href?.startsWith('.'))) {
|
||||||
|
@ -65,14 +92,38 @@ export function treeToVNode(
|
||||||
return h(
|
return h(
|
||||||
RouterLink as any,
|
RouterLink as any,
|
||||||
attrs,
|
attrs,
|
||||||
() => node.childNodes.map(n => treeToVNode(n, handle)),
|
() => node.childNodes.map(treeToVNode),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return h(
|
return h(
|
||||||
node.nodeName,
|
node.nodeName,
|
||||||
attrs,
|
attrs,
|
||||||
node.childNodes.map(n => treeToVNode(n, handle)),
|
node.childNodes.map(treeToVNode),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function htmlToText(html: string) {
|
||||||
|
const tree = parseFragment(html)
|
||||||
|
return tree.childNodes.map(n => treeToText(n)).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
function treeToText(input: Node): string {
|
||||||
|
let pre = ''
|
||||||
|
|
||||||
|
if (input.nodeName === '#text')
|
||||||
|
// @ts-expect-error casing
|
||||||
|
return input.value
|
||||||
|
|
||||||
|
if (input.nodeName === 'br')
|
||||||
|
return '\n'
|
||||||
|
|
||||||
|
if (input.nodeName === 'p')
|
||||||
|
pre = '\n'
|
||||||
|
|
||||||
|
if ('childNodes' in input)
|
||||||
|
return pre + input.childNodes.map(n => treeToText(n)).join('')
|
||||||
|
|
||||||
|
return pre
|
||||||
|
}
|
||||||
|
|
37
composables/shiki.ts
Normal file
37
composables/shiki.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import type { Highlighter, Lang } from 'shiki'
|
||||||
|
|
||||||
|
export const shiki = ref<Highlighter>()
|
||||||
|
|
||||||
|
const registeredLang = ref(new Map<string, boolean>())
|
||||||
|
let shikiImport: Promise<void> | undefined
|
||||||
|
|
||||||
|
export function highlightCode(code: string, lang: Lang) {
|
||||||
|
if (!shikiImport) {
|
||||||
|
shikiImport = import('shiki')
|
||||||
|
.then(async (r) => {
|
||||||
|
r.setCDN('/shiki/')
|
||||||
|
shiki.value = await r.getHighlighter({
|
||||||
|
themes: [
|
||||||
|
'vitesse-dark',
|
||||||
|
'vitesse-light',
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shiki.value)
|
||||||
|
return code
|
||||||
|
|
||||||
|
if (!registeredLang.value.get(lang)) {
|
||||||
|
shiki.value.loadLanguage(lang)
|
||||||
|
.then(() => {
|
||||||
|
registeredLang.value.set(lang, true)
|
||||||
|
})
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
return shiki.value.codeToHtml(code, {
|
||||||
|
lang,
|
||||||
|
theme: isDark.value ? 'vitesse-dark' : 'vitesse-light',
|
||||||
|
})
|
||||||
|
}
|
|
@ -23,3 +23,4 @@ export function getDataUrlFromArr(arr: Uint8ClampedArray, w: number, h: number)
|
||||||
export function emojisArrayToObject(emojis: Emoji[]) {
|
export function emojisArrayToObject(emojis: Emoji[]) {
|
||||||
return Object.fromEntries(emojis.map(i => [i.shortcode, i]))
|
return Object.fromEntries(emojis.map(i => [i.shortcode, i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@ export default defineNuxtConfig({
|
||||||
},
|
},
|
||||||
vite: {
|
vite: {
|
||||||
define: {
|
define: {
|
||||||
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
|
'__BUILD_TIME__': JSON.stringify(new Date().toISOString()),
|
||||||
|
'process.env.VSCODE_TEXTMATE_DEBUG': 'false',
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
target: 'esnext',
|
target: 'esnext',
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
postcss: {
|
postcss: {
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
"start": "node .output/server/index.mjs",
|
"start": "node .output/server/index.mjs",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"postinstall": "nuxi prepare",
|
"postinstall": "nuxi prepare",
|
||||||
|
"prepare": "esno scripts/prepare.ts",
|
||||||
"generate": "nuxi generate"
|
"generate": "nuxi generate"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
"@iconify-json/twemoji": "^1.1.5",
|
"@iconify-json/twemoji": "^1.1.5",
|
||||||
"@pinia/nuxt": "^0.4.3",
|
"@pinia/nuxt": "^0.4.3",
|
||||||
"@types/fs-extra": "^9.0.13",
|
"@types/fs-extra": "^9.0.13",
|
||||||
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/sanitize-html": "^2.6.2",
|
"@types/sanitize-html": "^2.6.2",
|
||||||
"@types/wicg-file-system-access": "^2020.9.5",
|
"@types/wicg-file-system-access": "^2020.9.5",
|
||||||
"@unocss/nuxt": "^0.46.5",
|
"@unocss/nuxt": "^0.46.5",
|
||||||
|
@ -28,6 +30,7 @@
|
||||||
"esno": "^0.16.3",
|
"esno": "^0.16.3",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"fs-extra": "^10.1.0",
|
"fs-extra": "^10.1.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
"masto": "^4.6.6",
|
"masto": "^4.6.6",
|
||||||
"nuxt": "^3.0.0",
|
"nuxt": "^3.0.0",
|
||||||
"parse5": "^7.1.1",
|
"parse5": "^7.1.1",
|
||||||
|
@ -35,6 +38,8 @@
|
||||||
"postcss-nested": "^6.0.0",
|
"postcss-nested": "^6.0.0",
|
||||||
"rollup-plugin-node-polyfills": "^0.2.1",
|
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||||
"sanitize-html": "^2.7.3",
|
"sanitize-html": "^2.7.3",
|
||||||
|
"shiki": "^0.11.1",
|
||||||
|
"theme-vitesse": "^0.6.0",
|
||||||
"typescript": "^4.9.3",
|
"typescript": "^4.9.3",
|
||||||
"ufo": "^1.0.0"
|
"ufo": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
lockfileVersion: 5.4
|
lockfileVersion: 5.4
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
debug: 4.3.4
|
||||||
|
|
||||||
specifiers:
|
specifiers:
|
||||||
'@antfu/eslint-config': ^0.30.1
|
'@antfu/eslint-config': ^0.30.1
|
||||||
'@iconify-json/carbon': ^1.1.10
|
'@iconify-json/carbon': ^1.1.10
|
||||||
|
@ -8,6 +11,7 @@ specifiers:
|
||||||
'@iconify-json/twemoji': ^1.1.5
|
'@iconify-json/twemoji': ^1.1.5
|
||||||
'@pinia/nuxt': ^0.4.3
|
'@pinia/nuxt': ^0.4.3
|
||||||
'@types/fs-extra': ^9.0.13
|
'@types/fs-extra': ^9.0.13
|
||||||
|
'@types/js-yaml': ^4.0.5
|
||||||
'@types/sanitize-html': ^2.6.2
|
'@types/sanitize-html': ^2.6.2
|
||||||
'@types/wicg-file-system-access': ^2020.9.5
|
'@types/wicg-file-system-access': ^2020.9.5
|
||||||
'@unocss/nuxt': ^0.46.5
|
'@unocss/nuxt': ^0.46.5
|
||||||
|
@ -18,6 +22,7 @@ specifiers:
|
||||||
esno: ^0.16.3
|
esno: ^0.16.3
|
||||||
form-data: ^4.0.0
|
form-data: ^4.0.0
|
||||||
fs-extra: ^10.1.0
|
fs-extra: ^10.1.0
|
||||||
|
js-yaml: ^4.1.0
|
||||||
masto: ^4.6.6
|
masto: ^4.6.6
|
||||||
nuxt: ^3.0.0
|
nuxt: ^3.0.0
|
||||||
parse5: ^7.1.1
|
parse5: ^7.1.1
|
||||||
|
@ -25,6 +30,8 @@ specifiers:
|
||||||
postcss-nested: ^6.0.0
|
postcss-nested: ^6.0.0
|
||||||
rollup-plugin-node-polyfills: ^0.2.1
|
rollup-plugin-node-polyfills: ^0.2.1
|
||||||
sanitize-html: ^2.7.3
|
sanitize-html: ^2.7.3
|
||||||
|
shiki: ^0.11.1
|
||||||
|
theme-vitesse: ^0.6.0
|
||||||
typescript: ^4.9.3
|
typescript: ^4.9.3
|
||||||
ufo: ^1.0.0
|
ufo: ^1.0.0
|
||||||
|
|
||||||
|
@ -36,6 +43,7 @@ devDependencies:
|
||||||
'@iconify-json/twemoji': 1.1.5
|
'@iconify-json/twemoji': 1.1.5
|
||||||
'@pinia/nuxt': 0.4.3_typescript@4.9.3
|
'@pinia/nuxt': 0.4.3_typescript@4.9.3
|
||||||
'@types/fs-extra': 9.0.13
|
'@types/fs-extra': 9.0.13
|
||||||
|
'@types/js-yaml': 4.0.5
|
||||||
'@types/sanitize-html': 2.6.2
|
'@types/sanitize-html': 2.6.2
|
||||||
'@types/wicg-file-system-access': 2020.9.5
|
'@types/wicg-file-system-access': 2020.9.5
|
||||||
'@unocss/nuxt': 0.46.5
|
'@unocss/nuxt': 0.46.5
|
||||||
|
@ -46,6 +54,7 @@ devDependencies:
|
||||||
esno: 0.16.3
|
esno: 0.16.3
|
||||||
form-data: 4.0.0
|
form-data: 4.0.0
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
|
js-yaml: 4.1.0
|
||||||
masto: 4.6.6
|
masto: 4.6.6
|
||||||
nuxt: 3.0.0_e3uo4sehh4zr4i6m57mkkxxv7y
|
nuxt: 3.0.0_e3uo4sehh4zr4i6m57mkkxxv7y
|
||||||
parse5: 7.1.1
|
parse5: 7.1.1
|
||||||
|
@ -53,6 +62,8 @@ devDependencies:
|
||||||
postcss-nested: 6.0.0
|
postcss-nested: 6.0.0
|
||||||
rollup-plugin-node-polyfills: 0.2.1
|
rollup-plugin-node-polyfills: 0.2.1
|
||||||
sanitize-html: 2.7.3
|
sanitize-html: 2.7.3
|
||||||
|
shiki: 0.11.1
|
||||||
|
theme-vitesse: 0.6.0
|
||||||
typescript: 4.9.3
|
typescript: 4.9.3
|
||||||
ufo: 1.0.0
|
ufo: 1.0.0
|
||||||
|
|
||||||
|
@ -1255,6 +1266,10 @@ packages:
|
||||||
'@types/node': 18.7.23
|
'@types/node': 18.7.23
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/js-yaml/4.0.5:
|
||||||
|
resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/json-schema/7.0.11:
|
/@types/json-schema/7.0.11:
|
||||||
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -2883,28 +2898,6 @@ packages:
|
||||||
engines: {node: '>= 12'}
|
engines: {node: '>= 12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/debug/2.6.9:
|
|
||||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
|
||||||
peerDependencies:
|
|
||||||
supports-color: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
supports-color:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
ms: 2.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/debug/3.2.7:
|
|
||||||
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
|
||||||
peerDependencies:
|
|
||||||
supports-color: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
supports-color:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
ms: 2.1.3
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/debug/4.3.4:
|
/debug/4.3.4:
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
|
@ -3432,7 +3425,7 @@ packages:
|
||||||
/eslint-import-resolver-node/0.3.6:
|
/eslint-import-resolver-node/0.3.6:
|
||||||
resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
|
resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 4.3.4
|
||||||
resolve: 1.22.1
|
resolve: 1.22.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -3460,7 +3453,7 @@ packages:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.42.1_e3uo4sehh4zr4i6m57mkkxxv7y
|
'@typescript-eslint/parser': 5.42.1_e3uo4sehh4zr4i6m57mkkxxv7y
|
||||||
debug: 3.2.7
|
debug: 4.3.4
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-import-resolver-node: 0.3.6
|
eslint-import-resolver-node: 0.3.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -3518,7 +3511,7 @@ packages:
|
||||||
'@typescript-eslint/parser': 5.42.1_e3uo4sehh4zr4i6m57mkkxxv7y
|
'@typescript-eslint/parser': 5.42.1_e3uo4sehh4zr4i6m57mkkxxv7y
|
||||||
array-includes: 3.1.5
|
array-includes: 3.1.5
|
||||||
array.prototype.flat: 1.3.0
|
array.prototype.flat: 1.3.0
|
||||||
debug: 2.6.9
|
debug: 4.3.4
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-import-resolver-node: 0.3.6
|
eslint-import-resolver-node: 0.3.6
|
||||||
|
@ -5160,10 +5153,6 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/ms/2.0.0:
|
|
||||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ms/2.1.2:
|
/ms/2.1.2:
|
||||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -6497,7 +6486,7 @@ packages:
|
||||||
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
|
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 2.6.9
|
debug: 4.3.4
|
||||||
depd: 2.0.0
|
depd: 2.0.0
|
||||||
destroy: 1.2.0
|
destroy: 1.2.0
|
||||||
encodeurl: 1.0.2
|
encodeurl: 1.0.2
|
||||||
|
@ -6566,6 +6555,14 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/shiki/0.11.1:
|
||||||
|
resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==}
|
||||||
|
dependencies:
|
||||||
|
jsonc-parser: 3.2.0
|
||||||
|
vscode-oniguruma: 1.6.2
|
||||||
|
vscode-textmate: 6.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/side-channel/1.0.4:
|
/side-channel/1.0.4:
|
||||||
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
|
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6882,6 +6879,11 @@ packages:
|
||||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/theme-vitesse/0.6.0:
|
||||||
|
resolution: {integrity: sha512-/XEZFGXLTK/AlWSe9t+NIXB1tP3yqdzugcSJJ2Fg0KYM1PcoL/zWs5AuaEcCFt1pfi/9Og++tzOdiU2aKf/+Xw==}
|
||||||
|
engines: {vscode: ^1.43.0}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/through/2.3.8:
|
/through/2.3.8:
|
||||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -7502,6 +7504,14 @@ packages:
|
||||||
vscode-languageserver-protocol: 3.16.0
|
vscode-languageserver-protocol: 3.16.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vscode-oniguruma/1.6.2:
|
||||||
|
resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/vscode-textmate/6.0.0:
|
||||||
|
resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vscode-uri/3.0.6:
|
/vscode-uri/3.0.6:
|
||||||
resolution: {integrity: sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==}
|
resolution: {integrity: sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
10
scripts/prepare.ts
Normal file
10
scripts/prepare.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { copy } from 'fs-extra'
|
||||||
|
|
||||||
|
const dereference = process.platform === 'win32' ? true : undefined
|
||||||
|
|
||||||
|
await copy('node_modules/shiki/', 'public/shiki/', {
|
||||||
|
dereference,
|
||||||
|
filter: src => src === 'node_modules/shiki/' || src.includes('languages') || src.includes('dist'),
|
||||||
|
})
|
||||||
|
await copy('node_modules/theme-vitesse/themes', 'public/shiki/themes', { dereference })
|
||||||
|
await copy('node_modules/theme-vitesse/themes', 'node_modules/shiki/themes', { overwrite: true, dereference })
|
|
@ -1,5 +1,5 @@
|
||||||
* {
|
* {
|
||||||
scrollbar-color: #5555 var(--c-border);
|
scrollbar-color: #8885 var(--c-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
@ -16,12 +16,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: #555;
|
background: #8885;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
background: #666;
|
background: #8886;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force vertical scrollbar to be always visible to avoid layout shift while loading the content */
|
/* Force vertical scrollbar to be always visible to avoid layout shift while loading the content */
|
||||||
|
@ -52,4 +52,12 @@ html {
|
||||||
p {
|
p {
|
||||||
--at-apply: my-2;
|
--at-apply: my-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
--at-apply: bg-code text-0.9rem p3 rounded overflow-auto leading-1.6em;
|
||||||
|
|
||||||
|
.shiki {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
--c-border: #88888820;
|
--c-border: #88888820;
|
||||||
--c-bg-base: #fff;
|
--c-bg-base: #fff;
|
||||||
--c-bg-active: #f6f6f6;
|
--c-bg-active: #f6f6f6;
|
||||||
|
--c-bg-code: #00000006;
|
||||||
--c-text-base: #222;
|
--c-text-base: #222;
|
||||||
--c-text-secondary: #888;
|
--c-text-secondary: #888;
|
||||||
}
|
}
|
||||||
|
@ -11,5 +12,6 @@
|
||||||
.dark {
|
.dark {
|
||||||
--c-bg-base: #111;
|
--c-bg-base: #111;
|
||||||
--c-bg-active: #151515;
|
--c-bg-active: #151515;
|
||||||
|
--c-bg-code: #ffffff06;
|
||||||
--c-text-base: #fff;
|
--c-text-base: #fff;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ export default defineConfig({
|
||||||
'border-base': 'border-$c-border',
|
'border-base': 'border-$c-border',
|
||||||
'bg-base': 'bg-$c-bg-base',
|
'bg-base': 'bg-$c-bg-base',
|
||||||
'bg-active': 'bg-$c-bg-active',
|
'bg-active': 'bg-$c-bg-active',
|
||||||
|
'bg-code': 'bg-$c-bg-code',
|
||||||
'text-base': 'text-$c-text-base',
|
'text-base': 'text-$c-text-base',
|
||||||
'text-secondary': 'text-$c-text-secondary',
|
'text-secondary': 'text-$c-text-secondary',
|
||||||
'interact-disabled': 'disabled:opacity-50 disabled:pointer-events-none disabled:saturate-0',
|
'interact-disabled': 'disabled:opacity-50 disabled:pointer-events-none disabled:saturate-0',
|
||||||
|
|
Loading…
Reference in a new issue