The project is in a healthy, maintained state
Hides mailto: addresses from scrapers and copies them to the clipboard on click instead.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

>= 2.0, < 3.0
~> 5.0
~> 13.0

Runtime

>= 3.9, < 5.0
>= 4.0, < 6.0
 Project Readme

al_email_protect

Email obfuscation for al-folio v1.x. Implements the plugin proposed in al-folio#3540.

What it does

When protect_email is on, addresses are never emitted as addresses. The HTML contains no user@host string and no mailto: target; the two halves are carried in separate attributes and rejoined by the browser when a visitor clicks.

This is the part that matters. An implementation that ships the plaintext address and rewrites it after DOMContentLoaded protects nobody — harvesters parse markup, they do not run your JavaScript. The obfuscation here happens at build time, in Liquid.

Clicking an address copies it to the clipboard and shows a brief toast, rather than opening a mail client.

Install

Add to your Gemfile:

gem "al_email_protect", "= 1.0.0"

and to _config.ymlboth lists, or the plugin is inert:

plugins:
  - al_email_protect

protect_email: true # off by default

Usage

The al-folio theme calls the asset tags for you. In your own layouts:

{% al_email_protect_link site.data.socials.email %}

Renders a click-to-copy element when enabled, and a plain mailto: link when disabled — so it is safe to call unconditionally.

For contexts that show an address as text rather than a link (a CV contact block, say):

{{ cv.email | al_email_obfuscate }}

gives someone [at] example [dot] com when enabled, and the address unchanged when not.

Behaviour worth knowing

  • Splits on the last @. A quoted local part may legally contain one (RFC 5321).
  • Falls back rather than mangling. A value that is not a usable address (someone@localhost, no dot in the domain) renders as an ordinary mailto: link. Publishing a broken contact address is worse than publishing an unprotected one.
  • Clipboard needs a secure context. navigator.clipboard is undefined over plain HTTP, so the runtime falls back to a hidden-textarea copy, and if even that fails it shows the address so the visitor can copy it by hand.
  • Keyboard accessible. The element is a focusable <a>; Enter and Space both activate it, and the toast is announced via role="status".

Scope

This gem owns obfuscation of addresses it is asked to render. It does not scan arbitrary page text for things that look like addresses — that is unreliable and would corrupt legitimate content.

al_folio_cv renders CV contact details; wiring al_email_obfuscate into those layouts is a change in that gem, not this one. See docs/BOUNDARIES.md.

Development

bundle install
bundle exec rake test
npm ci && npm run lint:prettier

License

MIT