@opendocsdev/cli 0.2.0
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.
- package/LICENSE +661 -0
- package/README.md +300 -0
- package/dist/bin/opendocs.js +712 -0
- package/dist/bin/opendocs.js.map +1 -0
- package/dist/templates/api-reference.mdx +308 -0
- package/dist/templates/components.mdx +286 -0
- package/dist/templates/configuration.mdx +190 -0
- package/dist/templates/docs.json +27 -0
- package/dist/templates/introduction.mdx +25 -0
- package/dist/templates/logo.svg +4 -0
- package/dist/templates/quickstart.mdx +59 -0
- package/dist/templates/writing-content.mdx +236 -0
- package/package.json +92 -0
- package/src/engine/astro.config.ts +75 -0
- package/src/engine/src/components/Analytics.astro +57 -0
- package/src/engine/src/components/ApiPlayground.astro +24 -0
- package/src/engine/src/components/Callout.astro +66 -0
- package/src/engine/src/components/Card.astro +75 -0
- package/src/engine/src/components/CardGroup.astro +29 -0
- package/src/engine/src/components/CodeGroup.astro +231 -0
- package/src/engine/src/components/CopyButton.astro +179 -0
- package/src/engine/src/components/Steps.astro +27 -0
- package/src/engine/src/components/Tab.astro +21 -0
- package/src/engine/src/components/TableOfContents.astro +119 -0
- package/src/engine/src/components/Tabs.astro +135 -0
- package/src/engine/src/components/index.ts +107 -0
- package/src/engine/src/components/react/ApiPlayground/AuthSection.tsx +91 -0
- package/src/engine/src/components/react/ApiPlayground/CodeBlock.tsx +66 -0
- package/src/engine/src/components/react/ApiPlayground/CodeSnippets.tsx +66 -0
- package/src/engine/src/components/react/ApiPlayground/CollapsibleSection.tsx +26 -0
- package/src/engine/src/components/react/ApiPlayground/KeyValueEditor.tsx +58 -0
- package/src/engine/src/components/react/ApiPlayground/ResponseDisplay.tsx +109 -0
- package/src/engine/src/components/react/ApiPlayground/Spinner.tsx +6 -0
- package/src/engine/src/components/react/ApiPlayground/constants.ts +16 -0
- package/src/engine/src/components/react/ApiPlayground/generators.test.ts +130 -0
- package/src/engine/src/components/react/ApiPlayground/generators.ts +75 -0
- package/src/engine/src/components/react/ApiPlayground/index.tsx +490 -0
- package/src/engine/src/components/react/ApiPlayground/types.ts +35 -0
- package/src/engine/src/components/react/Callout.tsx +54 -0
- package/src/engine/src/components/react/Card.tsx +48 -0
- package/src/engine/src/components/react/CardGroup.tsx +24 -0
- package/src/engine/src/components/react/FeedbackWidget.tsx +166 -0
- package/src/engine/src/components/react/GitHubLink.tsx +28 -0
- package/src/engine/src/components/react/NavigationCard.tsx +53 -0
- package/src/engine/src/components/react/PageActions.tsx +124 -0
- package/src/engine/src/components/react/PageFooter.tsx +91 -0
- package/src/engine/src/components/react/SearchModal.tsx +358 -0
- package/src/engine/src/components/react/SearchProvider.tsx +37 -0
- package/src/engine/src/components/react/Sidebar.tsx +369 -0
- package/src/engine/src/components/react/SidebarSearchTrigger.tsx +57 -0
- package/src/engine/src/components/react/Steps.tsx +25 -0
- package/src/engine/src/components/react/ThemeToggle.tsx +72 -0
- package/src/engine/src/components/react/index.ts +14 -0
- package/src/engine/src/env.d.ts +10 -0
- package/src/engine/src/layouts/DocsLayout.astro +357 -0
- package/src/engine/src/lib/__tests__/markdown.test.ts +124 -0
- package/src/engine/src/lib/__tests__/mdx-loader.test.ts +205 -0
- package/src/engine/src/lib/config.ts +79 -0
- package/src/engine/src/lib/markdown.ts +54 -0
- package/src/engine/src/lib/mdx-loader.ts +143 -0
- package/src/engine/src/lib/mdx-utils.ts +72 -0
- package/src/engine/src/lib/remark-opendocs.ts +195 -0
- package/src/engine/src/lib/utils.ts +221 -0
- package/src/engine/src/pages/[...slug].astro +115 -0
- package/src/engine/src/pages/index.astro +71 -0
- package/src/engine/src/scripts/mobile-sidebar.ts +56 -0
- package/src/engine/src/scripts/theme-init.ts +25 -0
- package/src/engine/src/styles/global.css +703 -0
- package/src/engine/tailwind.config.mjs +60 -0
- package/src/engine/tsconfig.json +15 -0
- package/src/templates/api-reference.mdx +308 -0
- package/src/templates/components.mdx +286 -0
- package/src/templates/configuration.mdx +190 -0
- package/src/templates/docs.json +27 -0
- package/src/templates/introduction.mdx +25 -0
- package/src/templates/logo.svg +4 -0
- package/src/templates/quickstart.mdx +59 -0
- package/src/templates/writing-content.mdx +236 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Writing Content
|
|
3
|
+
description: Learn how to write effective documentation with MDX
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Writing Content
|
|
7
|
+
|
|
8
|
+
opendocs uses MDX, which combines Markdown with JSX components for rich documentation.
|
|
9
|
+
|
|
10
|
+
## Frontmatter
|
|
11
|
+
|
|
12
|
+
Every page should start with frontmatter that defines metadata:
|
|
13
|
+
|
|
14
|
+
```mdx
|
|
15
|
+
---
|
|
16
|
+
title: Page Title
|
|
17
|
+
description: A brief description for SEO and previews
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Your Content Here
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Frontmatter Fields
|
|
24
|
+
|
|
25
|
+
| Field | Required | Description |
|
|
26
|
+
|-------|----------|-------------|
|
|
27
|
+
| `title` | Yes | Page title (shown in browser tab and navigation) |
|
|
28
|
+
| `description` | No | Short description for SEO and social sharing |
|
|
29
|
+
|
|
30
|
+
## Markdown Basics
|
|
31
|
+
|
|
32
|
+
opendocs supports all standard Markdown syntax.
|
|
33
|
+
|
|
34
|
+
### Headings
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
# Heading 1
|
|
38
|
+
## Heading 2
|
|
39
|
+
### Heading 3
|
|
40
|
+
#### Heading 4
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
<Callout type="tip">
|
|
44
|
+
Use `##` (H2) for main sections. These appear in the "On this page" table of contents.
|
|
45
|
+
</Callout>
|
|
46
|
+
|
|
47
|
+
### Text Formatting
|
|
48
|
+
|
|
49
|
+
| Syntax | Result |
|
|
50
|
+
|--------|--------|
|
|
51
|
+
| `**bold**` | **bold** |
|
|
52
|
+
| `*italic*` | *italic* |
|
|
53
|
+
| `~~strikethrough~~` | ~~strikethrough~~ |
|
|
54
|
+
| `` `inline code` `` | `inline code` |
|
|
55
|
+
|
|
56
|
+
### Lists
|
|
57
|
+
|
|
58
|
+
**Unordered lists:**
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
- First item
|
|
62
|
+
- Second item
|
|
63
|
+
- Nested item
|
|
64
|
+
- Another nested item
|
|
65
|
+
- Third item
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- First item
|
|
69
|
+
- Second item
|
|
70
|
+
- Nested item
|
|
71
|
+
- Another nested item
|
|
72
|
+
- Third item
|
|
73
|
+
|
|
74
|
+
**Ordered lists:**
|
|
75
|
+
|
|
76
|
+
```markdown
|
|
77
|
+
1. First step
|
|
78
|
+
2. Second step
|
|
79
|
+
3. Third step
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
1. First step
|
|
83
|
+
2. Second step
|
|
84
|
+
3. Third step
|
|
85
|
+
|
|
86
|
+
### Links
|
|
87
|
+
|
|
88
|
+
```markdown
|
|
89
|
+
[Link text](https://example.com)
|
|
90
|
+
[Internal link](/quickstart)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
[Link text](https://example.com) | [Internal link](/quickstart)
|
|
94
|
+
|
|
95
|
+
### Images
|
|
96
|
+
|
|
97
|
+
Place images in the `public` directory and reference them:
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+

|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Tables
|
|
104
|
+
|
|
105
|
+
```markdown
|
|
106
|
+
| Header 1 | Header 2 | Header 3 |
|
|
107
|
+
|----------|----------|----------|
|
|
108
|
+
| Cell 1 | Cell 2 | Cell 3 |
|
|
109
|
+
| Cell 4 | Cell 5 | Cell 6 |
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
| Header 1 | Header 2 | Header 3 |
|
|
113
|
+
|----------|----------|----------|
|
|
114
|
+
| Cell 1 | Cell 2 | Cell 3 |
|
|
115
|
+
| Cell 4 | Cell 5 | Cell 6 |
|
|
116
|
+
|
|
117
|
+
### Blockquotes
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
> This is a blockquote. Use it to highlight quotes or important notes.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> This is a blockquote. Use it to highlight quotes or important notes.
|
|
124
|
+
|
|
125
|
+
## Code Blocks
|
|
126
|
+
|
|
127
|
+
### Basic Code Blocks
|
|
128
|
+
|
|
129
|
+
Use triple backticks with a language identifier:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
function greet(name) {
|
|
133
|
+
return `Hello, ${name}!`;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
function greet(name) {
|
|
139
|
+
return `Hello, ${name}!`;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Supported Languages
|
|
144
|
+
|
|
145
|
+
opendocs supports syntax highlighting for 100+ languages including:
|
|
146
|
+
|
|
147
|
+
- JavaScript, TypeScript, JSX, TSX
|
|
148
|
+
- Python, Ruby, Go, Rust
|
|
149
|
+
- HTML, CSS, SCSS
|
|
150
|
+
- JSON, YAML, TOML
|
|
151
|
+
- Bash, Shell
|
|
152
|
+
- SQL, GraphQL
|
|
153
|
+
- And many more...
|
|
154
|
+
|
|
155
|
+
### Code Groups for Multiple Languages
|
|
156
|
+
|
|
157
|
+
Use the `CodeGroup` component to show code in multiple languages:
|
|
158
|
+
|
|
159
|
+
<CodeGroup>
|
|
160
|
+
```javascript Node.js
|
|
161
|
+
const express = require('express');
|
|
162
|
+
const app = express();
|
|
163
|
+
|
|
164
|
+
app.get('/', (req, res) => {
|
|
165
|
+
res.send('Hello World!');
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```python Flask
|
|
170
|
+
from flask import Flask
|
|
171
|
+
app = Flask(__name__)
|
|
172
|
+
|
|
173
|
+
@app.route('/')
|
|
174
|
+
def hello():
|
|
175
|
+
return 'Hello World!'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```go Go
|
|
179
|
+
package main
|
|
180
|
+
|
|
181
|
+
import "net/http"
|
|
182
|
+
|
|
183
|
+
func main() {
|
|
184
|
+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
185
|
+
w.Write([]byte("Hello World!"))
|
|
186
|
+
})
|
|
187
|
+
http.ListenAndServe(":8080", nil)
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
</CodeGroup>
|
|
191
|
+
|
|
192
|
+
## Using Components
|
|
193
|
+
|
|
194
|
+
Import and use built-in components directly in your MDX:
|
|
195
|
+
|
|
196
|
+
```mdx
|
|
197
|
+
<Callout type="info">
|
|
198
|
+
This is an informational callout.
|
|
199
|
+
</Callout>
|
|
200
|
+
|
|
201
|
+
<CardGroup cols={2}>
|
|
202
|
+
<Card title="Card 1" description="Description" href="/page1" />
|
|
203
|
+
<Card title="Card 2" description="Description" href="/page2" />
|
|
204
|
+
</CardGroup>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
See the [Components](/components) page for all available components.
|
|
208
|
+
|
|
209
|
+
## Best Practices
|
|
210
|
+
|
|
211
|
+
<CardGroup cols={2}>
|
|
212
|
+
<Card
|
|
213
|
+
title="Keep it concise"
|
|
214
|
+
description="Write short paragraphs. Use lists and tables for clarity."
|
|
215
|
+
icon="✂️"
|
|
216
|
+
/>
|
|
217
|
+
<Card
|
|
218
|
+
title="Use examples"
|
|
219
|
+
description="Show, don't tell. Include code samples and screenshots."
|
|
220
|
+
icon="💻"
|
|
221
|
+
/>
|
|
222
|
+
<Card
|
|
223
|
+
title="Structure content"
|
|
224
|
+
description="Use headings to create a clear hierarchy."
|
|
225
|
+
icon="📋"
|
|
226
|
+
/>
|
|
227
|
+
<Card
|
|
228
|
+
title="Add callouts"
|
|
229
|
+
description="Highlight important info, warnings, and tips."
|
|
230
|
+
icon="💡"
|
|
231
|
+
/>
|
|
232
|
+
</CardGroup>
|
|
233
|
+
|
|
234
|
+
<Callout type="tip">
|
|
235
|
+
Write documentation as if the reader is in a hurry. Get to the point quickly and make information easy to scan.
|
|
236
|
+
</Callout>
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opendocsdev/cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "Beautiful docs with zero config. Open-source Mintlify alternative.",
|
|
8
|
+
"license": "AGPL-3.0",
|
|
9
|
+
"author": "Chigala",
|
|
10
|
+
"homepage": "https://github.com/chigala/opendocs#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/chigala/opendocs/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"documentation",
|
|
16
|
+
"docs",
|
|
17
|
+
"mdx",
|
|
18
|
+
"astro",
|
|
19
|
+
"cli",
|
|
20
|
+
"static-site",
|
|
21
|
+
"mintlify",
|
|
22
|
+
"opendocs"
|
|
23
|
+
],
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/chigala/opendocs.git",
|
|
27
|
+
"directory": "packages/cli"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20.0.0"
|
|
31
|
+
},
|
|
32
|
+
"type": "module",
|
|
33
|
+
"bin": {
|
|
34
|
+
"opendocs": "./dist/bin/opendocs.js"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"src/engine/astro.config.ts",
|
|
39
|
+
"src/engine/tailwind.config.mjs",
|
|
40
|
+
"src/engine/tsconfig.json",
|
|
41
|
+
"src/engine/src",
|
|
42
|
+
"src/templates"
|
|
43
|
+
],
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@astrojs/mdx": "^3.1.0",
|
|
46
|
+
"@astrojs/react": "^4.4.2",
|
|
47
|
+
"@astrojs/tailwind": "^5.1.0",
|
|
48
|
+
"@fontsource-variable/geist": "^5.2.8",
|
|
49
|
+
"@fontsource-variable/geist-mono": "^5.2.7",
|
|
50
|
+
"@inquirer/prompts": "^8.2.0",
|
|
51
|
+
"@lucide/astro": "^0.563.0",
|
|
52
|
+
"@mdx-js/mdx": "^3.1.1",
|
|
53
|
+
"@types/react": "^18.2.0",
|
|
54
|
+
"@types/react-dom": "^18.2.0",
|
|
55
|
+
"astro": "^4.16.0",
|
|
56
|
+
"chalk": "^5.3.0",
|
|
57
|
+
"clsx": "^2.0.0",
|
|
58
|
+
"commander": "^12.1.0",
|
|
59
|
+
"fast-glob": "^3.3.2",
|
|
60
|
+
"fs-extra": "^11.2.0",
|
|
61
|
+
"lucide-react": "^0.563.0",
|
|
62
|
+
"ora": "^8.1.1",
|
|
63
|
+
"pagefind": "^1.2.0",
|
|
64
|
+
"react": "^18.2.0",
|
|
65
|
+
"react-dom": "^18.2.0",
|
|
66
|
+
"rehype-shiki": "^0.0.9",
|
|
67
|
+
"rehype-stringify": "^10.0.1",
|
|
68
|
+
"remark-gfm": "^4.0.1",
|
|
69
|
+
"remark-parse": "^11.0.0",
|
|
70
|
+
"remark-rehype": "^11.1.2",
|
|
71
|
+
"shiki": "^1.29.2",
|
|
72
|
+
"tailwind-merge": "^3.4.0",
|
|
73
|
+
"tar-stream": "^3.1.7",
|
|
74
|
+
"unified": "^11.0.5",
|
|
75
|
+
"unist-util-visit": "^5.1.0",
|
|
76
|
+
"zod": "^3.24.0"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@types/fs-extra": "^11.0.4",
|
|
80
|
+
"@types/node": "^22.0.0",
|
|
81
|
+
"@types/tar-stream": "^3.1.4",
|
|
82
|
+
"tsup": "^8.3.5",
|
|
83
|
+
"typescript": "^5.7.0",
|
|
84
|
+
"vitest": "^1.6.0"
|
|
85
|
+
},
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build": "tsup",
|
|
88
|
+
"typecheck": "tsc --noEmit",
|
|
89
|
+
"test": "vitest run",
|
|
90
|
+
"test:watch": "vitest"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { defineConfig } from "astro/config";
|
|
2
|
+
import mdx from "@astrojs/mdx";
|
|
3
|
+
import tailwind from "@astrojs/tailwind";
|
|
4
|
+
import react from "@astrojs/react";
|
|
5
|
+
import remarkGfm from "remark-gfm";
|
|
6
|
+
import { remarkOpendocs } from "./src/lib/remark-opendocs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import type { ShikiTransformer } from "shiki";
|
|
9
|
+
|
|
10
|
+
// Get the user's project directory from environment variable
|
|
11
|
+
const projectDir = process.env.OPENDOCS_PROJECT_DIR || process.cwd();
|
|
12
|
+
|
|
13
|
+
// Get the engine directory (where this config file lives)
|
|
14
|
+
const engineDir = new URL(".", import.meta.url).pathname;
|
|
15
|
+
|
|
16
|
+
// Custom Shiki transformer to expose meta string as data-title attribute
|
|
17
|
+
// This allows CodeGroup to extract tab labels from code fences like: ```bash npm
|
|
18
|
+
const metaTransformer: ShikiTransformer = {
|
|
19
|
+
name: "meta-to-data-title",
|
|
20
|
+
pre(node) {
|
|
21
|
+
const meta = this.options.meta?.__raw;
|
|
22
|
+
if (meta) {
|
|
23
|
+
node.properties["data-title"] = meta;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default defineConfig({
|
|
29
|
+
prefetch: {
|
|
30
|
+
prefetchAll: true, // Prefetch all links for instant navigation
|
|
31
|
+
},
|
|
32
|
+
integrations: [
|
|
33
|
+
react(),
|
|
34
|
+
mdx(),
|
|
35
|
+
tailwind({
|
|
36
|
+
applyBaseStyles: false,
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
markdown: {
|
|
40
|
+
remarkPlugins: [remarkGfm, remarkOpendocs],
|
|
41
|
+
shikiConfig: {
|
|
42
|
+
themes: {
|
|
43
|
+
light: "github-light",
|
|
44
|
+
dark: "github-dark",
|
|
45
|
+
},
|
|
46
|
+
defaultColor: false,
|
|
47
|
+
langs: [],
|
|
48
|
+
wrap: true,
|
|
49
|
+
transformers: [metaTransformer],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
// Allow importing MDX files from the user's project directory
|
|
53
|
+
vite: {
|
|
54
|
+
resolve: {
|
|
55
|
+
alias: [
|
|
56
|
+
// @content alias points to the user's project directory
|
|
57
|
+
// Used by mdx-loader.ts to glob all MDX/MD files
|
|
58
|
+
{ find: "@content", replacement: projectDir },
|
|
59
|
+
{
|
|
60
|
+
find: "@opendocs/components",
|
|
61
|
+
replacement: `${engineDir}src/components/react/index.ts`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
server: {
|
|
66
|
+
watch: {
|
|
67
|
+
ignored: [`!${projectDir}/**`],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
// Output directory relative to the engine
|
|
72
|
+
outDir: path.join(projectDir, "dist"),
|
|
73
|
+
// Serve content from the user's project directory
|
|
74
|
+
publicDir: path.join(projectDir, "public"),
|
|
75
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Analytics - Pageview tracking component
|
|
4
|
+
* Sends analytics to backend if configured in docs.json
|
|
5
|
+
*/
|
|
6
|
+
import { loadConfig } from "../lib/config.js";
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
path?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { path: propPath } = Astro.props;
|
|
13
|
+
|
|
14
|
+
// Load config and extract analytics settings
|
|
15
|
+
const config = await loadConfig();
|
|
16
|
+
const backendConfig = config.backend as { apiUrl?: string; siteId?: string } | undefined;
|
|
17
|
+
const backend = backendConfig?.apiUrl;
|
|
18
|
+
const siteId = backendConfig?.siteId;
|
|
19
|
+
const analyticsEnabled = config.features?.analytics !== false;
|
|
20
|
+
|
|
21
|
+
// Only render script if backend and siteId are configured
|
|
22
|
+
const shouldTrack = backend && siteId && analyticsEnabled;
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
{shouldTrack && (
|
|
26
|
+
<script
|
|
27
|
+
data-backend={backend}
|
|
28
|
+
data-site-id={siteId}
|
|
29
|
+
data-path={propPath}
|
|
30
|
+
is:inline
|
|
31
|
+
>
|
|
32
|
+
(function() {
|
|
33
|
+
// Get configuration from script tag
|
|
34
|
+
const script = document.currentScript;
|
|
35
|
+
const backend = script.getAttribute('data-backend');
|
|
36
|
+
const siteId = script.getAttribute('data-site-id');
|
|
37
|
+
const pathFromProp = script.getAttribute('data-path');
|
|
38
|
+
|
|
39
|
+
// Use provided path or current pathname
|
|
40
|
+
const path = pathFromProp || window.location.pathname;
|
|
41
|
+
|
|
42
|
+
// Send pageview to backend (short path to avoid ad blockers)
|
|
43
|
+
fetch(`${backend}/api/analytics/pv`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
siteId: siteId,
|
|
50
|
+
path: path,
|
|
51
|
+
}),
|
|
52
|
+
}).catch(function(err) {
|
|
53
|
+
console.debug('[opendocs] Analytics error:', err);
|
|
54
|
+
});
|
|
55
|
+
})();
|
|
56
|
+
</script>
|
|
57
|
+
)}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
import ApiPlaygroundReact from "./react/ApiPlayground/index";
|
|
3
|
+
|
|
4
|
+
export interface Props {
|
|
5
|
+
endpoint: string;
|
|
6
|
+
method: string;
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
defaultHeaders?: Record<string, string>;
|
|
9
|
+
defaultBody?: Record<string, unknown> | string;
|
|
10
|
+
defaultParams?: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { endpoint, method, baseUrl, defaultHeaders, defaultBody, defaultParams } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<ApiPlaygroundReact
|
|
17
|
+
client:load
|
|
18
|
+
endpoint={endpoint}
|
|
19
|
+
method={method}
|
|
20
|
+
baseUrl={baseUrl}
|
|
21
|
+
defaultHeaders={defaultHeaders}
|
|
22
|
+
defaultBody={defaultBody}
|
|
23
|
+
defaultParams={defaultParams}
|
|
24
|
+
/>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Callout - Informational alert boxes
|
|
4
|
+
* Pure Astro component - no client-side JavaScript needed
|
|
5
|
+
*/
|
|
6
|
+
import { Info, AlertTriangle, XCircle, Lightbulb } from '@lucide/astro';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
type?: "info" | "warning" | "error" | "tip";
|
|
10
|
+
title?: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { type = "info", title, class: className } = Astro.props;
|
|
15
|
+
|
|
16
|
+
const variants = {
|
|
17
|
+
info: {
|
|
18
|
+
border: "border-l-[var(--color-info)]",
|
|
19
|
+
iconColor: "text-[var(--color-info)]",
|
|
20
|
+
icon: Info,
|
|
21
|
+
},
|
|
22
|
+
warning: {
|
|
23
|
+
border: "border-l-[var(--color-warning)]",
|
|
24
|
+
iconColor: "text-[var(--color-warning)]",
|
|
25
|
+
icon: AlertTriangle,
|
|
26
|
+
},
|
|
27
|
+
error: {
|
|
28
|
+
border: "border-l-[var(--color-error)]",
|
|
29
|
+
iconColor: "text-[var(--color-error)]",
|
|
30
|
+
icon: XCircle,
|
|
31
|
+
},
|
|
32
|
+
tip: {
|
|
33
|
+
border: "border-l-[var(--color-success)]",
|
|
34
|
+
iconColor: "text-[var(--color-success)]",
|
|
35
|
+
icon: Lightbulb,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const variant = variants[type] || variants.info;
|
|
40
|
+
const Icon = variant.icon;
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
<div
|
|
44
|
+
class:list={[
|
|
45
|
+
"callout rounded-lg border-l-4 my-6 p-4",
|
|
46
|
+
"bg-[var(--color-surface-raised)]",
|
|
47
|
+
variant.border,
|
|
48
|
+
className,
|
|
49
|
+
]}
|
|
50
|
+
role="alert"
|
|
51
|
+
data-type={type}
|
|
52
|
+
>
|
|
53
|
+
<div class="flex gap-3">
|
|
54
|
+
<span class:list={["flex-shrink-0 mt-0.5", variant.iconColor]}>
|
|
55
|
+
<Icon class="w-5 h-5" aria-hidden="true" />
|
|
56
|
+
</span>
|
|
57
|
+
<div class="flex-1 min-w-0">
|
|
58
|
+
{title && (
|
|
59
|
+
<p class="font-semibold text-[var(--color-foreground)] mb-1">{title}</p>
|
|
60
|
+
)}
|
|
61
|
+
<div class="callout-content text-[var(--color-muted)] text-sm [&>p]:my-0 [&>p+p]:mt-2 [&>ul]:my-2 [&>ol]:my-2 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0">
|
|
62
|
+
<slot />
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Card - Content card with optional link
|
|
4
|
+
* Pure Astro component - no client-side JavaScript needed
|
|
5
|
+
*/
|
|
6
|
+
interface Props {
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
href?: string;
|
|
10
|
+
icon?: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { title, description, href, icon, class: className } = Astro.props;
|
|
15
|
+
const isLink = !!href;
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
{isLink ? (
|
|
19
|
+
<a
|
|
20
|
+
href={href}
|
|
21
|
+
class:list={[
|
|
22
|
+
"card group block p-6 rounded-xl cursor-pointer no-underline",
|
|
23
|
+
"bg-[var(--color-surface-raised)]",
|
|
24
|
+
className,
|
|
25
|
+
]}
|
|
26
|
+
>
|
|
27
|
+
{icon && (
|
|
28
|
+
<span
|
|
29
|
+
class="card-icon flex items-center justify-center w-10 h-10 mb-4 rounded-lg bg-[var(--color-surface-sunken)] text-xl"
|
|
30
|
+
aria-hidden="true"
|
|
31
|
+
>
|
|
32
|
+
{icon}
|
|
33
|
+
</span>
|
|
34
|
+
)}
|
|
35
|
+
<h3 class="card-title text-base font-semibold m-0 text-[var(--color-primary)]">
|
|
36
|
+
{title}
|
|
37
|
+
</h3>
|
|
38
|
+
{description && (
|
|
39
|
+
<p class="card-description text-sm text-[var(--color-muted)] mt-2 mb-0">
|
|
40
|
+
{description}
|
|
41
|
+
</p>
|
|
42
|
+
)}
|
|
43
|
+
<div class="card-content text-sm text-[var(--color-muted)] mt-2">
|
|
44
|
+
<slot />
|
|
45
|
+
</div>
|
|
46
|
+
</a>
|
|
47
|
+
) : (
|
|
48
|
+
<div
|
|
49
|
+
class:list={[
|
|
50
|
+
"card group block p-6 rounded-xl",
|
|
51
|
+
"bg-[var(--color-surface-raised)]",
|
|
52
|
+
className,
|
|
53
|
+
]}
|
|
54
|
+
>
|
|
55
|
+
{icon && (
|
|
56
|
+
<span
|
|
57
|
+
class="card-icon flex items-center justify-center w-10 h-10 mb-4 rounded-lg bg-[var(--color-surface-sunken)] text-xl"
|
|
58
|
+
aria-hidden="true"
|
|
59
|
+
>
|
|
60
|
+
{icon}
|
|
61
|
+
</span>
|
|
62
|
+
)}
|
|
63
|
+
<h3 class="card-title text-base font-semibold m-0 text-[var(--color-foreground)]">
|
|
64
|
+
{title}
|
|
65
|
+
</h3>
|
|
66
|
+
{description && (
|
|
67
|
+
<p class="card-description text-sm text-[var(--color-muted)] mt-2 mb-0">
|
|
68
|
+
{description}
|
|
69
|
+
</p>
|
|
70
|
+
)}
|
|
71
|
+
<div class="card-content text-sm text-[var(--color-muted)] mt-2">
|
|
72
|
+
<slot />
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* CardGroup - Grid layout for Card components
|
|
4
|
+
* Pure Astro component - no client-side JavaScript needed
|
|
5
|
+
*/
|
|
6
|
+
interface Props {
|
|
7
|
+
cols?: 1 | 2 | 3 | 4;
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { cols = 2, class: className } = Astro.props;
|
|
12
|
+
|
|
13
|
+
const colVariants: Record<number, string> = {
|
|
14
|
+
1: "grid-cols-1",
|
|
15
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
16
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
17
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
|
|
18
|
+
};
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<div
|
|
22
|
+
class:list={[
|
|
23
|
+
"card-group grid gap-4 my-6 not-prose",
|
|
24
|
+
colVariants[cols],
|
|
25
|
+
className,
|
|
26
|
+
]}
|
|
27
|
+
>
|
|
28
|
+
<slot />
|
|
29
|
+
</div>
|