web-garden
web-garden copied to clipboard
Feature Request: Link: Obfuscate email/phone in <slot />
Allow to obfuscate the email/phone in the link text.
I see different options:
- Search for the value in
and obfuscate it. - Using a placeholder in the link text (e.g.
[email]). Same as 1 without having to duplicate the value. - Provide a helper so that we can obfuscate the displayed text "manually".
- If no
or with a useValueAsTextprop (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>