@life-and-dev/mdsite 0.5.3 → 0.7.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.
Files changed (70) hide show
  1. package/README.md +29 -37
  2. package/dist/commands/clean.d.ts +1 -0
  3. package/dist/commands/clean.js +70 -0
  4. package/dist/commands/clean.js.map +1 -0
  5. package/dist/commands/commands.test.js +157 -75
  6. package/dist/commands/commands.test.js.map +1 -1
  7. package/dist/commands/generate.js +5 -4
  8. package/dist/commands/generate.js.map +1 -1
  9. package/dist/commands/init.js +5 -64
  10. package/dist/commands/init.js.map +1 -1
  11. package/dist/commands/prepare.js +2 -14
  12. package/dist/commands/prepare.js.map +1 -1
  13. package/dist/commands/prepare.test.js +26 -24
  14. package/dist/commands/prepare.test.js.map +1 -1
  15. package/dist/commands/preview.js +21 -21
  16. package/dist/commands/preview.js.map +1 -1
  17. package/dist/commands/start.js +13 -11
  18. package/dist/commands/start.js.map +1 -1
  19. package/dist/commands/stop.js +7 -4
  20. package/dist/commands/stop.js.map +1 -1
  21. package/dist/commands/workflows.test.js +42 -56
  22. package/dist/commands/workflows.test.js.map +1 -1
  23. package/dist/config/default-mdsite-config.js +7 -8
  24. package/dist/config/default-mdsite-config.js.map +1 -1
  25. package/dist/config/default-mdsite-config.test.js +7 -8
  26. package/dist/config/default-mdsite-config.test.js.map +1 -1
  27. package/dist/config/mdsite-config.d.ts +46 -10
  28. package/dist/config/mdsite-config.js +46 -24
  29. package/dist/config/mdsite-config.js.map +1 -1
  30. package/dist/config/mdsite-config.test.js +55 -50
  31. package/dist/config/mdsite-config.test.js.map +1 -1
  32. package/dist/index.js +8 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.test.js +13 -0
  35. package/dist/index.test.js.map +1 -1
  36. package/dist/process/child-process.d.ts +4 -0
  37. package/dist/process/child-process.js +33 -1
  38. package/dist/process/child-process.js.map +1 -1
  39. package/dist/process/child-process.test.js +41 -5
  40. package/dist/process/child-process.test.js.map +1 -1
  41. package/dist/process/runtime-state.d.ts +13 -5
  42. package/dist/process/runtime-state.js +25 -13
  43. package/dist/process/runtime-state.js.map +1 -1
  44. package/dist/process/runtime-state.test.js +10 -10
  45. package/dist/process/runtime-state.test.js.map +1 -1
  46. package/dist/renderer/mdsite-nuxt.d.ts +28 -3
  47. package/dist/renderer/mdsite-nuxt.js +32 -27
  48. package/dist/renderer/mdsite-nuxt.js.map +1 -1
  49. package/dist/renderer/mdsite-nuxt.test.js +40 -39
  50. package/dist/renderer/mdsite-nuxt.test.js.map +1 -1
  51. package/mdsite-nuxt/app/components/AppFooter.vue +84 -22
  52. package/mdsite-nuxt/app/composables/useFooter.test.ts +54 -0
  53. package/mdsite-nuxt/app/composables/useFooter.ts +48 -31
  54. package/mdsite-nuxt/app/composables/useSiteConfig.test.ts +13 -87
  55. package/mdsite-nuxt/app/composables/useSiteConfig.ts +7 -26
  56. package/mdsite-nuxt/app/composables/useSourceEdit.test.ts +103 -0
  57. package/mdsite-nuxt/app/composables/useSourceEdit.ts +39 -51
  58. package/mdsite-nuxt/app/layouts/default.vue +10 -3
  59. package/mdsite-nuxt/nuxt.config.ts +22 -15
  60. package/mdsite-nuxt/scripts/generate-favicons.test.ts +3 -3
  61. package/mdsite-nuxt/scripts/generate-favicons.ts +4 -4
  62. package/mdsite-nuxt/scripts/generate-indices.test.ts +71 -10
  63. package/mdsite-nuxt/scripts/generate-indices.ts +161 -27
  64. package/mdsite-nuxt/scripts/renderer-hooks.test.ts +0 -91
  65. package/mdsite-nuxt/scripts/renderer-hooks.ts +1 -50
  66. package/mdsite-nuxt/scripts/start.test.ts +0 -1
  67. package/mdsite-nuxt/scripts/start.ts +0 -1
  68. package/mdsite-nuxt/utils/mdsite-config.ts +86 -41
  69. package/package.json +1 -1
  70. package/mdsite-nuxt/example.config.yml +0 -67
package/README.md CHANGED
@@ -22,32 +22,28 @@ You write Markdown. For example, your content directory with a few pages and a l
22
22
 
23
23
  ```yaml
24
24
  my-docs/
25
- └── content
26
- ├── index.md
27
- ├── about.md
28
- ├── blog/
29
- ├── 2026-01-hello.md
30
- └── 2026-03-release.md
31
- └── logo.png
25
+ ├── index.md
26
+ ├── about.md
27
+ ├── blog/
28
+ ├── 2026-01-hello.md
29
+ └── 2026-03-release.md
30
+ └── logo.png
32
31
  ```
33
32
 
34
33
  Run the `mdsite static` in your repo to generate the static pages:
35
34
 
36
35
  ```yaml
37
36
  my-docs/
38
- ├── content
39
- ├── index.md
40
- ├── about.md
41
- │ ├── blog/
42
- │ ├── 2026-01-hello.md
43
- │ │ └── 2026-03-release.md
44
- │ └── logo.png
37
+ ├── index.md
38
+ ├── about.md
39
+ ├── blog/
40
+ │ ├── 2026-01-hello.md
41
+ └── 2026-03-release.md
42
+ ├── logo.png
45
43
  ├── mdsite.yml # site configuration
46
- ├── package.json # package configuration
47
- ├── package-lock.json # package lock
48
44
  ├── .mdsite/ # renderer working dir (gitignored)
49
45
  │ ├── mdsite.log # detached webserver logs
50
- │ └── ... # Other Nuxt render files
46
+ │ └── ... # Other Node and Nuxt render files
51
47
  └── .output/ # deployable static site
52
48
  └── public/
53
49
  ├── index.html
@@ -63,9 +59,6 @@ my-docs/
63
59
  └── ...
64
60
  ```
65
61
 
66
- > [!NOTE]
67
- > You can technically mix your content and project files in the same directory, but it's easier to maintain content and generated files separately.
68
-
69
62
  ## Install
70
63
 
71
64
  Install the CLI globally from the npm registry on any machine with Node.js (>= 24.0.0) and npm:
@@ -82,8 +75,7 @@ The following commands will be available after installation:
82
75
  4. `mdsite static` : Start the static website - preview how it would behave on static webserver like Cloudflare Pages.
83
76
  5. `mdsite stop` : Stop tracked detached `mdsite live -d` or `mdsite static -d` processes.
84
77
  6. `mdsite prepare github` : Generate a Github Pages deployment workflow.
85
-
86
- After install, the `mdsite` command is available from any content directory.
78
+ 7. `mdsite clean` : Delete the renderer working dir and the generated output (refuses while a tracked process is running).
87
79
 
88
80
  All commands operate on the **current working directory** as the content/project directory. `-d`/`--detached` to runs a tracked background webserver, and `--host` (or `--host <addr>`) to expose the server on the network — see the start and preview sections below. Run `mdsite help` for more details.
89
81
 
@@ -91,20 +83,20 @@ All commands operate on the **current working directory** as the content/project
91
83
 
92
84
  `mdsite.yml` is the only active content-directory configuration file. `mdsite init` creates it and fills defaults from local markdown files where possible.
93
85
 
94
- | Key | Default | Description |
95
- | ------------------------ | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
96
- | `favicon` | empty string | Source image path relative to the content directory (any format `sharp` supports). The renderer generates derived favicons into the renderer's `public/` dir. |
97
- | `features.bibleTooltips` | `true` | Enables renderer Bible tooltip support. |
98
- | `features.sourceEdit` | `true` | Enables renderer source-edit support. |
99
- | `footer` | empty array | Flat list of markdown file names (no `.md`) that appear in the bottom bar. Files listed here are excluded from `menu`. |
100
- | `menu` | derived from markdown files | Menu structure for the sidebar navigation. |
101
- | `server.output` | `.output` | Static output path under the content directory. |
102
- | `server.path` | `.mdsite` | The renderer working directory, relative to the content directory. End-user runs materialize the bundled renderer here; in the dev repo the bundled submodule runs in place. |
103
- | `server.repo` | `https://github.com/life-and-dev/mdsite` | Stored for compatibility and generated renderer config. It is not used for active clone/pull behaviour. |
104
- | `site.canonical` | empty string | Canonical site URL passed to the renderer. |
105
- | `site.name` | derived from `index.md` or directory | Site name passed to the renderer. |
106
- | `themes.light.colors` | built-in palette | Light theme colour overrides. |
107
- | `themes.dark.colors` | built-in palette | Dark theme colour overrides. |
86
+ | Key | Default | Description |
87
+ | ------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | `features.bible-tooltips` | `true` | Enables renderer Bible tooltip support. |
89
+ | `features.source-edit` | empty string | URL prefix for the Edit button. When non-empty, the renderer appends `<page>.md` to this prefix to build the Edit link (e.g. `https://github.com/<owner>/<repo>/blob/main/`). An empty string (the default) disables the Edit button entirely. |
90
+ | `features.footer` | empty array | List of links, separators, and external URLs rendered in the bottom bar. Mirrors the `menu` item shape (string, `null`, or single-key object) without sub-menus. |
91
+ | `menu` | derived from markdown files | Menu structure for the sidebar navigation. |
92
+ | `paths.input` | directory of `mdsite.yml` | Path to the directory holding your Markdown files, relative to the directory containing `mdsite.yml`. When omitted, MD-Site uses the directory of `mdsite.yml` as the content directory. |
93
+ | `paths.build` | `.mdsite` | The renderer working directory, relative to the content directory. End-user runs materialize the bundled renderer here; in the dev repo the bundled submodule runs in place. |
94
+ | `paths.output` | `.output` | Static output path under the content directory. |
95
+ | `site.canonical` | empty string | Canonical site URL passed to the renderer. |
96
+ | `site.favicon` | empty string | Source image path relative to the content directory (any format `sharp` supports). The renderer generates derived favicons into the renderer's `public/` dir. |
97
+ | `site.name` | derived from `index.md` or directory | Browser title, navbar, breadcrumb root, and web manifest name; overrides `index.md` H1. |
98
+ | `themes.light.colors` | built-in palette | Light theme colour overrides. |
99
+ | `themes.dark.colors` | built-in palette | Dark theme colour overrides. |
108
100
 
109
101
  The full documentation lives at [https://life-and-dev.github.io/mdsite/](https://life-and-dev.github.io/mdsite/).
110
102
 
@@ -125,7 +117,7 @@ We have prepared a series of tutorials to guide you through every aspect of work
125
117
  Learn the syntax of the `menu` section in `mdsite.yml`.
126
118
 
127
119
  - **[Footer Configuration](https://life-and-dev.github.io/mdsite/footer)**
128
- Learn how to populate the bottom bar with the `footer` section in `mdsite.yml`.
120
+ Learn how to populate the bottom bar with links, separators, and external URLs via the `footer` section in `mdsite.yml`.
129
121
 
130
122
  - **[Generating Favicons](https://life-and-dev.github.io/mdsite/favicon)**
131
123
  Learn how to configure a favicon path in `mdsite.yml`.
@@ -0,0 +1 @@
1
+ export declare function runCleanCommand(contentDir: string): Promise<string>;
@@ -0,0 +1,70 @@
1
+ import { access, rm } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { loadMdsiteConfig } from '../config/mdsite-config.js';
4
+ import { isProcessRunning, readRuntimeState } from '../process/runtime-state.js';
5
+ async function pathExists(targetPath) {
6
+ try {
7
+ await access(targetPath);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ export async function runCleanCommand(contentDir) {
15
+ const loaded = await loadMdsiteConfig(contentDir);
16
+ const { config, contentDir: resolvedContentDir } = loaded;
17
+ // Refuse to wipe state while a tracked process is still pointing at it.
18
+ // Tracked PIDs live inside <paths.build>, so the clean would orphan them.
19
+ const trackedStates = await Promise.all([
20
+ readRuntimeState(resolvedContentDir, config, 'start'),
21
+ readRuntimeState(resolvedContentDir, config, 'preview')
22
+ ]);
23
+ for (const state of trackedStates) {
24
+ if (state && isProcessRunning(state.pid)) {
25
+ const alias = state.kind === 'start' ? 'live' : 'static';
26
+ throw new Error(`mdsite ${alias} is running with PID ${state.pid}. Run \`mdsite stop\` before \`mdsite clean\`.`);
27
+ }
28
+ }
29
+ // Anchor on the resolved content directory (not the config directory or
30
+ // the cwd passed in), so that `paths.input: <subdir>` setups (where
31
+ // `mdsite.yml` lives at the repo root and the markdown content lives in
32
+ // a sub-folder) still resolve <paths.build> and <paths.output> to the
33
+ // project that was actually built.
34
+ const rendererPath = path.resolve(resolvedContentDir, config.paths.build);
35
+ const outputPath = path.resolve(resolvedContentDir, config.paths.output);
36
+ const [rendererExists, outputExists] = await Promise.all([
37
+ pathExists(rendererPath),
38
+ pathExists(outputPath)
39
+ ]);
40
+ // `force: true` lets us skip non-existent paths without a separate branch.
41
+ await Promise.all([
42
+ rm(rendererPath, { recursive: true, force: true }),
43
+ rm(outputPath, { recursive: true, force: true })
44
+ ]);
45
+ const removed = [];
46
+ if (rendererExists) {
47
+ removed.push(config.paths.build);
48
+ }
49
+ if (outputExists) {
50
+ removed.push(config.paths.output);
51
+ }
52
+ if (removed.length === 0) {
53
+ return `Nothing to clean in ${resolvedContentDir}.`;
54
+ }
55
+ return `Removed ${joinRemoved(removed)} from ${resolvedContentDir}.`;
56
+ }
57
+ /**
58
+ * Join the cleaned paths in a single human-readable phrase.
59
+ * One path: `<a>`. Two: `<a> and <b>`. Three or more: `<a>, <b>, and <c>`.
60
+ */
61
+ function joinRemoved(parts) {
62
+ if (parts.length === 1) {
63
+ return parts[0];
64
+ }
65
+ if (parts.length === 2) {
66
+ return `${parts[0]} and ${parts[1]}`;
67
+ }
68
+ return `${parts.slice(0, -1).join(', ')}, and ${parts[parts.length - 1]}`;
69
+ }
70
+ //# sourceMappingURL=clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"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"}