al_email_protect 1.0.0 → 1.0.1
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/al_email_protect/version.rb +1 -1
- data/lib/al_email_protect.rb +53 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eda48a119414b48f22f99423d978f6b4fbc0ffd48d8624825aaaa07b75349492
|
|
4
|
+
data.tar.gz: c604de4cc07165de773b748e2748a43e3350cba1d5c2051106702ef9578a7db5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2d93ea976edc2dd4b057d2670c2ea46fe49714ee9aa820c337cd5db3ede3e0227ea5ed6edfa16720098ff938ec7be02a3609682ef8759e6be73a2485df4e8318
|
|
7
|
+
data.tar.gz: 0a660b1b7d1c21f2d1e0f58c5f4c999e7b06aa0ed38f0cf0e6c35b88a5daa2c371ec1e5ac921d3d01368ff87353d9c5e66ee886e8d045dcf169e34113fd30106
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.1 — 2026-08-03
|
|
4
|
+
|
|
5
|
+
- Added `al_email_protect_html`, a filter that rewrites `mailto:` anchors inside already-rendered HTML. al-folio's social
|
|
6
|
+
links come from the third-party `jekyll-socials` gem, which owns the whole block and offers no hook to render the email
|
|
7
|
+
entry differently — capturing its output and rewriting it afterwards is the only interception point, and it works
|
|
8
|
+
regardless of which gem produced the markup. Percent-encoded targets (as `encode_email` produces) are decoded first,
|
|
9
|
+
visible address text is replaced so the plaintext does not survive, non-`mailto:` links and unusable addresses are left
|
|
10
|
+
untouched, and the filter is a pass-through when the feature is off.
|
|
11
|
+
|
|
3
12
|
## 1.0.0 — 2026-08-02
|
|
4
13
|
|
|
5
14
|
- Initial release of `al_email_protect`, implementing the email obfuscation proposed in
|
data/lib/al_email_protect.rb
CHANGED
|
@@ -148,12 +148,65 @@ module AlEmailProtect
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
# {{ cv.email | al_email_obfuscate }}
|
|
151
|
+
# Rewrites every `mailto:` anchor in a fragment of already-rendered HTML.
|
|
152
|
+
#
|
|
153
|
+
# This exists because the markup that needs protecting is frequently not ours.
|
|
154
|
+
# al-folio's social links come from the third-party `jekyll-socials` gem, which
|
|
155
|
+
# owns the whole block and emits `mailto:%s` for the email entry — there is no
|
|
156
|
+
# hook to render that one link differently. Capturing its output and rewriting
|
|
157
|
+
# it afterwards is the only interception point, and it works regardless of
|
|
158
|
+
# which gem produced the markup.
|
|
159
|
+
#
|
|
160
|
+
# Deliberately narrow: it matches an <a> whose href begins with `mailto:` and
|
|
161
|
+
# replaces the whole element. It does not attempt to parse HTML generally.
|
|
162
|
+
ANCHOR = %r{<a\b([^>]*?)href=(["'])mailto:([^"']+)\2([^>]*)>(.*?)</a>}im.freeze
|
|
163
|
+
|
|
164
|
+
# `mailto:` targets are commonly percent-encoded (jekyll-email-protect's
|
|
165
|
+
# `encode_email` does exactly that), so decode before splitting or the local
|
|
166
|
+
# and domain halves come out as escape sequences.
|
|
167
|
+
def decode_target(value)
|
|
168
|
+
CGI.unescape(value.to_s.split("?").first.to_s)
|
|
169
|
+
rescue StandardError
|
|
170
|
+
value.to_s
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def rewrite_html(html)
|
|
174
|
+
html.to_s.gsub(ANCHOR) do
|
|
175
|
+
before = Regexp.last_match(1)
|
|
176
|
+
after = Regexp.last_match(4)
|
|
177
|
+
address = decode_target(Regexp.last_match(3))
|
|
178
|
+
label = Regexp.last_match(5)
|
|
179
|
+
parts = split_address(address)
|
|
180
|
+
|
|
181
|
+
# Leave anything that is not a usable address exactly as it was; a
|
|
182
|
+
# half-rewritten contact link is worse than an unprotected one.
|
|
183
|
+
next Regexp.last_match(0) unless parts
|
|
184
|
+
|
|
185
|
+
local, domain = parts
|
|
186
|
+
attributes = "#{before}#{after}".gsub(/\s+/, " ").strip
|
|
187
|
+
# The visible text often *is* the address. Replace it with the split
|
|
188
|
+
# rendering, or the plaintext survives in the markup and the rewrite
|
|
189
|
+
# achieves nothing.
|
|
190
|
+
inner = label.to_s.include?("@") ? "#{escape(local)}<span class=\"al-email-sep\"> [at] </span>#{domain_markup(domain)}" : label
|
|
191
|
+
|
|
192
|
+
%(<a href="#" class="al-email-protect #{attributes}" data-eu="#{escape(local)}" data-ed="#{escape(domain)}">#{inner}</a>)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
151
196
|
module Filters
|
|
152
197
|
def al_email_obfuscate(value)
|
|
153
198
|
return value.to_s unless AlEmailProtect.enabled?(@context.registers[:site])
|
|
154
199
|
|
|
155
200
|
AlEmailProtect.obfuscate_text(value)
|
|
156
201
|
end
|
|
202
|
+
|
|
203
|
+
# `{{ captured_html | al_email_protect_html }}` — a pass-through when the
|
|
204
|
+
# feature is off, so callers can pipe unconditionally.
|
|
205
|
+
def al_email_protect_html(value)
|
|
206
|
+
return value.to_s unless AlEmailProtect.enabled?(@context.registers[:site])
|
|
207
|
+
|
|
208
|
+
AlEmailProtect.rewrite_html(value)
|
|
209
|
+
end
|
|
157
210
|
end
|
|
158
211
|
end
|
|
159
212
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: al_email_protect
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- al-folio maintainers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|