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 +7 -0
- data/LICENSE +21 -0
- data/README.md +207 -0
- data/lib/jekyll/taxonomy_redirects/version.rb +7 -0
- data/lib/jekyll/taxonomy_redirects.rb +98 -0
- data/lib/jekyll-taxonomy-redirects.rb +3 -0
- metadata +69 -0
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,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
|
+
|
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: []
|