Skip to content
This repository has been archived by the owner on Dec 17, 2024. It is now read-only.

Feature Request: Link: Obfuscate email/phone in <slot /> #98

Open
ppo opened this issue Jul 31, 2024 · 0 comments
Open

Feature Request: Link: Obfuscate email/phone in <slot /> #98

ppo opened this issue Jul 31, 2024 · 0 comments

Comments

@ppo
Copy link

ppo commented Jul 31, 2024

Allow to obfuscate the email/phone in the link text.

I see different options:

  1. Search for the value in and obfuscate it.
  2. Using a placeholder in the link text (e.g. [email]). Same as 1 without having to duplicate the value.
  3. Provide a helper so that we can obfuscate the displayed text "manually".
  4. If no or with a useValueAsText prop (awful name 😂), force the link text to be the obfuscated value.

FYI, here's a component I made to obfuscate an email or phone; with the link text always being the value itself.

---
// Check:
//   https://spencermortensen.com/articles/email-obfuscation/
//   https://codereview.stackexchange.com/questions/222003/obfuscation-of-email-and-phone-using-javascript
/**
 * Props:
 *   value: The regular email or the phone number as it must be displayed. This component takes
 *     care of the conversions that are needed for the display value or the code value.
 *
 * In client-side code:
 *   u(): `unobfuscate()`, reverse of `obfuscate()` on server-side.
 *   h(): `toHtmlEntities()`, encode a string as HTML entities (`&#n`).
 *   p(): `toPercentEncoding()`, encode a string as percent encoding (`%n`).
 */

// Type-protocol mapping.
const TYPES = {
  'email': 'mailto:',
  'phone': 'tel:',
};


// Convert a string into an array of hexadecimal char codes.
function obfuscate(v: string): string[] {
  return v.split('').map(c => '0x' + c.charCodeAt(0).toString(16));
}


interface Props {
  type: 'email' | 'phone';
  value: string;
};
const { type, value } = Astro.props;


const id: string = crypto.randomUUID();

const s: string[] = obfuscate(TYPES[type]);  // Obfuscated protocol.
let d: string[];  // Obfuscated display value (email or phone).
let v: string[];  // Obfuscated code value (email or phone).

switch (type) {
  case 'email':
    d = obfuscate(value);
    v = obfuscate(value);
    break;

  case 'phone':
    d = obfuscate(value.replaceAll(' ', ' '));  // Non-breaking space.
    v = obfuscate(value.replaceAll(' ', ''));
    break;
}
---


<span id={id} />

<script is:inline define:vars={{ id, s, v, d }}>
  function u(s) { return s.map(c => String.fromCharCode(parseInt(c))).join(''); }
  function h(s) { return s.split('').map(c => '&#' + c.charCodeAt(0) + ';').join(''); }
  function p(s) { return s.split('').map(c => '%' + c.charCodeAt(0).toString(16)).join(''); }
  const e = document.createElement(u(['0x61']));
  e.setAttribute(u(['0x68', '0x72', '0x65', '0x66']), u(s) + p(u(v)));
  e.setAttribute('rel', 'nofollow');
  e.innerHTML = h(u(d));
  document.getElementById(id).replaceWith(e);
</script>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant