create-svelte-docsmith 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 George Daskalakis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # create-svelte-docsmith
2
+
3
+ Scaffold a documentation site powered by [Svelte DocSmith](https://www.npmjs.com/package/svelte-docsmith).
4
+
5
+ ```bash
6
+ npm create svelte-docsmith@latest my-docs
7
+ ```
8
+
9
+ ```bash
10
+ pnpm create svelte-docsmith my-docs
11
+ ```
12
+
13
+ ```bash
14
+ yarn create svelte-docsmith my-docs
15
+ ```
16
+
17
+ You can also run it without a name and answer the prompts:
18
+
19
+ ```bash
20
+ npm create svelte-docsmith@latest
21
+ ```
22
+
23
+ It asks a short set of questions (all with sensible defaults):
24
+
25
+ - **Directory** — where to create the project (skipped if you passed a name).
26
+ - **Site title** — used in the header and `site-config.ts`.
27
+ - **Theme** — a built-in preset, or the default.
28
+ - **Install dependencies?** — runs your package manager for you.
29
+ - **Initialize a git repository?**
30
+
31
+ Then it writes a ready-to-run SvelteKit + Tailwind v4 project wired with
32
+ DocSmith: the markdown pipeline, the Vite plugin, the style contract, a
33
+ `DocsShell` layout, a 404 page, and two sample doc pages.
34
+
35
+ ```bash
36
+ cd my-docs
37
+ npm run dev
38
+ ```
39
+
40
+ Add markdown files under `src/routes/docs/` and they appear in the sidebar,
41
+ styled, highlighted, and searchable.
42
+
43
+ ## License
44
+
45
+ MIT
package/index.js ADDED
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { spawn, spawnSync } from 'node:child_process';
6
+ import * as p from '@clack/prompts';
7
+
8
+ const templateDir = fileURLToPath(new URL('./template', import.meta.url));
9
+
10
+ const PRESETS = [
11
+ { value: 'default', label: 'Default (Tangerine)' },
12
+ { value: 'darkmatter', label: 'Darkmatter' },
13
+ { value: 'amethyst', label: 'Amethyst' },
14
+ { value: 'graphite', label: 'Graphite' },
15
+ { value: 'evergreen', label: 'Evergreen' },
16
+ { value: 'rose', label: 'Rose' },
17
+ { value: 'ocean', label: 'Ocean' },
18
+ { value: 'nord', label: 'Nord' },
19
+ { value: 'claude', label: 'Claude' },
20
+ { value: 'bubblegum', label: 'Bubblegum' },
21
+ { value: 'mono', label: 'Mono' }
22
+ ];
23
+
24
+ /** Copy `src` into `dest`, renaming the packaged `_gitignore` back to `.gitignore`. */
25
+ function copyTemplate(src, dest) {
26
+ fs.mkdirSync(dest, { recursive: true });
27
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
28
+ const from = path.join(src, entry.name);
29
+ const name = entry.name === '_gitignore' ? '.gitignore' : entry.name;
30
+ const to = path.join(dest, name);
31
+ if (entry.isDirectory()) copyTemplate(from, to);
32
+ else fs.copyFileSync(from, to);
33
+ }
34
+ }
35
+
36
+ /** Detect the package manager that invoked us (npm/pnpm/yarn/bun). */
37
+ function detectPackageManager() {
38
+ const ua = process.env.npm_config_user_agent ?? '';
39
+ if (ua.startsWith('pnpm')) return 'pnpm';
40
+ if (ua.startsWith('yarn')) return 'yarn';
41
+ if (ua.startsWith('bun')) return 'bun';
42
+ return 'npm';
43
+ }
44
+
45
+ function toPackageName(dir) {
46
+ return (
47
+ path
48
+ .basename(path.resolve(dir))
49
+ .toLowerCase()
50
+ .replace(/[^a-z0-9-~]/g, '-')
51
+ .replace(/^-+|-+$/g, '') || 'my-docs'
52
+ );
53
+ }
54
+
55
+ function toTitle(name) {
56
+ return (
57
+ name
58
+ .split(/[-_\s]+/)
59
+ .filter(Boolean)
60
+ .map((w) => w[0].toUpperCase() + w.slice(1))
61
+ .join(' ') || 'My Docs'
62
+ );
63
+ }
64
+
65
+ /** Fill the template placeholders, and wire the chosen theme preset into app.css. */
66
+ function applyOptions(dest, { pkgName, title, preset }) {
67
+ const edit = (rel, fn) => {
68
+ const file = path.join(dest, rel);
69
+ fs.writeFileSync(file, fn(fs.readFileSync(file, 'utf-8')));
70
+ };
71
+ edit('package.json', (t) => t.replaceAll('{{PROJECT_NAME}}', pkgName));
72
+ edit('README.md', (t) => t.replaceAll('{{PROJECT_NAME}}', title));
73
+ edit('src/lib/site-config.ts', (t) => t.replaceAll('{{SITE_TITLE}}', title));
74
+ if (preset && preset !== 'default') {
75
+ edit('src/app.css', (t) =>
76
+ t.replace(
77
+ "@import 'svelte-docsmith/theme.css';\n",
78
+ `@import 'svelte-docsmith/theme.css';\n@import 'svelte-docsmith/themes/${preset}.css';\n`
79
+ )
80
+ );
81
+ }
82
+ }
83
+
84
+ /** Run a command asynchronously so the event loop stays free (a synchronous
85
+ * child would freeze the spinner animation). Resolves with the exit code. */
86
+ function run(cmd, args, cwd) {
87
+ return new Promise((resolve) => {
88
+ const child = spawn(cmd, args, {
89
+ cwd,
90
+ stdio: 'ignore',
91
+ shell: process.platform === 'win32'
92
+ });
93
+ child.on('close', (code) => resolve(code ?? 1));
94
+ child.on('error', () => resolve(1));
95
+ });
96
+ }
97
+
98
+ /** Exit gracefully when the user hits Ctrl+C at a prompt. */
99
+ function unlessCancelled(value) {
100
+ if (p.isCancel(value)) {
101
+ p.cancel('Cancelled.');
102
+ process.exit(0);
103
+ }
104
+ return value;
105
+ }
106
+
107
+ async function main() {
108
+ p.intro('create-svelte-docsmith');
109
+ const interactive = Boolean(process.stdin.isTTY);
110
+ const pm = detectPackageManager();
111
+
112
+ // 1. Target directory (skip the prompt if passed as an argument).
113
+ let target = process.argv[2];
114
+ if (!target) {
115
+ target = interactive
116
+ ? unlessCancelled(
117
+ await p.text({
118
+ message: 'Where should we create your docs?',
119
+ placeholder: './my-docs',
120
+ defaultValue: './my-docs'
121
+ })
122
+ )
123
+ : './my-docs';
124
+ }
125
+ const dest = path.resolve(process.cwd(), target);
126
+ const rel = path.relative(process.cwd(), dest) || '.';
127
+
128
+ // 2. Refuse to clobber a non-empty directory (unless the user confirms).
129
+ if (fs.existsSync(dest) && fs.readdirSync(dest).length > 0) {
130
+ const overwrite = interactive
131
+ ? unlessCancelled(
132
+ await p.confirm({
133
+ message: `${rel} is not empty. Create the site here anyway?`,
134
+ initialValue: false
135
+ })
136
+ )
137
+ : false;
138
+ if (!overwrite) {
139
+ p.cancel(`${rel} is not empty. Aborting.`);
140
+ process.exit(1);
141
+ }
142
+ }
143
+
144
+ const defaultTitle = toTitle(toPackageName(dest));
145
+
146
+ // 3. Site title.
147
+ const title = interactive
148
+ ? unlessCancelled(
149
+ await p.text({
150
+ message: 'Site title',
151
+ placeholder: defaultTitle,
152
+ defaultValue: defaultTitle
153
+ })
154
+ ) || defaultTitle
155
+ : defaultTitle;
156
+
157
+ // 4. Theme preset.
158
+ const preset = interactive
159
+ ? unlessCancelled(
160
+ await p.select({ message: 'Theme', options: PRESETS, initialValue: 'default' })
161
+ )
162
+ : 'default';
163
+
164
+ // 5 & 6. Install dependencies / init git.
165
+ const doInstall = interactive
166
+ ? unlessCancelled(
167
+ await p.confirm({ message: `Install dependencies with ${pm}?`, initialValue: true })
168
+ )
169
+ : false;
170
+ const doGit = interactive
171
+ ? unlessCancelled(
172
+ await p.confirm({ message: 'Initialize a git repository?', initialValue: true })
173
+ )
174
+ : false;
175
+
176
+ // Scaffold.
177
+ copyTemplate(templateDir, dest);
178
+ applyOptions(dest, { pkgName: toPackageName(dest), title, preset });
179
+
180
+ if (doInstall) {
181
+ const s = p.spinner();
182
+ s.start(`Installing dependencies with ${pm} (this can take a minute)`);
183
+ const code = await run(pm, ['install'], dest);
184
+ if (code === 0) s.stop('Dependencies installed');
185
+ else s.stop(`Could not install with ${pm}; run it yourself later`);
186
+ }
187
+
188
+ if (doGit) {
189
+ // Fast and non-interactive, so a synchronous call is fine here.
190
+ spawnSync('git', ['init', '-q'], { cwd: dest, stdio: 'ignore' });
191
+ }
192
+
193
+ // Next steps.
194
+ const runCmd = pm === 'npm' ? 'npm run' : pm;
195
+ const steps = [];
196
+ if (rel !== '.') steps.push(`cd ${rel}`);
197
+ if (!doInstall) steps.push(`${pm} install`);
198
+ steps.push(`${runCmd} dev`);
199
+ p.note(steps.join('\n'), 'Next steps');
200
+ p.outro('Add markdown under src/routes/docs/ and it appears in the sidebar.');
201
+ }
202
+
203
+ main().catch((err) => {
204
+ console.error(err instanceof Error ? err.message : err);
205
+ process.exit(1);
206
+ });
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "create-svelte-docsmith",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold a documentation site powered by Svelte DocSmith.",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-svelte-docsmith": "index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "template"
12
+ ],
13
+ "keywords": [
14
+ "svelte",
15
+ "sveltekit",
16
+ "documentation",
17
+ "docs",
18
+ "create",
19
+ "scaffold",
20
+ "svelte-docsmith"
21
+ ],
22
+ "author": {
23
+ "name": "George Daskalakis",
24
+ "email": "george.dask97@gmail.com",
25
+ "url": "https://github.com/geodask"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/geodask/svelte-docsmith.git",
30
+ "directory": "packages/create-svelte-docsmith"
31
+ },
32
+ "license": "MIT",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "dependencies": {
40
+ "@clack/prompts": "^1.7.0"
41
+ }
42
+ }
@@ -0,0 +1,41 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ A documentation site built with [Svelte DocSmith](https://docsmith.geodask.com).
4
+
5
+ ## Develop
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev
10
+ ```
11
+
12
+ ## Write docs
13
+
14
+ Add a `+page.md` file under `src/routes/docs/`. Its frontmatter drives the
15
+ sidebar:
16
+
17
+ ```md
18
+ ---
19
+ title: My Page
20
+ section: Guides
21
+ order: 1
22
+ ---
23
+
24
+ ## Hello
25
+
26
+ Your content here.
27
+ ```
28
+
29
+ Save it and the page appears in the sidebar, styled and highlighted.
30
+
31
+ ## Configure
32
+
33
+ - **Site title, nav, footer, SEO** — `src/lib/site-config.ts`
34
+ - **Theme** — `src/app.css` (import a preset, or override tokens)
35
+
36
+ ## Build
37
+
38
+ ```bash
39
+ npm run build
40
+ npm run preview
41
+ ```
@@ -0,0 +1,21 @@
1
+ node_modules
2
+
3
+ # Output
4
+ .output
5
+ .vercel
6
+ .netlify
7
+ .wrangler
8
+ /.svelte-kit
9
+ /build
10
+
11
+ # OS / editor
12
+ .DS_Store
13
+ Thumbs.db
14
+ .vscode/*
15
+ !.vscode/extensions.json
16
+ .idea
17
+
18
+ # Env
19
+ .env
20
+ .env.*
21
+ !.env.example
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite dev",
8
+ "build": "vite build",
9
+ "preview": "vite preview",
10
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"
11
+ },
12
+ "dependencies": {
13
+ "svelte-docsmith": "^0.3.0"
14
+ },
15
+ "devDependencies": {
16
+ "@sveltejs/adapter-auto": "^7.0.1",
17
+ "@sveltejs/kit": "^2.16.0",
18
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
19
+ "@tailwindcss/vite": "^4.0.0",
20
+ "svelte": "^5.0.0",
21
+ "svelte-check": "^4.0.0",
22
+ "tailwindcss": "^4.0.0",
23
+ "typescript": "^5.0.0",
24
+ "vite": "^8.0.0"
25
+ }
26
+ }
@@ -0,0 +1,11 @@
1
+ @import 'tailwindcss';
2
+
3
+ /* The whole Svelte DocSmith style contract in one import: it makes Tailwind scan
4
+ * the package, registers the design tokens for light and dark, and pulls in the
5
+ * typography and animation plugins. */
6
+ @import 'svelte-docsmith/theme.css';
7
+
8
+ /* Prefer a different look? Import a preset after theme.css and it wins:
9
+ * @import 'svelte-docsmith/themes/darkmatter.css';
10
+ * Available: darkmatter, tangerine, amethyst, graphite, evergreen, rose, ocean,
11
+ * nord, claude, bubblegum, mono. Or override individual tokens yourself. */
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%sveltekit.assets%/favicon.svg" type="image/svg+xml" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ %sveltekit.head%
8
+ </head>
9
+ <body data-sveltekit-preload-data="hover">
10
+ <div style="display: contents">%sveltekit.body%</div>
11
+ </body>
12
+ </html>
@@ -0,0 +1,14 @@
1
+ import type { DocsmithConfig } from 'svelte-docsmith';
2
+
3
+ // The whole-site config passed to DocsShell. Set your title, links, and the
4
+ // SEO/social defaults here. See https://docsmith.geodask.com.
5
+ export const siteConfig: DocsmithConfig = {
6
+ title: '{{SITE_TITLE}}',
7
+ // github: 'https://github.com/you/your-library',
8
+ // description: 'A short tagline, used as the default meta description.',
9
+ // url: 'https://your-docs.dev',
10
+ nav: [{ label: 'Docs', href: '/docs/introduction' }],
11
+ footer: {
12
+ copyright: `© ${new Date().getFullYear()} {{SITE_TITLE}}`
13
+ }
14
+ };
@@ -0,0 +1,13 @@
1
+ <script lang="ts">
2
+ import { docs } from 'svelte-docsmith/content';
3
+ import { ErrorPage } from 'svelte-docsmith';
4
+ import { siteConfig } from '$lib/site-config';
5
+ </script>
6
+
7
+ <ErrorPage
8
+ config={siteConfig}
9
+ content={docs}
10
+ search={() => import('svelte-docsmith/search').then((m) => m.docs)}
11
+ home="/docs/introduction"
12
+ homeLabel="Back to the docs"
13
+ />
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ import '../app.css';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ const { children }: { children: Snippet } = $props();
6
+ </script>
7
+
8
+ {@render children()}
@@ -0,0 +1,7 @@
1
+ import { redirect } from '@sveltejs/kit';
2
+
3
+ // Send the site root to the first docs page. Replace this file with a
4
+ // `+page.svelte` if you'd rather have a custom landing page.
5
+ export function load() {
6
+ redirect(307, '/docs/introduction');
7
+ }
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import { docs } from 'svelte-docsmith/content';
3
+ import { DocsShell } from 'svelte-docsmith';
4
+ import { siteConfig } from '$lib/site-config';
5
+ import type { Snippet } from 'svelte';
6
+
7
+ const { children }: { children: Snippet } = $props();
8
+ </script>
9
+
10
+ <DocsShell
11
+ config={siteConfig}
12
+ content={docs}
13
+ search={() => import('svelte-docsmith/search').then((m) => m.docs)}
14
+ pattern
15
+ >
16
+ {@render children()}
17
+ </DocsShell>
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Introduction
3
+ description: Welcome to your new documentation site.
4
+ section: Getting Started
5
+ order: 1
6
+ ---
7
+
8
+ <script>
9
+ import { Callout } from 'svelte-docsmith';
10
+ </script>
11
+
12
+ Welcome to your new documentation site, built with Svelte DocSmith.
13
+
14
+ ## How it works
15
+
16
+ Every `+page.md` file under `src/routes/docs/` becomes a page, and its
17
+ frontmatter drives the sidebar:
18
+
19
+ - `title` names the page and its sidebar entry.
20
+ - `section` groups pages in the sidebar.
21
+ - `order` sorts pages within a group.
22
+
23
+ <Callout variant="tip" title="Try it">
24
+
25
+ Open `src/routes/docs/introduction/+page.md`, edit this text, and save. The page
26
+ updates instantly.
27
+
28
+ </Callout>
29
+
30
+ ## Next
31
+
32
+ Head to the [Quick Start](/docs/quick-start) for the authoring basics.
@@ -0,0 +1,26 @@
1
+ ---
2
+ title: Quick Start
3
+ description: Write your first pages.
4
+ section: Getting Started
5
+ order: 2
6
+ ---
7
+
8
+ Add a markdown file anywhere under `src/routes/docs/` and it shows up in the
9
+ sidebar, styled and highlighted.
10
+
11
+ ## Code blocks
12
+
13
+ Fenced code is highlighted by Shiki. Emphasize a line with a comment marker:
14
+
15
+ ```ts
16
+ const docs = loadDocs();
17
+ const active = docs.find((d) => d.current); // [!code highlight]
18
+ ```
19
+
20
+ ## Components
21
+
22
+ DocSmith ships components you can use right inside markdown: callouts, tabs,
23
+ cards, steps, and more. Import them in a `<script>` block at the top of the page,
24
+ then use them in the body.
25
+
26
+ Learn more in the [Svelte DocSmith documentation](https://docsmith.geodask.com).
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2
+ <path d="M12 7v14" />
3
+ <path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
4
+ </svg>
@@ -0,0 +1,15 @@
1
+ import adapter from '@sveltejs/adapter-auto';
2
+ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3
+ import { docsmith } from 'svelte-docsmith/preprocess';
4
+
5
+ /** @type {import('@sveltejs/kit').Config} */
6
+ const config = {
7
+ // `.md` files are compiled as routes by the DocSmith preprocessor.
8
+ extensions: ['.svelte', '.md'],
9
+ preprocess: [vitePreprocess(), docsmith()],
10
+ kit: {
11
+ adapter: adapter()
12
+ }
13
+ };
14
+
15
+ export default config;
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "./.svelte-kit/tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "checkJs": true,
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "resolveJsonModule": true,
9
+ "skipLibCheck": true,
10
+ "sourceMap": true,
11
+ "strict": true,
12
+ "moduleResolution": "bundler"
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ import tailwindcss from '@tailwindcss/vite';
2
+ import { sveltekit } from '@sveltejs/kit/vite';
3
+ import { defineConfig } from 'vite';
4
+ import { docsmith } from 'svelte-docsmith/vite';
5
+
6
+ export default defineConfig({
7
+ // `docsmith()` builds the content + search indexes and powers LiveExample.
8
+ // It must come before sveltekit().
9
+ plugins: [docsmith(), tailwindcss(), sveltekit()]
10
+ });