Skip to content

Commit 6d23d0d

Browse files
Tahulfarnabaz
authored andcommitted
feat(navigation): allow _dir.yml to filter navigation (#1261)
1 parent 975345e commit 6d23d0d

File tree

31 files changed

+389
-103
lines changed

31 files changed

+389
-103
lines changed

docs/components/content/ReadMore.vue

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<template>
2+
<Alert>
3+
<Icon class="inline-block w-5 h-5" name="heroicons-outline:information-circle" />
4+
Read more in
5+
<NuxtLink :to="link">
6+
{{ computedTitle }}
7+
</NuxtLink>.
8+
</Alert>
9+
</template>
10+
11+
<script setup lang="ts">
12+
import { splitByCase, upperFirst } from 'scule'
13+
14+
const props = defineProps({
15+
link: {
16+
type: String,
17+
required: true
18+
},
19+
title: {
20+
type: String,
21+
required: false,
22+
default: undefined
23+
}
24+
})
25+
26+
const createTitle = (title, link) => (title || link.split('/').filter(Boolean).map(part => splitByCase(part).map(p => upperFirst(p)).join(' ')).join(' > ').replace('Api', 'API'))
27+
28+
const computedTitle = computed(() => createTitle(props.title, props.link))
29+
</script>

docs/content/3.guide/2.displaying/3.navigation.md

Lines changed: 141 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,78 +3,149 @@ title: Navigation
33
description: 'The fetchContentNavigation utility returns a tree of items based on the content/ directory structure and files.'
44
---
55

6-
Use the `title`{lang="ts"} and `path`{lang="ts"} properties of each item to create your application's navigation.
6+
Navigation generation is based on your content sources directory structure.
77

8-
## Nested navigation
8+
Based on the generated `_id` and `_path` keys, we generate a whole navigation structure for your content.
99

10-
You can pass a `queryContent()`{lang="ts"} instance to the `fetchContentNavigation()`{lang="ts"} utility to filter the items returned.
10+
It allows you to create advanced navigation components without having to maintain any querying logic related to it.
1111

12-
That allows to create navigation objects for which the starting point is based on a specific content directory.
12+
## Structure
1313

14-
```ts
15-
const query = queryContent({
16-
where: {
17-
_path: { $contains: '/your/navigation/starting/point' }
14+
The navigation object can be seen as a tree representing in a JSON format the structure of your content sources.
15+
16+
It is divided in two type of nodes, **pages** and **directories**.
17+
18+
::code-group
19+
20+
``` [Directory structure]
21+
content/
22+
my-directory/
23+
page.md
24+
```
25+
26+
```json [Directory node]
27+
{
28+
"title": "My Directory",
29+
"_path": "/my-directory",
30+
"children": [
31+
...pagesNodes
32+
]
33+
}
34+
```
35+
36+
```json [Page node]
37+
{
38+
"title": "Page title",
39+
"_path": "/my-directory/my-page",
40+
"_id": "content:my-directory:page.md"
41+
}
42+
```
43+
44+
```json [Complete navigation]
45+
[
46+
{
47+
"title": "My Directory",
48+
"_path": "/my-directory",
49+
"children": [
50+
{
51+
"title": "Page title",
52+
"_path": "/my-directory/my-page",
53+
"_id": "content:my-directory:page.md"
54+
}
55+
]
1856
}
19-
})
57+
]
2058
```
2159

60+
::
61+
2262
## Configuration
2363

24-
Set `navigation: false` in the [front-matter](/guide/writing/markdown) of a page to exclude it in `fetchContentNavigation()` return value.
64+
### Module
65+
66+
The only key available in [module configuration](/api/configuration#navigation) about navigation is `fields`.
67+
68+
`fields` allows you to define the properties that will be included in the navigation items.
69+
70+
::code-group
71+
72+
```ts [nuxt.config.ts]
73+
defineNuxtConfig({
74+
content: {
75+
navigation: {
76+
fields: ['author', 'publishedAt']
77+
}
78+
}
79+
})
80+
```
2581

26-
```md
82+
```md [page.md]
2783
---
28-
navigation: false
84+
title: My Page
85+
author: 'Sébastien Chopin'
86+
publishedAt: '15-06-2022'
2987
---
3088
```
3189

32-
## Example
90+
```json [Navigation node]
91+
{
92+
"title": "My Page",
93+
"author": "Sébastien Chopin",
94+
"publishedAt": "15-06-2022",
95+
"_path": "/page",
96+
"_id": "content:page.md",
97+
}
98+
```
3399

34-
::code-group
100+
::
35101

36-
```Text [Directory structure]
37-
content/
38-
index.md
39-
sub-folder
40-
about.md
102+
### Per-directory
103+
104+
Alternatively, the navigation also allows you to configure directory nodes via `_dir.yml` files.
105+
106+
It allows you to overwrite directory names, and add custom properties to directory nodes in navigation.
107+
108+
## Excluding
109+
110+
Set `navigation: false` in the [front-matter](/guide/writing/markdown) of a page to filter it out of navigation.
111+
112+
```md [page.md]
113+
---
114+
navigation: false
115+
---
41116
```
42117

43-
```vue [app.vue]
44-
<script setup>
45-
const { data: navigation } = await useAsyncData('navigation', () => {
46-
return fetchContentNavigation()
47-
})
48-
</script>
118+
This pattern also works inside `_dir.yml` file, allowing you to filter out content directories and files.
119+
120+
```yaml [_dir.yml]
121+
navigation: false
122+
```
123+
124+
You can also use the `_` content prefix to exclude content directories and files.
125+
126+
::code-group
49127

50-
<template>
51-
<pre>
52-
{{ navigation }}
53-
</pre>
54-
</template>
128+
``` [Directory structure]
129+
content/
130+
_hidden-directory/
131+
page.md
132+
index.md
133+
not-hidden-directory/
134+
_dir.yml
135+
index.md
136+
page.md
55137
```
56138

57-
```Text [Output]
139+
```json [Navigation object]
58140
[
59141
{
60-
"title": "Hello Content V2",
61-
"_path": "/",
62-
"children": [
63-
{
64-
"_id": "content:index.md",
65-
"title": "Hello Content V2",
66-
"_path": "/"
67-
}
68-
]
69-
},
70-
{
71-
"title": "Sub Directory",
72-
"_path": "/sub-directory",
142+
"title": "Not Hidden Directory",
143+
"_path": "/not-hidden-directory",
73144
"children": [
74145
{
75-
"_id": "content:sub-directory:about.md",
76-
"title": "About Content V2",
77-
"_path": "/sub-directory/about"
146+
"title": "Page",
147+
"_id": "content:not-hidden-directory:page.md",
148+
"_path": "/not-hidden-directory/page"
78149
}
79150
]
80151
}
@@ -83,4 +154,26 @@ const { data: navigation } = await useAsyncData('navigation', () => {
83154

84155
::
85156

86-
:ReadMore{link="/examples/navigation/fetch-content-navigation"}
157+
158+
## Nested navigation
159+
160+
You can pass a `queryContent()`{lang="ts"} instance to the `fetchContentNavigation()`{lang="ts"} utility to filter the items returned.
161+
162+
That allows to create navigation objects for which the starting point is based on a specific content directory.
163+
164+
```ts
165+
const query = queryContent({
166+
where: {
167+
_path: { $contains: '/your/navigation/starting/point' }
168+
}
169+
})
170+
```
171+
172+
---
173+
174+
::alert
175+
Go deeper in the **API** section:
176+
177+
- [fetchContentNavigation()](/api/composables/fetch-content-navigation) composable to fetch navigation in `<script>`
178+
- [ContentNavigation](/api/components/content-navigation) component made to shorten access to navigation in `<template>`
179+
::

docs/content/4.api/2.composables/2.fetch-content-navigation.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,64 @@ title: 'fetchContentNavigation()'
33
description: 'The fetchContentNavigation utility returns a tree of items based on the content/ directory structure and files.'
44
---
55

6+
## Usage
7+
8+
::code-group
9+
10+
```Text [Directory structure]
11+
content/
12+
index.md
13+
sub-folder
14+
about.md
15+
```
16+
17+
```vue [app.vue]
18+
<script setup>
19+
const { data: navigation } = await useAsyncData('navigation', fetchContentNavigation())
20+
</script>
21+
22+
<template>
23+
<pre>
24+
{{ navigation }}
25+
</pre>
26+
</template>
27+
```
28+
29+
```json [Output]
30+
[
31+
{
32+
"title": "Hello Content V2",
33+
"_path": "/",
34+
"children": [
35+
{
36+
"title": "Hello Content V2",
37+
"_id": "content:index.md",
38+
"_path": "/"
39+
}
40+
]
41+
},
42+
{
43+
"title": "Sub Directory",
44+
"_path": "/sub-directory",
45+
"children": [
46+
{
47+
"title": "About Content V2",
48+
"_id": "content:sub-directory:about.md",
49+
"_path": "/sub-directory/about"
50+
}
51+
]
52+
}
53+
]
54+
```
55+
56+
::
57+
658
## Arguments
759

860
- `queryBuilder`{lang=ts}
961
- Type: `QueryBuilder`{lang=ts}
1062
- Definition: Any query built via `queryContent()`{lang=ts}
1163
- Default: `/`{lang=ts}
1264

13-
:ReadMore{link="/examples/navigation/fetch-content-navigation"}
65+
::ReadMore{link="/examples/navigation/fetch-content-navigation"}
66+
::

docs/content/4.api/3.configuration.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,18 @@ Options for yaml parser.
242242

243243
## `navigation`
244244

245-
- Type: `Boolean`{lang=ts}
245+
- Type: `false or Object`{lang=ts}
246246
- Default: `true`{lang=ts}
247247

248-
Enable/Disable content navigation.
248+
Configure the navigation feature.
249+
250+
Can be set to `false` to disable the feature completely.
251+
252+
### `navigation` options
253+
254+
| Option | Type | Description |
255+
| ----------------- | :--------: | :-------- |
256+
| `fields` | `string[]` | A list of fields to inherit from front-matter to navigation nodes. |
249257

250258
## `locales`
251259

docs/content/5.examples/1.essentials/1.hello-world.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ toc: false
33
title: 'Hello world'
44
---
55

6-
:ReadMore{link="/get-started"}
6+
::ReadMore{link="/get-started"}
7+
::
78

8-
:sandbox{repo="nuxt/content" branch="main" dir="examples/essentials/hello-world" file="app.vue"}
9+
::sandbox{repo="nuxt/content" branch="main" dir="examples/essentials/hello-world" file="app.vue"}
10+
::

docs/content/5.examples/2.mdc/1.inline-components.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Inline components are components that don't contain any slot.
88

99
After creating them in the `components/` directory, declare them in your markdown files with the `:` MDC syntax.
1010

11-
:ReadMore{link="/guide/writing/mdc#inline-components"}
11+
::ReadMore{link="/guide/writing/mdc#inline-components"}
12+
::
1213

13-
:sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/inline-component" file="content/index.md"}
14+
::sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/inline-component" file="content/index.md"}
15+
::

docs/content/5.examples/2.mdc/2.nested-components.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The MDC syntax allow you to nest components within a parent slot using indentati
88

99
The `components/AppNested.vue` component uses the `<Markdown>` component as markdown-rendering slot.
1010

11-
:ReadMore{link="/guide/writing/mdc#nesting"}
11+
::ReadMore{link="/guide/writing/mdc#nesting"}
1212

13-
:sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/nested-components" file="content/index.md"}
13+
::sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/nested-components" file="content/index.md"}
14+
::

docs/content/5.examples/2.mdc/3.props.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ description: ''
66

77
Pass props to your components in Markdown files using the `{}` MDC syntax.
88

9-
:ReadMore{link="/guide/writing/mdc#props"}
9+
::ReadMore{link="/guide/writing/mdc#props"}
10+
::
1011

11-
:sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/props" file="content/index.md"}
12+
::sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/props" file="content/index.md"}
13+
::

docs/content/5.examples/2.mdc/4.slots.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ You can fill a component's default slot by inserting content between `::`.
88

99
Use the `#` MDC syntax to fill a named slot inside a component.
1010

11-
:ReadMore{link="/guide/writing/mdc#slots"}
11+
::ReadMore{link="/guide/writing/mdc#slots"}
12+
::
1213

13-
:sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/slots" file="content/index.md"}
14+
::sandbox{repo="nuxt/content" branch="main" dir="examples/mdc/slots" file="content/index.md"}
15+
::

0 commit comments

Comments
 (0)