@life-and-dev/mdsite 0.5.1 → 0.5.2

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.
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Unit tests for the pure `mapSiteConfig` helper extracted from
3
+ * `useSiteConfig`. The `sourceEdit` Edit-on-GitHub link in `AppBar` and
4
+ * `AppFooter` is only rendered when `getEditUrl()` produces a URL, which
5
+ * in turn requires `contentGitRepo` to be populated from `server.repo`.
6
+ * These tests pin that mapping down so a future refactor cannot regress
7
+ * it back to the empty-string default.
8
+ */
9
+
10
+ import { describe, expect, it } from 'vitest'
11
+ import { mapSiteConfig } from './useSiteConfig'
12
+
13
+ describe('mapSiteConfig', () => {
14
+ it('returns safe defaults when siteConfig is undefined', () => {
15
+ const result = mapSiteConfig(undefined, undefined)
16
+
17
+ expect(result).toEqual({
18
+ siteName: '',
19
+ siteCanonical: '',
20
+ contentGitRepo: '',
21
+ contentGitBranch: 'main',
22
+ contentGitPath: '.',
23
+ contentPath: '.',
24
+ features: {
25
+ bibleTooltips: false,
26
+ sourceEdit: false
27
+ },
28
+ themeColorLight: '#000000',
29
+ themeColorDark: '#ffffff'
30
+ })
31
+ })
32
+
33
+ it('reads site metadata from site.name and site.canonical', () => {
34
+ const result = mapSiteConfig({
35
+ site: { name: 'My Site', canonical: 'https://example.test' }
36
+ }, undefined)
37
+
38
+ expect(result.siteName).toBe('My Site')
39
+ expect(result.siteCanonical).toBe('https://example.test')
40
+ })
41
+
42
+ describe('contentGitRepo (Edit on GitHub source)', () => {
43
+ it('reads server.repo into contentGitRepo', () => {
44
+ const result = mapSiteConfig({
45
+ server: { repo: 'https://github.com/life-and-dev/mdsite' }
46
+ }, undefined)
47
+
48
+ expect(result.contentGitRepo).toBe('https://github.com/life-and-dev/mdsite')
49
+ })
50
+
51
+ it('defaults to empty string when server.repo is missing', () => {
52
+ const result = mapSiteConfig({ server: {} }, undefined)
53
+
54
+ expect(result.contentGitRepo).toBe('')
55
+ })
56
+
57
+ it('defaults to empty string when server is missing entirely', () => {
58
+ const result = mapSiteConfig({}, undefined)
59
+
60
+ expect(result.contentGitRepo).toBe('')
61
+ })
62
+ })
63
+
64
+ describe('features', () => {
65
+ it('defaults both feature flags to false when features is missing', () => {
66
+ const result = mapSiteConfig({}, undefined)
67
+
68
+ expect(result.features.bibleTooltips).toBe(false)
69
+ expect(result.features.sourceEdit).toBe(false)
70
+ })
71
+
72
+ it('reads sourceEdit from features.sourceEdit', () => {
73
+ const result = mapSiteConfig({
74
+ features: { sourceEdit: true, bibleTooltips: false }
75
+ }, undefined)
76
+
77
+ expect(result.features.sourceEdit).toBe(true)
78
+ expect(result.features.bibleTooltips).toBe(false)
79
+ })
80
+
81
+ it('reads bibleTooltips from features.bibleTooltips', () => {
82
+ const result = mapSiteConfig({
83
+ features: { sourceEdit: false, bibleTooltips: true }
84
+ }, undefined)
85
+
86
+ expect(result.features.sourceEdit).toBe(false)
87
+ expect(result.features.bibleTooltips).toBe(true)
88
+ })
89
+ })
90
+
91
+ describe('theme colors', () => {
92
+ it('uses the configured light/dark primary colors when present', () => {
93
+ const result = mapSiteConfig({
94
+ themes: {
95
+ light: { colors: { primary: '#111111' } },
96
+ dark: { colors: { primary: '#eeeeee' } }
97
+ }
98
+ }, undefined)
99
+
100
+ expect(result.themeColorLight).toBe('#111111')
101
+ expect(result.themeColorDark).toBe('#eeeeee')
102
+ })
103
+
104
+ it('falls back to defaults when theme colors are missing', () => {
105
+ const result = mapSiteConfig({ themes: { light: {}, dark: {} } }, undefined)
106
+
107
+ expect(result.themeColorLight).toBe('#000000')
108
+ expect(result.themeColorDark).toBe('#ffffff')
109
+ })
110
+ })
111
+
112
+ it('passes through the contentPath argument with a dot default', () => {
113
+ expect(mapSiteConfig({}, '/abs/docs').contentPath).toBe('/abs/docs')
114
+ expect(mapSiteConfig({}, undefined).contentPath).toBe('.')
115
+ expect(mapSiteConfig({}, '').contentPath).toBe('.')
116
+ })
117
+ })
@@ -1,4 +1,28 @@
1
- interface SiteConfig {
1
+ /**
2
+ * Subset of the runtime `mdsite.yml` config shape that `useSiteConfig`
3
+ * consumes. The runtime value is the full `MdsiteConfig`, but we type only
4
+ * the fields this composable reads so the pure mapper below can be unit
5
+ * tested without pulling in the entire config schema.
6
+ */
7
+ export interface RawSiteConfig {
8
+ site?: {
9
+ name?: string
10
+ canonical?: string
11
+ }
12
+ server?: {
13
+ repo?: string
14
+ }
15
+ features?: {
16
+ bibleTooltips?: boolean
17
+ sourceEdit?: boolean
18
+ }
19
+ themes?: {
20
+ light?: { colors?: { primary?: string } }
21
+ dark?: { colors?: { primary?: string } }
22
+ }
23
+ }
24
+
25
+ export interface SiteConfig {
2
26
  siteName: string
3
27
  siteCanonical: string
4
28
  contentGitRepo: string
@@ -14,19 +38,23 @@ interface SiteConfig {
14
38
  }
15
39
 
16
40
  /**
17
- * Get site configuration based on runtime config
41
+ * Pure helper that maps the raw runtime `siteConfig` object into the shape
42
+ * the renderer actually consumes. Extracted from `useSiteConfig` so the
43
+ * field mapping (notably `contentGitRepo` ← `server.repo`, which is what
44
+ * powers the Edit on GitHub link in `AppBar` and `AppFooter`) can be unit
45
+ * tested independently of the Nuxt runtime.
18
46
  */
19
- export function useSiteConfig(): SiteConfig {
20
- const config = useRuntimeConfig()
21
- const siteConfig = config.public.siteConfig as any
22
-
47
+ export function mapSiteConfig(
48
+ siteConfig: RawSiteConfig | undefined,
49
+ contentPath: string | undefined,
50
+ ): SiteConfig {
23
51
  return {
24
52
  siteName: siteConfig?.site?.name || '',
25
53
  siteCanonical: siteConfig?.site?.canonical || '',
26
- contentGitRepo: '',
54
+ contentGitRepo: siteConfig?.server?.repo || '',
27
55
  contentGitBranch: 'main',
28
56
  contentGitPath: '.',
29
- contentPath: config.public.contentPath || '.',
57
+ contentPath: contentPath || '.',
30
58
  features: {
31
59
  bibleTooltips: siteConfig?.features?.bibleTooltips ?? false,
32
60
  sourceEdit: siteConfig?.features?.sourceEdit ?? false
@@ -35,3 +63,13 @@ export function useSiteConfig(): SiteConfig {
35
63
  themeColorDark: siteConfig?.themes?.dark?.colors?.primary || '#ffffff'
36
64
  }
37
65
  }
66
+
67
+ /**
68
+ * Get site configuration based on runtime config
69
+ */
70
+ export function useSiteConfig(): SiteConfig {
71
+ const config = useRuntimeConfig()
72
+ const siteConfig = config.public.siteConfig as RawSiteConfig | undefined
73
+
74
+ return mapSiteConfig(siteConfig, config.public.contentPath)
75
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@life-and-dev/mdsite",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "Local-first CLI that orchestrates mdsite-nuxt",