From 86385f97490adb59fa322ef661e8b77e5b1379c1 Mon Sep 17 00:00:00 2001 From: Arthals Date: Fri, 15 Nov 2024 21:28:26 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Shiki=20transformer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astro.config.ts | 12 ++- bun.lockb | Bin 410041 -> 423055 bytes package.json | 2 +- public/icons/code.svg | 29 +++++++ public/styles/global.css | 44 +++++++++++ src/components/BaseHead.astro | 1 - src/pages/index.astro | 1 - src/site.config.ts | 1 + src/types.ts | 1 + src/utils/const.ts | 1 + src/utils/shiki.ts | 142 ++++++++++++++++++++++++++++++++++ 11 files changed, 227 insertions(+), 7 deletions(-) create mode 100644 public/icons/code.svg create mode 100644 src/utils/const.ts create mode 100644 src/utils/shiki.ts diff --git a/astro.config.ts b/astro.config.ts index 2f317fd..7509918 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -9,7 +9,6 @@ import vercel from '@astrojs/vercel/serverless' import mdx from '@astrojs/mdx' import sitemap from '@astrojs/sitemap' import tailwind from '@astrojs/tailwind' -import playformCompress from '@playform/compress' import icon from 'astro-icon' // Markdown import rehypeExternalLinks from 'rehype-external-links' @@ -18,8 +17,10 @@ import { remarkAlert } from 'remark-github-blockquote-alert' import remarkMath from 'remark-math' import remarkUnwrapImages from 'remark-unwrap-images' import { siteConfig } from './src/site.config.ts' +import { addCopyButton, addLanguage } from './src/utils/shiki.ts' import { remarkGithubCards, remarkReadingTime, remarkArxivCards } from './src/utils/remarkParser.ts' + // https://astro.build/config export default defineConfig({ // Top-Level Options @@ -45,8 +46,9 @@ export default defineConfig({ sitemap(), mdx(), icon(), - playformCompress({ - SVG: false + (await import('@playform/compress')).default({ + SVG: false, + Exclude: ['index.*.js'] }) ], // root: './my-project-directory', @@ -72,6 +74,7 @@ export default defineConfig({ [ rehypeExternalLinks, { + ...(siteConfig.externalLinkArrow && { content: { type: 'text', value: ' ↗' } }), target: '_blank', rel: ['nofollow, noopener, noreferrer'] } @@ -86,7 +89,8 @@ export default defineConfig({ themes: { dark: 'github-dark', light: 'github-light' - } + }, + transformers: [addLanguage(), addCopyButton(2000)] } } }) diff --git a/bun.lockb b/bun.lockb index 163af8fd6cbf09ac971b92988923ce7ac6a83b6a..8c68e0eb66c5034b352ece26a33867359532552e 100755 GIT binary patch delta 11859 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 delta 5270 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 + + + + + + + + + + + + + + + + + + diff --git a/public/styles/global.css b/public/styles/global.css index 990a22a..60b3de2 100644 --- a/public/styles/global.css +++ b/public/styles/global.css @@ -59,3 +59,47 @@ body::-webkit-scrollbar { ::-webkit-scrollbar-track { background: transparent; } + +/* Shiki transformer */ +.astro-code:has(code) { + position: relative; +} +.astro-code:has(div.title) pre { + padding-top: 2.25rem; +} +.astro-code button.copy { + & .success::before { + content: 'Copied!'; + position: absolute; + right: 100%; + top: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + font-size: 0.75rem; + padding: 0.5rem; + margin-right: 0.5rem; + border-radius: 0.25rem; + color: hsl(var(--muted-foreground)); + background-color: hsl(var(--primary-foreground)); + border: 1px solid hsl(var(--border)); + } + &.copied { + & .success { + display: block; + } + + & .ready { + display: none; + } + } +} +.astro-code:hover { + button.copy { + opacity: 1; + } + .language { + opacity: 0; + } +} diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro index db73b28..6381bef 100644 --- a/src/components/BaseHead.astro +++ b/src/components/BaseHead.astro @@ -12,7 +12,6 @@ const titleSeparator = '•' const siteTitle = `${title} ${titleSeparator} ${siteConfig.title}` const canonicalURL = new URL(Astro.url.pathname, Astro.site) const socialImageURL = new URL(ogImage ? ogImage : '/images/social-card.png', Astro.url).href -const { walineServerUrl } = siteConfig --- diff --git a/src/pages/index.astro b/src/pages/index.astro index 6d06e44..933a35b 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -12,7 +12,6 @@ import PostPreview from '@/components/blog/PostPreview.astro' import Button from '@/components/Button.astro' import { siteConfig } from '@/site-config' import { getAllPosts, sortMDByDate } from '@/utils' -import GithubCard from '@/components/GithubCard.astro' import avatar from '@/assets/avatar.png' diff --git a/src/site.config.ts b/src/site.config.ts index 82b8072..9b88f90 100644 --- a/src/site.config.ts +++ b/src/site.config.ts @@ -24,6 +24,7 @@ export const siteConfig: SiteConfig = { }, // Customize pageSize: 8, + externalLinkArrow: true, registration: { url: 'https://icp.gov.moe/?keyword=APTX4869', text: '萌ICP备APTX4869号' diff --git a/src/types.ts b/src/types.ts index f6be62e..92423ac 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,6 +10,7 @@ export type SiteConfig = { options: Intl.DateTimeFormatOptions } pageSize: number + externalLinkArrow: boolean registration?: { url: string text: string diff --git a/src/utils/const.ts b/src/utils/const.ts new file mode 100644 index 0000000..5a238cf --- /dev/null +++ b/src/utils/const.ts @@ -0,0 +1 @@ +export const GITHUB_TOKEN = '' diff --git a/src/utils/shiki.ts b/src/utils/shiki.ts new file mode 100644 index 0000000..d73c173 --- /dev/null +++ b/src/utils/shiki.ts @@ -0,0 +1,142 @@ +import { h } from 'hastscript' +import type { ShikiTransformer } from 'shiki' + +function parseMetaString(str = '') { + return Object.fromEntries( + str.split(' ').reduce((acc: [string, string | true][], cur) => { + const matched = cur.match(/(.+)?=("(.+)"|'(.+)')$/) + if (matched === null) return acc + const key = matched[1] + const value = matched[3] || matched[4] || true + acc = [...acc, [key, value]] + return acc + }, []) + ) +} + +export const updateStyle = (): ShikiTransformer => { + return { + name: 'shiki-transformer-update-style', + pre(node) { + const container = h( + 'pre', + { + class: 'code-container overflow-x-scroll' + }, + node.children + ) + node.children = [container] + node.tagName = 'div' + } + } +} + +export const processMeta = (): ShikiTransformer => { + return { + name: 'shiki-transformer-process-meta', + preprocess() { + if (!this.options.meta) return + const rawMeta = this.options.meta?.__raw + if (!rawMeta) return + const meta = parseMetaString(rawMeta) + Object.assign(this.options.meta, meta) + } + } +} + +export const addTitle = (): ShikiTransformer => { + return { + name: 'shiki-transformer-add-title', + pre(node) { + const rawMeta = this.options.meta?.__raw + if (!rawMeta) return + const meta = parseMetaString(rawMeta) + if (this.options.meta) { + Object.assign(this.options.meta, meta) + } + console.log(this.options.meta) + + if (!meta.title) return + + const div = h( + 'div', + { + class: + 'title absolute top-2 left-3 text-sm text-foreground px-2 py-0.5 bg-primary-foreground rounded-lg border border-border' + }, + meta.title.toString() + ) + node.children.unshift(div) + } + } +} + +export const addLanguage = (): ShikiTransformer => { + return { + name: 'shiki-transformer-add-language', + pre(node) { + const span = h( + 'span', + { + class: + 'language transition-opacity duration-300 absolute top-3 right-3 text-sm text-muted-foreground' + }, + this.options.lang + ) + node.children.push(span) + } + } +} + +export const addCopyButton = (timeout?: number): ShikiTransformer => { + const toggleMs = timeout || 3000 + + return { + name: 'shiki-transformer-copy-button', + pre(node) { + const button = h( + 'button', + { + class: + 'copy transition-opacity duration-300 opacity-0 absolute top-3 right-3 text-muted-foreground p-1 box-content border border-border rounded bg-primary-foreground', + 'data-code': this.source, + onclick: ` + navigator.clipboard.writeText(this.dataset.code); + this.classList.add('copied'); + setTimeout(() => this.classList.remove('copied'), ${toggleMs}) + ` + }, + [ + h('div', { class: 'ready' }, [ + h( + 'svg', + { + class: 'size-5' + }, + [ + h('use', { + href: '/icons/code.svg#mingcute-clipboard-line' + }) + ] + ) + ]), + h('div', { class: 'success hidden' }, [ + h( + 'svg', + { + class: 'size-5' + }, + [ + h('use', { + href: '/icons/code.svg#mingcute-file-check-line' + }) + ] + ) + ]) + ] + ) + + node.children.push(button) + } + } +}