refactor: move shiki package, split rsc and rcc boundary component and dynamic import shiki resource (#1820)
* refactor: move shiki package, split rsc and rcc boundary component Signed-off-by: Innei <i@innei.in> * chore: cleanup Signed-off-by: Innei <i@innei.in> * fix: typing Signed-off-by: Innei <i@innei.in> * fix: deps Signed-off-by: Innei <i@innei.in> * fix: import Signed-off-by: Innei <i@innei.in> * fix: patch package Signed-off-by: Innei <i@innei.in> * fix: tw class Signed-off-by: Innei <i@innei.in> --------- Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
7391642cc0
commit
abc6a8d832
|
|
@ -59,7 +59,6 @@
|
||||||
"@monaco-editor/react": "4.6.0",
|
"@monaco-editor/react": "4.6.0",
|
||||||
"@popperjs/core": "2.11.8",
|
"@popperjs/core": "2.11.8",
|
||||||
"@prisma/client": "5.13.0",
|
"@prisma/client": "5.13.0",
|
||||||
"@shikijs/rehype": "^1.5.1",
|
|
||||||
"@shikijs/transformers": "^1.5.1",
|
"@shikijs/transformers": "^1.5.1",
|
||||||
"@supercharge/request-ip": "1.2.0",
|
"@supercharge/request-ip": "1.2.0",
|
||||||
"@tanstack/react-query": "4.36.1",
|
"@tanstack/react-query": "4.36.1",
|
||||||
|
|
@ -67,12 +66,14 @@
|
||||||
"@urql/core": "5.0.3",
|
"@urql/core": "5.0.3",
|
||||||
"@vercel/otel": "1.8.2",
|
"@vercel/otel": "1.8.2",
|
||||||
"@wagmi/core": "1",
|
"@wagmi/core": "1",
|
||||||
|
"@xlog/shiki": "link:./packages/shiki",
|
||||||
"ahooks": "3.7.11",
|
"ahooks": "3.7.11",
|
||||||
"aplayer": "1.10.1",
|
"aplayer": "1.10.1",
|
||||||
"async-lock": "1.4.1",
|
"async-lock": "1.4.1",
|
||||||
"canvas-confetti": "1.9.3",
|
"canvas-confetti": "1.9.3",
|
||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"chroma-js": "2.4.2",
|
"chroma-js": "2.4.2",
|
||||||
|
"client-only": "0.0.1",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
"crossbell": "1.11.9",
|
"crossbell": "1.11.9",
|
||||||
"dayjs": "1.11.11",
|
"dayjs": "1.11.11",
|
||||||
|
|
@ -143,6 +144,7 @@
|
||||||
"remove-markdown": "0.5.0",
|
"remove-markdown": "0.5.0",
|
||||||
"rss-parser": "3.13.0",
|
"rss-parser": "3.13.0",
|
||||||
"serialize-javascript": "6.0.2",
|
"serialize-javascript": "6.0.2",
|
||||||
|
"server-only": "0.0.1",
|
||||||
"sharp": "0.32.6",
|
"sharp": "0.32.6",
|
||||||
"shiki": "^1.5.1",
|
"shiki": "^1.5.1",
|
||||||
"sortablejs": "1.15.2",
|
"sortablejs": "1.15.2",
|
||||||
|
|
@ -212,6 +214,9 @@
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@wagmi/core": "$@wagmi/core",
|
"@wagmi/core": "$@wagmi/core",
|
||||||
"open-graph-scraper>undici": "6.6.2"
|
"open-graph-scraper>undici": "6.6.2"
|
||||||
|
},
|
||||||
|
"patchedDependencies": {
|
||||||
|
"tailwindcss-variable-colors@0.0.2": "patches/tailwindcss-variable-colors@0.0.2.patch"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "@xlog/shiki",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"react-server": "./shiki.server.tsx",
|
||||||
|
"default": "./shiki.client.tsx"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import type { ShikiTransformer } from "shiki"
|
||||||
|
|
||||||
|
import {
|
||||||
|
transformerMetaHighlight,
|
||||||
|
transformerNotationDiff,
|
||||||
|
transformerNotationHighlight,
|
||||||
|
} from "@shikijs/transformers"
|
||||||
|
|
||||||
|
export const shikiTransformers: ShikiTransformer[] = [
|
||||||
|
transformerMetaHighlight(),
|
||||||
|
transformerNotationDiff(),
|
||||||
|
transformerNotationHighlight(),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Suspense, use, useMemo, useRef, type FC } from "react"
|
||||||
|
import {
|
||||||
|
bundledLanguages,
|
||||||
|
bundledThemes,
|
||||||
|
getHighlighter,
|
||||||
|
type BundledLanguage,
|
||||||
|
type BundledTheme,
|
||||||
|
type DynamicImportLanguageRegistration,
|
||||||
|
type DynamicImportThemeRegistration,
|
||||||
|
type Highlighter,
|
||||||
|
type HighlighterCore,
|
||||||
|
} from "shiki"
|
||||||
|
|
||||||
|
import { shikiTransformers } from "./shared"
|
||||||
|
import type { ShikiCodeProps } from "./types"
|
||||||
|
|
||||||
|
let highlighter: Highlighter | undefined
|
||||||
|
export const createHighlighter = async () => {
|
||||||
|
if (!highlighter) {
|
||||||
|
highlighter = await getHighlighter({
|
||||||
|
themes: Object.keys(bundledThemes),
|
||||||
|
langs: Object.keys(bundledLanguages),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return highlighter
|
||||||
|
}
|
||||||
|
|
||||||
|
let highlighterCore: HighlighterCore | null = null
|
||||||
|
const codeHighlighterPromise = (async () => {
|
||||||
|
if (highlighterCore) return highlighterCore
|
||||||
|
const [{ getHighlighterCore }, getWasm] = await Promise.all([
|
||||||
|
import("shiki/core"),
|
||||||
|
import("shiki/wasm").then((m) => m.default),
|
||||||
|
])
|
||||||
|
|
||||||
|
const core = await getHighlighterCore({
|
||||||
|
themes: [
|
||||||
|
import("shiki/themes/github-light.mjs"),
|
||||||
|
import("shiki/themes/github-dark.mjs"),
|
||||||
|
],
|
||||||
|
langs: [],
|
||||||
|
loadWasm: getWasm,
|
||||||
|
})
|
||||||
|
|
||||||
|
highlighterCore = core
|
||||||
|
return core
|
||||||
|
})()
|
||||||
|
|
||||||
|
export const ShikiRender: FC<ShikiCodeProps> = (props) => {
|
||||||
|
return (
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<pre>
|
||||||
|
<code>{props.code}</code>
|
||||||
|
</pre>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ShikiRenderInternal {...props} />
|
||||||
|
</Suspense>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let langModule: Record<
|
||||||
|
BundledLanguage,
|
||||||
|
DynamicImportLanguageRegistration
|
||||||
|
> | null = null
|
||||||
|
let themeModule: Record<BundledTheme, DynamicImportThemeRegistration> | null =
|
||||||
|
null
|
||||||
|
|
||||||
|
const ShikiRenderInternal: FC<ShikiCodeProps> = ({
|
||||||
|
code,
|
||||||
|
codeTheme = {
|
||||||
|
light: "github-light-default",
|
||||||
|
dark: "github-dark-default",
|
||||||
|
},
|
||||||
|
language,
|
||||||
|
}) => {
|
||||||
|
const shiki = use(codeHighlighterPromise)
|
||||||
|
const loadThemesRef = useRef([] as string[])
|
||||||
|
const loadLanguagesRef = useRef([] as string[])
|
||||||
|
|
||||||
|
use(
|
||||||
|
useMemo(() => {
|
||||||
|
async function register() {
|
||||||
|
if (!language || !codeTheme) return
|
||||||
|
|
||||||
|
async function loadShikiLanguage(
|
||||||
|
language: string,
|
||||||
|
languageModule: any,
|
||||||
|
) {
|
||||||
|
if (!shiki) return
|
||||||
|
if (!shiki.getLoadedLanguages().includes(language)) {
|
||||||
|
await shiki.loadLanguage(await languageModule())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function loadShikiTheme(theme: string, themeModule: any) {
|
||||||
|
if (!shiki) return
|
||||||
|
if (!shiki.getLoadedThemes().includes(theme)) {
|
||||||
|
await shiki.loadTheme(await themeModule())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [{ bundledLanguages }, { bundledThemes }] =
|
||||||
|
langModule && themeModule
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
bundledLanguages: langModule,
|
||||||
|
},
|
||||||
|
{ bundledThemes: themeModule },
|
||||||
|
]
|
||||||
|
: await Promise.all([import("shiki/langs"), import("shiki/themes")])
|
||||||
|
|
||||||
|
langModule = bundledLanguages
|
||||||
|
themeModule = bundledThemes
|
||||||
|
|
||||||
|
if (
|
||||||
|
language &&
|
||||||
|
loadLanguagesRef.current.includes(language) &&
|
||||||
|
codeTheme &&
|
||||||
|
loadThemesRef.current.includes(codeTheme)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
return Promise.all([
|
||||||
|
(async () => {
|
||||||
|
if (language) {
|
||||||
|
const importFn = (bundledLanguages as any)[language]
|
||||||
|
if (!importFn) return
|
||||||
|
await loadShikiLanguage(language || "", importFn)
|
||||||
|
loadLanguagesRef.current.push(language)
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
(async () => {
|
||||||
|
if (codeTheme) {
|
||||||
|
const themes = [codeTheme.light, codeTheme.dark]
|
||||||
|
return themes.map(async (theme) => {
|
||||||
|
const importFn = (bundledThemes as any)[theme]
|
||||||
|
if (!importFn) return
|
||||||
|
await loadShikiTheme(theme || "", importFn)
|
||||||
|
loadThemesRef.current.push(theme)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
return register()
|
||||||
|
}, [codeTheme, language, shiki]),
|
||||||
|
)
|
||||||
|
|
||||||
|
const rendered = useMemo(() => {
|
||||||
|
try {
|
||||||
|
return shiki.codeToHtml(code, {
|
||||||
|
lang: language!,
|
||||||
|
themes: codeTheme,
|
||||||
|
transformers: shikiTransformers,
|
||||||
|
})
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}, [shiki, code, language, codeTheme])
|
||||||
|
|
||||||
|
if (!rendered)
|
||||||
|
return (
|
||||||
|
<pre>
|
||||||
|
<code>{code}</code>
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
return <div dangerouslySetInnerHTML={{ __html: rendered }} />
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import type { FC } from "react"
|
||||||
|
import {
|
||||||
|
bundledLanguages,
|
||||||
|
bundledThemes,
|
||||||
|
getHighlighter,
|
||||||
|
type Highlighter,
|
||||||
|
} from "shiki"
|
||||||
|
|
||||||
|
import { shikiTransformers } from "./shared"
|
||||||
|
import type { ShikiCodeProps } from "./types"
|
||||||
|
|
||||||
|
export const ShikiRender: FC<ShikiCodeProps> = async ({
|
||||||
|
code,
|
||||||
|
codeTheme,
|
||||||
|
language,
|
||||||
|
}) => {
|
||||||
|
const highlighter = await createHighlighter()
|
||||||
|
|
||||||
|
const rendered = highlighter.codeToHtml(code, {
|
||||||
|
lang: language || "text",
|
||||||
|
themes: codeTheme || {
|
||||||
|
light: "github-light-default",
|
||||||
|
dark: "github-dark-default",
|
||||||
|
},
|
||||||
|
transformers: shikiTransformers,
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div dangerouslySetInnerHTML={{ __html: rendered }} />
|
||||||
|
}
|
||||||
|
|
||||||
|
let highlighter: Highlighter | undefined
|
||||||
|
|
||||||
|
export const createHighlighter = async () => {
|
||||||
|
if (!highlighter) {
|
||||||
|
highlighter = await getHighlighter({
|
||||||
|
themes: Object.keys(bundledThemes),
|
||||||
|
langs: Object.keys(bundledLanguages),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return highlighter
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type { StringLiteralUnion, ThemeRegistrationAny } from "shiki/types.mjs"
|
||||||
|
|
||||||
|
export interface ShikiCodeProps {
|
||||||
|
codeTheme?: ThemeRegistrationAny | StringLiteralUnion<any>
|
||||||
|
language?: string
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
diff --git a/package.json b/package.json
|
||||||
|
index 01142d760fc17a9a5202ce09f9ddd4cd203e860d..64db0fa428cf3daed5685ee72bd3c2844a03977f 100644
|
||||||
|
--- a/package.json
|
||||||
|
+++ b/package.json
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"module": "./dist/index.mjs",
|
||||||
|
"exports": {
|
||||||
|
+ "types": "./dist/index.d.ts",
|
||||||
|
"require": "./dist/index.js",
|
||||||
|
"import": "./dist/index.mjs"
|
||||||
|
},
|
||||||
|
|
@ -8,6 +8,11 @@ overrides:
|
||||||
'@wagmi/core': '1'
|
'@wagmi/core': '1'
|
||||||
open-graph-scraper>undici: 6.6.2
|
open-graph-scraper>undici: 6.6.2
|
||||||
|
|
||||||
|
patchedDependencies:
|
||||||
|
tailwindcss-variable-colors@0.0.2:
|
||||||
|
hash: uq3gxwrbflqvdc47smhui7x62u
|
||||||
|
path: patches/tailwindcss-variable-colors@0.0.2.patch
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
|
|
@ -99,9 +104,6 @@ importers:
|
||||||
'@prisma/client':
|
'@prisma/client':
|
||||||
specifier: 5.13.0
|
specifier: 5.13.0
|
||||||
version: 5.13.0(prisma@5.13.0)
|
version: 5.13.0(prisma@5.13.0)
|
||||||
'@shikijs/rehype':
|
|
||||||
specifier: ^1.5.1
|
|
||||||
version: 1.5.1
|
|
||||||
'@shikijs/transformers':
|
'@shikijs/transformers':
|
||||||
specifier: ^1.5.1
|
specifier: ^1.5.1
|
||||||
version: 1.5.1
|
version: 1.5.1
|
||||||
|
|
@ -123,6 +125,9 @@ importers:
|
||||||
'@wagmi/core':
|
'@wagmi/core':
|
||||||
specifier: '1'
|
specifier: '1'
|
||||||
version: 1.4.13(@types/react@18.3.1)(bufferutil@4.0.8)(immer@10.1.1)(ioredis@5.4.1)(react@18.3.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@1.21.1(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
|
version: 1.4.13(@types/react@18.3.1)(bufferutil@4.0.8)(immer@10.1.1)(ioredis@5.4.1)(react@18.3.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@1.21.1(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
|
||||||
|
'@xlog/shiki':
|
||||||
|
specifier: link:./packages/shiki
|
||||||
|
version: link:packages/shiki
|
||||||
ahooks:
|
ahooks:
|
||||||
specifier: 3.7.11
|
specifier: 3.7.11
|
||||||
version: 3.7.11(react@18.3.1)
|
version: 3.7.11(react@18.3.1)
|
||||||
|
|
@ -141,6 +146,9 @@ importers:
|
||||||
chroma-js:
|
chroma-js:
|
||||||
specifier: 2.4.2
|
specifier: 2.4.2
|
||||||
version: 2.4.2
|
version: 2.4.2
|
||||||
|
client-only:
|
||||||
|
specifier: 0.0.1
|
||||||
|
version: 0.0.1
|
||||||
clsx:
|
clsx:
|
||||||
specifier: 2.1.1
|
specifier: 2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
|
|
@ -351,6 +359,9 @@ importers:
|
||||||
serialize-javascript:
|
serialize-javascript:
|
||||||
specifier: 6.0.2
|
specifier: 6.0.2
|
||||||
version: 6.0.2
|
version: 6.0.2
|
||||||
|
server-only:
|
||||||
|
specifier: 0.0.1
|
||||||
|
version: 0.0.1
|
||||||
sharp:
|
sharp:
|
||||||
specifier: 0.32.6
|
specifier: 0.32.6
|
||||||
version: 0.32.6
|
version: 0.32.6
|
||||||
|
|
@ -507,7 +518,7 @@ importers:
|
||||||
version: 3.4.3
|
version: 3.4.3
|
||||||
tailwindcss-variable-colors:
|
tailwindcss-variable-colors:
|
||||||
specifier: 0.0.2
|
specifier: 0.0.2
|
||||||
version: 0.0.2(tailwindcss@3.4.3)
|
version: 0.0.2(patch_hash=uq3gxwrbflqvdc47smhui7x62u)(tailwindcss@3.4.3)
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.4.5
|
specifier: 5.4.5
|
||||||
version: 5.4.5
|
version: 5.4.5
|
||||||
|
|
@ -1992,9 +2003,6 @@ packages:
|
||||||
'@shikijs/core@1.5.1':
|
'@shikijs/core@1.5.1':
|
||||||
resolution: {integrity: sha512-xjV63pRUBvxA1LsxOUhRKLPh0uUjwBLzAKLdEuYSLIylo71sYuwDcttqNP01Ib1TZlLfO840CXHPlgUUsYFjzg==}
|
resolution: {integrity: sha512-xjV63pRUBvxA1LsxOUhRKLPh0uUjwBLzAKLdEuYSLIylo71sYuwDcttqNP01Ib1TZlLfO840CXHPlgUUsYFjzg==}
|
||||||
|
|
||||||
'@shikijs/rehype@1.5.1':
|
|
||||||
resolution: {integrity: sha512-UzmDzid4Zv4ZeY+GvJlKabBVdTt40aCCoOyeq/JwLJ0YmiZhm5vOicpzdbmMcUClgpCtBjJRLaOg8mkhd7YX/w==}
|
|
||||||
|
|
||||||
'@shikijs/transformers@1.5.1':
|
'@shikijs/transformers@1.5.1':
|
||||||
resolution: {integrity: sha512-vir+y0elkjh2CepLVbqeGX+ftuc6WpfWNCMV/EBIallSLzhBfDO9r/TORDVOzegbTg9JMEmtOFv6PT9cSZTcyA==}
|
resolution: {integrity: sha512-vir+y0elkjh2CepLVbqeGX+ftuc6WpfWNCMV/EBIallSLzhBfDO9r/TORDVOzegbTg9JMEmtOFv6PT9cSZTcyA==}
|
||||||
|
|
||||||
|
|
@ -6188,6 +6196,9 @@ packages:
|
||||||
serialize-javascript@6.0.2:
|
serialize-javascript@6.0.2:
|
||||||
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
|
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
|
||||||
|
|
||||||
|
server-only@0.0.1:
|
||||||
|
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
|
||||||
|
|
||||||
set-blocking@2.0.0:
|
set-blocking@2.0.0:
|
||||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||||
|
|
||||||
|
|
@ -8880,15 +8891,6 @@ snapshots:
|
||||||
|
|
||||||
'@shikijs/core@1.5.1': {}
|
'@shikijs/core@1.5.1': {}
|
||||||
|
|
||||||
'@shikijs/rehype@1.5.1':
|
|
||||||
dependencies:
|
|
||||||
'@shikijs/transformers': 1.5.1
|
|
||||||
'@types/hast': 3.0.4
|
|
||||||
hast-util-to-string: 3.0.0
|
|
||||||
shiki: 1.5.1
|
|
||||||
unified: 11.0.4
|
|
||||||
unist-util-visit: 5.0.0
|
|
||||||
|
|
||||||
'@shikijs/transformers@1.5.1':
|
'@shikijs/transformers@1.5.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
shiki: 1.5.1
|
shiki: 1.5.1
|
||||||
|
|
@ -14225,6 +14227,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
randombytes: 2.1.0
|
randombytes: 2.1.0
|
||||||
|
|
||||||
|
server-only@0.0.1: {}
|
||||||
|
|
||||||
set-blocking@2.0.0: {}
|
set-blocking@2.0.0: {}
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
|
|
@ -14518,7 +14522,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
tailwindcss: 3.4.3
|
tailwindcss: 3.4.3
|
||||||
|
|
||||||
tailwindcss-variable-colors@0.0.2(tailwindcss@3.4.3):
|
tailwindcss-variable-colors@0.0.2(patch_hash=uq3gxwrbflqvdc47smhui7x62u)(tailwindcss@3.4.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
tailwindcss: 3.4.3
|
tailwindcss: 3.4.3
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ export default async function Home() {
|
||||||
<div className="text-center mt-28" key={feature.title}>
|
<div className="text-center mt-28" key={feature.title}>
|
||||||
<div className="">
|
<div className="">
|
||||||
<div
|
<div
|
||||||
className={`h-20 w-[1px] bg-gradient-to-b mx-auto text-feature-${feature.title.toLocaleLowerCase()}`}
|
className={`h-20 w-px bg-gradient-to-b mx-auto text-feature-${feature.title.toLocaleLowerCase()}`}
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"--tw-gradient-from": "transparent",
|
"--tw-gradient-from": "transparent",
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import { Avatar } from "~/components/ui/Avatar"
|
||||||
import { Button } from "~/components/ui/Button"
|
import { Button } from "~/components/ui/Button"
|
||||||
import { UniLink } from "~/components/ui/UniLink"
|
import { UniLink } from "~/components/ui/UniLink"
|
||||||
import { useDate } from "~/hooks/useDate"
|
import { useDate } from "~/hooks/useDate"
|
||||||
import { useHighlighter } from "~/hooks/useHighlighter"
|
|
||||||
import { CSB_SCAN } from "~/lib/env"
|
import { CSB_SCAN } from "~/lib/env"
|
||||||
import { getSiteLink } from "~/lib/helpers"
|
import { getSiteLink } from "~/lib/helpers"
|
||||||
import { cn } from "~/lib/utils"
|
import { cn } from "~/lib/utils"
|
||||||
|
|
@ -58,8 +57,6 @@ export const CommentItem = ({
|
||||||
])
|
])
|
||||||
}, [deletePage.isSuccess, originalCharacterId, originalNoteId, queryClient])
|
}, [deletePage.isSuccess, originalCharacterId, originalNoteId, queryClient])
|
||||||
|
|
||||||
const highlighter = useHighlighter()
|
|
||||||
|
|
||||||
if (!comment.metadata?.content?.content) {
|
if (!comment.metadata?.content?.content) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +139,6 @@ export const CommentItem = ({
|
||||||
<MarkdownContent
|
<MarkdownContent
|
||||||
content={comment.metadata?.content?.content}
|
content={comment.metadata?.content?.content}
|
||||||
strictMode={true}
|
strictMode={true}
|
||||||
highlighter={highlighter}
|
|
||||||
></MarkdownContent>
|
></MarkdownContent>
|
||||||
<div className="mt-1 flex items-center">
|
<div className="mt-1 flex items-center">
|
||||||
<div
|
<div
|
||||||
|
|
@ -157,7 +153,7 @@ export const CommentItem = ({
|
||||||
</div>
|
</div>
|
||||||
{depth < 2 && (
|
{depth < 2 && (
|
||||||
<Button
|
<Button
|
||||||
className="text-gray-500 text-[13px] ml-1 mt-[-1px]"
|
className="text-gray-500 text-[13px] ml-1 -mt-px"
|
||||||
variant="text"
|
variant="text"
|
||||||
onClick={() => setReplyOpen(!replyOpen)}
|
onClick={() => setReplyOpen(!replyOpen)}
|
||||||
>
|
>
|
||||||
|
|
@ -171,7 +167,7 @@ export const CommentItem = ({
|
||||||
)}
|
)}
|
||||||
{comment.characterId === account?.characterId && (
|
{comment.characterId === account?.characterId && (
|
||||||
<Button
|
<Button
|
||||||
className="text-gray-500 text-[13px] mt-[-1px]"
|
className="text-gray-500 text-[13px] -mt-px"
|
||||||
variant="text"
|
variant="text"
|
||||||
onClick={() => setEditOpen(!editOpen)}
|
onClick={() => setEditOpen(!editOpen)}
|
||||||
>
|
>
|
||||||
|
|
@ -183,7 +179,7 @@ export const CommentItem = ({
|
||||||
!(comment as any)?.fromNotes?.list?.length && (
|
!(comment as any)?.fromNotes?.list?.length && (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
className="text-gray-500 text-[13px] mt-[-1px]"
|
className="text-gray-500 text-[13px] -mt-px"
|
||||||
variant="text"
|
variant="text"
|
||||||
onClick={() => setDeleteConfirmModalOpen(true)}
|
onClick={() => setDeleteConfirmModalOpen(true)}
|
||||||
isLoading={deletePage.isLoading}
|
isLoading={deletePage.isLoading}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ const FadeIn = ({
|
||||||
isInView === false && !locked
|
isInView === false && !locked
|
||||||
? // @see https://www.debugbear.com/blog/opacity-animation-poor-lcp
|
? // @see https://www.debugbear.com/blog/opacity-animation-poor-lcp
|
||||||
"opacity-[0.00001] translate-y-[20%]"
|
"opacity-[0.00001] translate-y-[20%]"
|
||||||
: "opacity-[1] translate-y-0",
|
: "opacity-100 translate-y-0",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import type { Result as TocResult } from "mdast-util-toc"
|
import type { Result as TocResult } from "mdast-util-toc"
|
||||||
import { memo, type MutableRefObject } from "react"
|
import { memo, type MutableRefObject } from "react"
|
||||||
import { Highlighter } from "shiki"
|
|
||||||
import type { BundledTheme } from "shiki/themes"
|
import type { BundledTheme } from "shiki/themes"
|
||||||
|
|
||||||
import PostActions from "~/components/site/PostActions"
|
import PostActions from "~/components/site/PostActions"
|
||||||
|
|
@ -24,7 +23,6 @@ const MarkdownContent = memo(function PageContent({
|
||||||
site,
|
site,
|
||||||
withActions,
|
withActions,
|
||||||
onlyContent,
|
onlyContent,
|
||||||
highlighter,
|
|
||||||
codeTheme,
|
codeTheme,
|
||||||
}: {
|
}: {
|
||||||
content?: string
|
content?: string
|
||||||
|
|
@ -39,7 +37,6 @@ const MarkdownContent = memo(function PageContent({
|
||||||
site?: ExpandedCharacter
|
site?: ExpandedCharacter
|
||||||
withActions?: boolean
|
withActions?: boolean
|
||||||
onlyContent?: boolean
|
onlyContent?: boolean
|
||||||
highlighter?: Highlighter
|
|
||||||
codeTheme?: {
|
codeTheme?: {
|
||||||
light?: BundledTheme
|
light?: BundledTheme
|
||||||
dark?: BundledTheme
|
dark?: BundledTheme
|
||||||
|
|
@ -53,7 +50,6 @@ const MarkdownContent = memo(function PageContent({
|
||||||
content,
|
content,
|
||||||
strictMode,
|
strictMode,
|
||||||
codeTheme,
|
codeTheme,
|
||||||
highlighter,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import { createHighlighter } from "~/lib/highlighter"
|
|
||||||
|
|
||||||
import MarkdownContent from "./MarkdownContent"
|
import MarkdownContent from "./MarkdownContent"
|
||||||
|
|
||||||
type MarkdownContentServerProps = Omit<
|
type MarkdownContentServerProps = Omit<
|
||||||
|
|
@ -8,8 +6,7 @@ type MarkdownContentServerProps = Omit<
|
||||||
>
|
>
|
||||||
|
|
||||||
const MarkdownContentServer = async (props: MarkdownContentServerProps) => {
|
const MarkdownContentServer = async (props: MarkdownContentServerProps) => {
|
||||||
const highlighter = await createHighlighter()
|
return <MarkdownContent {...props} />
|
||||||
return <MarkdownContent {...props} highlighter={highlighter} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MarkdownContentServer
|
export default MarkdownContentServer
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ export const usePatronModal = () => {
|
||||||
present({
|
present({
|
||||||
title: (
|
title: (
|
||||||
<span className="inline-flex items-center justify-center w-full space-x-1">
|
<span className="inline-flex items-center justify-center w-full space-x-1">
|
||||||
<span className="text-red-500 flex size-6 mb-[-1px]">
|
<span className="text-red-500 flex size-6 -mb-px">
|
||||||
<i className="i-mingcute-heart-fill text-2xl mb-[-1px]" />
|
<i className="i-mingcute-heart-fill text-2xl -mb-px" />
|
||||||
</span>
|
</span>
|
||||||
<span className="truncate">{title}</span>
|
<span className="truncate">{title}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ const ShareModal: FC<ShareModalProps> = ({ url, text, title }) => {
|
||||||
{shareList.map(({ name, icon, onClick }) => (
|
{shareList.map(({ name, icon, onClick }) => (
|
||||||
<li
|
<li
|
||||||
key={name}
|
key={name}
|
||||||
className="flex cursor-pointer items-center space-x-2 rounded-md px-3 py-2 text-lg transition-colors hover:bg-gray-100 [&_img]:size-[1rem]"
|
className="flex cursor-pointer items-center space-x-2 rounded-md px-3 py-2 text-lg transition-colors hover:bg-gray-100 [&_img]:size-4"
|
||||||
aria-label={`Share to ${name}`}
|
aria-label={`Share to ${name}`}
|
||||||
role="button"
|
role="button"
|
||||||
onClick={() => onClick({ url, text, title })}
|
onClick={() => onClick({ url, text, title })}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ export const Titles = ({ characterId }: { characterId?: number }) => {
|
||||||
label={title.name}
|
label={title.name}
|
||||||
childrenClassName={cn(
|
childrenClassName={cn(
|
||||||
icons[title.name].bg,
|
icons[title.name].bg,
|
||||||
"inline-flex p-[1px] rounded-sm",
|
"inline-flex p-px rounded-sm",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import MarkdownContent from "~/components/common/MarkdownContent"
|
||||||
import { toolbarShortcuts } from "~/components/dashboard/toolbars"
|
import { toolbarShortcuts } from "~/components/dashboard/toolbars"
|
||||||
import { editorUpload } from "~/components/dashboard/toolbars/Multimedia"
|
import { editorUpload } from "~/components/dashboard/toolbars/Multimedia"
|
||||||
import CodeMirror from "~/components/ui/CodeMirror"
|
import CodeMirror from "~/components/ui/CodeMirror"
|
||||||
import { useHighlighter } from "~/hooks/useHighlighter"
|
|
||||||
import { useIsMobileLayout } from "~/hooks/useMobileLayout"
|
import { useIsMobileLayout } from "~/hooks/useMobileLayout"
|
||||||
import { cn } from "~/lib/utils"
|
import { cn } from "~/lib/utils"
|
||||||
import { renderPageContent } from "~/markdown"
|
import { renderPageContent } from "~/markdown"
|
||||||
|
|
@ -33,7 +32,6 @@ export default function DualColumnEditor({
|
||||||
dark?: BundledTheme
|
dark?: BundledTheme
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
const highlighter = useHighlighter()
|
|
||||||
const isMobileLayout = useIsMobileLayout()
|
const isMobileLayout = useIsMobileLayout()
|
||||||
const t = useTranslations()
|
const t = useTranslations()
|
||||||
|
|
||||||
|
|
@ -53,17 +51,15 @@ export default function DualColumnEditor({
|
||||||
|
|
||||||
useDebounceEffect(
|
useDebounceEffect(
|
||||||
() => {
|
() => {
|
||||||
if (!highlighter) return
|
|
||||||
const result = renderPageContent({
|
const result = renderPageContent({
|
||||||
content: values,
|
content: values,
|
||||||
highlighter,
|
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
codeTheme,
|
codeTheme,
|
||||||
})
|
})
|
||||||
setTree(result.tree)
|
setTree(result.tree)
|
||||||
setParsedContent(result)
|
setParsedContent(result)
|
||||||
},
|
},
|
||||||
[values, codeTheme, highlighter],
|
[values, codeTheme],
|
||||||
{
|
{
|
||||||
wait: 500,
|
wait: 500,
|
||||||
},
|
},
|
||||||
|
|
@ -225,7 +221,7 @@ export default function DualColumnEditor({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isMobileLayout && (
|
{!isMobileLayout && (
|
||||||
<div className="z-10 w-[1px]">
|
<div className="z-10 w-px">
|
||||||
<div
|
<div
|
||||||
aria-label="Toggle preview view"
|
aria-label="Toggle preview view"
|
||||||
className="bg-accent rounded-full cursor-pointer text-white size-6 -translate-x-1/2"
|
className="bg-accent rounded-full cursor-pointer text-white size-6 -translate-x-1/2"
|
||||||
|
|
@ -248,7 +244,6 @@ export default function DualColumnEditor({
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
setCurrentScrollArea("preview")
|
setCurrentScrollArea("preview")
|
||||||
}}
|
}}
|
||||||
highlighter={highlighter}
|
|
||||||
codeTheme={codeTheme}
|
codeTheme={codeTheme}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import dynamic from "next/dynamic"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
import { useDate } from "~/hooks/useDate"
|
import { useDate } from "~/hooks/useDate"
|
||||||
import { useHighlighter } from "~/hooks/useHighlighter"
|
|
||||||
import { RESERVED_TAGS } from "~/lib/constants"
|
import { RESERVED_TAGS } from "~/lib/constants"
|
||||||
import { cn } from "~/lib/utils"
|
import { cn } from "~/lib/utils"
|
||||||
|
|
||||||
|
|
@ -19,7 +18,6 @@ export const ImportPreview = ({ note }: { note: NoteMetadata }) => {
|
||||||
const date = useDate()
|
const date = useDate()
|
||||||
const [showcaseMore, setShowcaseMore] = useState(false)
|
const [showcaseMore, setShowcaseMore] = useState(false)
|
||||||
const t = useTranslations()
|
const t = useTranslations()
|
||||||
const highlighter = useHighlighter()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className="border rounded-xl p-6 mt-4">
|
<article className="border rounded-xl p-6 mt-4">
|
||||||
|
|
@ -62,7 +60,6 @@ export const ImportPreview = ({ note }: { note: NoteMetadata }) => {
|
||||||
<DynamicMarkdownContent
|
<DynamicMarkdownContent
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
content={note?.content}
|
content={note?.content}
|
||||||
highlighter={highlighter}
|
|
||||||
></DynamicMarkdownContent>
|
></DynamicMarkdownContent>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { type FC, type ReactNode } from "react"
|
||||||
|
import type { BundledTheme } from "shiki/themes"
|
||||||
|
|
||||||
|
import { ShikiRender } from "@xlog/shiki"
|
||||||
|
|
||||||
|
const ShikiRemark: FC<{
|
||||||
|
codeTheme?: {
|
||||||
|
light?: BundledTheme
|
||||||
|
dark?: BundledTheme
|
||||||
|
}
|
||||||
|
children?: ReactNode
|
||||||
|
}> = (props) => {
|
||||||
|
const code = pickMdAstCode(props)
|
||||||
|
const language = pickCodeLanguage(props)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ShikiRender code={code} language={language} codeTheme={props.codeTheme} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pickMdAstCode = (props: any) => {
|
||||||
|
return props.children.type === "code"
|
||||||
|
? (props.children.props.children as string)
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const pickCodeLanguage = (props: any) => {
|
||||||
|
const className =
|
||||||
|
props.children.type === "code"
|
||||||
|
? (props.children.props.className as string)
|
||||||
|
: ""
|
||||||
|
|
||||||
|
if (className.includes("language-")) {
|
||||||
|
return className.replace("language-", "")
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ShikiRemark
|
||||||
|
|
@ -4,7 +4,7 @@ import type { Extension } from "@codemirror/state"
|
||||||
import { Compartment } from "@codemirror/state"
|
import { Compartment } from "@codemirror/state"
|
||||||
import { oneDark } from "@codemirror/theme-one-dark"
|
import { oneDark } from "@codemirror/theme-one-dark"
|
||||||
import { EditorView } from "@codemirror/view"
|
import { EditorView } from "@codemirror/view"
|
||||||
import { githubLight } from "@ddietr/codemirror-themes/theme/github-light"
|
import { githubLight } from "@ddietr/codemirror-themes/github-light.js"
|
||||||
|
|
||||||
import { useIsUnmounted } from "./useLifecycle"
|
import { useIsUnmounted } from "./useLifecycle"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import { useEffect, useState } from "react"
|
|
||||||
import type { Highlighter } from "shiki"
|
|
||||||
|
|
||||||
import { createHighlighter } from "~/lib/highlighter"
|
|
||||||
|
|
||||||
export function useHighlighter() {
|
|
||||||
const [highlighter, setHighlighter] = useState<Highlighter | undefined>()
|
|
||||||
useEffect(() => {
|
|
||||||
createHighlighter()
|
|
||||||
.then((h) => {
|
|
||||||
setHighlighter(h)
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(e)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
return highlighter
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
import type { Root as HashRoot } from "hast"
|
import type { Root as HashRoot } from "hast"
|
||||||
import { toHtml } from "hast-util-to-html"
|
import { toHtml } from "hast-util-to-html"
|
||||||
import { toJsxRuntime } from "hast-util-to-jsx-runtime"
|
import { toJsxRuntime, type ExtraProps } from "hast-util-to-jsx-runtime"
|
||||||
import jsYaml from "js-yaml"
|
import jsYaml from "js-yaml"
|
||||||
import type { Root as MdashRoot } from "mdast"
|
import type { Root as MdashRoot } from "mdast"
|
||||||
import { toc } from "mdast-util-toc"
|
import { toc } from "mdast-util-toc"
|
||||||
import dynamic from "next/dynamic"
|
import dynamic from "next/dynamic"
|
||||||
|
import {
|
||||||
|
createElement,
|
||||||
|
type ClassAttributes,
|
||||||
|
type FC,
|
||||||
|
type HTMLAttributes,
|
||||||
|
} from "react"
|
||||||
import { toast } from "react-hot-toast"
|
import { toast } from "react-hot-toast"
|
||||||
import { Fragment, jsx, jsxs } from "react/jsx-runtime"
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime"
|
||||||
import rehypeAutolinkHeadings from "rehype-autolink-headings"
|
import rehypeAutolinkHeadings from "rehype-autolink-headings"
|
||||||
|
|
@ -23,7 +29,6 @@ import remarkGithubAlerts from "remark-github-alerts"
|
||||||
import remarkMath from "remark-math"
|
import remarkMath from "remark-math"
|
||||||
import remarkParse from "remark-parse"
|
import remarkParse from "remark-parse"
|
||||||
import remarkRehype from "remark-rehype"
|
import remarkRehype from "remark-rehype"
|
||||||
import type { Highlighter } from "shiki"
|
|
||||||
import type { BundledTheme } from "shiki/themes"
|
import type { BundledTheme } from "shiki/themes"
|
||||||
import { unified } from "unified"
|
import { unified } from "unified"
|
||||||
import { visit } from "unist-util-visit"
|
import { visit } from "unist-util-visit"
|
||||||
|
|
@ -31,8 +36,6 @@ import { VFile } from "vfile"
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
|
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
|
||||||
import rehypeShikiFromHighlighter from "@shikijs/rehype/core"
|
|
||||||
import { transformerMetaHighlight } from "@shikijs/transformers"
|
|
||||||
|
|
||||||
import AdvancedImage from "~/components/ui/AdvancedImage"
|
import AdvancedImage from "~/components/ui/AdvancedImage"
|
||||||
import { isServerSide } from "~/lib/utils"
|
import { isServerSide } from "~/lib/utils"
|
||||||
|
|
@ -59,15 +62,20 @@ const XLogPost = dynamic(() => import("~/components/ui/XLogPost"))
|
||||||
const APlayer = dynamic(() => import("~/components/ui/APlayer"))
|
const APlayer = dynamic(() => import("~/components/ui/APlayer"))
|
||||||
const DPlayer = dynamic(() => import("~/components/ui/DPlayer"))
|
const DPlayer = dynamic(() => import("~/components/ui/DPlayer"))
|
||||||
const RSS = dynamic(() => import("~/components/ui/RSS"))
|
const RSS = dynamic(() => import("~/components/ui/RSS"))
|
||||||
|
const ShikiRemark = dynamic(() => import("~/components/ui/ShikiRemark"))
|
||||||
|
|
||||||
|
const memoedPreComponentMap = {} as Record<string, any>
|
||||||
|
const hashCodeThemeKey = (codeTheme?: Record<string, any>): string => {
|
||||||
|
if (!codeTheme) return "default"
|
||||||
|
return Object.values(codeTheme).join(",")
|
||||||
|
}
|
||||||
|
|
||||||
export const renderPageContent = ({
|
export const renderPageContent = ({
|
||||||
content,
|
content,
|
||||||
highlighter,
|
|
||||||
strictMode,
|
strictMode,
|
||||||
codeTheme,
|
codeTheme,
|
||||||
}: {
|
}: {
|
||||||
content: string
|
content: string
|
||||||
highlighter?: Highlighter
|
|
||||||
strictMode?: boolean
|
strictMode?: boolean
|
||||||
codeTheme?: {
|
codeTheme?: {
|
||||||
light?: BundledTheme
|
light?: BundledTheme
|
||||||
|
|
@ -128,18 +136,6 @@ export const renderPageContent = ({
|
||||||
})
|
})
|
||||||
.use(rehypeRemoveH1)
|
.use(rehypeRemoveH1)
|
||||||
|
|
||||||
if (highlighter) {
|
|
||||||
pipeline.use(rehypeShikiFromHighlighter, highlighter, {
|
|
||||||
themes: codeTheme ?? {
|
|
||||||
light: "github-light-default",
|
|
||||||
dark: "github-dark-default",
|
|
||||||
},
|
|
||||||
onError: (e) => {
|
|
||||||
console.error(e)
|
|
||||||
},
|
|
||||||
transformers: [transformerMetaHighlight()],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pipeline
|
pipeline
|
||||||
.use(rehypeKatex, {
|
.use(rehypeKatex, {
|
||||||
strict: false,
|
strict: false,
|
||||||
|
|
@ -157,7 +153,17 @@ export const renderPageContent = ({
|
||||||
toast.error(error?.message)
|
toast.error(error?.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let Pre: FC<
|
||||||
|
ClassAttributes<HTMLPreElement> &
|
||||||
|
HTMLAttributes<HTMLPreElement> &
|
||||||
|
ExtraProps
|
||||||
|
> = memoedPreComponentMap[hashCodeThemeKey(codeTheme)]
|
||||||
|
if (!Pre) {
|
||||||
|
Pre = function Pre(props: any) {
|
||||||
|
return createElement(ShikiRemark, { ...props, codeTheme }, props.children)
|
||||||
|
}
|
||||||
|
memoedPreComponentMap[hashCodeThemeKey(codeTheme)] = Pre
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
tree: hastTree,
|
tree: hastTree,
|
||||||
toToc: () =>
|
toToc: () =>
|
||||||
|
|
@ -186,6 +192,9 @@ export const renderPageContent = ({
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
style: Style,
|
style: Style,
|
||||||
rss: RSS,
|
rss: RSS,
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
pre: Pre,
|
||||||
},
|
},
|
||||||
ignoreInvalidStyle: true,
|
ignoreInvalidStyle: true,
|
||||||
// @ts-expect-error: untyped.
|
// @ts-expect-error: untyped.
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["DOM", "DOM.Iterable", "esnext"],
|
"lib": [
|
||||||
|
"DOM",
|
||||||
|
"DOM.Iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "Bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"target": "ES2019",
|
"target": "ES2019",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["./src/*"]
|
"~/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|
@ -18,13 +24,23 @@
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"typeRoots": ["./types"],
|
"typeRoots": [
|
||||||
|
"./types"
|
||||||
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "next"
|
"name": "next"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": [
|
||||||
"exclude": ["node_modules"]
|
"next-env.d.ts",
|
||||||
}
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
"packages/**/*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue