@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
@@ -13,7 +13,7 @@ vi.mock('../process/child-process.js', () => ({
13
13
  }));
14
14
  import { access, cp, mkdir, stat, writeFile } from 'node:fs/promises';
15
15
  import { runBackground, runForeground } from '../process/child-process.js';
16
- import { ensurePreviewArtifacts, ensureConfiguredRendererInstalled, ensureRendererDependencies, generateRenderer, getRendererGeneratedOutputPath, isInsideNodeModules, prepareRendererBackend, prepareConfiguredRenderer, prepareRenderer, previewRendererForeground, previewRendererInBackground, startRendererForeground, startRendererInBackground } from './mdsite-nuxt.js';
16
+ import { ensurePreviewArtifacts, ensureConfiguredRendererInstalled, ensureRendererDependencies, generateRenderer, isInsideNodeModules, prepareRendererBackend, prepareConfiguredRenderer, prepareRenderer, previewRendererForeground, previewRendererInBackground, startRendererForeground, startRendererInBackground } from './mdsite-nuxt.js';
17
17
  const accessMock = vi.mocked(access);
18
18
  const cpMock = vi.mocked(cp);
19
19
  const mkdirMock = vi.mocked(mkdir);
@@ -22,12 +22,10 @@ const writeFileMock = vi.mocked(writeFile);
22
22
  const runForegroundMock = vi.mocked(runForeground);
23
23
  const runBackgroundMock = vi.mocked(runBackground);
24
24
  const baseConfig = {
25
- favicon: '',
26
- features: { bibleTooltips: true, sourceEdit: true },
27
- footer: [],
25
+ features: { bibleTooltips: true, sourceEdit: '', footer: [] },
28
26
  menu: [],
29
- server: { output: '.output', path: '.renderer', repo: 'repo', gitBranch: 'main' },
30
- site: { canonical: '', name: 'Docs' },
27
+ paths: { input: '', build: '.renderer', output: '.output' },
28
+ site: { canonical: '', favicon: '', name: 'Docs' },
31
29
  themes: {
32
30
  light: { colors: { primary: '#111111' } },
33
31
  dark: { colors: { primary: '#222222' } }
@@ -45,10 +43,17 @@ describe('mdsite-nuxt renderer helpers', () => {
45
43
  const rendererDir = path.resolve(process.cwd(), 'mdsite-nuxt');
46
44
  const prepared = await prepareRenderer(contentDir, baseConfig);
47
45
  expect(prepared.rendererDir).toBe(rendererDir);
46
+ // In dev the renderer IS the checked-in submodule, so the build output
47
+ // is redirected to <contentDir>/<paths.build>/.output (covered by
48
+ // `mdsite clean`) instead of inside the submodule.
49
+ expect(prepared.rendererOutputDir).toBe(path.join(contentDir, baseConfig.paths.build, '.output'));
50
+ expect(prepared.rendererEnv.MDSITE_NITRO_OUTPUT_DIR).toBe(prepared.rendererOutputDir);
48
51
  expect(prepared.rendererEnv.NUXT_CONTENT_PATH).toBe(contentDir);
49
52
  expect(prepared.rendererEnv.MDSITE_CONFIG_PATH).toBe(path.join(contentDir, 'mdsite.yml'));
53
+ expect(mkdirMock).toHaveBeenCalledWith(prepared.rendererOutputDir, { recursive: true });
50
54
  expect(writeFileMock).toHaveBeenCalledWith(path.join(rendererDir, 'content.config.yml'), expect.stringContaining('siteName: Docs'), 'utf8');
51
55
  expect(writeFileMock).toHaveBeenCalledWith(path.join(rendererDir, '.env'), expect.stringContaining(`NUXT_CONTENT_PATH=${JSON.stringify(contentDir)}`), 'utf8');
56
+ expect(writeFileMock).toHaveBeenCalledWith(path.join(rendererDir, '.env'), expect.stringContaining(`MDSITE_NITRO_OUTPUT_DIR=${JSON.stringify(prepared.rendererOutputDir)}`), 'utf8');
52
57
  });
53
58
  it('prepareRenderer uses effective content dir for content env and runs the checked-in renderer in place', async () => {
54
59
  const configDir = '/workspace';
@@ -57,10 +62,28 @@ describe('mdsite-nuxt renderer helpers', () => {
57
62
  const configPath = path.join(configDir, 'mdsite.yml');
58
63
  const prepared = await prepareRenderer(contentDir, baseConfig, { configDir, configPath });
59
64
  expect(prepared.rendererDir).toBe(rendererDir);
65
+ // Output dir is anchored on the content dir, not the config dir, so a
66
+ // sibling `mdsite.yml` (e.g. `paths.input: docs`) still routes the
67
+ // build to the project's own working dir.
68
+ expect(prepared.rendererOutputDir).toBe(path.join(contentDir, baseConfig.paths.build, '.output'));
60
69
  expect(prepared.rendererEnv.NUXT_CONTENT_PATH).toBe(contentDir);
61
70
  expect(prepared.rendererEnv.CONTENT_DIR).toBe(contentDir);
62
71
  expect(prepared.rendererEnv.MDSITE_CONFIG_PATH).toBe(configPath);
63
72
  });
73
+ it('prepareRenderer does not redirect the build output when the renderer is the configured build dir', async () => {
74
+ // Production: `ensureConfiguredRendererInstalled` materializes the
75
+ // renderer into `<configDir>/<paths.build>`. Nitro's default `.output`
76
+ // already lives inside `paths.build`, so no env var is needed and
77
+ // `mdsite clean` covers it via the existing `paths.build` removal.
78
+ const contentDir = '/workspace/content';
79
+ const configuredRendererDir = path.resolve(contentDir, baseConfig.paths.build);
80
+ statMock.mockResolvedValueOnce({ isDirectory: () => true });
81
+ mkdirMock.mockResolvedValueOnce(undefined);
82
+ const prepared = await prepareConfiguredRenderer(contentDir, baseConfig);
83
+ expect(prepared.rendererDir).toBe(configuredRendererDir);
84
+ expect(prepared.rendererOutputDir).toBe(path.join(configuredRendererDir, '.output'));
85
+ expect(prepared.rendererEnv.MDSITE_NITRO_OUTPUT_DIR).toBeUndefined();
86
+ });
64
87
  it('runs the checked-in renderer in place when the configured renderer dir is absent', async () => {
65
88
  const contentDir = '/workspace/content';
66
89
  const checkedInRendererDir = path.resolve(process.cwd(), 'mdsite-nuxt');
@@ -93,12 +116,6 @@ describe('mdsite-nuxt renderer helpers', () => {
93
116
  const configuredRendererDir = path.resolve(contentDir, '.renderer');
94
117
  const checkedInRendererDir = path.resolve(process.cwd(), 'mdsite-nuxt');
95
118
  statMock.mockRejectedValueOnce(new Error('missing renderer'));
96
- accessMock.mockImplementation(async (targetPath) => {
97
- if (targetPath === path.join(configuredRendererDir, 'package.json') ||
98
- targetPath === path.join(configuredRendererDir, 'package-lock.json')) {
99
- throw new Error('missing package file');
100
- }
101
- });
102
119
  await expect(ensureConfiguredRendererInstalled(contentDir, baseConfig)).resolves.toBe(configuredRendererDir);
103
120
  expect(mkdirMock).toHaveBeenCalledWith(configuredRendererDir, { recursive: true });
104
121
  expect(cpMock).toHaveBeenCalledWith(checkedInRendererDir, configuredRendererDir, expect.objectContaining({
@@ -107,29 +124,14 @@ describe('mdsite-nuxt renderer helpers', () => {
107
124
  }));
108
125
  const copyOptions = cpMock.mock.calls[0]?.[2];
109
126
  expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'package.json'), configuredRendererDir)).toBe(true);
127
+ expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'package-lock.json'), configuredRendererDir)).toBe(true);
128
+ expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'nuxt.config.ts'), configuredRendererDir)).toBe(true);
110
129
  expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'node_modules'), configuredRendererDir)).toBe(false);
111
130
  expect(copyOptions?.filter?.(path.join(checkedInRendererDir, '.nuxt'), configuredRendererDir)).toBe(false);
112
131
  expect(copyOptions?.filter?.(path.join(checkedInRendererDir, '.output'), configuredRendererDir)).toBe(false);
113
132
  expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'dist'), configuredRendererDir)).toBe(false);
114
133
  expect(copyOptions?.filter?.(path.join(checkedInRendererDir, '.cache'), configuredRendererDir)).toBe(false);
115
134
  });
116
- it('ensureConfiguredRendererInstalled preserves existing committed package.json and package-lock.json', async () => {
117
- const contentDir = '/workspace/content';
118
- const configuredRendererDir = path.resolve(contentDir, '.renderer');
119
- const checkedInRendererDir = path.resolve(process.cwd(), 'mdsite-nuxt');
120
- statMock.mockRejectedValueOnce(new Error('missing renderer'));
121
- await expect(ensureConfiguredRendererInstalled(contentDir, baseConfig)).resolves.toBe(configuredRendererDir);
122
- expect(mkdirMock).toHaveBeenCalledWith(configuredRendererDir, { recursive: true });
123
- expect(cpMock).toHaveBeenCalledWith(checkedInRendererDir, configuredRendererDir, expect.objectContaining({
124
- force: true,
125
- recursive: true
126
- }));
127
- const copyOptions = cpMock.mock.calls[0]?.[2];
128
- expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'package.json'), configuredRendererDir)).toBe(false);
129
- expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'package-lock.json'), configuredRendererDir)).toBe(false);
130
- expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'nuxt.config.ts'), configuredRendererDir)).toBe(true);
131
- expect(copyOptions?.filter?.(path.join(checkedInRendererDir, 'node_modules'), configuredRendererDir)).toBe(false);
132
- });
133
135
  it('isInsideNodeModules detects renderer paths inside node_modules', () => {
134
136
  expect(isInsideNodeModules('/usr/lib/node_modules/@life-and-dev/mdsite/mdsite-nuxt')).toBe(true);
135
137
  expect(isInsideNodeModules('/home/user/proj/mdsite-nuxt')).toBe(false);
@@ -173,25 +175,24 @@ describe('mdsite-nuxt renderer helpers', () => {
173
175
  await ensureRendererDependencies(rendererDir);
174
176
  expect(runForegroundMock).not.toHaveBeenCalled();
175
177
  });
176
- it('checks the generated preview artifact and exposes the generated output path', async () => {
177
- const rendererDir = '/renderer';
178
- await expect(ensurePreviewArtifacts(rendererDir)).resolves.toBeUndefined();
179
- expect(getRendererGeneratedOutputPath(rendererDir)).toBe(path.join(rendererDir, '.output', 'public'));
180
- expect(accessMock).toHaveBeenCalledWith(path.join(rendererDir, '.output', 'public'));
178
+ it('checks the generated preview artifact inside the resolved renderer output dir', async () => {
179
+ const rendererOutputDir = '/renderer/.output';
180
+ await expect(ensurePreviewArtifacts(rendererOutputDir)).resolves.toBeUndefined();
181
+ expect(accessMock).toHaveBeenCalledWith(path.join(rendererOutputDir, 'public'));
181
182
  accessMock.mockImplementationOnce(async () => {
182
183
  throw new Error('missing public output');
183
184
  });
184
- await expect(ensurePreviewArtifacts(rendererDir)).rejects.toThrow('Preview is unavailable. Run `mdsite generate` before `mdsite static`.');
185
+ await expect(ensurePreviewArtifacts(rendererOutputDir)).rejects.toThrow('Preview is unavailable. Run `mdsite generate` before `mdsite static`.');
185
186
  });
186
187
  it('delegates stable dev/generate/preview script names to child-process helpers', async () => {
187
188
  const env = { TEST: '1' };
188
- await startRendererInBackground('/renderer', env, '/logs/start.log');
189
- await previewRendererInBackground('/renderer', env, '/logs/preview.log');
189
+ await startRendererInBackground('/renderer', env, '/logs/live.log');
190
+ await previewRendererInBackground('/renderer', env, '/logs/static.log');
190
191
  await generateRenderer('/renderer', env);
191
192
  await startRendererForeground('/renderer', env);
192
193
  await previewRendererForeground('/renderer', env);
193
- expect(runBackgroundMock).toHaveBeenNthCalledWith(1, 'npm', ['run', 'dev'], '/renderer', env, '/logs/start.log');
194
- expect(runBackgroundMock).toHaveBeenNthCalledWith(2, 'npm', ['run', 'preview'], '/renderer', env, '/logs/preview.log');
194
+ expect(runBackgroundMock).toHaveBeenNthCalledWith(1, 'npm', ['run', 'dev'], '/renderer', env, '/logs/live.log');
195
+ expect(runBackgroundMock).toHaveBeenNthCalledWith(2, 'npm', ['run', 'preview'], '/renderer', env, '/logs/static.log');
195
196
  expect(runForegroundMock).toHaveBeenNthCalledWith(1, 'npm', ['run', 'generate'], '/renderer', env);
196
197
  expect(runForegroundMock).toHaveBeenNthCalledWith(2, 'npm', ['run', 'dev'], '/renderer', env);
197
198
  expect(runForegroundMock).toHaveBeenNthCalledWith(3, 'npm', ['run', 'preview'], '/renderer', env);
@@ -1 +1 @@
1
- {"version":3,"file":"mdsite-nuxt.test.js","sourceRoot":"","sources":["../../src/renderer/mdsite-nuxt.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mdsite-nuxt.test.js","sourceRoot":"","sources":["../../src/renderer/mdsite-nuxt.test.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,44 @@
1
1
  <template>
2
- <v-app-bar
2
+ <!--
3
+ In-flow footer: rendered inside <v-main> by the default layout, so it sits
4
+ at the end of the article and only becomes visible after the user scrolls
5
+ all the way down. Not a fixed/anchored bar.
6
+ -->
7
+ <v-footer
3
8
  v-if="hasFooterEntries"
4
- location="bottom"
5
- height="56"
6
9
  class="app-footer"
7
- flat
10
+ color="surface-appbar"
11
+ border="top"
8
12
  >
9
- <v-container class="d-flex justify-center align-center">
13
+ <v-container class="d-flex justify-center align-center py-3">
10
14
  <div class="footer-links">
11
- <template v-for="(link, index) in footerHrefs" :key="link.path">
15
+ <template v-for="(link, index) in footerHrefs" :key="linkKey(link, index)">
16
+ <!-- Separator (null entry in mdsite.yml) -->
17
+ <v-divider
18
+ v-if="link.type === 'separator'"
19
+ vertical
20
+ class="mx-2 footer-separator"
21
+ />
22
+ <!-- Internal link or external URL -->
12
23
  <v-btn
24
+ v-else
13
25
  :href="link.path"
14
26
  variant="text"
15
27
  color="on-surface-appbar"
16
28
  class="footer-link"
29
+ :target="link.isExternal ? '_blank' : undefined"
30
+ :rel="link.isExternal ? 'noopener noreferrer' : undefined"
17
31
  >
18
32
  {{ link.title }}
33
+ <v-icon
34
+ v-if="link.isExternal"
35
+ icon="mdi-open-in-new"
36
+ size="14"
37
+ class="ml-1 external-icon"
38
+ />
19
39
  </v-btn>
20
40
  <v-divider
21
- v-if="index < footerHrefs.length - 1 || editUrl"
41
+ v-if="shouldRenderInterDivider(link, index)"
22
42
  vertical
23
43
  class="mx-2"
24
44
  />
@@ -36,7 +56,7 @@
36
56
  </v-btn>
37
57
  </div>
38
58
  </v-container>
39
- </v-app-bar>
59
+ </v-footer>
40
60
  </template>
41
61
 
42
62
  <script setup lang="ts">
@@ -44,38 +64,70 @@ import { useSourceEdit } from '~/composables/useSourceEdit';
44
64
  import { useFooter } from '~/composables/useFooter'
45
65
  import { withBasePath } from '../../utils/base-url'
46
66
 
67
+ interface FooterHref {
68
+ path: string
69
+ title: string
70
+ type: 'link' | 'separator'
71
+ isExternal: boolean
72
+ }
73
+
47
74
  const appBaseURL = useRuntimeConfig().app.baseURL
48
75
  const { getEditUrl } = useSourceEdit()
49
- const { links: footerLinks, loadFooter } = useFooter()
76
+ const { links: footerLinks } = useFooter()
50
77
 
51
78
  const editUrl = computed(() => getEditUrl())
52
79
 
53
80
  // Render the bar only after the footer JSON has loaded and contains at least
54
- // one entry. While loading (links === null) or when the array is empty, the
55
- // whole bar (including the Edit button) is hidden.
81
+ // one entry. While loading (links is the default empty array) or when the
82
+ // array is empty, the whole bar (including the Edit button) is hidden.
56
83
  const hasFooterEntries = computed(() =>
57
- footerLinks.value !== null && footerLinks.value.length > 0
84
+ (footerLinks.value?.length ?? 0) > 0
58
85
  )
59
86
 
60
- const footerHrefs = computed(() => (footerLinks.value ?? []).map(link => ({
87
+ /**
88
+ * Map raw FooterLink entries into the shape the template renders. External
89
+ * URLs keep their raw path (withBasePath passes http(s) through unchanged);
90
+ * internal links get the app base path prepended.
91
+ */
92
+ const footerHrefs = computed<FooterHref[]>(() => (footerLinks.value ?? []).map(link => ({
61
93
  path: withBasePath(link.path, appBaseURL),
62
- title: link.title
94
+ title: link.title,
95
+ type: link.type,
96
+ isExternal: link.isExternal
63
97
  })))
64
98
 
65
- onMounted(async () => {
66
- await loadFooter()
67
- })
68
- </script>
99
+ /**
100
+ * Stable key for the v-for. External URLs and separators can have empty or
101
+ * colliding paths, so fall back to the index to guarantee uniqueness.
102
+ */
103
+ function linkKey(link: FooterHref, index: number): string {
104
+ if (link.path) return link.path
105
+ return `${link.type}-${index}`
106
+ }
69
107
 
70
- <style scoped>
71
- .app-footer {
72
- z-index: 1000 !important;
108
+ /**
109
+ * The original layout rendered a trailing v-divider after every entry (except
110
+ * the last) plus an extra one before the Edit button. With separators now
111
+ * living inside the entries themselves, only render the inter-entry divider
112
+ * when the NEXT item is a link — otherwise two visual dividers would stack
113
+ * (e.g. between a separator and the Edit button or between two separators).
114
+ */
115
+ function shouldRenderInterDivider(link: FooterHref, index: number): boolean {
116
+ if (link.type === 'separator') return false
117
+ const next = footerHrefs.value[index + 1]
118
+ if (next && next.type === 'separator') return false
119
+ // Preserve the original "always add a divider before Edit" behavior.
120
+ return Boolean(editUrl.value) || index < footerHrefs.value.length - 1
73
121
  }
122
+ </script>
74
123
 
124
+ <style scoped>
75
125
  .footer-links {
76
126
  display: flex;
77
127
  align-items: center;
78
128
  gap: 0.5rem;
129
+ flex-wrap: wrap;
130
+ justify-content: center;
79
131
  }
80
132
 
81
133
  .footer-link {
@@ -84,13 +136,23 @@ onMounted(async () => {
84
136
  font-weight: 400;
85
137
  }
86
138
 
139
+ .external-icon {
140
+ opacity: 0.7;
141
+ vertical-align: middle;
142
+ }
143
+
144
+ .footer-separator {
145
+ opacity: 0.3;
146
+ }
147
+
87
148
  /* Make dividers visible with theme colors */
88
149
  :deep(.v-divider) {
89
150
  opacity: 0.3;
90
151
  height: 1.5rem;
91
152
  }
92
153
 
93
- /* Print: Hide Footer */
154
+ /* Print: Hide Footer (also covered by the layout's `.v-footer` rule,
155
+ but kept here as a defensive scoped fallback). */
94
156
  @media print {
95
157
  .app-footer {
96
158
  display: none !important;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Unit tests for the pure `toFooterLinks` helper extracted from
3
+ * `useFooter`. The composable now uses `useAsyncData`, which fetches
4
+ * `/_footer.json` during SSR. The Nitro static preset (used by
5
+ * `mdsite generate`) does not serve that file as a static asset, so the
6
+ * prerender's `localFetch` falls through to the catch-all HTML route and
7
+ * returns the page HTML string. Without coercion that string ends up in
8
+ * `data.value` and the AppFooter's `.map()` call throws. These tests pin
9
+ * the defensive behaviour down.
10
+ */
11
+
12
+ import { describe, expect, it } from 'vitest'
13
+
14
+ import { toFooterLinks } from './useFooter'
15
+
16
+ describe('toFooterLinks', () => {
17
+ it('returns the array unchanged when the response is a valid FooterLink[]', () => {
18
+ const links = [
19
+ { path: '/about', title: 'About', type: 'link' as const, isExternal: false },
20
+ { path: 'https://example.com', title: 'Example', type: 'link' as const, isExternal: true }
21
+ ]
22
+
23
+ expect(toFooterLinks(links)).toBe(links)
24
+ })
25
+
26
+ it('returns an empty array when the response is an empty array', () => {
27
+ expect(toFooterLinks([])).toEqual([])
28
+ })
29
+
30
+ it('returns an empty array when the response is an HTML string (Nitro static preset prerender fallback)', () => {
31
+ const html = '<!DOCTYPE html><html><body>Page</body></html>'
32
+
33
+ expect(toFooterLinks(html)).toEqual([])
34
+ })
35
+
36
+ it('returns an empty array when the response is null', () => {
37
+ expect(toFooterLinks(null)).toEqual([])
38
+ })
39
+
40
+ it('returns an empty array when the response is undefined', () => {
41
+ expect(toFooterLinks(undefined)).toEqual([])
42
+ })
43
+
44
+ it('returns an empty array when the response is a plain object (e.g. 404 JSON body)', () => {
45
+ expect(toFooterLinks({ error: true, statusCode: 404 })).toEqual([])
46
+ })
47
+
48
+ it('returns an empty array when the response is a number or boolean', () => {
49
+ expect(toFooterLinks(0)).toEqual([])
50
+ expect(toFooterLinks(1)).toEqual([])
51
+ expect(toFooterLinks(false)).toEqual([])
52
+ expect(toFooterLinks(true)).toEqual([])
53
+ })
54
+ })
@@ -1,46 +1,63 @@
1
1
  import type { FooterLink } from '../../scripts/generate-indices'
2
2
  import { withBasePath } from '../../utils/base-url'
3
3
 
4
+ /**
5
+ * Coerce an unknown `$fetch` response into a `FooterLink[]`. Returns the
6
+ * array unchanged when the response is an array, and an empty array for
7
+ * anything else (object, string, null, undefined, primitive). Extracted so
8
+ * the type-guard can be unit-tested without mocking `$fetch`.
9
+ *
10
+ * Guards against two known environments where `/_footer.json` is not
11
+ * served as JSON:
12
+ * - `mdsite generate` (Nitro static preset) — `localFetch('/_footer.json')`
13
+ * falls through to the catch-all HTML route and returns the page HTML
14
+ * string instead of the JSON payload.
15
+ * - Bare `node-server` boot before `generateFooterJson` has written the
16
+ * file yet — the catch-all returns the not-found HTML page.
17
+ */
18
+ export function toFooterLinks(result: unknown): FooterLink[] {
19
+ return Array.isArray(result) ? (result as FooterLink[]) : []
20
+ }
21
+
4
22
  /**
5
23
  * Fetch and cache footer links from the pre-built JSON file.
6
- * Uses useState to prevent duplicate fetches across component instances.
24
+ *
25
+ * Uses `useAsyncData` so the fetch happens during SSR — the result is
26
+ * transferred to the client on hydration and the footer is part of the
27
+ * initial HTML payload (no FOUC). The fetch is cached by the
28
+ * `'footer-links'` key, so repeated calls return the same data.
7
29
  */
8
30
  export function useFooter() {
9
31
  const appBaseURL = useRuntimeConfig().app.baseURL
10
- const links = useState<FooterLink[] | null>('footer-links', () => null)
11
- const isLoading = useState<boolean>('footer-links-loading', () => false)
12
-
13
- /**
14
- * Load footer links from the pre-built JSON file.
15
- * Cached result prevents duplicate fetches.
16
- */
17
- async function loadFooter(): Promise<FooterLink[]> {
18
- if (links.value !== null) {
19
- return links.value
32
+ const { data, pending, error, refresh } = useAsyncData<FooterLink[]>(
33
+ 'footer-links',
34
+ async () => {
35
+ try {
36
+ return toFooterLinks(
37
+ await $fetch<unknown>(withBasePath('/_footer.json', appBaseURL))
38
+ )
39
+ } catch (err) {
40
+ console.error('Error loading footer links:', err)
41
+ return []
42
+ }
43
+ },
44
+ {
45
+ // Default to an empty array so the SSR shell can render without
46
+ // waiting for the data; `hasFooterEntries` stays `false` until the
47
+ // fetch resolves with at least one entry.
48
+ default: () => []
20
49
  }
50
+ )
21
51
 
22
- if (isLoading.value) {
23
- return []
24
- }
25
-
26
- isLoading.value = true
27
-
28
- try {
29
- const data = await $fetch<FooterLink[]>(withBasePath('/_footer.json', appBaseURL))
30
- links.value = data
31
- return data
32
- } catch (error) {
33
- console.error('Error loading footer links:', error)
34
- links.value = []
35
- return []
36
- } finally {
37
- isLoading.value = false
38
- }
52
+ // `error` is still exposed for consumers that want to surface it, even
53
+ // though we no longer let it short-circuit the SSR pass.
54
+ if (error.value) {
55
+ console.error('Error loading footer links:', error.value)
39
56
  }
40
57
 
41
58
  return {
42
- links,
43
- isLoading,
44
- loadFooter
59
+ links: data,
60
+ isLoading: pending,
61
+ refresh
45
62
  }
46
63
  }