Skip to content

Commit

Permalink
refactor(code): rehype code wrapper (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
iamdin authored Aug 25, 2024
1 parent 0073201 commit fa3b658
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 70 deletions.
6 changes: 2 additions & 4 deletions apps/www/astro.config.mjs → apps/www/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import tailwind from "@astrojs/tailwind"
import vue from "@astrojs/vue"
import { defineConfig } from "astro/config"
import Inspect from "vite-plugin-inspect"
import { shikiConfig } from "./src/config/shiki"
import { rehypeCodeWrapper, shikiConfig } from "./src/lib/code"

// https://astro.build/config
export default defineConfig({
integrations: [
mdx({
shikiConfig,
}),
mdx({ shikiConfig, rehypePlugins: [rehypeCodeWrapper] }),
react(),
vue(),
tailwind(),
Expand Down
4 changes: 4 additions & 0 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@
"devDependencies": {
"@astrojs/markdown-remark": "^5.2.0",
"@shikijs/transformers": "^1.13.0",
"@types/hast": "^3.0.4",
"@types/node": "^20.14.15",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.20",
"mdast-util-mdx": "^3.0.0",
"mdast-util-mdx-jsx": "^3.1.2",
"mlly": "^1.7.1",
"postcss": "^8.4.41",
"shiki": "^1.13.0",
"tailwindcss": "^3.4.10",
"tailwindcss-animate": "^1.0.7",
"unist-util-visit": "^5.0.0",
"vite": "^5.4.1",
"vite-plugin-inspect": "^0.8.5"
}
Expand Down
17 changes: 8 additions & 9 deletions apps/www/src/components/content/code-wrapper.astro
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
---
import { Code } from "astro/components"
import type { HTMLAttributes } from "astro/types"
import { CopyButton } from "@/components/copy-button"
import { cn } from "@/lib/utils"
interface Props {
lang?: "tsx" | "vue"
interface Props extends HTMLAttributes<"div"> {
lang?: "tsx" | "vue" | "ts" | "json"
className?: string
src: string
hidden?: boolean
}
const { src, lang, hidden } = Astro.props
const html = Astro.slots.render("default")
const { src, lang, className } = Astro.props
---

<div class="code-wrapper relative" hidden={hidden}>
<div class={cn("code-wrapper relative", className)}>
{
lang && src ? (
<Code lang={lang} wrap={false} theme="vesper" code={src} />
) : (
<Fragment set:html={html} />
)
) : null
}
<CopyButton client:visible className="absolute top-4 right-4" value={src} />
</div>
23 changes: 9 additions & 14 deletions apps/www/src/components/content/component-preview/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,7 @@ const sourceVue = await resolvePathAndReadFile(`@ui/vue/examples/${name}`, {
>
{
source ? (
<Preview
client:visible
name={name}
/>
<Preview client:visible name={name} />
) : (
<NotFound component={name} />
)
Expand All @@ -67,23 +64,21 @@ const sourceVue = await resolvePathAndReadFile(`@ui/vue/examples/${name}`, {
>
{
sourceVue ? (
<PreviewVue
client:visible
name={name}
/>
<PreviewVue client:visible name={name} />
) : (
<NotFound component={name} />
)
}
</div>
</div>
<Fragment slot="code">
<div data-framework="react">
<CodeWrapper lang="tsx" src={source || ""} />
</div>
<div data-framework="vue" hidden>
<CodeWrapper lang="vue" src={sourceVue || ""} />
</div>
<CodeWrapper data-framework="react" lang="tsx" src={source || ""} />
<CodeWrapper
data-framework="vue"
lang="vue"
src={sourceVue || ""}
hidden
/>
</Fragment>
</Tabs>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/components/content/component-preview/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface Props {
export default function ({ preview, code }: Props) {
return (
<Tabs defaultValue="preview" className="w-full">
<TabsList className="mb-5 flex h-8 justify-start rounded-none border-b bg-transparent p-0">
<TabsList className=" flex h-8 justify-start rounded-none border-b bg-transparent p-0">
<TabsTrigger
value="preview"
className="h-full font-semibold data-[selected]:text-foreground"
Expand Down
29 changes: 0 additions & 29 deletions apps/www/src/config/shiki.ts

This file was deleted.

83 changes: 83 additions & 0 deletions apps/www/src/lib/code.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import type { ShikiConfig } from "@astrojs/markdown-remark"
import { transformerMetaHighlight } from "@shikijs/transformers"
import type { Element, Root } from "hast"
import type { MdxjsEsm } from "mdast-util-mdx"
import type { MdxJsxFlowElementHast } from "mdast-util-mdx-jsx"
import { visit } from "unist-util-visit"

export const shikiConfig = {
theme: "vesper",
transformers: [
{
root(root) {
const pre = root.children?.[0] as Element
if (pre) pre.properties.source = this.source
},
},
transformerMetaHighlight({
className: "line--highlighted",
}),
],
} satisfies ShikiConfig

export function rehypeCodeWrapper() {
return (tree: Root) => {
visit(tree, { type: "element", tagName: "pre" }, (node, index, parent) => {
if (
typeof node.properties.dataLanguage === "string" &&
typeof node.properties.source === "string"
) {
const componentElement: MdxJsxFlowElementHast = {
type: "mdxJsxFlowElement",
name: "CodeWrapper",
attributes: [
{
type: "mdxJsxAttribute",
name: "lang",
value: node.properties.dataLanguage,
},
{
type: "mdxJsxAttribute",
name: "src",
value: node.properties.source,
},
],
children: node.children,
}
// biome-ignore lint/style/noNonNullAssertion: <explanation>
parent!.children.splice(index!, 1, componentElement)
}
})

const codeWrapperImport: MdxjsEsm = {
type: "mdxjsEsm",
value: "",
data: {
estree: {
body: [
{
type: "ImportDeclaration",
specifiers: [
{
type: "ImportDefaultSpecifier",
local: {
type: "Identifier",
name: "CodeWrapper",
},
},
],
source: {
type: "Literal",
value: "@/components/content/code-wrapper.astro",
},
},
],
type: "Program",
sourceType: "module",
},
},
}

tree.children.unshift(codeWrapperImport)
}
}
13 changes: 0 additions & 13 deletions apps/www/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
import fs from "node:fs"
import path from "node:path"
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

export const loadFileSource = async (relativePath: string) => {
try {
if (!relativePath) return "No file provided"

return fs.readFileSync(path.resolve("./src", relativePath), "utf-8")
} catch (e) {
console.error(e)
return "Not yet available"
}
}
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fa3b658

Please sign in to comment.