feat: rehype code block

This commit is contained in:
enscribe 2024-09-11 01:58:29 -07:00
parent f705c07d55
commit 0cf5cf226c
No known key found for this signature in database
GPG key ID: 9BBD5C4114E25322
20 changed files with 503 additions and 145 deletions

View file

@ -1,15 +1,19 @@
import { rehypeHeadingIds } from '@astrojs/markdown-remark'
import mdx from '@astrojs/mdx'
import react from '@astrojs/react'
import sitemap from '@astrojs/sitemap'
import tailwind from '@astrojs/tailwind'
import {
transformerMetaHighlight,
transformerNotationDiff,
} from '@shikijs/transformers'
import { defineConfig } from 'astro/config'
import rehypeKatex from 'rehype-katex'
import rehypePrettyCode from 'rehype-pretty-code'
import remarkEmoji from 'remark-emoji'
import remarkMath from 'remark-math'
import remarkToc from 'remark-toc'
import react from '@astrojs/react'
// https://astro.build/config
export default defineConfig({
site: 'https://astro-micro-academic.vercel.app',
@ -22,10 +26,28 @@ export default defineConfig({
react(),
],
markdown: {
shikiConfig: {
theme: 'css-variables',
},
rehypePlugins: [rehypeHeadingIds, rehypeKatex],
// shikiConfig: {
// transformers: [
// transformerNotationDiff(),
// transformerNotationFocus(),
// transformerMetaHighlight(),
// ],
// },
syntaxHighlight: false,
rehypePlugins: [
rehypeHeadingIds,
rehypeKatex,
[
rehypePrettyCode,
{
theme: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
transformers: [transformerNotationDiff(), transformerMetaHighlight()],
},
],
],
remarkPlugins: [remarkToc, remarkMath, remarkEmoji],
},
server: {

86
package-lock.json generated
View file

@ -22,6 +22,7 @@
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@shikijs/transformers": "^1.16.3",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"astro": "^4.11.3",
@ -32,6 +33,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rehype-katex": "^7.0.0",
"rehype-pretty-code": "^0.14.0",
"remark-emoji": "^5.0.1",
"remark-math": "^6.0.0",
"remark-toc": "^9.0.0",
@ -2551,14 +2553,29 @@
]
},
"node_modules/@shikijs/core": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz",
"integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==",
"license": "MIT",
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.16.3.tgz",
"integrity": "sha512-yETIvrETCeC39gSPIiSADmjri9FwKmxz0QvONMtTIUYlKZe90CJkvcjPksayC2VQOtzOJonEiULUa8v8crUQvA==",
"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": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@ -4747,6 +4764,18 @@
"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": {
"version": "4.0.2",
"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"
}
},
"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": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz",
@ -6899,6 +6936,11 @@
"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": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
@ -7563,6 +7605,11 @@
"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": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.1.tgz",
@ -7612,6 +7659,25 @@
"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": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
@ -8106,12 +8172,12 @@
}
},
"node_modules/shiki": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz",
"integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==",
"license": "MIT",
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.16.3.tgz",
"integrity": "sha512-GypUE+fEd06FqDs63LSAVlmq7WsahhPQU62cgZxGF+TJT5LjD2k7HTxXj4/CKOVuMM3+wWQ1t4Y5oooeJFRRBQ==",
"dependencies": {
"@shikijs/core": "1.10.3",
"@shikijs/core": "1.16.3",
"@shikijs/vscode-textmate": "^9.2.0",
"@types/hast": "^3.0.4"
}
},

View file

@ -26,6 +26,7 @@
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@shikijs/transformers": "^1.16.3",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"astro": "^4.11.3",
@ -36,6 +37,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rehype-katex": "^7.0.0",
"rehype-pretty-code": "^0.14.0",
"remark-emoji": "^5.0.1",
"remark-math": "^6.0.0",
"remark-toc": "^9.0.0",

View file

@ -65,21 +65,23 @@ if (
<div
class="mb-2 flex items-center space-x-2 text-xs text-muted-foreground"
>
{author && (
<>
<div class="flex items-center gap-1.5">
<Image
src={author.data.avatar}
alt={author.data.name}
width={18}
height={18}
class="rounded-full"
/>
<span>{author.data.name}</span>
</div>
<Separator orientation="vertical" className="h-4" />
</>
)}
{
author && (
<>
<div class="flex items-center gap-1.5">
<Image
src={author.data.avatar}
alt={author.data.name}
width={18}
height={18}
class="rounded-full"
/>
<span>{author.data.name}</span>
</div>
<Separator orientation="vertical" className="h-4" />
</>
)
}
<span>{formattedDate}</span>
<Separator orientation="vertical" className="h-4" />
<span>{readTime}</span>

View file

@ -2,6 +2,7 @@
import '../styles/global.css'
import '../styles/katex.css'
import '../styles/typography.css'
import '../styles/codeblocks.css'
import '@fontsource/geist-sans'
import '@fontsource/geist-mono'

View file

@ -12,28 +12,42 @@ const { prevPost, nextPost } = Astro.props
href={prevPost ? `/blog/${prevPost.slug}` : '#'}
class={cn(
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',
)}
aria-disabled={!prevPost}
>
<ArrowLeft
className="h-4 w-4 transition-transform group-hover:-translate-x-1"
/>
<span class="truncate">{prevPost?.data.title || 'Latest post!'}</span>
<div class="mr-2 flex-shrink-0">
<ArrowLeft
className="h-4 w-4 transition-transform group-hover:-translate-x-1"
/>
</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
href={nextPost ? `/blog/${nextPost.slug}` : '#'}
class={cn(
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',
)}
aria-disabled={!nextPost}
>
<span class="truncate">{nextPost?.data.title || 'Last post!'}</span>
<ArrowRight
className="h-4 w-4 transition-transform group-hover:translate-x-1"
/>
<div class="flex flex-col items-end overflow-hidden">
<span class="text-right text-xs text-muted-foreground">Next Post</span>
<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>
</div>

View file

@ -40,8 +40,12 @@ function buildToc(headings: Heading[]) {
<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"
>
<h2 class="mb-4 text-xl font-semibold">Table of Contents</h2>
<ul class="space-y-2">
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
</ul>
<div class="mr-6 flex justify-end">
<ul class="space-y-2">
<li>
<h2 class="mb-2 text-lg font-semibold">Table of Contents</h2>
</li>
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
</ul>
</div>
</nav>

View file

@ -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<
HTMLDivElement,
@ -9,13 +9,13 @@ const Card = React.forwardRef<
<div
ref={ref}
className={cn(
"rounded-xl border bg-card text-card-foreground shadow",
className
'rounded-xl border bg-card text-card-foreground shadow',
className,
)}
{...props}
/>
))
Card.displayName = "Card"
Card.displayName = 'Card'
const CardHeader = React.forwardRef<
HTMLDivElement,
@ -23,11 +23,11 @@ const CardHeader = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
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}
/>
))
CardHeader.displayName = "CardHeader"
CardHeader.displayName = 'CardHeader'
const CardTitle = React.forwardRef<
HTMLParagraphElement,
@ -35,11 +35,11 @@ const CardTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn("font-semibold leading-none tracking-tight", className)}
className={cn('font-semibold leading-none tracking-tight', className)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"
CardTitle.displayName = 'CardTitle'
const CardDescription = React.forwardRef<
HTMLParagraphElement,
@ -47,19 +47,19 @@ const CardDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"
CardDescription.displayName = 'CardDescription'
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ 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<
HTMLDivElement,
@ -67,10 +67,10 @@ const CardFooter = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
className={cn('flex items-center p-6 pt-0', className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"
CardFooter.displayName = 'CardFooter'
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }

View file

@ -7,107 +7,270 @@ image: '/1200x630.png'
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
![Alt text](./full/or/relative/path/of/image)
```
#### Output
![blog placeholder](/blog-placeholder-about.jpg)
## Blockquotes
> Blockquotes can also be nested...
>
> > ...by using additional greater-than signs right next to each other...
> >
> > > ...or with spaces between arrows.
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.
## Lists
### Blockquote without attribution
Unordered
#### Syntax
- Create a list by starting a line with `+`, `-`, or `*`
- Sub-lists are made by indenting 2 spaces:
- Marker character change forces new list start:
- 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...
```markdown
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
> **Note** that you can use _Markdown syntax_ within a blockquote.
```
Syntax highlighting
#### Output
```js
var foo = function (bar) {
return bar++
}
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
> **Note** that you can use _Markdown syntax_ within a blockquote.
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
| Option | Description |
| ------ | ------------------------------------------------------------------------- |
| 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. |
#### Syntax
Right aligned columns
```markdown
| Italics | Bold | Code |
| --------- | -------- | ------ |
| _italics_ | **bold** | `code` |
```
| Option | Description |
| -----: | ------------------------------------------------------------------------: |
| 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. |
#### Output
## 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)
})
```

View file

@ -18,7 +18,7 @@ const { title, description } = Astro.props
<Head title={`${title} | ${SITE.TITLE}`} description={description} />
</head>
<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 />
<main class="flex-grow">

View file

@ -17,7 +17,7 @@ import { HomeIcon } from 'lucide-react'
<Layout title="404" description={SITE.DESCRIPTION}>
<Container>
<Breadcrumb className="mb-4">
<Breadcrumb className="mb-6">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/"

View file

@ -16,7 +16,7 @@ import { HomeIcon } from 'lucide-react'
<Layout title="About" description={SITE.DESCRIPTION}>
<Container>
<Breadcrumb className="mb-4">
<Breadcrumb className="mb-6">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/"

View file

@ -47,7 +47,7 @@ const authorPosts = allPosts
description={author.data.bio || `Profile of ${author.data.name}`}
>
<Container>
<Breadcrumb className="mb-4">
<Breadcrumb className="mb-6">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/"

View file

@ -18,7 +18,7 @@ const authors = await getCollection('authors')
<Layout title="Authors" description="Authors">
<Container>
<Breadcrumb className="mb-4">
<Breadcrumb className="mb-6">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/"

View file

@ -78,7 +78,7 @@ if (
<Layout title={post.data.title} description={post.data.description}>
<Container>
<Breadcrumb className="mb-4">
<Breadcrumb className="mb-6">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/"

View file

@ -35,7 +35,7 @@ const years = Object.keys(posts).sort((a, b) => parseInt(b) - parseInt(a))
<Layout title="Blog" description="Blog">
<Container>
<Breadcrumb className="mb-4">
<Breadcrumb className="mb-6">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/"

View file

@ -6,7 +6,13 @@ import BlogCard from '@components/BlogCard.astro'
import { buttonVariants } from '@/components/ui/button'
import { getCollection } from 'astro:content'
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'))
.filter((post) => !post.data.draft)

61
src/styles/codeblocks.css Normal file
View 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);
}
}

View file

@ -2,7 +2,7 @@
@tailwind components;
@tailwind utilities;
@layer base {
@layer components {
article {
@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;

View file

@ -1,6 +1,16 @@
import type { Config } from 'tailwindcss'
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 = {
darkMode: ['selector'],
content: ['./src/**/*.{astro,md,mdx,ts,tsx}'],
@ -57,6 +67,13 @@ const config: Config = {
'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')],