@axerity/cli 0.1.2 → 0.1.4

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/bin/axerity.js CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  readdirSync,
11
11
  rmSync,
12
12
  symlinkSync,
13
+ watch,
13
14
  writeFileSync
14
15
  } from 'node:fs';
15
16
  import { basename, dirname, join, relative, resolve } from 'node:path';
@@ -67,6 +68,11 @@ function mountSpecs(config) {
67
68
  return { ...config, openapi };
68
69
  }
69
70
 
71
+ function writeConfig() {
72
+ const config = JSON.parse(readFileSync(join(userRoot, 'axerity.json'), 'utf8'));
73
+ writeFileSync(ENGINE_CONFIG, JSON.stringify(mountSpecs(config), null, '\t'));
74
+ }
75
+
70
76
  function mount(contentDir) {
71
77
  rmSync(ENGINE_DOCS, { recursive: true, force: true });
72
78
  mkdirSync(ENGINE_DOCS, { recursive: true });
@@ -74,8 +80,7 @@ function mount(contentDir) {
74
80
  symlinkSync(join(contentDir, entry), join(ENGINE_DOCS, entry), symlinkType);
75
81
  }
76
82
 
77
- const config = JSON.parse(readFileSync(join(userRoot, 'axerity.json'), 'utf8'));
78
- writeFileSync(ENGINE_CONFIG, JSON.stringify(mountSpecs(config), null, '\t'));
83
+ writeConfig();
79
84
 
80
85
  rmSync(ASSETS_DIR, { recursive: true, force: true });
81
86
  cpSync(ENGINE_STATIC, ASSETS_DIR, { recursive: true });
@@ -102,7 +107,9 @@ const strip = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
102
107
  const banner = (sub) => process.stdout.write(`\n ${mark} ${bold('axerity')} ${dim(sub)}\n\n`);
103
108
 
104
109
  const NOISE =
105
- /^\s*(VITE v|➜|press h|ready in|Local:|Network:|\[vite\].*(optimiz|dependencies)|\[optimizer\]|Forced re-opt|watching for file changes|use --host)/i;
110
+ /^\s*(VITE v|➜|press h|ready in|Local:|Network:|use --host|watching for file changes)/i;
111
+ const VITE_CHATTER =
112
+ /\[optimizer\]|\[vite\].*(re-?optimiz|optimized dependencies|new dependencies|page reload|hmr update|dependencies because)/i;
106
113
 
107
114
  function streamServer(child) {
108
115
  let shown = false;
@@ -120,7 +127,7 @@ function streamServer(child) {
120
127
  process.stdout.write(` ${dim('Ctrl+C to stop')}\n\n`);
121
128
  continue;
122
129
  }
123
- if (!clean.trim() || NOISE.test(clean.trim())) continue;
130
+ if (!clean.trim() || NOISE.test(clean.trim()) || VITE_CHATTER.test(clean)) continue;
124
131
  process.stdout.write(` ${line}\n`);
125
132
  }
126
133
  };
@@ -163,10 +170,27 @@ function runEngine(sub, extra, { mounted, onSuccess }) {
163
170
  banner(sub);
164
171
  const build = sub === 'build' ? streamBuild(child) : (streamServer(child), null);
165
172
 
173
+ let configWatcher = null;
174
+ if (mounted && sub === 'dev') {
175
+ let timer = null;
176
+ configWatcher = watch(userRoot, (_event, filename) => {
177
+ if (filename !== 'axerity.json') return;
178
+ clearTimeout(timer);
179
+ timer = setTimeout(() => {
180
+ try {
181
+ writeConfig();
182
+ } catch {
183
+ return;
184
+ }
185
+ }, 80);
186
+ });
187
+ }
188
+
166
189
  let cleaned = false;
167
190
  const cleanup = () => {
168
191
  if (cleaned || !mounted) return;
169
192
  cleaned = true;
193
+ configWatcher?.close();
170
194
  tidy();
171
195
  };
172
196
 
@@ -233,7 +257,7 @@ function init() {
233
257
  const files = {
234
258
  'axerity.json': `${JSON.stringify(
235
259
  {
236
- $schema: 'https://axerity.com/axerity.schema.json',
260
+ $schema: 'https://unpkg.com/@axerity/cli/axerity.schema.json',
237
261
  name: 'My Docs',
238
262
  description: 'Documentation built with Axerity.',
239
263
  theme: 'neutral',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axerity/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "A documentation site generator built with Svelte.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -59,6 +59,7 @@
59
59
  "@tailwindcss/forms": "^0.5.11",
60
60
  "@tailwindcss/typography": "^0.5.19",
61
61
  "@tailwindcss/vite": "^4.3.0",
62
+ "lucide": "^1.17.0",
62
63
  "mdsvex": "^0.12.7",
63
64
  "mermaid": "^11.15.0",
64
65
  "rehype-slug": "^6.0.0",
@@ -18,8 +18,8 @@ axerity build # build the static site
18
18
  axerity preview # preview the production build
19
19
  ```
20
20
 
21
- Run them with `npx axerity <command>`, or install globally with
22
- `npm install -g axerity` and call `axerity` directly.
21
+ Run them with `pnpm dlx @axerity/cli <command>` (or `npx @axerity/cli <command>`),
22
+ or add `@axerity/cli` as a dev dependency and call `axerity` through your scripts.
23
23
 
24
24
  ## init
25
25
 
@@ -35,12 +35,14 @@ example `axerity dev --port 4000`.
35
35
 
36
36
  ## build
37
37
 
38
- `axerity build` produces a static site. Every page is prerendered to HTML, and
39
- the search index, `llms.txt`, sitemap, RSS feed, and OpenGraph images are all
40
- written out, ready to host anywhere.
38
+ `axerity build` produces a static site in `build/`. Every page is prerendered to
39
+ HTML, and the search index, `llms.txt`, sitemap, RSS feed, and OpenGraph images
40
+ are all written out, ready to host anywhere.
41
41
 
42
42
  ## How it works
43
43
 
44
- The CLI never touches your content. It assembles a hidden `.axerity` workspace
45
- that pairs the packaged engine with your `docs/` folder and `axerity.json`, then
46
- runs Vite there. Add `.axerity` to your `.gitignore`; `init` does this for you.
44
+ The engine runs from its own install, not from your repo. When you run a command,
45
+ Axerity reads your `docs/` and `axerity.json` and renders against them, then
46
+ writes the result to `build/` in your project. Your content is the source of
47
+ truth and nothing else in your folder is touched, so there is no workspace to
48
+ gitignore beyond `build/`.
@@ -40,7 +40,7 @@ Settings and set the Framework Preset to **Other**.
40
40
 
41
41
  In the Pages project settings:
42
42
 
43
- - **Build command:** `npx axerity build`
43
+ - **Build command:** `npx @axerity/cli build`
44
44
  - **Build output directory:** `build`
45
45
  - **Framework preset:** None
46
46
 
@@ -50,7 +50,7 @@ Cloudflare serves clean URLs automatically.
50
50
 
51
51
  ```toml title="netlify.toml"
52
52
  [build]
53
- command = "npx axerity build"
53
+ command = "npx @axerity/cli build"
54
54
  publish = "build"
55
55
  ```
56
56
 
@@ -59,7 +59,7 @@ Netlify serves clean URLs (pretty URLs) by default.
59
59
  ## GitHub Pages
60
60
 
61
61
  Build, then publish the `build/` folder (for example with a GitHub Action that
62
- runs `npx axerity build` and uploads `build/` as the Pages artifact).
62
+ runs `npx @axerity/cli build` and uploads `build/` as the Pages artifact).
63
63
 
64
64
  Project sites are served from `https://<user>.github.io/<repo>/`, a sub-path, so
65
65
  set the base in `axerity.json`:
@@ -6,35 +6,52 @@ icon: download
6
6
 
7
7
  # Installation
8
8
 
9
- Axerity is a CLI. You do not clone or fork anything. Install it, scaffold a site,
10
- and start writing Markdown.
9
+ Axerity is a CLI. You do not clone or fork anything. Run it, scaffold a site, and
10
+ start writing Markdown.
11
11
 
12
12
  ## Requirements
13
13
 
14
- - Node.js 20 or newer
14
+ - Node.js 24 or newer
15
15
 
16
16
  ## Create a site
17
17
 
18
18
  Scaffold a new site with `init`, then start the dev server:
19
19
 
20
20
  ```bash
21
- npx axerity init my-docs
21
+ pnpm dlx @axerity/cli init my-docs
22
22
  cd my-docs
23
- npx axerity dev
23
+ pnpm dlx @axerity/cli dev
24
24
  ```
25
25
 
26
- Your site is running at `http://localhost:5173`. Or install it globally and drop
27
- the `npx`:
26
+ Your site is running at `http://localhost:5173`. `pnpm dlx` runs the CLI without
27
+ installing it. `npx @axerity/cli <command>` works the same way.
28
+
29
+ ## Install it
30
+
31
+ For a project you build often, add it as a dev dependency so the version is
32
+ pinned:
28
33
 
29
34
  ```bash
30
- npm install -g axerity
31
- axerity init my-docs
35
+ pnpm add -D @axerity/cli
36
+ ```
37
+
38
+ Then wire up scripts in your `package.json`:
39
+
40
+ ```json
41
+ {
42
+ "scripts": {
43
+ "dev": "axerity dev",
44
+ "build": "axerity build",
45
+ "preview": "axerity preview"
46
+ }
47
+ }
32
48
  ```
33
49
 
50
+ Now `pnpm dev` and `pnpm build` just work, no global install or PATH setup.
51
+
34
52
  ## Project layout
35
53
 
36
- A site is just your content and one config file. Everything else lives in the
37
- package:
54
+ A site is your content and one config file:
38
55
 
39
56
  ```
40
57
  my-docs/
@@ -44,6 +61,6 @@ my-docs/
44
61
  ```
45
62
 
46
63
  Write Markdown in `docs/`, order pages with `meta.json`, and configure the site
47
- in [`axerity.json`](/configuration). The CLI builds a hidden `.axerity`
48
- workspace to run the engine against your content, so add `.axerity` to your
49
- `.gitignore` (the scaffold does this for you).
64
+ in [`axerity.json`](/configuration). The engine runs from its own install, so the
65
+ only thing Axerity ever creates in your project is the `build/` folder. The
66
+ scaffold adds it to your `.gitignore` for you.
@@ -1,8 +1,8 @@
1
1
  <script lang="ts" module>
2
- import type { Component } from 'svelte';
3
- import * as icons from '@lucide/svelte';
2
+ import { icons } from 'lucide';
4
3
 
5
- const registry = icons as unknown as Record<string, Component>;
4
+ type IconNode = [string, Record<string, string | number>][];
5
+ const registry = icons as unknown as Record<string, IconNode>;
6
6
 
7
7
  const pascal = (name: string) =>
8
8
  name
@@ -18,9 +18,24 @@
18
18
  class: className = ''
19
19
  }: { name?: string; size?: number; class?: string } = $props();
20
20
 
21
- const Icon = $derived(name ? registry[pascal(name)] : undefined);
21
+ const node = $derived(name ? registry[pascal(name)] : undefined);
22
22
  </script>
23
23
 
24
- {#if Icon}
25
- <Icon {size} class={className} />
24
+ {#if node}
25
+ <svg
26
+ xmlns="http://www.w3.org/2000/svg"
27
+ width={size}
28
+ height={size}
29
+ viewBox="0 0 24 24"
30
+ fill="none"
31
+ stroke="currentColor"
32
+ stroke-width="2"
33
+ stroke-linecap="round"
34
+ stroke-linejoin="round"
35
+ class={`lucide ${className}`}
36
+ >
37
+ {#each node as [tag, attrs], i (i)}
38
+ <svelte:element this={tag} {...attrs} />
39
+ {/each}
40
+ </svg>
26
41
  {/if}
package/vite.config.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { readFileSync } from 'node:fs';
1
+ import { existsSync, readFileSync, watch } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
3
  import tailwindcss from '@tailwindcss/vite';
4
4
  import { sveltekit } from '@sveltejs/kit/vite';
5
5
  import { defineConfig } from 'vite';
6
6
  import { generateApiDocs } from './src/lib/openapi/generate';
7
7
 
8
- const allow = process.env.AXERITY_FS_ALLOW;
8
+ const mounted = !!process.env.AXERITY_FS_ALLOW;
9
9
 
10
10
  function openapi() {
11
11
  const localSpecs: string[] = [];
@@ -40,7 +40,28 @@ function openapi() {
40
40
  };
41
41
  }
42
42
 
43
+ function configReload() {
44
+ const file = resolve('axerity.json');
45
+ let watcher: ReturnType<typeof watch> | null = null;
46
+ return {
47
+ name: 'axerity:config-reload',
48
+ configureServer(server: import('vite').ViteDevServer) {
49
+ if (!existsSync(file)) return;
50
+ let timer: ReturnType<typeof setTimeout> | null = null;
51
+ watcher = watch(file, () => {
52
+ if (timer) clearTimeout(timer);
53
+ timer = setTimeout(() => server.watcher.emit('change', file), 50);
54
+ });
55
+ },
56
+ closeBundle() {
57
+ watcher?.close();
58
+ watcher = null;
59
+ }
60
+ };
61
+ }
62
+
43
63
  export default defineConfig({
44
- plugins: [openapi(), tailwindcss(), sveltekit()],
45
- server: allow ? { fs: { strict: false } } : undefined
64
+ plugins: [openapi(), ...(mounted ? [configReload()] : []), tailwindcss(), sveltekit()],
65
+ server: mounted ? { fs: { strict: false } } : undefined,
66
+ optimizeDeps: mounted ? { noDiscovery: true, include: ['@orama/orama', 'mermaid'] } : undefined
46
67
  });