@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 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
- - **Flexible Navigation Structure**: Define one or more navigations via YAML config
8
- - **Template Integration**: Access navigation data in your templates (`app.nav`)
9
- - **Multi-Level Support**: Support for multi-level navigations (e.g. main, footer)
10
- - **Built-in Templates**: Includes ready-to-use Pug templates and mixins:
11
- - Pipe-separated links
12
- - Link lists
13
- - Mixin-powered flexible layout
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
- You can install this plugin by running the following in the root folder of your Nera project:
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 a `navigation.yaml` file inside your project’s `config/` directory:
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
- Nera will automatically detect the plugin and load your navigation configuration. No additional setup or imports are required.
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
- ### Single Navigation
46
+ Define your navigation(s) in `config/navigation.yaml`.
38
47
 
39
- Example `navigation/config/navigation.yaml`:
48
+ ### Single Navigation
40
49
 
41
50
  ```yaml
42
51
  elements:
43
- - href: /index.html
44
- name: Home
45
- - href: /service/service.html
46
- name: Service
47
- - href: /prices.html
48
- name: Prices
49
- - href: /contact.html
50
- name: Contact
51
- - href: /about-us/index.html
52
- name: About us
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 it in your templates via:
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
- main:
66
- - href: /index.html
67
- name: Home
68
- - href: /service/service.html
69
- name: Service
70
- footer:
71
- - href: /imprint.html
72
- name: Imprint
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
- Use:
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 has: `href`, `name`, `path`.
91
+ Each element includes `href`, `name`, and `path`.
83
92
 
84
- ## 🧩 Rendering Options
93
+ ## 🧩 Usage
85
94
 
86
- ### Custom Rendering
95
+ ### Manual Rendering
87
96
 
88
- Use the `app.nav.*.elements` arrays in your templates manually or via your own loops.
97
+ Loop through `app.nav.*.elements` directly in your Pug templates.
89
98
 
90
- ### Built-in Templates
99
+ ## 🛠️ Template Publishing
91
100
 
92
- If you like to, include one of the built-in templates in `views/`:
101
+ Use the default templates provided by the plugin:
93
102
 
94
- ```pug
95
- include ../../src/plugins/navigation/views/simple-navigation
103
+ ```bash
104
+ npx nera-navigation
96
105
  ```
97
106
 
98
- Other available templates:
107
+ This copies every template file — including `partials/` and `helper/`, which
108
+ the top-level templates include — to:
99
109
 
100
- - `pipe-separated-navigation.pug`
101
- - `link-list-navigation.pug`
110
+ ```
111
+ views/vendor/plugin-navigation/
112
+ ```
102
113
 
103
- ### Built-in Mixins
114
+ Then include them in your layouts or pages as needed.
104
115
 
105
- If using multiple navigations, use the mixins in `views/mixins/`:
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
- ```pug
108
- include ../../src/plugins/navigation/views/mixins/pipe-separated-navigation
109
-
110
- +pipeSeparatedNav(app.nav.main.elements, app.nav.main.className)
120
+ ```bash
121
+ npx nera-navigation --force
111
122
  ```
112
123
 
113
- > The optional `nav_class` value can be set in the YAML config.
124
+ ## 🎨 Styling
114
125
 
115
- ## 🧪 Development
126
+ The plugin uses BEM CSS methodology:
116
127
 
117
- ```bash
118
- npm install
119
- npm run test
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
- ## 🎨 CSS Classes (BEM Methodology)
139
+ Override or extend these classes in your project’s CSS.
123
140
 
124
- The generated HTML uses BEM (Block Element Modifier) CSS classes for consistent styling:
141
+ ## 📊 Generated Output
125
142
 
126
- ```css
127
- /* Navigation Block */
128
- .nav {
129
- /* Main navigation container */
130
- }
131
-
132
- /* Navigation Elements */
133
- .nav__list {
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
- ## 📋 Version History
153
+ Tests use [Vitest](https://vitest.dev) and validate:
159
154
 
160
- All changes are documented in [CHANGELOG.md](./CHANGELOG.md).
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
- - [Plugin Repository](https://github.com/seebaermichi/nera-plugin-navigation)
170
- - [NPM Package](https://www.npmjs.com/package/@nera-static/plugin-navigation)
171
- - [Nera Static Site Generator](https://github.com/seebaermichi/nera)
172
- - [Plugin Documentation](https://github.com/seebaermichi/nera-plugins#plugins)
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
- // Default location to look for navigation.yaml in host project
5
- const HOST_CONFIG_PATH = path.resolve(process.cwd(), 'config/navigation.yaml')
6
-
7
- function getNavElements(elements) {
8
- return elements.map((element) => ({
9
- ...element,
10
- path: path.posix.dirname(element.href),
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(HOST_CONFIG_PATH)
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.1.0",
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.1.0"
44
+ "@nera-static/plugin-utils": "^1.2.0"
39
45
  },
40
46
  "engines": {
41
47
  "node": ">=18"