@nera-static/plugin-navigation 2.1.0 → 2.2.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.
- package/CHANGELOG.md +91 -0
- package/README.md +100 -97
- package/bin/publish-template.js +18 -0
- package/config/navigation.yaml +30 -0
- package/index.js +35 -10
- package/package.json +9 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [2.2.0] - 2026-07-19
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- the `publish-template` command is now actually shipped. `bin/` was absent
|
|
13
|
+
from the published package and no `bin` entry existed, so the command
|
|
14
|
+
documented in the README could never resolve
|
|
15
|
+
- published templates now include their `partials/` and `helper/` files, so
|
|
16
|
+
they compile. Previously only the three top-level templates were copied and
|
|
17
|
+
every one of them failed on its first `include` (requires
|
|
18
|
+
`@nera-static/plugin-utils` ^1.2.0)
|
|
19
|
+
- a `navigation.yaml` entry missing `href` no longer crashes the build with a
|
|
20
|
+
`TypeError` from inside `node_modules`; the entry is skipped with a warning
|
|
21
|
+
naming its position
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- a commented default `config/navigation.yaml` is now shipped
|
|
26
|
+
- `npx nera-navigation --force` re-publishes over existing templates,
|
|
27
|
+
discarding local edits
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- `@nera-static/plugin-utils` range widened to `^1.2.0`
|
|
32
|
+
- navigation config is resolved per call rather than at module load
|
|
33
|
+
|
|
34
|
+
## [2.1.0] - 2024-12-27
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- Professional CHANGELOG.md for release tracking
|
|
39
|
+
- Enhanced README.md with comprehensive documentation
|
|
40
|
+
- Support for Nera v4.1.0 static site generator
|
|
41
|
+
- Template publishing system via `bin/publish-template.js`
|
|
42
|
+
- BEM (Block Element Modifier) CSS methodology for all templates
|
|
43
|
+
- Comprehensive test suite with 14 tests covering all functionality
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- Updated development dependencies for security and performance
|
|
48
|
+
- Improved package.json metadata and repository references
|
|
49
|
+
- Enhanced code documentation and examples
|
|
50
|
+
- Modernized CSS classes using BEM methodology:
|
|
51
|
+
- `.nav`, `.nav__list`, `.nav__item`, `.nav__link`
|
|
52
|
+
- `.nav__link--active`, `.nav__link--active-path`
|
|
53
|
+
- `.nav--list`, `.nav__list--pipe-separated`
|
|
54
|
+
|
|
55
|
+
### Technical Details
|
|
56
|
+
|
|
57
|
+
- Maintains stable API with `getAppData()` function
|
|
58
|
+
- Full compatibility with Nera's plugin system
|
|
59
|
+
- Zero breaking changes from previous version
|
|
60
|
+
- All tests passing (14/14)
|
|
61
|
+
- Template publishing to `views/vendor/plugin-navigation/`
|
|
62
|
+
|
|
63
|
+
## [2.0.1] - Previous Release
|
|
64
|
+
|
|
65
|
+
### Note
|
|
66
|
+
|
|
67
|
+
- This version was already published on npm before our enhancements
|
|
68
|
+
|
|
69
|
+
## [2.0.0] - 2024-07-19
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- Initial stable release for Nera static site generator
|
|
74
|
+
- Navigation generation from YAML configuration
|
|
75
|
+
- Support for multi-level navigations (main, footer, etc.)
|
|
76
|
+
- Built-in Pug templates and mixins
|
|
77
|
+
- Automatic active/path highlighting
|
|
78
|
+
- Comprehensive test coverage
|
|
79
|
+
|
|
80
|
+
### Features
|
|
81
|
+
|
|
82
|
+
- Single and multi-navigation support
|
|
83
|
+
- Flexible CSS class configuration
|
|
84
|
+
- Template inheritance and mixins
|
|
85
|
+
- Integration with @nera-static/plugin-utils
|
|
86
|
+
|
|
87
|
+
### Dependencies
|
|
88
|
+
|
|
89
|
+
- Node.js >=18 support
|
|
90
|
+
- ES modules architecture
|
|
91
|
+
- Modern development tooling
|
package/README.md
CHANGED
|
@@ -1,58 +1,67 @@
|
|
|
1
1
|
# @nera-static/plugin-navigation
|
|
2
2
|
|
|
3
|
-
A plugin for the [Nera](https://github.com/seebaermichi/nera) static site generator to create navigations from config files. Supports mixins and templates for easy rendering.
|
|
3
|
+
A plugin for the [Nera](https://github.com/seebaermichi/nera) static site generator to create navigations from config files. Supports mixins and templates for easy rendering and styling.
|
|
4
4
|
|
|
5
5
|
## ✨ Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **Active State Management**: Automatic active/path highlighting support
|
|
15
|
-
- **Zero Runtime**: Static navigation structure, no client-side processing
|
|
16
|
-
- **Nera v4.1.0 Compatible**: Optimized for the latest Nera architecture
|
|
7
|
+
- Define one or more navigations via YAML config
|
|
8
|
+
- Access navigation data directly in templates (`app.nav`)
|
|
9
|
+
- Support for multi-level navigations (e.g., main, footer)
|
|
10
|
+
- Includes ready-to-use Pug templates and mixins
|
|
11
|
+
- Automatic active and path highlighting
|
|
12
|
+
- Static, zero-runtime overhead
|
|
13
|
+
- Full compatibility with Nera v4.1.0+
|
|
17
14
|
|
|
18
15
|
## 🚀 Installation
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
Install the plugin in your Nera project:
|
|
21
18
|
|
|
22
19
|
```bash
|
|
23
20
|
npm install @nera-static/plugin-navigation
|
|
24
21
|
```
|
|
25
22
|
|
|
26
|
-
Then create
|
|
23
|
+
Then create the configuration file in your project:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
mkdir -p config
|
|
27
|
+
touch config/navigation.yaml
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This creates:
|
|
27
31
|
|
|
28
32
|
```
|
|
29
33
|
config/
|
|
30
34
|
└── navigation.yaml
|
|
31
35
|
```
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
The plugin ships a commented default at
|
|
38
|
+
`node_modules/@nera-static/plugin-navigation/config/navigation.yaml` — copy it
|
|
39
|
+
as a starting point. It is read from **your** project only; the packaged copy
|
|
40
|
+
is documentation, not a fallback.
|
|
41
|
+
|
|
42
|
+
Nera will automatically detect the plugin and load the configuration.
|
|
34
43
|
|
|
35
44
|
## ⚙️ Configuration
|
|
36
45
|
|
|
37
|
-
|
|
46
|
+
Define your navigation(s) in `config/navigation.yaml`.
|
|
38
47
|
|
|
39
|
-
|
|
48
|
+
### Single Navigation
|
|
40
49
|
|
|
41
50
|
```yaml
|
|
42
51
|
elements:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
- href: /index.html
|
|
53
|
+
name: Home
|
|
54
|
+
- href: /service/service.html
|
|
55
|
+
name: Service
|
|
56
|
+
- href: /prices.html
|
|
57
|
+
name: Prices
|
|
58
|
+
- href: /contact.html
|
|
59
|
+
name: Contact
|
|
60
|
+
- href: /about-us/index.html
|
|
61
|
+
name: About us
|
|
53
62
|
```
|
|
54
63
|
|
|
55
|
-
Access
|
|
64
|
+
Access in templates:
|
|
56
65
|
|
|
57
66
|
```pug
|
|
58
67
|
app.nav.elements
|
|
@@ -62,114 +71,108 @@ app.nav.elements
|
|
|
62
71
|
|
|
63
72
|
```yaml
|
|
64
73
|
elements:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
main:
|
|
75
|
+
- href: /index.html
|
|
76
|
+
name: Home
|
|
77
|
+
- href: /service/service.html
|
|
78
|
+
name: Service
|
|
79
|
+
footer:
|
|
80
|
+
- href: /imprint.html
|
|
81
|
+
name: Imprint
|
|
73
82
|
```
|
|
74
83
|
|
|
75
|
-
|
|
84
|
+
Access in templates:
|
|
76
85
|
|
|
77
86
|
```pug
|
|
78
87
|
app.nav.main.elements
|
|
79
88
|
app.nav.footer.elements
|
|
80
89
|
```
|
|
81
90
|
|
|
82
|
-
Each element
|
|
91
|
+
Each element includes `href`, `name`, and `path`.
|
|
83
92
|
|
|
84
|
-
## 🧩
|
|
93
|
+
## 🧩 Usage
|
|
85
94
|
|
|
86
|
-
###
|
|
95
|
+
### Manual Rendering
|
|
87
96
|
|
|
88
|
-
|
|
97
|
+
Loop through `app.nav.*.elements` directly in your Pug templates.
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
## 🛠️ Template Publishing
|
|
91
100
|
|
|
92
|
-
|
|
101
|
+
Use the default templates provided by the plugin:
|
|
93
102
|
|
|
94
|
-
```
|
|
95
|
-
|
|
103
|
+
```bash
|
|
104
|
+
npx nera-navigation
|
|
96
105
|
```
|
|
97
106
|
|
|
98
|
-
|
|
107
|
+
This copies every template file — including `partials/` and `helper/`, which
|
|
108
|
+
the top-level templates include — to:
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
-
|
|
110
|
+
```
|
|
111
|
+
views/vendor/plugin-navigation/
|
|
112
|
+
```
|
|
102
113
|
|
|
103
|
-
|
|
114
|
+
Then include them in your layouts or pages as needed.
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
Publishing **skips** if `views/vendor/plugin-navigation/` already exists, so
|
|
117
|
+
your edits are never overwritten. To pull in updated templates after a plugin
|
|
118
|
+
upgrade, discarding your changes to them:
|
|
106
119
|
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
+pipeSeparatedNav(app.nav.main.elements, app.nav.main.className)
|
|
120
|
+
```bash
|
|
121
|
+
npx nera-navigation --force
|
|
111
122
|
```
|
|
112
123
|
|
|
113
|
-
|
|
124
|
+
## 🎨 Styling
|
|
114
125
|
|
|
115
|
-
|
|
126
|
+
The plugin uses BEM CSS methodology:
|
|
116
127
|
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
|
|
128
|
+
```css
|
|
129
|
+
.nav { }
|
|
130
|
+
.nav__list { }
|
|
131
|
+
.nav__item { }
|
|
132
|
+
.nav__item--inline { }
|
|
133
|
+
.nav__link { }
|
|
134
|
+
.nav__separator { }
|
|
135
|
+
.nav__link--active { }
|
|
136
|
+
.nav__link--active-path { }
|
|
120
137
|
```
|
|
121
138
|
|
|
122
|
-
|
|
139
|
+
Override or extend these classes in your project’s CSS.
|
|
123
140
|
|
|
124
|
-
|
|
141
|
+
## 📊 Generated Output
|
|
125
142
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
/* Navigation list container */
|
|
135
|
-
}
|
|
136
|
-
.nav__item {
|
|
137
|
-
/* Individual navigation item */
|
|
138
|
-
}
|
|
139
|
-
.nav__item--inline {
|
|
140
|
-
/* Inline item modifier */
|
|
141
|
-
}
|
|
142
|
-
.nav__link {
|
|
143
|
-
/* Navigation link */
|
|
144
|
-
}
|
|
145
|
-
.nav__separator {
|
|
146
|
-
/* Pipe separator element */
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/* Navigation Modifiers */
|
|
150
|
-
.nav__link--active {
|
|
151
|
-
/* Currently active link */
|
|
152
|
-
}
|
|
153
|
-
.nav__link--active-path {
|
|
154
|
-
/* Parent path link */
|
|
155
|
-
}
|
|
143
|
+
The plugin injects navigation data into `app.nav` without generating HTML. Use templates or mixins for output.
|
|
144
|
+
|
|
145
|
+
## 🧪 Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm install
|
|
149
|
+
npm test
|
|
150
|
+
npm run lint
|
|
156
151
|
```
|
|
157
152
|
|
|
158
|
-
|
|
153
|
+
Tests use [Vitest](https://vitest.dev) and validate:
|
|
159
154
|
|
|
160
|
-
|
|
155
|
+
- Navigation data structure
|
|
156
|
+
- Multi-level navigation support
|
|
157
|
+
- Template rendering
|
|
158
|
+
- Class handling and active link detection
|
|
161
159
|
|
|
162
160
|
## 🧑💻 Author
|
|
163
161
|
|
|
164
|
-
Michael Becker
|
|
162
|
+
Michael Becker
|
|
165
163
|
[https://github.com/seebaermichi](https://github.com/seebaermichi)
|
|
166
164
|
|
|
167
165
|
## 🔗 Links
|
|
168
166
|
|
|
169
|
-
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
|
|
167
|
+
- [Plugin Repository](https://github.com/seebaermichi/nera-plugin-navigation)
|
|
168
|
+
- [NPM Package](https://www.npmjs.com/package/@nera-static/plugin-navigation)
|
|
169
|
+
- [Nera Static Site Generator](https://github.com/seebaermichi/nera)
|
|
170
|
+
|
|
171
|
+
## 🧩 Compatibility
|
|
172
|
+
|
|
173
|
+
- **Nera**: v4.1.0+
|
|
174
|
+
- **Node.js**: >= 18
|
|
175
|
+
- **Plugin API**: Uses `getAppData()` for injecting navigation structure
|
|
173
176
|
|
|
174
177
|
## 📦 License
|
|
175
178
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { fileURLToPath } from 'url'
|
|
5
|
+
import { publishAllTemplates } from '@nera-static/plugin-utils'
|
|
6
|
+
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const pluginName = 'plugin-navigation'
|
|
9
|
+
const sourceDir = path.resolve(__dirname, '../views/')
|
|
10
|
+
const force = process.argv.includes('--force')
|
|
11
|
+
|
|
12
|
+
const result = publishAllTemplates({
|
|
13
|
+
pluginName,
|
|
14
|
+
sourceDir,
|
|
15
|
+
force,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
process.exit(result ? 0 : 1)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Default configuration for @nera-static/plugin-navigation.
|
|
2
|
+
#
|
|
3
|
+
# This file is documentation and a starting point. The plugin reads
|
|
4
|
+
# config/navigation.yaml from YOUR project root, not from this package —
|
|
5
|
+
# copy this file there and edit it.
|
|
6
|
+
|
|
7
|
+
# CSS class applied to the link matching the current page.
|
|
8
|
+
active_class: active
|
|
9
|
+
|
|
10
|
+
# CSS class applied to a link whose path is an ancestor of the current page.
|
|
11
|
+
active_path_class: active-path
|
|
12
|
+
|
|
13
|
+
# Base CSS class for the navigation element.
|
|
14
|
+
nav_class: nav
|
|
15
|
+
|
|
16
|
+
# A single navigation: a flat list, available as app.nav.elements
|
|
17
|
+
elements:
|
|
18
|
+
- href: /index.html
|
|
19
|
+
name: Home
|
|
20
|
+
|
|
21
|
+
# For several navigations, nest them under names instead. Each becomes
|
|
22
|
+
# app.nav.<name>.elements:
|
|
23
|
+
#
|
|
24
|
+
# elements:
|
|
25
|
+
# main:
|
|
26
|
+
# - href: /index.html
|
|
27
|
+
# name: Home
|
|
28
|
+
# footer:
|
|
29
|
+
# - href: /imprint.html
|
|
30
|
+
# name: Imprint
|
package/index.js
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import { getConfig } from '@nera-static/plugin-utils'
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
// Resolved per call rather than at module scope: the host project's cwd is
|
|
5
|
+
// what matters, and resolving lazily is what makes this testable.
|
|
6
|
+
function getHostConfigPath() {
|
|
7
|
+
return path.resolve(process.cwd(), 'config/navigation.yaml')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getNavElements(elements, groupName) {
|
|
11
|
+
if (!Array.isArray(elements)) {
|
|
12
|
+
console.warn(
|
|
13
|
+
`⚠️ navigation.yaml: expected a list of elements${groupName ? ` under "${groupName}"` : ''}, got ${typeof elements}. Skipping.`
|
|
14
|
+
)
|
|
15
|
+
return []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return elements
|
|
19
|
+
.filter((element, index) => {
|
|
20
|
+
// A missing href is an ordinary YAML typo. Without this guard
|
|
21
|
+
// path.posix.dirname throws a TypeError from inside node_modules,
|
|
22
|
+
// which tells the user nothing about which entry is at fault.
|
|
23
|
+
if (!element || typeof element.href !== 'string') {
|
|
24
|
+
const where = groupName ? `${groupName}[${index}]` : `elements[${index}]`
|
|
25
|
+
console.warn(
|
|
26
|
+
`⚠️ navigation.yaml: skipping ${where} — it has no "href".`
|
|
27
|
+
)
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true
|
|
32
|
+
})
|
|
33
|
+
.map((element) => ({
|
|
34
|
+
...element,
|
|
35
|
+
path: path.posix.dirname(element.href),
|
|
36
|
+
}))
|
|
12
37
|
}
|
|
13
38
|
|
|
14
39
|
function getMainNav() {
|
|
15
|
-
const navConfig = getConfig(
|
|
40
|
+
const navConfig = getConfig(getHostConfigPath())
|
|
16
41
|
|
|
17
42
|
navConfig.activeClass = navConfig.active_class || 'active'
|
|
18
43
|
navConfig.activePathClass = navConfig.active_path_class || 'active-path'
|
|
@@ -24,7 +49,7 @@ function getMainNav() {
|
|
|
24
49
|
for (const key in navConfig.elements) {
|
|
25
50
|
navConfig[key] = {
|
|
26
51
|
className: `${key}-${navConfig.navClass}`,
|
|
27
|
-
elements: getNavElements(navConfig.elements[key]),
|
|
52
|
+
elements: getNavElements(navConfig.elements[key], key),
|
|
28
53
|
}
|
|
29
54
|
}
|
|
30
55
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nera-static/plugin-navigation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A plugin for Nera static site generator to generate navigations with optional templates and mixins.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"publish-template": "node ./bin/publish-template.js",
|
|
7
8
|
"lint": "eslint .",
|
|
8
9
|
"test": "vitest"
|
|
9
10
|
},
|
|
@@ -11,10 +12,15 @@
|
|
|
11
12
|
"exports": {
|
|
12
13
|
".": "./index.js"
|
|
13
14
|
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"nera-navigation": "./bin/publish-template.js"
|
|
17
|
+
},
|
|
14
18
|
"files": [
|
|
19
|
+
"bin",
|
|
15
20
|
"config",
|
|
16
21
|
"index.js",
|
|
17
|
-
"views"
|
|
22
|
+
"views",
|
|
23
|
+
"CHANGELOG.md"
|
|
18
24
|
],
|
|
19
25
|
"keywords": [
|
|
20
26
|
"nera",
|
|
@@ -35,7 +41,7 @@
|
|
|
35
41
|
},
|
|
36
42
|
"homepage": "https://github.com/seebaermichi/nera-plugin-navigation#readme",
|
|
37
43
|
"dependencies": {
|
|
38
|
-
"@nera-static/plugin-utils": "^1.
|
|
44
|
+
"@nera-static/plugin-utils": "^1.2.0"
|
|
39
45
|
},
|
|
40
46
|
"engines": {
|
|
41
47
|
"node": ">=18"
|