create-riebeckite 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +7 -7
  2. package/README_ja.md +2 -2
  3. package/dist/src/arguments.d.ts +3 -5
  4. package/dist/src/index.js +3161 -37
  5. package/dist/src/interactive.d.ts +8 -9
  6. package/dist/src/scaffold/content-pages.d.ts +16 -0
  7. package/dist/src/scaffold/deployment.d.ts +7 -0
  8. package/dist/src/scaffold/index.d.ts +7 -0
  9. package/dist/src/scaffold/index.js +3134 -0
  10. package/dist/src/scaffold/next-steps.d.ts +7 -0
  11. package/dist/src/scaffold/options.d.ts +43 -0
  12. package/dist/src/scaffold/presets.d.ts +102 -0
  13. package/dist/src/scaffold/template-loader.d.ts +4 -0
  14. package/dist/src/scaffold/templates.d.ts +53 -0
  15. package/dist/src/scaffold/version.d.ts +1 -0
  16. package/dist/src/scaffold/wrangler-defaults.d.ts +46 -0
  17. package/package.json +16 -5
  18. package/templates/scaffold/base/app/client.ts +14 -0
  19. package/templates/scaffold/base/app/config.ts +18 -0
  20. package/templates/scaffold/base/app/constants/paths.ts +10 -0
  21. package/templates/scaffold/base/app/content.ts +12 -0
  22. package/templates/scaffold/base/app/global.d.ts +15 -0
  23. package/templates/scaffold/base/app/server.ts +13 -0
  24. package/templates/scaffold/base/public/favicon.ico +0 -0
  25. package/templates/scaffold/base/public/riebeckite-logo.png +0 -0
  26. package/templates/scaffold/base/tsconfig.json +30 -0
  27. package/templates/scaffold/base/vite.config.ts +34 -0
  28. package/templates/scaffold/biome.json +6 -0
  29. package/templates/scaffold/deployment/github-actions/content-checkout.yml +6 -0
  30. package/templates/scaffold/deployment/github-actions/deploy.yml +54 -0
  31. package/templates/scaffold/deployment/github-actions/notify-site.yml +31 -0
  32. package/templates/scaffold/presets/empty/app/routes/_renderer.tsx +21 -0
  33. package/templates/scaffold/presets/empty/app/routes/index.tsx +11 -0
  34. package/templates/scaffold/presets/empty/app/style.css +17 -0
  35. package/templates/scaffold/presets/minimal/app/components/article.tsx +66 -0
  36. package/templates/scaffold/presets/minimal/app/routes/[slug{.+}].tsx +48 -0
  37. package/templates/scaffold/presets/minimal/app/routes/_renderer.tsx +59 -0
  38. package/templates/scaffold/presets/minimal/app/routes/index.tsx +29 -0
  39. package/templates/scaffold/presets/minimal/app/style.css +84 -0
  40. package/templates/scaffold/presets/minimal/content/index.en.md +12 -0
  41. package/templates/scaffold/presets/showcase/app/components/article.tsx +66 -0
  42. package/templates/scaffold/presets/showcase/app/components/site-header.tsx +113 -0
  43. package/templates/scaffold/presets/showcase/app/routes/[slug{.+}].tsx +52 -0
  44. package/templates/scaffold/presets/showcase/app/routes/_renderer.tsx +69 -0
  45. package/templates/scaffold/presets/showcase/app/routes/index.tsx +39 -0
  46. package/templates/scaffold/presets/showcase/app/style.css +227 -0
  47. package/templates/scaffold/presets/showcase/content/attachments/project-brief.pdf +5 -0
  48. package/templates/scaffold/presets/showcase/content/demo/planning.md +16 -0
  49. package/templates/scaffold/presets/showcase/content/demo/writing.md +15 -0
  50. package/templates/scaffold/presets/showcase/content/drawings/Architecture.excalidraw +1 -0
  51. package/templates/scaffold/presets/showcase/content/drawings/site.canvas +1 -0
  52. package/templates/scaffold/presets/showcase/content/guide.en.md +46 -0
  53. package/templates/scaffold/presets/showcase/content/images/demo.svg +1 -0
  54. package/templates/scaffold/presets/showcase/content/index.de.md +17 -0
  55. package/templates/scaffold/presets/showcase/content/index.en.md +17 -0
  56. package/templates/scaffold/presets/showcase/content/index.es.md +17 -0
  57. package/templates/scaffold/presets/showcase/content/index.fr.md +17 -0
  58. package/templates/scaffold/presets/showcase/content/index.ja.md +17 -0
  59. package/templates/scaffold/presets/showcase/content/index.ko.md +17 -0
  60. package/templates/scaffold/presets/showcase/content/index.zh-CN.md +17 -0
  61. package/templates/scaffold/presets/starter/app/components/article.tsx +66 -0
  62. package/templates/scaffold/presets/starter/app/components/site-header.tsx +113 -0
  63. package/templates/scaffold/presets/starter/app/routes/[slug{.+}].tsx +52 -0
  64. package/templates/scaffold/presets/starter/app/routes/_renderer.tsx +69 -0
  65. package/templates/scaffold/presets/starter/app/routes/index.tsx +37 -0
  66. package/templates/scaffold/presets/starter/app/style.css +227 -0
  67. package/templates/scaffold/presets/starter/content/guide.en.md +60 -0
  68. package/templates/scaffold/presets/starter/content/index.de.md +19 -0
  69. package/templates/scaffold/presets/starter/content/index.en.md +19 -0
  70. package/templates/scaffold/presets/starter/content/index.es.md +19 -0
  71. package/templates/scaffold/presets/starter/content/index.fr.md +19 -0
  72. package/templates/scaffold/presets/starter/content/index.ja.md +19 -0
  73. package/templates/scaffold/presets/starter/content/index.ko.md +19 -0
  74. package/templates/scaffold/presets/starter/content/index.zh-CN.md +19 -0
  75. package/templates/scaffold/presets/starter/content/notes/planning.md +16 -0
  76. package/templates/scaffold/presets/starter/content/notes/writing.md +15 -0
@@ -0,0 +1,227 @@
1
+ @import "./.riebeckite/plugin-styles.css";
2
+ @import "./.riebeckite/theme-styles.css";
3
+
4
+ *,
5
+ *::before,
6
+ *::after {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ body {
11
+ margin: 0;
12
+ font-family: system-ui, sans-serif;
13
+ }
14
+
15
+ .riebeckite-page {
16
+ display: flex;
17
+ min-height: 100vh;
18
+ width: 100%;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ padding-block: var(--rb-space-8, 4rem);
22
+ }
23
+
24
+ .site-header {
25
+ display: flex;
26
+ align-items: center;
27
+ gap: var(--rb-space-3, 1.5rem);
28
+ padding-block: var(--rb-space-3, 1.5rem);
29
+ border-bottom: 1px solid var(--rb-color-border);
30
+ }
31
+
32
+ .site-header,
33
+ .rb-site-footer {
34
+ width: min(100% - 2rem, var(--rb-layout-article-max, 48rem));
35
+ }
36
+
37
+ .site-header__home {
38
+ display: inline-flex;
39
+ align-items: center;
40
+ gap: 0.5rem;
41
+ margin-right: auto;
42
+ color: var(--rb-color-ink);
43
+ font-weight: 700;
44
+ text-decoration: none;
45
+ }
46
+
47
+ .rb-nav {
48
+ color: var(--rb-color-ink);
49
+ }
50
+
51
+ .rb-nav__list {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: var(--rb-space-3, 1.5rem);
55
+ margin: 0;
56
+ padding: 0;
57
+ list-style: none;
58
+ }
59
+
60
+ .rb-nav__item {
61
+ position: relative;
62
+ }
63
+
64
+ .rb-nav__link {
65
+ color: inherit;
66
+ text-decoration: none;
67
+ }
68
+
69
+ .rb-nav__link:hover,
70
+ .rb-nav__link:focus-visible,
71
+ .rb-nav__link--active {
72
+ color: var(--rb-color-accent);
73
+ }
74
+
75
+ .rb-nav__link:focus-visible,
76
+ .rb-nav__toggle:focus-visible {
77
+ outline: 2px solid var(--rb-color-accent);
78
+ outline-offset: 2px;
79
+ }
80
+
81
+ .rb-nav__children {
82
+ display: none;
83
+ position: absolute;
84
+ top: 100%;
85
+ left: 0;
86
+ min-width: max-content;
87
+ padding: var(--rb-space-2, 1rem);
88
+ background: var(--rb-color-surface);
89
+ border: 1px solid var(--rb-color-border);
90
+ }
91
+
92
+ .rb-nav__item:hover > .rb-nav__children,
93
+ .rb-nav__item:focus-within > .rb-nav__children {
94
+ display: flex;
95
+ flex-direction: column;
96
+ align-items: stretch;
97
+ }
98
+
99
+ .rb-nav__mobile {
100
+ display: none;
101
+ }
102
+
103
+ .rb-site-footer {
104
+ margin-top: 1rem;
105
+ padding-block: var(--rb-space-4, 2rem);
106
+ border-top: 1px solid var(--rb-color-border);
107
+ }
108
+
109
+ @media (max-width: 48rem) {
110
+ .riebeckite-page {
111
+ padding-block: var(--rb-space-3, 1.5rem);
112
+ }
113
+
114
+ .rb-site-header {
115
+ flex-wrap: wrap;
116
+ }
117
+
118
+ .rb-site-header > .rb-nav {
119
+ display: none;
120
+ }
121
+
122
+ .rb-nav__mobile {
123
+ position: relative;
124
+ display: block;
125
+ }
126
+
127
+ .rb-nav__mobile > .rb-nav {
128
+ position: absolute;
129
+ z-index: 10;
130
+ top: calc(100% + var(--rb-space-2, 1rem));
131
+ right: 0;
132
+ min-width: 12rem;
133
+ padding: var(--rb-space-3, 1.5rem);
134
+ background: var(--rb-color-surface);
135
+ border: 1px solid var(--rb-color-border);
136
+ box-shadow: 0 4px 12px
137
+ color-mix(in oklab, var(--rb-color-ink) 14%, transparent);
138
+ }
139
+
140
+ .rb-nav__mobile .rb-nav__list,
141
+ .rb-nav__mobile .rb-nav__children {
142
+ display: flex;
143
+ flex-direction: column;
144
+ align-items: flex-start;
145
+ gap: var(--rb-space-2, 1rem);
146
+ }
147
+
148
+ .rb-nav__mobile .rb-nav__list {
149
+ padding: 0;
150
+ }
151
+
152
+ .rb-nav__mobile .rb-nav__children {
153
+ position: static;
154
+ margin-top: var(--rb-space-2, 1rem);
155
+ padding: 0;
156
+ background: transparent;
157
+ border: 0;
158
+ }
159
+ }
160
+
161
+ .site-header__logo {
162
+ width: 1.75rem;
163
+ height: 1.75rem;
164
+ object-fit: contain;
165
+ }
166
+
167
+ .site-article {
168
+ display: block;
169
+ width: min(100% - 2rem, var(--rb-layout-article-max, 48rem));
170
+ padding-block: 2rem;
171
+ margin: 0 auto;
172
+ }
173
+
174
+ .rb-article-layout {
175
+ display: grid;
176
+ grid-template-columns: minmax(0, var(--rb-layout-article-max, 48rem));
177
+ justify-content: center;
178
+ gap: var(--rb-layout-gap, 2rem);
179
+ }
180
+
181
+ .rb-article-body {
182
+ min-width: 0;
183
+ padding-inline: var(--rb-space-2, 1rem);
184
+ }
185
+
186
+ .site-article__aside {
187
+ display: none;
188
+ }
189
+
190
+ .site-article__footer {
191
+ min-width: 0;
192
+ }
193
+
194
+ @media (min-width: 88rem) {
195
+ :is(:root, .rb-theme-root)[data-article-layout="article"] .rb-article-layout {
196
+ grid-template-columns: minmax(0, var(--rb-layout-article-max, 48rem));
197
+ position: relative;
198
+ }
199
+
200
+ :is(:root, .rb-theme-root)[data-article-layout="article"] .rb-article-body {
201
+ grid-column: 1;
202
+ grid-row: 1;
203
+ }
204
+
205
+ :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__footer {
206
+ grid-column: 1;
207
+ }
208
+
209
+ :is(:root, .rb-theme-root)[data-article-layout="article"] .site-article__aside {
210
+ display: block;
211
+ grid-column: 1;
212
+ grid-row: 1;
213
+ position: sticky;
214
+ top: 4rem;
215
+ align-self: start;
216
+ width: var(--rb-layout-sidebar, 14rem);
217
+ max-height: calc(100dvh - 8rem);
218
+ margin-inline-start: calc(
219
+ -1 * var(--rb-layout-sidebar, 14rem) -
220
+ var(--rb-layout-gap, 2rem)
221
+ );
222
+ overflow: auto;
223
+ padding-inline-end: 1rem;
224
+ border-inline-end: 1px solid
225
+ color-mix(in oklab, currentColor 18%, transparent);
226
+ }
227
+ }
@@ -0,0 +1,5 @@
1
+ %PDF-1.1
2
+ 1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
3
+ 2 0 obj<</Type/Pages/Count 0/Kids[]>>endobj
4
+ trailer<</Root 1 0 R>>
5
+ %%EOF
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Planning a Markdown site
3
+ description: A related note used by the generated discovery examples.
4
+ date: 2026-09-30
5
+ tags: [riebeckite, project]
6
+ status: active
7
+ aliases: [/start-here/]
8
+ series: publish-a-site
9
+ series_title: Publish a site
10
+ series_order: 1
11
+ publish: true
12
+ ---
13
+
14
+ # Planning a Markdown site
15
+
16
+ Start with [[writing]] to see backlinks, related posts, tags, and the series navigation working together.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: Writing the first note
3
+ description: A second connected note for search and related-content examples.
4
+ date: 2026-10-01
5
+ tags: [riebeckite, project]
6
+ status: active
7
+ series: publish-a-site
8
+ series_title: Publish a site
9
+ series_order: 2
10
+ publish: true
11
+ ---
12
+
13
+ # Writing the first note
14
+
15
+ This note links back to [[planning]]. Search for **Markdown site** or browse the generated tags.
@@ -0,0 +1 @@
1
+ {"type":"excalidraw","version":2,"elements":[],"appState":{"viewBackgroundColor":"#ffffff"},"files":{}}
@@ -0,0 +1 @@
1
+ {"nodes":[{"id":"note","type":"text","text":"Note","x":0,"y":0,"width":200,"height":60}],"edges":[]}
@@ -0,0 +1,46 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # Getting started
6
+
7
+ This site was generated from a Riebeckite scaffold preset. Everything
8
+ you see lives in this repository, ready to edit.
9
+
10
+ ## Add a page
11
+
12
+ Drop a Markdown file into `content/` with `publish: true` in its
13
+ frontmatter and it appears in the built site:
14
+
15
+ ```md
16
+ ---
17
+ publish: true
18
+ ---
19
+
20
+ # Hello
21
+
22
+ Body text...
23
+ ```
24
+
25
+
26
+ ## Run the site
27
+
28
+ ```sh
29
+ npm install
30
+ npm exec riebeckite dev
31
+ npm exec riebeckite build
32
+ ```
33
+
34
+
35
+ ## Localize a page
36
+
37
+ Add a translated file next to the default one using the
38
+ `<base>.<lang>.md` convention (`about.ja.md`, `about.en.md`). With the
39
+ l10n plugin enabled, translations are served under `/lang/` paths and
40
+ linked by the language switcher.
41
+
42
+ ## Extend
43
+
44
+ Plugins and themes are registered in `riebeckite.config.ts`. Install a
45
+ package, import its factory, and add it to the `plugins` array or point
46
+ `theme` at a new theme factory.
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="640" height="360" viewBox="0 0 640 360"><rect width="640" height="360" fill="#315b8c"/><text x="320" y="180" fill="white" font-size="32" text-anchor="middle">Riebeckite showcase</text></svg>
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ Willkommen auf deiner Riebeckite-Seite.
7
+ Jede Seite dieses Starters ist in sieben Sprachen verfügbar. Wechsel mit dem Auswahlfeld unter dem Seitentitel.
8
+ ## Was ist Riebeckite?
9
+ Riebeckite ist ein erweiterbares, inhaltsorientiertes Framework, das schnelle statische Seiten aus einfachem Markdown baut — denselben Notizen, die du in Obsidian führst. Das Ökosystem umfasst 50+ Plugins und sechs Themes; diese Seite demonstriert beides.
10
+ ## Weiter erkunden
11
+ - [Plugins — repräsentative Pakete nach Fähigkeit](/framework/plugins)
12
+ - [Themes — mitgelieferte Design-Pakete und wie man wechselt](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## Diese Seite bearbeiten
16
+ Inhalte liegen als einfaches Markdown in `content/`. Füge eine Datei hinzu, setze `publish: true` ins Frontmatter, und sie erscheint in der gebauten Seite.
17
+ Übersetzte Seiten folgen der Konvention `<base>.<lang>.md` neben der Standarddatei (z. B. `about.ja.md`). Das l10n-Plugin liefert sie unter `/lang/`-Pfaden und verlinkt sie automatisch.
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ Welcome to your Riebeckite site.
7
+ Every page of this starter is available in seven languages. Switch with the selector below the page title.
8
+ ## What is Riebeckite?
9
+ Riebeckite is an extensible, content-first framework that builds fast static sites from plain Markdown — the same notes you keep in Obsidian. The ecosystem includes 50+ plugins and six themes, and this site demos both.
10
+ ## Explore
11
+ - [Plugins — representative packages grouped by capability](/framework/plugins)
12
+ - [Themes — built-in design packages and how to switch](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## Edit this site
16
+ Content lives in `content/` as plain Markdown. Add a file, give it `publish: true` in the frontmatter, and it appears in the built site.
17
+ Localized pages use the `<base>.<lang>.md` convention next to the default file — for example `about.ja.md`. The l10n plugin serves them under `/lang/` paths and links them automatically.
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ Bienvenido a tu sitio Riebeckite.
7
+ Cada página de este starter está disponible en siete idiomas. Cámbialos con el selector bajo el título.
8
+ ## ¿Qué es Riebeckite?
9
+ Riebeckite es un framework extensible y orientado al contenido que construye sitios estáticos rápidos desde Markdown simple — las mismas notas que guardas en Obsidian. El ecosistema incluye más de 50 plugins y seis temas; este sitio demuestra ambos.
10
+ ## Explorar
11
+ - [Plugins — paquetes representativos por capacidad](/framework/plugins)
12
+ - [Temas — paquetes de diseño incluidos y cómo cambiar](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## Editar este sitio
16
+ El contenido vive en `content/` como Markdown simple. Añade un archivo, pon `publish: true` en el frontmatter y aparecerá en el sitio compilado.
17
+ Las páginas localizadas usan la convención `<base>.<lang>.md` junto al archivo por defecto (p. ej. `about.ja.md`). El plugin l10n las sirve bajo rutas `/lang/` y las enlaza automáticamente.
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ Bienvenue sur votre site Riebeckite.
7
+ Chaque page de ce starter est disponible en sept langues. Changez avec le sélecteur sous le titre.
8
+ ## Qu'est-ce que Riebeckite ?
9
+ Riebeckite est un framework extensible et centré sur le contenu qui construit des sites statiques rapides à partir de Markdown simple — les mêmes notes que vous gardez dans Obsidian. L'écosystème inclut plus de 50 plugins et six thèmes ; ce site en démontre les deux.
10
+ ## Explorer
11
+ - [Plugins — paquets représentatifs par capacité](/framework/plugins)
12
+ - [Thèmes — paquets de design inclus et comment changer](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## Éditer ce site
16
+ Le contenu vit dans `content/` en Markdown simple. Ajoutez un fichier, donnez-lui `publish: true` dans le frontmatter, et il apparaîtra dans le site construit.
17
+ Les pages localisées suivent la convention `<base>.<lang>.md` à côté du fichier par défaut (ex. `about.ja.md`). Le plugin l10n les sert sous des chemins `/lang/` et les relie automatiquement.
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ あなたの Riebeckite サイトへようこそ。
7
+ このスターターのすべてのページは 7 言語で利用できます。ページタイトル下のセレクターで切り替えられます。
8
+ ## Riebeckite とは
9
+ Riebeckite は、プレーンな Markdown(Obsidian で管理しているのと同じノート)から高速な静的サイトを生成する、拡張性のあるコンテンツファーストのフレームワークです。エコシステムには 50 以上のプラグインと 6 つのテーマがあり、このサイトはその両方をデモしています。
10
+ ## さらに深く
11
+ - [プラグイン — 機能別の代表的なパッケージ](/framework/plugins)
12
+ - [テーマ — 同梱のデザインパッケージと切り替え方](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## サイトの編集
16
+ コンテンツは `content/` にプレーンな Markdown として置きます。ファイルを追加してフロントマターに `publish: true` を書けば、ビルドされたサイトに反映されます。
17
+ 翻訳ページは既定ファイルの隣に `<base>.<lang>.md` の命名規則で置きます(例:`about.ja.md`)。l10n プラグインが `/lang/` パスの配下で配信し、自動的にリンクします。
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ Riebeckite 사이트에 오신 것을 환영합니다.
7
+ 이 스타터의 모든 페이지는 7개 언어로 제공됩니다. 페이지 제목 아래 선택기로 전환하세요.
8
+ ## Riebeckite란?
9
+ Riebeckite는 일반 Markdown(Obsidian에서 관리하는 노트)에서 빠른 정적 사이트를 만드는 확장 가능한 콘텐츠 우선 프레임워크입니다. 생태계에는 50개 이상의 플러그인과 6개 테마가 있으며, 이 사이트가 그 두 가지를 보여줍니다.
10
+ ## 더 살펴보기
11
+ - [플러그인 — 기능별 대표 패키지](/framework/plugins)
12
+ - [테마 — 내장 디자인 패키지와 전환 방법](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## 사이트 편집
16
+ 콘텐츠는 `content/`에 일반 Markdown으로 저장됩니다. 파일을 추가하고 프론트매터에 `publish: true`를 쓰면 빌드된 사이트에 나타납니다.
17
+ 번역 페이지는 기본 파일 옆에 `<base>.<lang>.md` 규칙으로 둡니다(예: `about.ja.md`). l10n 플러그인이 `/lang/` 경로로 서빙하며 자동으로 링크합니다.
@@ -0,0 +1,17 @@
1
+ ---
2
+ publish: true
3
+ ---
4
+
5
+ # {{title}}
6
+ 欢迎来到你的 Riebeckite 站点。
7
+ 本模板的每个页面均提供七种语言版本,可用页面标题下方的选择器切换。
8
+ ## 什么是 Riebeckite?
9
+ Riebeckite 是一个可扩展、内容优先的框架,可从纯 Markdown(即你在 Obsidian 中保存的笔记)构建快速的静态站点。生态包含 50+ 插件与六个主题,本站点同时演示两者。
10
+ ## 继续探索
11
+ - [插件 — 按能力分组的代表性包](/framework/plugins)
12
+ - [主题 — 内置设计包与切换方法](/framework/themes)
13
+ - [Working examples](/examples/)
14
+ - [Plugin reference](/reference/plugins/)
15
+ ## 编辑本站点
16
+ 内容以纯 Markdown 存于 `content/`。新建文件并在 frontmatter 中写入 `publish: true`,它就会出现在构建后的站点中。
17
+ 本地化页面采用默认文件旁的 `<base>.<lang>.md` 命名约定(例如 `about.ja.md`)。l10n 插件会在 `/lang/` 路径下提供服务并自动互链。
@@ -0,0 +1,66 @@
1
+ import type { PostContent } from "@riebeckite/core";
2
+ import { Article, ArticleContent, ArticleLayout } from "@riebeckite/honox/ui";
3
+
4
+ export function SiteArticle({
5
+ post,
6
+ bodySlots,
7
+ asideContent,
8
+ afterContent,
9
+ footerContent,
10
+ }: {
11
+ post: PostContent;
12
+ bodySlots?: Readonly<Record<string, string>>;
13
+ asideContent?: unknown;
14
+ afterContent?: unknown;
15
+ footerContent?: unknown;
16
+ }) {
17
+ return (
18
+ <Article class="site-article">
19
+ <ArticleLayout>
20
+ {asideContent}
21
+ {bodySlots?.["article.aside"] ? (
22
+ <div
23
+ class="site-article__aside"
24
+ dangerouslySetInnerHTML={{ __html: bodySlots["article.aside"] }}
25
+ />
26
+ ) : null}
27
+ <ArticleContent>
28
+ {bodySlots?.["article.header"] ? (
29
+ <div
30
+ class="site-article__header"
31
+ dangerouslySetInnerHTML={{ __html: bodySlots["article.header"] }}
32
+ />
33
+ ) : null}
34
+ {bodySlots?.["article.metadata"] ? (
35
+ <div
36
+ class="site-article__metadata"
37
+ dangerouslySetInnerHTML={{ __html: bodySlots["article.metadata"] }}
38
+ />
39
+ ) : null}
40
+ {bodySlots?.["article.before-content"] ? (
41
+ <div
42
+ class="site-article__before-content"
43
+ dangerouslySetInnerHTML={{ __html: bodySlots["article.before-content"] }}
44
+ />
45
+ ) : null}
46
+ <div dangerouslySetInnerHTML={{ __html: post.html ?? "" }} />
47
+ {afterContent}
48
+ {bodySlots?.["article.after-content"] ? (
49
+ <div
50
+ class="site-article__after-content"
51
+ dangerouslySetInnerHTML={{ __html: bodySlots["article.after-content"] }}
52
+ />
53
+ ) : null}
54
+ </ArticleContent>
55
+ {bodySlots?.["article.footer"] || footerContent ? (
56
+ <div class="site-article__footer">
57
+ {bodySlots?.["article.footer"] ? (
58
+ <div dangerouslySetInnerHTML={{ __html: bodySlots["article.footer"] }} />
59
+ ) : null}
60
+ {footerContent}
61
+ </div>
62
+ ) : null}
63
+ </ArticleLayout>
64
+ </Article>
65
+ );
66
+ }
@@ -0,0 +1,113 @@
1
+ import type { NavigationItem } from "@riebeckite/plugin-navigation";
2
+ import { ColorModeToggle } from "@riebeckite/plugin-color-mode";
3
+ import { config } from "../config";
4
+
5
+ export function SiteHeader({
6
+ path,
7
+ items,
8
+ }: {
9
+ path: string;
10
+ items: readonly NavigationItem[];
11
+ }) {
12
+ const navigation = items.filter((item) => item.href !== "/");
13
+
14
+ return (
15
+ <header class="site-header rb-site-header">
16
+ <a href="/" class="site-header__home rb-site-header__home">
17
+ <img
18
+ src="/riebeckite-logo.png"
19
+ alt=""
20
+ class="site-header__logo"
21
+ width="28"
22
+ height="28"
23
+ />
24
+ {config.site.title}
25
+ </a>
26
+ {navigation.length > 0 ? (
27
+ <>
28
+ <SiteNavigation items={navigation} path={path} />
29
+ <details class="site-navigation__mobile rb-nav__mobile">
30
+ <summary class="rb-nav__toggle">Menu</summary>
31
+ <SiteNavigation items={navigation} path={path} />
32
+ </details>
33
+ </>
34
+ ) : null}
35
+ <ColorModeToggle />
36
+ </header>
37
+ );
38
+ }
39
+
40
+ export function SiteFooter({
41
+ path,
42
+ items,
43
+ }: {
44
+ path: string;
45
+ items: readonly NavigationItem[];
46
+ }) {
47
+ if (items.length === 0) return null;
48
+
49
+ return (
50
+ <footer class="site-footer rb-site-footer">
51
+ <SiteNavigation items={items} path={path} />
52
+ </footer>
53
+ );
54
+ }
55
+
56
+ function SiteNavigation({
57
+ items,
58
+ path,
59
+ }: {
60
+ items: readonly NavigationItem[];
61
+ path: string;
62
+ }) {
63
+ return (
64
+ <nav class="site-navigation rb-nav" aria-label="Site navigation">
65
+ <NavigationItems items={items} path={path} />
66
+ </nav>
67
+ );
68
+ }
69
+
70
+ function NavigationItems({
71
+ items,
72
+ path,
73
+ isChildList = false,
74
+ }: {
75
+ items: readonly NavigationItem[];
76
+ path: string;
77
+ isChildList?: boolean;
78
+ }) {
79
+ return (
80
+ <ul class={isChildList ? "site-navigation__list rb-nav__list rb-nav__children" : "site-navigation__list rb-nav__list"}>
81
+ {items.map((item) => {
82
+ const active = item.href ? isActive(item.href, path) : false;
83
+ return (
84
+ <li class="site-navigation__item rb-nav__item">
85
+ {item.href ? (
86
+ <a
87
+ href={item.href}
88
+ class={active ? "site-navigation__link rb-nav__link rb-nav__link--active is-active" : "site-navigation__link rb-nav__link"}
89
+ aria-current={active ? "page" : undefined}
90
+ target={item.external ? "_blank" : undefined}
91
+ rel={item.external ? "noreferrer" : undefined}
92
+ >
93
+ {item.label}
94
+ </a>
95
+ ) : (
96
+ <span class="site-navigation__label rb-nav__label">{item.label}</span>
97
+ )}
98
+ {item.children && item.children.length > 0 ? (
99
+ <NavigationItems items={item.children} path={path} isChildList />
100
+ ) : null}
101
+ </li>
102
+ );
103
+ })}
104
+ </ul>
105
+ );
106
+ }
107
+
108
+ function isActive(href: string, path: string): boolean {
109
+ if (!href.startsWith("/")) return false;
110
+ const target = href.replace(/\/+$/, "") || "/";
111
+ const current = path.replace(/^\/[a-z]{2}(?:-[A-Z]{2})?(?=\/|$)/, "").replace(/\/+$/, "") || "/";
112
+ return target === "/" ? current === target : current === target || current.startsWith(`${target}/`);
113
+ }
@@ -0,0 +1,52 @@
1
+ import { getEntryLanguage } from "@riebeckite/core";
2
+ import {
3
+ contentRouteSsgParams,
4
+ pluginPageSsgParams,
5
+ resolveRiebeckiteRoute,
6
+ } from "@riebeckite/honox/server";
7
+ import { extractTableOfContents, TableOfContents } from "@riebeckite/plugin-toc";
8
+ import { createRoute } from "honox/factory";
9
+ import { SiteArticle } from "../components/article";
10
+ import { content } from "../content";
11
+
12
+ export default createRoute(
13
+ contentRouteSsgParams("/:slug{.+}", async () => {
14
+ const manifest = await content.getManifest();
15
+ const contentPaths = manifest.publicEntries
16
+ .filter((entry) => entry.permalink !== "/")
17
+ .map((entry) => ({ slug: entry.permalink.replace(/^\/+/, "") }));
18
+ return [...contentPaths, ...(await pluginPageSsgParams(content))];
19
+ }),
20
+ async (c) => {
21
+ const requestedSlug = c.req.param("slug");
22
+ if (!requestedSlug) return c.notFound();
23
+ if (/\.[a-zA-Z0-9]+$/.test(requestedSlug)) return c.notFound();
24
+
25
+ const route = await resolveRiebeckiteRoute(content, c.req.path);
26
+ if (!route) return c.notFound();
27
+ if (route.kind === "redirect")
28
+ return c.redirect(route.location, route.status);
29
+ if (route.kind === "page") {
30
+ c.set("headTags", route.page.headTags ?? []);
31
+ c.set("htmlLanguage", route.page.language);
32
+ return c.render(
33
+ <div dangerouslySetInnerHTML={{ __html: route.page.body }} />,
34
+ );
35
+ }
36
+
37
+ const post = await content.getProcessedContent(route.entry.slug);
38
+
39
+ const tableOfContents = extractTableOfContents(post.html ?? "");
40
+
41
+ c.set("htmlLanguage", getEntryLanguage(route.entry));
42
+ c.set("headTags", route.entry.headTags ?? []);
43
+
44
+ return c.render(
45
+ <SiteArticle
46
+ post={post}
47
+ bodySlots={route.entry.bodySlots}
48
+ asideContent={<TableOfContents className="table-of-contents--desktop" items={tableOfContents} />}
49
+ />,
50
+ );
51
+ },
52
+ );