stropress 0.0.1

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 (41) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +307 -0
  3. package/dist/theme-default/package.json +20 -0
  4. package/dist/theme-default/postcss.config.mjs +5 -0
  5. package/dist/theme-default/src/components/BaseHead.astro +53 -0
  6. package/dist/theme-default/src/components/DocToc.astro +111 -0
  7. package/dist/theme-default/src/components/GithubIcon.astro +35 -0
  8. package/dist/theme-default/src/components/HomePage.astro +198 -0
  9. package/dist/theme-default/src/components/Icon.astro +78 -0
  10. package/dist/theme-default/src/components/LocaleSelect.astro +187 -0
  11. package/dist/theme-default/src/components/NavBar.astro +231 -0
  12. package/dist/theme-default/src/components/SearchInput.astro +84 -0
  13. package/dist/theme-default/src/components/SearchModal.astro +209 -0
  14. package/dist/theme-default/src/components/Sidebar.astro +101 -0
  15. package/dist/theme-default/src/content/docs/guide/configuration.mdx +195 -0
  16. package/dist/theme-default/src/content/docs/guide/getting-started.md +98 -0
  17. package/dist/theme-default/src/content/docs/guide/search.mdx +41 -0
  18. package/dist/theme-default/src/content/docs/index.css +0 -0
  19. package/dist/theme-default/src/content/docs/index.md +6 -0
  20. package/dist/theme-default/src/content/docs/zh/guide/configuration.mdx +149 -0
  21. package/dist/theme-default/src/content/docs/zh/guide/getting-started.md +31 -0
  22. package/dist/theme-default/src/content/docs/zh/guide/search.mdx +23 -0
  23. package/dist/theme-default/src/content/docs/zh/index.astro +75 -0
  24. package/dist/theme-default/src/content/docs/zh/index.md +6 -0
  25. package/dist/theme-default/src/content.config.ts +14 -0
  26. package/dist/theme-default/src/env.d.ts +15 -0
  27. package/dist/theme-default/src/layouts/DocsLayout.astro +278 -0
  28. package/dist/theme-default/src/lib/config.ts +195 -0
  29. package/dist/theme-default/src/lib/custom-home.ts +40 -0
  30. package/dist/theme-default/src/lib/custom-style.ts +11 -0
  31. package/dist/theme-default/src/lib/og.ts +275 -0
  32. package/dist/theme-default/src/pages/[...slug]/index.astro +83 -0
  33. package/dist/theme-default/src/pages/index.astro +47 -0
  34. package/dist/theme-default/src/pages/og/[...slug].png.ts +70 -0
  35. package/dist/theme-default/src/scripts/code-copy.ts +54 -0
  36. package/dist/theme-default/src/scripts/doc-toc.ts +109 -0
  37. package/dist/theme-default/src/scripts/search.ts +329 -0
  38. package/dist/theme-default/src/styles/global.css +70 -0
  39. package/dist/theme-default/src/styles/markdown.css +141 -0
  40. package/dist/theme-default/tsconfig.json +10 -0
  41. package/package.json +32 -0
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Search
3
+ description: Configure and use search in your Stropress documentation site
4
+ ---
5
+
6
+ # Search
7
+
8
+ Stropress has built-in search that works out of the box — no configuration required.
9
+ Search is powered by local MiniSearch.
10
+
11
+ ## How it works
12
+
13
+ A search button is displayed in the header. Clicking it opens a modal where you can type to find pages across your docs.
14
+
15
+ **Keyboard shortcuts**
16
+
17
+ | Key | Action |
18
+ | :-------------- | :------------------- |
19
+ | `⌘K` / `Ctrl K` | Open search |
20
+ | `↑` / `↓` | Navigate results |
21
+ | `Enter` | Open selected result |
22
+ | `Esc` | Close search |
23
+
24
+ ## Local search (default)
25
+
26
+ By default, Stropress indexes all your `.md` and `.mdx` pages at build time using [MiniSearch](https://lucaong.github.io/minisearch/).
27
+ No extra setup is needed.
28
+
29
+ ```json
30
+ {
31
+ "search": {
32
+ "provider": "local"
33
+ }
34
+ }
35
+ ```
36
+
37
+ The `provider: "local"` line is optional — local search is enabled even without a `search` field.
38
+
39
+ ## Notes
40
+
41
+ Search indexes your markdown content and runs fully on the client.
File without changes
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: Home
3
+ description: Welcome to stropress
4
+ ---
5
+
6
+ Home page content is driven by `docs/config.json#home`.
@@ -0,0 +1,149 @@
1
+ ---
2
+ title: 配置
3
+ description: 配置导航、侧边栏和双语
4
+ ---
5
+
6
+ # 配置
7
+
8
+ 使用 `docs/config.json` 配置站点信息与导航结构。
9
+
10
+ - `navbar`:顶部导航
11
+ - `nav`:显示在社交链接旁边的主导航
12
+ - `sidebar`:侧边栏分组
13
+ - `search`:本地搜索选项
14
+ - `markdown`:Markdown 渲染选项
15
+ - `locales`:多语言配置
16
+
17
+ ## 搜索
18
+
19
+ 默认搜索使用内置 MiniSearch,无需额外依赖。
20
+
21
+ ```json
22
+ {
23
+ "search": {
24
+ "provider": "local"
25
+ }
26
+ }
27
+ ```
28
+
29
+ ## 代码块主题
30
+
31
+ 你可以在 `docs/config.json` 中通过 `markdown.codeTheme` 配置代码块高亮主题。
32
+
33
+ 使用单一主题:
34
+
35
+ ```json
36
+ {
37
+ "markdown": {
38
+ "codeTheme": "github-dark"
39
+ }
40
+ }
41
+ ```
42
+
43
+ 或分别配置亮色/暗色主题:
44
+
45
+ ```json
46
+ {
47
+ "markdown": {
48
+ "codeTheme": {
49
+ "light": "github-light",
50
+ "dark": "github-dark"
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ 常见主题名(由 Astro 通过 Shiki 提供,具体可用性取决于 Astro/Shiki 版本):
57
+
58
+ - `github-light`
59
+ - `github-dark`
60
+ - `one-dark-pro`
61
+ - `dracula`
62
+ - `nord`
63
+ - `material-theme-darker`
64
+ - `catppuccin-latte`
65
+ - `catppuccin-frappe`
66
+ - `catppuccin-macchiato`
67
+ - `catppuccin-mocha`
68
+
69
+ One Dark + Catppuccin 示例:
70
+
71
+ ```json
72
+ {
73
+ "markdown": {
74
+ "codeTheme": {
75
+ "light": "catppuccin-latte",
76
+ "dark": "one-dark-pro"
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ 如果主题名在当前版本不可用,`dev/build` 会提示主题加载错误。
83
+
84
+ ## 双语配置
85
+
86
+ 推荐将中文文档放在 `docs/zh/...` 目录下,并在 `locales` 中配置 `/zh/`:
87
+
88
+ ```json
89
+ {
90
+ "locales": {
91
+ "/": {
92
+ "label": "English",
93
+ "lang": "en-US"
94
+ },
95
+ "/zh/": {
96
+ "label": "简体中文",
97
+ "lang": "zh-CN"
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## 自定义首页
104
+
105
+ 如果 `config.json` 里的 `home` 配置不够灵活,可以直接在 `config.json` 同目录放置 Astro 首页文件:
106
+
107
+ ```text
108
+ docs/
109
+ config.json
110
+ index.astro
111
+ zh/
112
+ index.astro
113
+ ```
114
+
115
+ - `docs/index.astro` 会覆盖根路径 `/` 的首页。
116
+ - `docs/zh/index.astro` 会覆盖 `/zh/` 的多语言首页。
117
+ - 只要存在匹配的 `index.astro`,Stropress 就会优先使用它,而不是 `home` 或 `locales[locale].home`。
118
+
119
+ 这些文件会渲染在默认文档布局内部。你也可以在 Astro frontmatter 中导出一些可选元信息:
120
+
121
+ ```astro
122
+ ---
123
+ export const title = "自定义首页";
124
+ export const description = "使用 Astro 编写的首页";
125
+ export const sidebar = false;
126
+ ---
127
+
128
+ <section>
129
+ <h1>自定义首页</h1>
130
+ </section>
131
+ ```
132
+
133
+ ## 全局样式覆盖
134
+
135
+ 你可以在根目录增加 `docs/index.css`,用来全局覆盖默认主题样式。
136
+
137
+ 这份文件会在内置主题 CSS 之后加载,因此适合用来重写 `:root` 变量,或者覆盖主题里的选择器。
138
+
139
+ ```css
140
+ :root {
141
+ --background-color: 250 247 240;
142
+ --foreground-color: 28 28 28;
143
+ --primary-color: 176 78 44;
144
+ }
145
+
146
+ .topbar {
147
+ backdrop-filter: blur(20px);
148
+ }
149
+ ```
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: 快速开始
3
+ description: 快速启动你的文档站点
4
+ ---
5
+
6
+ # 快速开始
7
+
8
+ `docs/` 目录下的 Markdown 文件会被渲染为静态页面。
9
+
10
+ ## 运行开发环境
11
+
12
+ ```bash
13
+ bun run dev --dir=docs
14
+ ```
15
+
16
+ ## 构建生产版本
17
+
18
+ ```bash
19
+ bun run build --dir=docs
20
+ ```
21
+
22
+ ## 目录建议
23
+
24
+ ```text
25
+ docs/
26
+ config.json
27
+ index.md
28
+ guide/
29
+ getting-started.md
30
+ configuration.mdx
31
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: 搜索
3
+ description: 配置与使用站点搜索
4
+ ---
5
+
6
+ # 搜索
7
+
8
+ Stropress 内置本地搜索,开箱即用。
9
+
10
+ ## 使用方式
11
+
12
+ 在 Header 点击搜索按钮,输入关键词即可检索文档内容。
13
+
14
+ 快捷键:
15
+
16
+ - `⌘K` / `Ctrl K`:打开搜索
17
+ - `↑` / `↓`:切换结果
18
+ - `Enter`:打开结果
19
+ - `Esc`:关闭弹窗
20
+
21
+ ## 说明
22
+
23
+ 搜索会索引当前语言下的文档内容,并在前端完成查询。
@@ -0,0 +1,75 @@
1
+ ---
2
+ export const title = "自定义首页";
3
+ export const description = "用于验证 docs/zh/index.astro 是否生效的示例首页";
4
+ export const sidebar = false;
5
+ ---
6
+
7
+ <section class="custom-home">
8
+ <p class="eyebrow">Custom Astro Home</p>
9
+ <h1>这是 docs/zh/index.astro</h1>
10
+ <p class="lead">
11
+ 如果你现在访问 <code>/zh/</code
12
+ >,看到的是这块内容,就说明多语言自定义首页已经生效。
13
+ </p>
14
+
15
+ <div class="actions">
16
+ <a class="action primary" href="/zh/guide/getting-started">快速开始</a>
17
+ <a class="action secondary" href="/zh/guide/configuration">查看配置</a>
18
+ </div>
19
+ </section>
20
+
21
+ <style>
22
+ .custom-home {
23
+ padding: 2rem 1rem 3rem;
24
+ }
25
+
26
+ .eyebrow {
27
+ margin: 0 0 0.75rem;
28
+ font-size: 0.85rem;
29
+ font-weight: 700;
30
+ letter-spacing: 0.08em;
31
+ text-transform: uppercase;
32
+ color: rgba(var(--muted-color) / 1);
33
+ }
34
+
35
+ h1 {
36
+ margin: 0;
37
+ font-size: clamp(2.5rem, 7vw, 4.5rem);
38
+ line-height: 1;
39
+ }
40
+
41
+ .lead {
42
+ max-width: 42rem;
43
+ margin: 1rem 0 0;
44
+ font-size: 1.05rem;
45
+ line-height: 1.8;
46
+ color: rgba(var(--muted-color) / 1);
47
+ }
48
+
49
+ .actions {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ gap: 0.75rem;
53
+ margin-top: 1.75rem;
54
+ }
55
+
56
+ .action {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ padding: 0.85rem 1.15rem;
61
+ font-weight: 700;
62
+ text-decoration: none;
63
+ border: 1px solid rgba(var(--border-color) / 1);
64
+ }
65
+
66
+ .action.primary {
67
+ background: rgba(var(--primary-color) / 1);
68
+ border-color: rgba(var(--primary-color) / 1);
69
+ color: rgba(var(--primary-foreground-color) / 1);
70
+ }
71
+
72
+ .action.secondary {
73
+ color: rgba(var(--foreground-color) / 1);
74
+ }
75
+ </style>
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: 首页
3
+ description: 欢迎使用 Stropress
4
+ ---
5
+
6
+ 首页内容由 `docs/config.json` 中的 `locales["/zh/"].home` 驱动。
@@ -0,0 +1,14 @@
1
+ import { defineCollection, z } from "astro:content";
2
+ import { glob } from "astro/loaders";
3
+
4
+ const docs = defineCollection({
5
+ loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/content/docs" }),
6
+ schema: z.object({
7
+ title: z.string(),
8
+ description: z.string().optional(),
9
+ }),
10
+ });
11
+
12
+ export const collections = {
13
+ docs,
14
+ };
@@ -0,0 +1,15 @@
1
+ declare module "@lucide/astro" {
2
+ export type LucideIconComponent = (props: Record<string, unknown>) => any;
3
+ export const icons: Record<string, LucideIconComponent>;
4
+ }
5
+
6
+ declare module "copy-to-clipboard" {
7
+ interface Options {
8
+ debug?: boolean;
9
+ message?: string;
10
+ format?: string;
11
+ onCopy?: (clipboardData: object) => void;
12
+ }
13
+ const copy: (text: string, options?: Options) => boolean;
14
+ export default copy;
15
+ }
@@ -0,0 +1,278 @@
1
+ ---
2
+ import NavBar from "../components/NavBar.astro";
3
+ import Sidebar from "../components/Sidebar.astro";
4
+ import DocToc from "../components/DocToc.astro";
5
+ import BaseHead from "../components/BaseHead.astro";
6
+ import { getResolvedSiteConfig } from "../lib/config";
7
+ import { customGlobalStyle } from "../lib/custom-style";
8
+ import "../styles/global.css";
9
+ import "../styles/markdown.css";
10
+
11
+ interface Props {
12
+ title?: string;
13
+ description?: string;
14
+ sidebar?: boolean;
15
+ contentClass?: string;
16
+ tocHeadings?: Array<{
17
+ depth: number;
18
+ slug: string;
19
+ text: string;
20
+ }>;
21
+ }
22
+
23
+ const {
24
+ title,
25
+ description,
26
+ sidebar = true,
27
+ contentClass = "",
28
+ tocHeadings = [],
29
+ } = Astro.props;
30
+ const resolvedConfig = getResolvedSiteConfig(Astro.url.pathname);
31
+ const pageTitle = title
32
+ ? `${title} | ${resolvedConfig.siteTitle}`
33
+ : resolvedConfig.siteTitle;
34
+ const pageDescription = description || resolvedConfig.siteDescription;
35
+ const ogImagePath =
36
+ Astro.url.pathname === "/"
37
+ ? "/og/index.png"
38
+ : `/og${Astro.url.pathname.endsWith("/") ? Astro.url.pathname.slice(0, -1) : Astro.url.pathname}.png`;
39
+ const tocItems = tocHeadings.filter(
40
+ (heading) => heading.depth >= 2 && heading.depth <= 3,
41
+ );
42
+ ---
43
+
44
+ <!doctype html>
45
+ <html lang={resolvedConfig.localeLang}>
46
+ <head>
47
+ <BaseHead
48
+ title={pageTitle}
49
+ description={pageDescription}
50
+ lang={resolvedConfig.localeLang}
51
+ image={ogImagePath}
52
+ ogType={sidebar ? "article" : "website"}
53
+ />
54
+ {customGlobalStyle && <style is:global set:html={customGlobalStyle} />}
55
+ </head>
56
+ <body>
57
+ <NavBar showSidebarToggle={sidebar} />
58
+ <div class:list={["wrapper", !sidebar && "wrapper-without-sidebar"]}>
59
+ {
60
+ sidebar && (
61
+ <>
62
+ <button
63
+ type="button"
64
+ class="sider-backdrop"
65
+ data-sidebar-backdrop
66
+ data-state="closed"
67
+ aria-label="Close navigation menu"
68
+ />
69
+ <aside
70
+ id="sidebar-drawer"
71
+ class="sider"
72
+ data-sidebar-drawer
73
+ data-state="closed"
74
+ >
75
+ <Sidebar />
76
+ </aside>
77
+ </>
78
+ )
79
+ }
80
+ <main class:list={["content", contentClass]}>
81
+ <div
82
+ class:list={[
83
+ "docs-main",
84
+ tocItems.length > 0 && "docs-main-with-toc",
85
+ ]}
86
+ >
87
+ <div class="docs-main-content">
88
+ <slot />
89
+ </div>
90
+ <DocToc items={tocItems} />
91
+ </div>
92
+ </main>
93
+ </div>
94
+ <script>
95
+ import { setupCodeCopyButtons } from "../scripts/code-copy";
96
+
97
+ setupCodeCopyButtons();
98
+
99
+ let sidebarCleanup: (() => void) | null = null;
100
+
101
+ const setupSidebarDrawer = () => {
102
+ if (typeof sidebarCleanup === "function") {
103
+ sidebarCleanup();
104
+ sidebarCleanup = null;
105
+ }
106
+
107
+ const drawer = document.querySelector<HTMLElement>(
108
+ "[data-sidebar-drawer]",
109
+ );
110
+ const backdrop = document.querySelector<HTMLElement>(
111
+ "[data-sidebar-backdrop]",
112
+ );
113
+ const toggle = document.querySelector<HTMLElement>(
114
+ "[data-sidebar-toggle]",
115
+ );
116
+
117
+ if (!drawer || !backdrop || !toggle) {
118
+ return;
119
+ }
120
+
121
+ const linkElements = Array.from(
122
+ drawer.querySelectorAll<HTMLAnchorElement>("a"),
123
+ );
124
+
125
+ const setOpen = (open: boolean) => {
126
+ drawer.dataset.state = open ? "open" : "closed";
127
+ backdrop.dataset.state = open ? "open" : "closed";
128
+ toggle.setAttribute("aria-expanded", open ? "true" : "false");
129
+ document.body.style.overflow = open ? "hidden" : "";
130
+ };
131
+
132
+ const close = () => setOpen(false);
133
+ const onToggle = () => setOpen(drawer.dataset.state !== "open");
134
+
135
+ toggle.addEventListener("click", onToggle);
136
+ backdrop.addEventListener("click", close);
137
+ linkElements.forEach((element: HTMLAnchorElement) =>
138
+ element.addEventListener("click", close),
139
+ );
140
+
141
+ const onKeydown = (event: KeyboardEvent) => {
142
+ if (event.key === "Escape") {
143
+ close();
144
+ }
145
+ };
146
+
147
+ const onResize = () => {
148
+ if (window.innerWidth > 900) {
149
+ close();
150
+ }
151
+ };
152
+
153
+ document.addEventListener("keydown", onKeydown);
154
+ window.addEventListener("resize", onResize);
155
+
156
+ sidebarCleanup = () => {
157
+ toggle.removeEventListener("click", onToggle);
158
+ backdrop.removeEventListener("click", close);
159
+ linkElements.forEach((element: HTMLAnchorElement) =>
160
+ element.removeEventListener("click", close),
161
+ );
162
+ document.removeEventListener("keydown", onKeydown);
163
+ window.removeEventListener("resize", onResize);
164
+ document.body.style.overflow = "";
165
+ };
166
+ };
167
+
168
+ setupSidebarDrawer();
169
+ document.addEventListener("astro:page-load", setupSidebarDrawer);
170
+ </script>
171
+ </body>
172
+ </html>
173
+
174
+ <style is:global>
175
+ body {
176
+ min-height: 100vh;
177
+ display: flex;
178
+ flex-direction: column;
179
+ }
180
+
181
+ .sider {
182
+ flex-shrink: 0;
183
+ width: 16rem;
184
+ }
185
+
186
+ .sider-backdrop {
187
+ display: none;
188
+ }
189
+
190
+ .wrapper {
191
+ display: flex;
192
+ flex-direction: row;
193
+ width: 100%;
194
+ max-width: 80rem;
195
+ margin: 0 auto;
196
+ flex: 1;
197
+ min-height: 0;
198
+ }
199
+
200
+ .content {
201
+ flex: 1;
202
+ min-width: 0;
203
+ }
204
+
205
+ .docs-main {
206
+ width: 100%;
207
+ min-width: 0;
208
+ }
209
+
210
+ .wrapper-without-sidebar {
211
+ width: 100%;
212
+ border-width: 0 1px 0 1px;
213
+ border-style: solid;
214
+ border-color: rgba(var(--border-color) / 1);
215
+ }
216
+
217
+ @media (min-width: 1200px) {
218
+ .docs-main-with-toc {
219
+ display: grid;
220
+ grid-template-columns: minmax(0, 1fr) 15rem;
221
+ gap: 2rem;
222
+ align-items: start;
223
+ }
224
+ }
225
+
226
+ @media (max-width: 900px) {
227
+ .wrapper {
228
+ flex-direction: column;
229
+ }
230
+
231
+ .wrapper-without-sidebar {
232
+ border-width: 0 0 0 0;
233
+ }
234
+
235
+ .sider-backdrop {
236
+ display: block;
237
+ position: fixed;
238
+ inset: 0;
239
+ z-index: 20;
240
+ border: 0;
241
+ background: rgba(0 0 0 / 0.4);
242
+ opacity: 0;
243
+ pointer-events: none;
244
+ transition: opacity 180ms ease;
245
+ }
246
+
247
+ .sider-backdrop[data-state="open"] {
248
+ opacity: 1;
249
+ pointer-events: auto;
250
+ }
251
+
252
+ .sider {
253
+ position: fixed;
254
+ left: 0;
255
+ top: 0;
256
+ z-index: 30;
257
+ width: min(84vw, 18rem);
258
+ height: 100dvh;
259
+ transform: translateX(-100%);
260
+ transition: transform 220ms ease;
261
+ background: rgba(var(--background-color) / 1);
262
+ border-right: 1px solid rgba(var(--border-color) / 1);
263
+ padding: 5rem 0.5rem 1rem;
264
+ overflow-y: auto;
265
+ }
266
+
267
+ .sider[data-state="open"] {
268
+ transform: translateX(0);
269
+ }
270
+
271
+ .content {
272
+ border-left: 0;
273
+ padding-inline: 0;
274
+ padding-bottom: 0;
275
+ padding-top: 1.5rem;
276
+ }
277
+ }
278
+ </style>