feat: rehype code block
This commit is contained in:
parent
f705c07d55
commit
0cf5cf226c
20 changed files with 503 additions and 145 deletions
|
@ -1,15 +1,19 @@
|
||||||
import { rehypeHeadingIds } from '@astrojs/markdown-remark'
|
import { rehypeHeadingIds } from '@astrojs/markdown-remark'
|
||||||
import mdx from '@astrojs/mdx'
|
import mdx from '@astrojs/mdx'
|
||||||
|
import react from '@astrojs/react'
|
||||||
import sitemap from '@astrojs/sitemap'
|
import sitemap from '@astrojs/sitemap'
|
||||||
import tailwind from '@astrojs/tailwind'
|
import tailwind from '@astrojs/tailwind'
|
||||||
|
import {
|
||||||
|
transformerMetaHighlight,
|
||||||
|
transformerNotationDiff,
|
||||||
|
} from '@shikijs/transformers'
|
||||||
import { defineConfig } from 'astro/config'
|
import { defineConfig } from 'astro/config'
|
||||||
import rehypeKatex from 'rehype-katex'
|
import rehypeKatex from 'rehype-katex'
|
||||||
|
import rehypePrettyCode from 'rehype-pretty-code'
|
||||||
import remarkEmoji from 'remark-emoji'
|
import remarkEmoji from 'remark-emoji'
|
||||||
import remarkMath from 'remark-math'
|
import remarkMath from 'remark-math'
|
||||||
import remarkToc from 'remark-toc'
|
import remarkToc from 'remark-toc'
|
||||||
|
|
||||||
import react from '@astrojs/react'
|
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: 'https://astro-micro-academic.vercel.app',
|
site: 'https://astro-micro-academic.vercel.app',
|
||||||
|
@ -22,10 +26,28 @@ export default defineConfig({
|
||||||
react(),
|
react(),
|
||||||
],
|
],
|
||||||
markdown: {
|
markdown: {
|
||||||
shikiConfig: {
|
// shikiConfig: {
|
||||||
theme: 'css-variables',
|
// transformers: [
|
||||||
},
|
// transformerNotationDiff(),
|
||||||
rehypePlugins: [rehypeHeadingIds, rehypeKatex],
|
// transformerNotationFocus(),
|
||||||
|
// transformerMetaHighlight(),
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
syntaxHighlight: false,
|
||||||
|
rehypePlugins: [
|
||||||
|
rehypeHeadingIds,
|
||||||
|
rehypeKatex,
|
||||||
|
[
|
||||||
|
rehypePrettyCode,
|
||||||
|
{
|
||||||
|
theme: {
|
||||||
|
light: 'vitesse-light',
|
||||||
|
dark: 'vitesse-dark',
|
||||||
|
},
|
||||||
|
transformers: [transformerNotationDiff(), transformerMetaHighlight()],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
remarkPlugins: [remarkToc, remarkMath, remarkEmoji],
|
remarkPlugins: [remarkToc, remarkMath, remarkEmoji],
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
|
86
package-lock.json
generated
86
package-lock.json
generated
|
@ -22,6 +22,7 @@
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
"@shikijs/transformers": "^1.16.3",
|
||||||
"@types/react": "^18.3.5",
|
"@types/react": "^18.3.5",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"astro": "^4.11.3",
|
"astro": "^4.11.3",
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"rehype-katex": "^7.0.0",
|
"rehype-katex": "^7.0.0",
|
||||||
|
"rehype-pretty-code": "^0.14.0",
|
||||||
"remark-emoji": "^5.0.1",
|
"remark-emoji": "^5.0.1",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
|
@ -2551,14 +2553,29 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/core": {
|
"node_modules/@shikijs/core": {
|
||||||
"version": "1.10.3",
|
"version": "1.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.16.3.tgz",
|
||||||
"integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==",
|
"integrity": "sha512-yETIvrETCeC39gSPIiSADmjri9FwKmxz0QvONMtTIUYlKZe90CJkvcjPksayC2VQOtzOJonEiULUa8v8crUQvA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/hast": "^3.0.4"
|
"@shikijs/vscode-textmate": "^9.2.0",
|
||||||
|
"@types/hast": "^3.0.4",
|
||||||
|
"oniguruma-to-js": "0.3.3",
|
||||||
|
"regex": "4.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@shikijs/transformers": {
|
||||||
|
"version": "1.16.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.16.3.tgz",
|
||||||
|
"integrity": "sha512-bu4IcpUWmch4NvIWQgyMk2r9sH1XNZjUFgu56d3TPD1wLmBB/krctzVYgmurQ45X4dBEpNZdNvdG3v5B27taSw==",
|
||||||
|
"dependencies": {
|
||||||
|
"shiki": "1.16.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@shikijs/vscode-textmate": {
|
||||||
|
"version": "9.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.2.2.tgz",
|
||||||
|
"integrity": "sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg=="
|
||||||
|
},
|
||||||
"node_modules/@sindresorhus/is": {
|
"node_modules/@sindresorhus/is": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||||
|
@ -4747,6 +4764,18 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-to-string": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-to-text": {
|
"node_modules/hast-util-to-text": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
|
||||||
|
@ -6720,6 +6749,14 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oniguruma-to-js": {
|
||||||
|
"version": "0.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.3.3.tgz",
|
||||||
|
"integrity": "sha512-m90/WEhgs8g4BxG37+Nu3YrMfJDs2YXtYtIllhsEPR+wP3+K4EZk6dDUvy2v2K4MNFDDOYKL4/yqYPXDqyozTQ==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ora": {
|
"node_modules/ora": {
|
||||||
"version": "8.0.1",
|
"version": "8.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz",
|
||||||
|
@ -6899,6 +6936,11 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parse-numeric-range": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ=="
|
||||||
|
},
|
||||||
"node_modules/parse5": {
|
"node_modules/parse5": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
|
||||||
|
@ -7563,6 +7605,11 @@
|
||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/regex": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/regex/-/regex-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-kK/AA3A9K6q2js89+VMymcboLOlF5lZRCYJv3gzszXFHBr6kO6qLGzbm+UIugBEV8SMMKCTR59txoY6ctRHYVw=="
|
||||||
|
},
|
||||||
"node_modules/rehype": {
|
"node_modules/rehype": {
|
||||||
"version": "13.0.1",
|
"version": "13.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.1.tgz",
|
||||||
|
@ -7612,6 +7659,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-pretty-code": {
|
||||||
|
"version": "0.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.14.0.tgz",
|
||||||
|
"integrity": "sha512-hBeKF/Wkkf3zyUS8lal9RCUuhypDWLQc+h9UrP9Pav25FUm/AQAVh4m5gdvJxh4Oz+U+xKvdsV01p1LdvsZTiQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.4",
|
||||||
|
"hast-util-to-string": "^3.0.0",
|
||||||
|
"parse-numeric-range": "^1.3.0",
|
||||||
|
"rehype-parse": "^9.0.0",
|
||||||
|
"unified": "^11.0.5",
|
||||||
|
"unist-util-visit": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"shiki": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-raw": {
|
"node_modules/rehype-raw": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
|
||||||
|
@ -8106,12 +8172,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shiki": {
|
"node_modules/shiki": {
|
||||||
"version": "1.10.3",
|
"version": "1.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz",
|
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.16.3.tgz",
|
||||||
"integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==",
|
"integrity": "sha512-GypUE+fEd06FqDs63LSAVlmq7WsahhPQU62cgZxGF+TJT5LjD2k7HTxXj4/CKOVuMM3+wWQ1t4Y5oooeJFRRBQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/core": "1.10.3",
|
"@shikijs/core": "1.16.3",
|
||||||
|
"@shikijs/vscode-textmate": "^9.2.0",
|
||||||
"@types/hast": "^3.0.4"
|
"@types/hast": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
"@shikijs/transformers": "^1.16.3",
|
||||||
"@types/react": "^18.3.5",
|
"@types/react": "^18.3.5",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"astro": "^4.11.3",
|
"astro": "^4.11.3",
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"rehype-katex": "^7.0.0",
|
"rehype-katex": "^7.0.0",
|
||||||
|
"rehype-pretty-code": "^0.14.0",
|
||||||
"remark-emoji": "^5.0.1",
|
"remark-emoji": "^5.0.1",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
|
|
|
@ -65,21 +65,23 @@ if (
|
||||||
<div
|
<div
|
||||||
class="mb-2 flex items-center space-x-2 text-xs text-muted-foreground"
|
class="mb-2 flex items-center space-x-2 text-xs text-muted-foreground"
|
||||||
>
|
>
|
||||||
{author && (
|
{
|
||||||
<>
|
author && (
|
||||||
<div class="flex items-center gap-1.5">
|
<>
|
||||||
<Image
|
<div class="flex items-center gap-1.5">
|
||||||
src={author.data.avatar}
|
<Image
|
||||||
alt={author.data.name}
|
src={author.data.avatar}
|
||||||
width={18}
|
alt={author.data.name}
|
||||||
height={18}
|
width={18}
|
||||||
class="rounded-full"
|
height={18}
|
||||||
/>
|
class="rounded-full"
|
||||||
<span>{author.data.name}</span>
|
/>
|
||||||
</div>
|
<span>{author.data.name}</span>
|
||||||
<Separator orientation="vertical" className="h-4" />
|
</div>
|
||||||
</>
|
<Separator orientation="vertical" className="h-4" />
|
||||||
)}
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
<span>{formattedDate}</span>
|
<span>{formattedDate}</span>
|
||||||
<Separator orientation="vertical" className="h-4" />
|
<Separator orientation="vertical" className="h-4" />
|
||||||
<span>{readTime}</span>
|
<span>{readTime}</span>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import '../styles/global.css'
|
import '../styles/global.css'
|
||||||
import '../styles/katex.css'
|
import '../styles/katex.css'
|
||||||
import '../styles/typography.css'
|
import '../styles/typography.css'
|
||||||
|
import '../styles/codeblocks.css'
|
||||||
|
|
||||||
import '@fontsource/geist-sans'
|
import '@fontsource/geist-sans'
|
||||||
import '@fontsource/geist-mono'
|
import '@fontsource/geist-mono'
|
||||||
|
|
|
@ -12,28 +12,42 @@ const { prevPost, nextPost } = Astro.props
|
||||||
href={prevPost ? `/blog/${prevPost.slug}` : '#'}
|
href={prevPost ? `/blog/${prevPost.slug}` : '#'}
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({ variant: 'outline' }),
|
buttonVariants({ variant: 'outline' }),
|
||||||
'group flex items-center justify-start gap-2 w-1/2',
|
'rounded-xl group flex items-center justify-start w-1/2 h-fit',
|
||||||
!prevPost && 'pointer-events-none opacity-50 cursor-not-allowed',
|
!prevPost && 'pointer-events-none opacity-50 cursor-not-allowed',
|
||||||
)}
|
)}
|
||||||
aria-disabled={!prevPost}
|
aria-disabled={!prevPost}
|
||||||
>
|
>
|
||||||
<ArrowLeft
|
<div class="mr-2 flex-shrink-0">
|
||||||
className="h-4 w-4 transition-transform group-hover:-translate-x-1"
|
<ArrowLeft
|
||||||
/>
|
className="h-4 w-4 transition-transform group-hover:-translate-x-1"
|
||||||
<span class="truncate">{prevPost?.data.title || 'Latest post!'}</span>
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-start overflow-hidden">
|
||||||
|
<span class="text-left text-xs text-muted-foreground">Previous Post</span>
|
||||||
|
<span class="w-full truncate text-left"
|
||||||
|
>{prevPost?.data.title || 'Latest post!'}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href={nextPost ? `/blog/${nextPost.slug}` : '#'}
|
href={nextPost ? `/blog/${nextPost.slug}` : '#'}
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({ variant: 'outline' }),
|
buttonVariants({ variant: 'outline' }),
|
||||||
'group flex items-center justify-end gap-2 w-1/2',
|
'rounded-xl group flex items-center justify-end w-1/2 h-fit',
|
||||||
!nextPost && 'pointer-events-none opacity-50 cursor-not-allowed',
|
!nextPost && 'pointer-events-none opacity-50 cursor-not-allowed',
|
||||||
)}
|
)}
|
||||||
aria-disabled={!nextPost}
|
aria-disabled={!nextPost}
|
||||||
>
|
>
|
||||||
<span class="truncate">{nextPost?.data.title || 'Last post!'}</span>
|
<div class="flex flex-col items-end overflow-hidden">
|
||||||
<ArrowRight
|
<span class="text-right text-xs text-muted-foreground">Next Post</span>
|
||||||
className="h-4 w-4 transition-transform group-hover:translate-x-1"
|
<span class="w-full truncate text-right"
|
||||||
/>
|
>{nextPost?.data.title || 'Last post!'}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="ml-2 flex-shrink-0">
|
||||||
|
<ArrowRight
|
||||||
|
className="h-4 w-4 transition-transform group-hover:translate-x-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -40,8 +40,12 @@ function buildToc(headings: Heading[]) {
|
||||||
<nav
|
<nav
|
||||||
class="overflow-wrap-break-word sticky top-16 hidden h-0 w-[calc(50vw-50%-4rem)] translate-x-[calc(-100%-2em)] text-xs leading-4 xl:block"
|
class="overflow-wrap-break-word sticky top-16 hidden h-0 w-[calc(50vw-50%-4rem)] translate-x-[calc(-100%-2em)] text-xs leading-4 xl:block"
|
||||||
>
|
>
|
||||||
<h2 class="mb-4 text-xl font-semibold">Table of Contents</h2>
|
<div class="mr-6 flex justify-end">
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
|
<li>
|
||||||
</ul>
|
<h2 class="mb-2 text-lg font-semibold">Table of Contents</h2>
|
||||||
|
</li>
|
||||||
|
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from "react"
|
import * as React from 'react'
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
const Card = React.forwardRef<
|
const Card = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
|
@ -9,13 +9,13 @@ const Card = React.forwardRef<
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-xl border bg-card text-card-foreground shadow",
|
'rounded-xl border bg-card text-card-foreground shadow',
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
Card.displayName = "Card"
|
Card.displayName = 'Card'
|
||||||
|
|
||||||
const CardHeader = React.forwardRef<
|
const CardHeader = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
|
@ -23,11 +23,11 @@ const CardHeader = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
className={cn('flex flex-col space-y-1.5 p-6', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
CardHeader.displayName = "CardHeader"
|
CardHeader.displayName = 'CardHeader'
|
||||||
|
|
||||||
const CardTitle = React.forwardRef<
|
const CardTitle = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
|
@ -35,11 +35,11 @@ const CardTitle = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<h3
|
<h3
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("font-semibold leading-none tracking-tight", className)}
|
className={cn('font-semibold leading-none tracking-tight', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
CardTitle.displayName = "CardTitle"
|
CardTitle.displayName = 'CardTitle'
|
||||||
|
|
||||||
const CardDescription = React.forwardRef<
|
const CardDescription = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
|
@ -47,19 +47,19 @@ const CardDescription = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<p
|
<p
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("text-sm text-muted-foreground", className)}
|
className={cn('text-sm text-muted-foreground', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
CardDescription.displayName = "CardDescription"
|
CardDescription.displayName = 'CardDescription'
|
||||||
|
|
||||||
const CardContent = React.forwardRef<
|
const CardContent = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
React.HTMLAttributes<HTMLDivElement>
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
|
||||||
))
|
))
|
||||||
CardContent.displayName = "CardContent"
|
CardContent.displayName = 'CardContent'
|
||||||
|
|
||||||
const CardFooter = React.forwardRef<
|
const CardFooter = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
|
@ -67,10 +67,10 @@ const CardFooter = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("flex items-center p-6 pt-0", className)}
|
className={cn('flex items-center p-6 pt-0', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
CardFooter.displayName = "CardFooter"
|
CardFooter.displayName = 'CardFooter'
|
||||||
|
|
||||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
|
||||||
|
|
|
@ -7,107 +7,270 @@ image: '/1200x630.png'
|
||||||
author: 'enscribe'
|
author: 'enscribe'
|
||||||
---
|
---
|
||||||
|
|
||||||
## h2 Heading
|
```elixir title="fib.ex" showLineNumbers /palindrome/ {1-2, 5-8}
|
||||||
|
defmodule Solution do
|
||||||
|
@spec is_palindrome(x :: integer) :: boolean
|
||||||
|
def is_palindrome(x) when x < 0, do: false
|
||||||
|
def is_palindrome(x), do: do_is_palindrome(x, get_base_10(x, 1))
|
||||||
|
|
||||||
### h3 Heading
|
defp do_is_palindrome(x, b10) when b10 > 1,
|
||||||
|
do: get_first_digit(x, b10) == rem(x, 10) and do_is_palindrome(div(x, 10), div(b10, 100))
|
||||||
|
|
||||||
#### h4 Heading
|
defp do_is_palindrome(_, _), do: true
|
||||||
|
|
||||||
##### h5 Heading
|
defp get_first_digit(n, b10), do: div(n, b10) |> rem(10)
|
||||||
|
|
||||||
###### h6 Heading
|
defp get_base_10(n, b10) when n >= b10, do: get_base_10(n, b10 * 10)
|
||||||
|
defp get_base_10(n, b10), do: div(b10, 10)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
## Emphasis
|
```tsx showLineNumbers
|
||||||
|
console.log('Introduction.')
|
||||||
|
|
||||||
**This is bold text**
|
console.log('Subtraction.') // [!code focus] // [!code --]
|
||||||
|
|
||||||
**This is bold text**
|
console.log('Addition.') // [!code focus] // [!code ++]
|
||||||
|
|
||||||
_This is italic text_
|
console.log('In focus.') // [!code focus]
|
||||||
|
|
||||||
_This is italic text_
|
console.log('End.')
|
||||||
|
```
|
||||||
|
|
||||||
~~Strikethrough~~
|
Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.
|
||||||
|
|
||||||
|
## Headings
|
||||||
|
|
||||||
|
The following HTML `<h1>`—`<h6>` elements represent six levels of section headings. `<h1>` is the highest section level while `<h6>` is the lowest.
|
||||||
|
|
||||||
|
## H2
|
||||||
|
|
||||||
|
### H3
|
||||||
|
|
||||||
|
#### H4
|
||||||
|
|
||||||
|
##### H5
|
||||||
|
|
||||||
|
###### H6
|
||||||
|
|
||||||
|
## Paragraph
|
||||||
|
|
||||||
|
Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.
|
||||||
|
|
||||||
|
Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.
|
||||||
|
|
||||||
|
## Images
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
|
||||||
|
```markdown
|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Blockquotes
|
## Blockquotes
|
||||||
|
|
||||||
> Blockquotes can also be nested...
|
The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a `footer` or `cite` element, and optionally with in-line changes such as annotations and abbreviations.
|
||||||
>
|
|
||||||
> > ...by using additional greater-than signs right next to each other...
|
|
||||||
> >
|
|
||||||
> > > ...or with spaces between arrows.
|
|
||||||
|
|
||||||
## Lists
|
### Blockquote without attribution
|
||||||
|
|
||||||
Unordered
|
#### Syntax
|
||||||
|
|
||||||
- Create a list by starting a line with `+`, `-`, or `*`
|
```markdown
|
||||||
- Sub-lists are made by indenting 2 spaces:
|
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
|
||||||
- Marker character change forces new list start:
|
> **Note** that you can use _Markdown syntax_ within a blockquote.
|
||||||
- Ac tristique libero volutpat at
|
|
||||||
* Facilisis in pretium nisl aliquet
|
|
||||||
- Nulla volutpat aliquam velit
|
|
||||||
- Very easy!
|
|
||||||
|
|
||||||
Ordered
|
|
||||||
|
|
||||||
1. Lorem ipsum dolor sit amet
|
|
||||||
2. Consectetur adipiscing elit
|
|
||||||
3. Integer molestie lorem at massa
|
|
||||||
|
|
||||||
4. You can use sequential numbers...
|
|
||||||
5. ...or keep all the numbers as `1.`
|
|
||||||
|
|
||||||
Start numbering with offset:
|
|
||||||
|
|
||||||
57. foo
|
|
||||||
1. bar
|
|
||||||
|
|
||||||
## Code
|
|
||||||
|
|
||||||
Inline `code`
|
|
||||||
|
|
||||||
Indented code
|
|
||||||
|
|
||||||
// Some comments
|
|
||||||
line 1 of code
|
|
||||||
line 2 of code
|
|
||||||
line 3 of code
|
|
||||||
|
|
||||||
Block code "fences"
|
|
||||||
|
|
||||||
```
|
|
||||||
Sample text here...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Syntax highlighting
|
#### Output
|
||||||
|
|
||||||
```js
|
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
|
||||||
var foo = function (bar) {
|
> **Note** that you can use _Markdown syntax_ within a blockquote.
|
||||||
return bar++
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(foo(5))
|
### Blockquote with attribution
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> Don't communicate by sharing memory, share memory by communicating.
|
||||||
|
> — <cite>Rob Pike[^1]</cite>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
> Don't communicate by sharing memory, share memory by communicating.
|
||||||
|
> — <cite>Rob Pike[^1]</cite>
|
||||||
|
|
||||||
|
[^1]: The above quote is excerpted from Rob Pike's [talk](https://www.youtube.com/watch?v=PAAkCSZUG1c) during Gopherfest, November 18, 2015.
|
||||||
|
|
||||||
## Tables
|
## Tables
|
||||||
|
|
||||||
| Option | Description |
|
#### Syntax
|
||||||
| ------ | ------------------------------------------------------------------------- |
|
|
||||||
| data | path to data files to supply the data that will be passed into templates. |
|
|
||||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
|
||||||
| ext | extension to be used for dest files. |
|
|
||||||
|
|
||||||
Right aligned columns
|
```markdown
|
||||||
|
| Italics | Bold | Code |
|
||||||
|
| --------- | -------- | ------ |
|
||||||
|
| _italics_ | **bold** | `code` |
|
||||||
|
```
|
||||||
|
|
||||||
| Option | Description |
|
#### Output
|
||||||
| -----: | ------------------------------------------------------------------------: |
|
|
||||||
| data | path to data files to supply the data that will be passed into templates. |
|
|
||||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
|
||||||
| ext | extension to be used for dest files. |
|
|
||||||
|
|
||||||
## Links
|
| Italics | Bold | Code |
|
||||||
|
| --------- | -------- | ------ |
|
||||||
|
| _italics_ | **bold** | `code` |
|
||||||
|
|
||||||
[link text](http://dev.nodeca.com)
|
## Code Blocks
|
||||||
|
|
||||||
[link with title](http://nodeca.github.io/pica/demo/ 'title text!')
|
#### Syntax
|
||||||
|
|
||||||
|
we can use 3 backticks ``` in new line and write snippet and close with 3 backticks on new line and to highlight language specific syntac, write one word of language name after first 3 backticks, for eg. html, javascript, css, markdown, typescript, txt, bash
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Example HTML5 Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
Output
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Example HTML5 Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
## List Types
|
||||||
|
|
||||||
|
### Ordered List
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
1. First item
|
||||||
|
2. Second item
|
||||||
|
3. Third item
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
1. First item
|
||||||
|
2. Second item
|
||||||
|
3. Third item
|
||||||
|
|
||||||
|
### Unordered List
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
- List item
|
||||||
|
- Another item
|
||||||
|
- And another item
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
- List item
|
||||||
|
- Another item
|
||||||
|
- And another item
|
||||||
|
|
||||||
|
### Nested list
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
- Fruit
|
||||||
|
- Apple
|
||||||
|
- Orange
|
||||||
|
- Banana
|
||||||
|
- Dairy
|
||||||
|
- Milk
|
||||||
|
- Cheese
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
- Fruit
|
||||||
|
- Apple
|
||||||
|
- Orange
|
||||||
|
- Banana
|
||||||
|
- Dairy
|
||||||
|
- Milk
|
||||||
|
- Cheese
|
||||||
|
|
||||||
|
## Other Elements — abbr, sub, sup, kbd, mark
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
||||||
|
|
||||||
|
H<sub>2</sub>O
|
||||||
|
|
||||||
|
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
||||||
|
|
||||||
|
Press <kbd><kbd>CTRL</kbd>+<kbd>ALT</kbd>+<kbd>Delete</kbd></kbd> to end the session.
|
||||||
|
|
||||||
|
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
||||||
|
|
||||||
|
H<sub>2</sub>O
|
||||||
|
|
||||||
|
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
||||||
|
|
||||||
|
Press <kbd><kbd>CTRL</kbd>+<kbd>ALT</kbd>+<kbd>Delete</kbd></kbd> to end the session.
|
||||||
|
|
||||||
|
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
||||||
|
|
||||||
|
```js title="/src/app/fetchMovie.js"
|
||||||
|
const movies = await fetchMovies()
|
||||||
|
```
|
||||||
|
|
||||||
|
```js caption="Fetch movies from our server"
|
||||||
|
export async function fetchMovies() {
|
||||||
|
const response = await fetch('http://example.com/movies.json')
|
||||||
|
return await response.json()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```js {2-4}
|
||||||
|
const movies = await fetchMovies()
|
||||||
|
movies.map((movie, i) => {
|
||||||
|
console.log(movie.title)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```js /movie.title/
|
||||||
|
const movies = await fetchMovies()
|
||||||
|
movies.map((movie, i) => {
|
||||||
|
console.log(movie.title)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```js showLineNumbers
|
||||||
|
const movies = await fetchMovies()
|
||||||
|
movies.map((movie, i) => {
|
||||||
|
console.log(movie.title)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
|
@ -18,7 +18,7 @@ const { title, description } = Astro.props
|
||||||
<Head title={`${title} | ${SITE.TITLE}`} description={description} />
|
<Head title={`${title} | ${SITE.TITLE}`} description={description} />
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
class="box-border flex h-fit min-h-screen flex-col gap-y-4 bg-background px-4 font-sans text-foreground antialiased"
|
class="box-border flex h-fit min-h-screen flex-col gap-y-6 bg-background px-4 font-sans text-foreground antialiased"
|
||||||
>
|
>
|
||||||
<Header />
|
<Header />
|
||||||
<main class="flex-grow">
|
<main class="flex-grow">
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { HomeIcon } from 'lucide-react'
|
||||||
|
|
||||||
<Layout title="404" description={SITE.DESCRIPTION}>
|
<Layout title="404" description={SITE.DESCRIPTION}>
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb className="mb-4">
|
<Breadcrumb className="mb-6">
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="/"
|
<BreadcrumbLink href="/"
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { HomeIcon } from 'lucide-react'
|
||||||
|
|
||||||
<Layout title="About" description={SITE.DESCRIPTION}>
|
<Layout title="About" description={SITE.DESCRIPTION}>
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb className="mb-4">
|
<Breadcrumb className="mb-6">
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="/"
|
<BreadcrumbLink href="/"
|
||||||
|
|
|
@ -47,7 +47,7 @@ const authorPosts = allPosts
|
||||||
description={author.data.bio || `Profile of ${author.data.name}`}
|
description={author.data.bio || `Profile of ${author.data.name}`}
|
||||||
>
|
>
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb className="mb-4">
|
<Breadcrumb className="mb-6">
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="/"
|
<BreadcrumbLink href="/"
|
||||||
|
|
|
@ -18,7 +18,7 @@ const authors = await getCollection('authors')
|
||||||
|
|
||||||
<Layout title="Authors" description="Authors">
|
<Layout title="Authors" description="Authors">
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb className="mb-4">
|
<Breadcrumb className="mb-6">
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="/"
|
<BreadcrumbLink href="/"
|
||||||
|
|
|
@ -78,7 +78,7 @@ if (
|
||||||
|
|
||||||
<Layout title={post.data.title} description={post.data.description}>
|
<Layout title={post.data.title} description={post.data.description}>
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb className="mb-4">
|
<Breadcrumb className="mb-6">
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="/"
|
<BreadcrumbLink href="/"
|
||||||
|
|
|
@ -35,7 +35,7 @@ const years = Object.keys(posts).sort((a, b) => parseInt(b) - parseInt(a))
|
||||||
|
|
||||||
<Layout title="Blog" description="Blog">
|
<Layout title="Blog" description="Blog">
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb className="mb-4">
|
<Breadcrumb className="mb-6">
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="/"
|
<BreadcrumbLink href="/"
|
||||||
|
|
|
@ -6,7 +6,13 @@ import BlogCard from '@components/BlogCard.astro'
|
||||||
import { buttonVariants } from '@/components/ui/button'
|
import { buttonVariants } from '@/components/ui/button'
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
import Link from '@components/Link.astro'
|
import Link from '@components/Link.astro'
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from '@/components/ui/card'
|
||||||
|
|
||||||
const blog = (await getCollection('blog'))
|
const blog = (await getCollection('blog'))
|
||||||
.filter((post) => !post.data.draft)
|
.filter((post) => !post.data.draft)
|
||||||
|
|
61
src/styles/codeblocks.css
Normal file
61
src/styles/codeblocks.css
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
code[data-theme*=' '] span {
|
||||||
|
color: var(--shiki-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark code[data-theme*=' '] span {
|
||||||
|
color: var(--shiki-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
@apply overflow-x-auto rounded-xl p-4 text-sm leading-loose;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code {
|
||||||
|
counter-reset: line;
|
||||||
|
}
|
||||||
|
|
||||||
|
code[data-line-numbers] {
|
||||||
|
counter-reset: line;
|
||||||
|
}
|
||||||
|
|
||||||
|
code[data-line-numbers] > [data-line]::before {
|
||||||
|
counter-increment: line;
|
||||||
|
content: counter(line);
|
||||||
|
@apply mr-4 inline-block w-4 text-right text-muted-foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-highlighted-line] {
|
||||||
|
@apply !bg-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-highlighted-chars] > span {
|
||||||
|
@apply rounded-md border !bg-secondary p-1 font-semibold;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-rehype-pretty-code-title] {
|
||||||
|
@apply rounded-t-xl border-x border-t p-2 text-sm font-semibold !text-foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-rehype-pretty-code-title] + pre {
|
||||||
|
@apply mt-0 rounded-t-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff.add {
|
||||||
|
background-color: #0505;
|
||||||
|
}
|
||||||
|
.diff.remove {
|
||||||
|
background-color: #8005;
|
||||||
|
}
|
||||||
|
|
||||||
|
.has-focused .line {
|
||||||
|
filter: blur(0.095rem);
|
||||||
|
}
|
||||||
|
.has-focused .focused {
|
||||||
|
filter: blur(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer components {
|
||||||
article {
|
article {
|
||||||
@apply prose prose-neutral dark:prose-invert;
|
@apply prose prose-neutral dark:prose-invert;
|
||||||
@apply prose-h1:scroll-m-20 prose-h1:text-4xl prose-h1:font-extrabold prose-h1:tracking-tight prose-h1:lg:text-5xl;
|
@apply prose-h1:scroll-m-20 prose-h1:text-4xl prose-h1:font-extrabold prose-h1:tracking-tight prose-h1:lg:text-5xl;
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
import type { Config } from 'tailwindcss'
|
import type { Config } from 'tailwindcss'
|
||||||
import defaultTheme from 'tailwindcss/defaultTheme'
|
import defaultTheme from 'tailwindcss/defaultTheme'
|
||||||
|
|
||||||
|
const disabledCss = {
|
||||||
|
'code::before': false,
|
||||||
|
'code::after': false,
|
||||||
|
'blockquote p:first-of-type::before': false,
|
||||||
|
'blockquote p:last-of-type::after': false,
|
||||||
|
pre: false,
|
||||||
|
code: false,
|
||||||
|
'pre code': false,
|
||||||
|
}
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
darkMode: ['selector'],
|
darkMode: ['selector'],
|
||||||
content: ['./src/**/*.{astro,md,mdx,ts,tsx}'],
|
content: ['./src/**/*.{astro,md,mdx,ts,tsx}'],
|
||||||
|
@ -57,6 +67,13 @@ const config: Config = {
|
||||||
'5': 'hsl(var(--chart-5))',
|
'5': 'hsl(var(--chart-5))',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
typography: {
|
||||||
|
DEFAULT: { css: disabledCss },
|
||||||
|
sm: { css: disabledCss },
|
||||||
|
lg: { css: disabledCss },
|
||||||
|
xl: { css: disabledCss },
|
||||||
|
'2xl': { css: disabledCss },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require('@tailwindcss/typography'), require('tailwindcss-animate')],
|
plugins: [require('@tailwindcss/typography'), require('tailwindcss-animate')],
|
||||||
|
|
Loading…
Add table
Reference in a new issue