Skip to content

Commit d00f733

Browse files
Fix syntax highlighting, add og meta/404/sitemap, appendix intros, title typos
1 parent 1ad45d7 commit d00f733

23 files changed

Lines changed: 159 additions & 42 deletions

File tree

‎app/book/[part]/chapter/[slug]/page.tsx‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import ChapterNav from '@/components/ChapterNav'
77
import remarkGfm from 'remark-gfm'
88
import rehypeSlug from 'rehype-slug'
99
import rehypeHighlight from 'rehype-highlight'
10+
import type { PluggableList } from 'unified'
11+
// highlight.js ships no racket grammar; scheme shares the s-expression shape.
12+
import scheme from 'highlight.js/lib/languages/scheme'
13+
14+
const mdxPlugins: PluggableList = [rehypeSlug, [rehypeHighlight, { languages: { racket: scheme } }]]
1015

1116
export function generateStaticParams() {
1217
return getAllChapterPaths().map(p => ({ part: p.part, slug: p.slug }))
@@ -42,7 +47,7 @@ export default async function ChapterPage({ params }: { params: { part: string;
4247
options={{
4348
mdxOptions: {
4449
remarkPlugins: [remarkGfm],
45-
rehypePlugins: [rehypeSlug, rehypeHighlight],
50+
rehypePlugins: mdxPlugins,
4651
},
4752
}}
4853
/>

‎app/book/preface/page.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { mdxComponents } from '@/app/mdx-components'
77
import remarkGfm from 'remark-gfm'
88
import rehypeSlug from 'rehype-slug'
99
import rehypeHighlight from 'rehype-highlight'
10+
// highlight.js ships no racket grammar; scheme shares the s-expression shape.
11+
import scheme from 'highlight.js/lib/languages/scheme'
1012

1113
export const metadata = {
1214
title: '写在前面 | Racket 编程入门',
@@ -31,7 +33,7 @@ export default function PrefacePage() {
3133
options={{
3234
mdxOptions: {
3335
remarkPlugins: [remarkGfm],
34-
rehypePlugins: [rehypeSlug, rehypeHighlight],
36+
rehypePlugins: [rehypeSlug, [rehypeHighlight, { languages: { racket: scheme } }]],
3537
},
3638
}}
3739
/>

‎app/globals.css‎

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,38 @@
2424
::-webkit-scrollbar-thumb:hover { background: #b8b3a8; }
2525

2626
/* Code blocks */
27-
pre {
28-
position: relative;
29-
border: 1px solid #E8E5DE;
30-
}
3127
pre code {
3228
display: block;
3329
line-height: 1.7;
3430
}
3531

36-
/* Racket syntax highlighting */
37-
.language-racket .keyword { color: #D97757; }
38-
.language-racket .string { color: #5E8C4A; }
39-
.language-racket .number { color: #8B6BAE; }
40-
.language-racket .comment { color: #A39E93; font-style: italic; }
41-
.language-racket .function { color: #3A7CA5; }
32+
/* Inline code chips (outside <pre>) — block code inside <pre> stays bare */
33+
.prose :not(pre) > code {
34+
background: #F5F3EE;
35+
color: #C4683F;
36+
padding: 0.15em 0.375em;
37+
border-radius: 0.25rem;
38+
font-size: 0.875em;
39+
font-family: var(--font-mono);
40+
}
41+
.prose pre > code {
42+
background: transparent;
43+
padding: 0;
44+
border-radius: 0;
45+
font-size: inherit;
46+
color: inherit;
47+
}
48+
49+
/* Syntax highlighting (highlight.js classes emitted by rehype-highlight) */
50+
.hljs-keyword, .hljs-selector-tag, .hljs-built_in, .hljs-symbol { color: #E08A67; }
51+
.hljs-string, .hljs-regexp { color: #97B87A; }
52+
.hljs-number, .hljs-literal { color: #B48ED8; }
53+
.hljs-comment, .hljs-quote { color: #8A857A; font-style: italic; }
54+
.hljs-title, .hljs-name { color: #7AADD3; }
55+
.hljs-type, .hljs-class { color: #63B0B0; }
56+
.hljs-attr, .hljs-attribute, .hljs-variable, .hljs-template-variable { color: #D9A967; }
57+
.hljs-section, .hljs-bullet { color: #E08A67; }
58+
.hljs-meta, .hljs-meta .hljs-keyword { color: #A39E93; }
59+
.hljs-operator, .hljs-punctuation { color: #C7C2B8; }
60+
.hljs-emphasis { font-style: italic; }
61+
.hljs-strong { font-weight: 700; }

‎app/layout.tsx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,22 @@ import type { Metadata } from 'next'
22
import './globals.css'
33

44
export const metadata: Metadata = {
5+
metadataBase: new URL('https://racket.jrtx.site'),
56
title: 'Racket 编程入门',
67
description: '从零基础到独立开发应用,全面掌握 Racket 编程。',
8+
openGraph: {
9+
type: 'website',
10+
siteName: 'Racket 编程入门',
11+
title: 'Racket 编程入门',
12+
description: '从零基础到独立开发应用,全面掌握 Racket 编程。',
13+
images: [{ url: '/og.jpg', width: 1200, height: 630, alt: 'Racket 编程入门' }],
14+
},
15+
twitter: {
16+
card: 'summary_large_image',
17+
title: 'Racket 编程入门',
18+
description: '从零基础到独立开发应用,全面掌握 Racket 编程。',
19+
images: ['/og.jpg'],
20+
},
721
}
822

923
export default function RootLayout({

‎app/mdx-components.tsx‎

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,14 @@ export const mdxComponents: MDXComponents = {
2626
<ol className="text-sand-800 mb-5 space-y-2 list-decimal pl-6 marker:text-sand-400">{children}</ol>
2727
),
2828
li: ({ children }) => <li className="leading-[1.8] pl-1">{children}</li>,
29-
code: ({ children, className }) => {
30-
const isBlock = className?.includes('language-')
31-
if (isBlock) {
32-
return (
33-
<pre className="bg-sand-900 text-sand-100 rounded-lg p-5 overflow-x-auto text-sm my-8 font-mono leading-[1.7]">
34-
<code className={className}>{children}</code>
35-
</pre>
36-
)
37-
}
38-
return (
39-
<code className="bg-sand-100 text-accent-600 px-1.5 py-0.5 rounded text-[0.875em] font-mono">
40-
{children}
41-
</code>
42-
)
43-
},
29+
pre: ({ children }) => (
30+
<pre className="!bg-sand-900 !text-sand-100 !rounded-lg !p-5 overflow-x-auto !text-sm my-8 font-mono !leading-[1.7] border border-sand-800">
31+
{children}
32+
</pre>
33+
),
34+
code: ({ children, className }) => (
35+
<code className={className}>{children}</code>
36+
),
4437
blockquote: ({ children }) => (
4538
<blockquote className="border-l-2 border-accent-400 pl-4 py-2 my-8 text-sand-600 italic">
4639
{children}

‎app/not-found.tsx‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Link from 'next/link'
2+
3+
export const metadata = {
4+
title: '页面不存在 | Racket 编程入门',
5+
}
6+
7+
export default function NotFound() {
8+
return (
9+
<div className="min-h-screen bg-sand-50 flex flex-col items-center justify-center px-6 text-center">
10+
<p className="text-xs tracking-widest uppercase text-sand-500 mb-4">404</p>
11+
<h1 className="text-3xl font-bold text-sand-900 tracking-tight mb-4">
12+
这一页不存在
13+
</h1>
14+
<p className="text-sand-600 mb-10 max-w-sm leading-relaxed">
15+
你找的章节可能换了地址,也可能还没写出来。
16+
</p>
17+
<div className="flex items-center gap-4">
18+
<Link
19+
href="/"
20+
className="inline-flex items-center px-5 py-2.5 bg-sand-900 text-sand-50 rounded-lg text-sm font-medium hover:bg-sand-800 transition-colors"
21+
>
22+
回到首页
23+
</Link>
24+
<Link
25+
href="/book/part-1/chapter/1"
26+
className="inline-flex items-center px-5 py-2.5 border border-sand-300 text-sand-700 rounded-lg text-sm font-medium hover:bg-sand-100 transition-colors"
27+
>
28+
从第 1 章开始
29+
</Link>
30+
</div>
31+
</div>
32+
)
33+
}

‎app/sitemap.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { MetadataRoute } from 'next'
2+
import { getParts, getPreface } from '@/lib/content'
3+
4+
const BASE = 'https://racket.jrtx.site'
5+
6+
export default function sitemap(): MetadataRoute.Sitemap {
7+
const entries: MetadataRoute.Sitemap = [{ url: BASE }]
8+
9+
const preface = getPreface()
10+
if (preface) entries.push({ url: `${BASE}${preface.href}` })
11+
12+
for (const part of getParts()) {
13+
entries.push({ url: `${BASE}/book/${part.id}` })
14+
for (const ch of part.chapters) {
15+
entries.push({ url: `${BASE}/book/${part.id}/chapter/${ch.slug}` })
16+
}
17+
}
18+
return entries
19+
}

‎content/appendix/1.mdx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Noise 精读(一):三层架构与异步模型
22

3+
> 想在 iOS 或 macOS 应用里嵌入一个像 Racket 这样的 Lisp 运行时?这一篇从 Noise 的三层架构与异步模型讲起,为整个系列搭好骨架。
4+
35
你是否想过在你的 iOS 或 macOS 应用中嵌入一个像 Racket 这样的 Lisp 运行时?或者,你是否在使用其他语言(如 Python, Rust, Go)时,想要引入某种脚本语言的能力,却苦于不知道如何优雅地实现跨语言交互?
46

57
[Noise](https://github.com/Bogdanp/Noise) 项目提供了一个非常精彩的范例。它不仅仅是一个简单的 FFI 绑定,更是一套完整的、类型安全的、支持异步并发的 **嵌入式后端架构**。

‎content/appendix/10.mdx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Racket 编译完全指南
22

3+
> 从源代码编译 Racket:Linux、macOS、Windows 三平台的完整步骤,以及编译过程中值得看懂的那些实现细节。
4+
35
作为一名开发者,从源代码编译 Racket 不仅能让你获得最新的功能和性能优化,还能深入了解这个强大的语言实现。无论你是在 Linux、macOS 还是 Windows 上,这篇指南都会带你一步步完成编译过程。
46

57
## 仓库结构

‎content/appendix/11.mdx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Racket 语言实现剖析
22

3+
> 跳过语法和生态,直接看一门语言的实现本身:Racket 从 Chez Scheme 继承了什么,编译管线与运行时如何协作。
4+
35
很多语言在介绍时都会强调语法、范式、库生态,但当你真正开始研究一门语言的 **实现本身** 时,关注点会自然转向另一些问题:
46

57
> 这门语言的 “ 本体 ” 是什么?

0 commit comments

Comments
 (0)