jekyll-taxonomy-redirects 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 65035b0cb53fc93b7f29fca64e8fb109e8ea6abff3278a348da6d32eb8297def
4
+ data.tar.gz: 8d46bee87ae966574ee0b55b33e6eb9cae0e7cd644aca5dd09be47e06a2def20
5
+ SHA512:
6
+ metadata.gz: 0c37a948918a5a9acb6458d29f92ff3e611377b8f36e4c95d8f1b9a50ac4a5033ac405caa0b23e0af28b706cfc509121db4a21c51847ace6bfb06de23c31dcf9
7
+ data.tar.gz: a77062f884247c4b0e14a7b2b9125db332ced70791bf6b3a69f302e1d7cb73a01a6a7ac77dd4ca1d485ebd080fd86c217c575c54e828589bc55868306ae96c34
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT Licence
2
+
3
+ Copyright (c) 2025 Dave Cross
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the “Software”), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # jekyll-taxonomy-redirects
2
+
3
+ Generate **legacy taxonomy redirects** for Jekyll sites. Handy when migratingi
4
+ from WordPress (or any site) where you used paths like `/category/:slug/` and
5
+ `/tags/:slug/`, but your new site uses `/venues/:slug/` and `/acts/:slug/`
6
+ (or any other mapping).
7
+
8
+ The plugin emits tiny, portable HTML redirect stubs at build time. It works
9
+ with GitHub Pages when you **build in CI** (Actions) and deploy `_site/`.
10
+
11
+ ---
12
+
13
+ ## Features
14
+
15
+ * Generate redirects for **category** and **tag** taxonomies (slugs from your content)
16
+ * Configurable **from** → **to** mappings (e.g. `/category` → `/venues`)
17
+ * Optional root redirects (e.g. `/category/` → `/venues/`)
18
+ * Portable HTML stubs using `<meta refresh>` + `location.replace()`
19
+ * Optional `<link rel="canonical">` for crawlers
20
+ * Works alongside `jekyll-archives` and `jekyll-redirect-from`
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ Add the gem to your site’s `Gemfile`:
27
+
28
+ ```ruby
29
+ # Gemfile
30
+ source "https://rubygems.org"
31
+
32
+ group :jekyll_plugins do
33
+ gem "jekyll-taxonomy-redirects", "~> 0.1"
34
+ end
35
+ ```
36
+
37
+ Enable the plugin in `_config.yml`:
38
+
39
+ ```yml
40
+ # _config.yml
41
+ plugins:
42
+ - jekyll-taxonomy-redirects
43
+ ```
44
+
45
+ > **GitHub Pages:** If you deploy with GitHub Pages, build the site in GitHub
46
+ > Actions (or another CI) and deploy the generated `_site/` artifact. The
47
+ > hosted Pages builder won’t run third‑party plugins.
48
+
49
+ ---
50
+
51
+ ## Configuration
52
+
53
+ Add a `taxonomy_redirects:` block to `_config.yml`.
54
+
55
+ ```yml
56
+ taxonomy_redirects:
57
+ # Optional: roots redirect to the new sections
58
+ roots:
59
+ - from: "/category"
60
+ to: "/venues"
61
+ - from: "/tags"
62
+ to: "/acts"
63
+
64
+ # Per‑slug redirects driven by your content’s taxonomies
65
+ maps:
66
+ - type: "category" # or "tag"
67
+ from: "/category"
68
+ to: "/venues"
69
+ - type: "tag"
70
+ from: "/tags"
71
+ to: "/acts"
72
+
73
+ # HTML output tweaks
74
+ emit_canonical: true # add <link rel="canonical" href="…"> (default: true)
75
+ ```
76
+
77
+ ### What gets generated
78
+
79
+ With the configuration above, the plugin creates:
80
+
81
+ * `/category/` → `/venues/`
82
+ * `/tags/` → `/acts/`
83
+ * `/category/<slug>/` → `/venues/<slug>/`
84
+ * `/tags/<slug>/` → `/acts/<slug>/`
85
+
86
+ It discovers the `<slug>` values from `site.categories.keys` and
87
+ `site.tags.keys` at build time.
88
+
89
+ The plugin runs late (`priority :low`) so taxonomies from your content are
90
+ available.
91
+
92
+ ---
93
+
94
+ ## How it works
95
+
96
+ For each redirect, the plugin writes a minimal `index.html` containing:
97
+
98
+ ```html
99
+ <!doctype html>
100
+ <meta http-equiv="refresh" content="0; url=/new/path/">
101
+ <link rel="canonical" href="/new/path/">
102
+ <script>location.replace('/new/path/');</script>
103
+ <p>Moved to <a href="/new/path/">/new/path/</a>.</p>
104
+ ```
105
+
106
+ This approach is **portable** across static hosts (including GitHub Pages).
107
+ If your host supports server‑side rules (e.g. Netlify), you can keep using
108
+ this, or open an issue to add an optional provider file emitter.
109
+
110
+ ---
111
+
112
+ ## Example: WordPress → Jekyll (venues/acts)
113
+
114
+ ```yml
115
+ # _config.yml
116
+ plugins:
117
+ - jekyll-archives
118
+ - jekyll-taxonomy-redirects
119
+
120
+ jekyll-archives:
121
+ enabled: [categories, tags]
122
+ layouts: { category: venue, tag: act }
123
+ permalinks:
124
+ category: /venues/:name/
125
+ tag: /acts/:name/
126
+
127
+ taxonomy_redirects:
128
+ roots:
129
+ - { from: "/category", to: "/venues" }
130
+ - { from: "/tags", to: "/acts" }
131
+ maps:
132
+ - { type: "category", from: "/category", to: "/venues" }
133
+ - { type: "tag", from: "/tags", to: "/acts" }
134
+ ```
135
+
136
+ Now the old `/category/foo/` and `/tags/bar/` URLs redirect to `/venues/foo/`
137
+ and `/acts/bar/`.
138
+
139
+ ---
140
+
141
+ ## Compatibility
142
+
143
+ * **Jekyll:** 4.x
144
+ * **Hosts:** Any static host. For GitHub Pages, build the site yourself (Actions) and deploy `_site/`.
145
+ * **Works with:** `jekyll-archives`, `jekyll-redirect-from` (for per‑document redirects).
146
+
147
+ ---
148
+
149
+ ## Development
150
+
151
+ Clone and run against a test site:
152
+
153
+ ```bash
154
+ bundle install
155
+ bundle exec jekyll build --trace
156
+ ```
157
+
158
+ While developing in the same repo as your site, you can point Bundler at the
159
+ local gem:
160
+
161
+ ```ruby
162
+ # Gemfile in your site
163
+ group :jekyll_plugins do
164
+ gem "jekyll-taxonomy-redirects", path: "../jekyll-taxonomy-redirects"
165
+ end
166
+ ```
167
+
168
+ ### Tests
169
+
170
+ TBD – a minimal fixture site that asserts redirect stubs are created for
171
+ sample slugs.
172
+
173
+ ---
174
+
175
+ ## Contributing
176
+
177
+ PRs welcome! Please:
178
+
179
+ * Keep the code tiny and dependency‑free
180
+ * Add/update docs for any new options
181
+ * Consider hosts with no server‑side redirect support (keep HTML stubs working)
182
+
183
+ ---
184
+
185
+ ## Versioning & Licence
186
+
187
+ * Versioned with SemVer (`0.y.z` until the API stabilises)
188
+ * © 2025 Dave Cross — Released under the **MIT Licence**
189
+
190
+ ---
191
+
192
+ ## FAQ
193
+
194
+ **Why not `jekyll-redirect-from`?**
195
+ That plugin reads front‑matter on individual documents. Archive pages aren’t
196
+ documents, so there’s nothing to attach front‑matter to. This plugin generates
197
+ the required stubs for the archive‑style URLs.
198
+
199
+ **Can this emit server 301 rules?**
200
+ On hosts that support provider files (e.g. Netlify `_redirects`), yes in theory
201
+ — open an issue. On GitHub Pages, server rules aren’t available, so HTML is the
202
+ portable choice.
203
+
204
+ **Will this slow down my build?**
205
+ It’s O(N) in the number of category/tag slugs. For typical blogs that’s
206
+ negligible.
207
+
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Jekyll
3
+ module TaxonomyRedirects
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Jekyll plugin: generates legacy taxonomy redirect stubs, e.g.
4
+ # /category/:slug/ -> /venues/:slug/
5
+ # /tags/:slug/ -> /acts/:slug/
6
+ #
7
+ # Works with any taxonomy provider (core categories/tags or jekyll-archives),
8
+ # because it only needs the slug lists (site.categories.keys / site.tags.keys).
9
+ #
10
+ # Add to Gemfile and enable in _config.yml under `plugins:` then configure:
11
+ #
12
+ # taxonomy_redirects:
13
+ # roots:
14
+ # - { from: "/category", to: "/venues" }
15
+ # - { from: "/tags", to: "/acts" }
16
+ # maps:
17
+ # - { type: "category", from: "/category", to: "/venues" }
18
+ # - { type: "tag", from: "/tags", to: "/acts" }
19
+ # emit_canonical: true
20
+ #
21
+ module Jekyll
22
+ module TaxonomyRedirects
23
+ class RedirectPage < Jekyll::Page
24
+ def initialize(site, from_path, dest_url, emit_canonical: true)
25
+ @site = site
26
+ @base = site.source
27
+ @dir = from_path # e.g. "category/union-chapel"
28
+ @name = "index.html"
29
+ process(@name)
30
+
31
+ self.data = { "layout" => nil, "sitemap" => false }
32
+ self.content = template(dest_url, emit_canonical)
33
+ end
34
+
35
+ def template(dest_url, emit_canonical)
36
+ canonical = emit_canonical ? %(<link rel="canonical" href="#{dest_url}">\n) : ""
37
+ <<~HTML
38
+ <!doctype html><meta charset="utf-8">
39
+ <meta http-equiv="refresh" content="0; url=#{dest_url}">
40
+ #{canonical}<title>Moved</title>
41
+ <p>Moved to <a href="#{dest_url}">#{dest_url}</a>.</p>
42
+ <script>location.replace(#{dest_url.to_json});</script>
43
+ HTML
44
+ end
45
+ end
46
+
47
+ class Generator < Jekyll::Generator
48
+ safe true
49
+ priority :low
50
+
51
+ def generate(site)
52
+ cfg = site.config["taxonomy_redirects"] || {}
53
+ roots = Array(cfg["roots"])
54
+ maps = Array(cfg["maps"])
55
+ emit_canonical = cfg.key?("emit_canonical") ? !!cfg["emit_canonical"] : true
56
+
57
+ # Root redirects like /category/ -> /venues/
58
+ roots.each do |r|
59
+ from = trim_slashes(r["from"].to_s)
60
+ to = ensure_trailing_slash(r["to"].to_s)
61
+ next if from.empty? || to.empty?
62
+ site.pages << RedirectPage.new(site, from, to, emit_canonical: emit_canonical)
63
+ end
64
+
65
+ # Map per-slug redirects
66
+ maps.each do |m|
67
+ type = m["type"].to_s # "category" or "tag"
68
+ from = trim_slashes(m["from"].to_s)
69
+ to = trim_slashes(m["to"].to_s)
70
+ next if type.empty? || from.empty? || to.empty?
71
+
72
+ slugs = case type
73
+ when "category" then site.categories.keys
74
+ when "tag" then site.tags.keys
75
+ else []
76
+ end
77
+
78
+ slugs.each do |slug|
79
+ from_path = File.join(from, slug) # e.g. "category/union-chapel"
80
+ dest_url = "/" + File.join(to, slug, "") # e.g. "/venues/union-chapel/"
81
+ site.pages << RedirectPage.new(site, from_path, dest_url, emit_canonical: emit_canonical)
82
+ end
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def trim_slashes(s)
89
+ s.sub(%r!\A/+, "").sub(%r!/+\z!, "")
90
+ end
91
+
92
+ def ensure_trailing_slash(s)
93
+ s.end_with?("/") ? s : "#{s}/"
94
+ end
95
+ end
96
+ end
97
+ end
98
+
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ require "jekyll/taxonomy_redirects"
3
+
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-taxonomy-redirects
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dave Cross
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: jekyll
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '4.0'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '5.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '4.0'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '5.0'
32
+ description: A Jekyll generator that outputs static redirect stubs for legacy taxonomy
33
+ paths. Useful when migrating from WordPress or changing tag/category permalink structures.
34
+ Plays nicely with jekyll-archives.
35
+ email:
36
+ - dave@davecross.co.uk
37
+ executables: []
38
+ extensions: []
39
+ extra_rdoc_files: []
40
+ files:
41
+ - LICENSE
42
+ - README.md
43
+ - lib/jekyll-taxonomy-redirects.rb
44
+ - lib/jekyll/taxonomy_redirects.rb
45
+ - lib/jekyll/taxonomy_redirects/version.rb
46
+ homepage: https://github.com/davorg/jekyll-taxonomy-redirects
47
+ licenses:
48
+ - MIT
49
+ metadata:
50
+ rubygems_mfa_required: 'true'
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '2.7'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.7.2
66
+ specification_version: 4
67
+ summary: Generate legacy taxonomy redirects (e.g. /category/:slug -> /venues/:slug)
68
+ for Jekyll.
69
+ test_files: []