@nera-static/plugin-canonical-links 2.0.1 → 2.1.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,100 @@
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.1.0] - 2026-07-19
9
+
10
+ ### Fixed
11
+
12
+ - no longer emits `<link rel="canonical" href="undefined/...">` on every page
13
+ when no origin is configured. That markup was worse than none — it told
14
+ search engines the authoritative URL was a broken string, and nothing was
15
+ printed to warn about it. The plugin now warns once and leaves pages
16
+ untouched
17
+
18
+ ### Added
19
+
20
+ - `publish-template` command (`npx nera-canonical-links`), so the shipped
21
+ templates can be copied into `views/vendor/` like every other plugin.
22
+ Previously there was no publish path at all and the README worked around it
23
+ by including straight out of `node_modules/`
24
+ - `--force` to re-publish over existing templates, discarding local edits
25
+
26
+ ### Changed
27
+
28
+ - `@nera-static/plugin-utils` range widened to `^1.2.0`, which is what makes
29
+ `partials/` publish alongside `index.pug`
30
+ - config is resolved per call rather than at module load
31
+ - README: `app_origin` was documented as overriding `app.origin`. It is the
32
+ other way round — `app.origin` wins. The docs now match the code
33
+ - README: documents that omitting `available_languages` silently disables
34
+ alternate links
35
+
36
+ ### Removed
37
+
38
+ - dead `if (!config)` guard — `getConfig` returns `{}`, so it never fired
39
+
40
+ ## [2.0.1] - 2025-07-19
41
+
42
+ ### Added
43
+
44
+ - Complete CHANGELOG.md with full version history
45
+ - Enhanced package.json keywords for better discoverability
46
+ - Compatibility section in README.md
47
+
48
+ ### Changed
49
+
50
+ - Improved documentation with Nera v4.1.0+ compatibility notes
51
+ - Enhanced keywords for NPM search optimization
52
+ - Better structured development and deployment information
53
+
54
+ ### Fixed
55
+
56
+ - Documentation consistency and clarity improvements
57
+
58
+ ## [2.0.0] - 2025-07-19
59
+
60
+ ### Breaking Changes
61
+
62
+ - Updated for compatibility with Nera v4.1.0+
63
+ - Requires Node.js >= 18
64
+
65
+ ### Added
66
+
67
+ - Support for Nera's enhanced plugin architecture
68
+ - Improved error handling and logging compatibility
69
+ - Full compatibility with Nera's parallel plugin loading
70
+
71
+ ### Changed
72
+
73
+ - Updated dependencies to latest versions
74
+ - Enhanced test coverage and reliability
75
+ - Improved documentation and development setup
76
+
77
+ ### Technical
78
+
79
+ - Compatible with Nera's new plugin data merging system
80
+ - Optimized for parallel execution performance
81
+ - Enhanced development tooling with Husky and ESLint
82
+
83
+ ## [1.x] - Previous Versions
84
+
85
+ ### Features
86
+
87
+ - Canonical link generation for SEO optimization
88
+ - Multi-language alternate link support
89
+ - Configurable page identifier and language detection
90
+ - Pug template integration for head section
91
+
92
+ ### Configuration
93
+
94
+ - Flexible origin URL configuration
95
+ - Support for multiple available languages
96
+ - Customizable page identifier field
97
+ - YAML-based configuration system
98
+
99
+ [2.0.1]: https://github.com/seebaermichi/nera-plugin-canonical-links/compare/v2.0.0...v2.0.1
100
+ [2.0.0]: https://github.com/seebaermichi/nera-plugin-canonical-links/compare/v1.0.0...v2.0.0
package/README.md CHANGED
@@ -39,17 +39,42 @@ available_languages:
39
39
  - fr
40
40
  ```
41
41
 
42
- - `app_origin`: The canonical base URL (overrides `app.origin`).
42
+ - `app_origin`: The canonical base URL. Used as a fallback — if `origin` is
43
+ set in `config/app.yaml`, **that wins**.
43
44
  - `page_identifier`: Shared key to match localized versions (defaults to `slug`).
44
- - `available_languages`: List of supported language codes (used to create alternate links).
45
+ - `available_languages`: List of supported language codes, used to create
46
+ alternate links. **Omitting it disables alternate links entirely** — you
47
+ get canonical tags only, with no warning.
48
+
49
+ If neither `app.origin` nor `app_origin` resolves, the plugin generates no
50
+ canonical links at all and prints a warning. Earlier versions emitted
51
+ `<link rel="canonical" href="undefined/…">` in that case.
52
+
53
+ ## 🛠️ Template Publishing
54
+
55
+ Copy the plugin's templates into your project:
56
+
57
+ ```bash
58
+ npx nera-canonical-links
59
+ ```
60
+
61
+ This copies `index.pug` and its `partials/` to:
62
+
63
+ ```
64
+ views/vendor/plugin-canonical-links/
65
+ ```
66
+
67
+ Publishing **skips** if that directory already exists, so your edits are never
68
+ overwritten. To pull in updated templates after an upgrade, discarding your
69
+ changes to them, use `npx nera-canonical-links --force`.
45
70
 
46
71
  ## 📄 Usage in Templates
47
72
 
48
- Include the plugin’s view in your layout head:
73
+ Include the published view in your layout head:
49
74
 
50
75
  ```pug
51
76
  head
52
- include /node_modules/@nera-static/plugin-canonical-links/views/index
77
+ include vendor/plugin-canonical-links/index
53
78
  ```
54
79
 
55
80
  This will generate:
@@ -121,7 +146,7 @@ The plugin provides a view file that includes two partials:
121
146
  link(href=alternate.href, hreflang=alternate.hreflang, rel=alternate.rel)
122
147
  ```
123
148
 
124
- You can copy or customize these templates for full control.
149
+ Publish them (see above) and customize the copies for full control.
125
150
 
126
151
  ## 🧪 Development
127
152
 
@@ -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-canonical-links'
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)
package/index.js CHANGED
@@ -1,18 +1,22 @@
1
1
  import path from 'path'
2
2
  import { getConfig } from '@nera-static/plugin-utils'
3
3
 
4
- const HOST_CONFIG_PATH = path.resolve(
5
- process.cwd(),
6
- 'config/canonical-links.yaml'
7
- )
8
-
9
- const config = getConfig(HOST_CONFIG_PATH)
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 getHostConfig() {
7
+ return getConfig(path.resolve(process.cwd(), 'config/canonical-links.yaml'))
8
+ }
10
9
 
11
- function getOrigin(data) {
12
- return data.app.origin || config.app_origin
10
+ /**
11
+ * The canonical base URL. `app.origin` from config/app.yaml wins over the
12
+ * plugin's own `app_origin` — the opposite of what the README claimed
13
+ * before 2.1.0.
14
+ */
15
+ function getOrigin(data, config) {
16
+ return data.app?.origin || config.app_origin
13
17
  }
14
18
 
15
- function getAlternates(pageMeta, data) {
19
+ function getAlternates(pageMeta, data, config, origin) {
16
20
  const pageIdentifier = config.page_identifier || 'slug'
17
21
  const availableLanguages = config.available_languages || []
18
22
  const multiLangCanonicals = []
@@ -27,7 +31,7 @@ function getAlternates(pageMeta, data) {
27
31
 
28
32
  if (relCanonical) {
29
33
  multiLangCanonicals.push({
30
- href: `${getOrigin(data)}${relCanonical.meta.href}`,
34
+ href: `${origin}${relCanonical.meta.href}`,
31
35
  hreflang: availableLang,
32
36
  rel: 'alternate',
33
37
  })
@@ -38,15 +42,26 @@ function getAlternates(pageMeta, data) {
38
42
  return multiLangCanonicals
39
43
  }
40
44
 
41
- function getCanonical(meta, data) {
45
+ function getCanonical(meta, origin) {
42
46
  return {
43
- href: `${getOrigin(data)}${meta.href}`,
47
+ href: `${origin}${meta.href}`,
44
48
  rel: 'canonical',
45
49
  }
46
50
  }
47
51
 
48
52
  export function getMetaData(data) {
49
- if (!config) {
53
+ const config = getHostConfig()
54
+ const origin = getOrigin(data, config)
55
+
56
+ // Without an origin every page used to get
57
+ // <link rel="canonical" href="undefined/blog/post.html">, which is worse
58
+ // than emitting nothing at all — it hands search engines a broken URL as
59
+ // the authoritative one. Bail out loudly instead.
60
+ if (!origin) {
61
+ console.warn(
62
+ '⚠️ plugin-canonical-links: no origin configured, so no canonical links were generated.\n' +
63
+ ' Set `origin` in config/app.yaml, or `app_origin` in config/canonical-links.yaml.'
64
+ )
50
65
  return data.pagesData
51
66
  }
52
67
 
@@ -54,8 +69,8 @@ export function getMetaData(data) {
54
69
  return {
55
70
  content,
56
71
  meta: Object.assign({}, meta, {
57
- canonicalLink: getCanonical(meta, data),
58
- alternateLinks: getAlternates(meta, data),
72
+ canonicalLink: getCanonical(meta, origin),
73
+ alternateLinks: getAlternates(meta, data, config, origin),
59
74
  }),
60
75
  }
61
76
  })
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@nera-static/plugin-canonical-links",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "A plugin for Nera static site generator to create canonical links in to be used in the head.",
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-canonical-links": "./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",
@@ -38,7 +44,7 @@
38
44
  },
39
45
  "homepage": "https://github.com/seebaermichi/nera-plugin-canonical-links#readme",
40
46
  "dependencies": {
41
- "@nera-static/plugin-utils": "^1.0.3"
47
+ "@nera-static/plugin-utils": "^1.2.0"
42
48
  },
43
49
  "engines": {
44
50
  "node": ">=18"