Module: AlEmailProtect

Defined in:
lib/al_email_protect.rb,
lib/al_email_protect/version.rb

Overview

Keeps published email addresses away from harvesters.

The scraper-facing half is deliberately server-side: when the feature is on, no mailto: string and no user@host string is present in the HTML at all. Address harvesters read markup, not JavaScript, so an approach that ships the plaintext and merely rewrites it on DOMContentLoaded protects nobody. The address is emitted as two halves and only rejoined in the browser.

Defined Under Namespace

Modules: Filters Classes: AssetsGenerator, LinkTag, PluginStaticFile, ScriptsTag, StylesTag

Constant Summary collapse

PLUGIN_ROOT =
File.expand_path("..", __dir__)
LIB_ROOT =

Jekyll writes a StaticFile to /

/, where is relative to the base below. That base must be lib/, not the gem root, or assets land at /lib/assets/... while every tag in this file points at /assets/... .

__dir__
ASSETS_ROOT =
File.join(LIB_ROOT, "assets")
VERSION =
"1.0.0"

Class Method Summary collapse

Class Method Details

.asset_entriesObject

[relative_dir, filename] for everything this gem publishes. Exposed so the destination path can be asserted without booting a full Jekyll site.



73
74
75
76
77
# File 'lib/al_email_protect.rb', line 73

def asset_entries
  Dir.glob(File.join(ASSETS_ROOT, "**", "*")).sort.reject { |p| File.directory?(p) }.map do |source_path|
    [File.dirname(source_path).sub("#{LIB_ROOT}/", ""), File.basename(source_path)]
  end
end

.domain_markup(domain) ⇒ Object

Builds "example [dot] com" as alternating styled spans.



66
67
68
69
# File 'lib/al_email_protect.rb', line 66

def domain_markup(domain)
  separator = %(<span class="al-email-sep"> [dot] </span>)
  domain.split(".").map { |label| %(<span class="al-email-text">#{escape(label)}</span>) }.join(separator)
end

.enabled?(site) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
30
31
# File 'lib/al_email_protect.rb', line 27

def enabled?(site)
  return false unless site

  site.config["protect_email"] == true
end

.escape(value) ⇒ Object



61
62
63
# File 'lib/al_email_protect.rb', line 61

def escape(value)
  CGI.escapeHTML(value.to_s)
end

.obfuscate_text(value) ⇒ Object

"someone [at] example [dot] com", for places that show an address as text rather than as a link (CV contact blocks, for instance).



53
54
55
56
57
58
59
# File 'lib/al_email_protect.rb', line 53

def obfuscate_text(value)
  parts = split_address(value)
  return value.to_s unless parts

  local, domain = parts
  "#{local} [at] #{domain.gsub(".", " [dot] ")}"
end

.split_address(value) ⇒ Object

Splits "someone@example.ac.uk" into ["someone", "example.ac.uk"].

Splits on the LAST "@" because the local part of an address may legally contain one when quoted (RFC 5321), and getting this backwards would emit a broken address rather than a protected one. Returns nil for anything not usable as an address, so callers can fall back to rendering it verbatim instead of silently publishing a mangled contact.



40
41
42
43
44
45
46
47
48
49
# File 'lib/al_email_protect.rb', line 40

def split_address(value)
  address = value.to_s.strip
  return nil if address.empty?

  local, _, domain = address.rpartition("@")
  return nil if local.empty? || domain.empty?
  return nil unless domain.include?(".")

  [local, domain]
end