ObfuscateLink Web Component in Astro

Using Web Components in Astro wasn’t as straightforward as expected. Here’s an example showing how to integrate the obfuscate-link web component into an Astro project. 

First, add the Obfuscate-Link web component to the project:

npm install obfuscate-link-web-component

Now register ObfuscateLink with customElements: 

<body>
    <slot />
    <script>
      import { ObfuscateLink } from 'obfuscate-link-web-component';
      // Only define the custom element if it hasn't been defined yet
      if (!customElements.get('obfuscate-link')) {
        customElements.define('obfuscate-link', ObfuscateLink);
      }
    </script>
</body>Code language: HTML, XML (xml)

This occurs in the Layout.astro component, making it available across all pages. The registration happens within a script tag in the HTML to execute only on the client side, avoiding it execution while SSR rendering performed by Astro beforehand.

Next, create an Astro component that wraps the web-component and handles the obfuscation by encoding the passed prop.

---
type BaseProps = {
  id?: string;
}
type EmailProps = BaseProps & {
  email: string;
  tel?: never;
  sms?: never;
  facetime?: never;
  href?: never;
}
type TelProps = BaseProps & {
  email?: never;
  tel: string;
  sms?: never;
  facetime?: never;
  href?: never;
}
type SmsProps = BaseProps & {
  email?: never;
  tel?: never;
  sms: string;
  facetime?: never;
  href?: never;
}
type FacetimeProps = BaseProps & {
  email?: never;
  tel?: never;
  sms?: never;
  facetime: string;
  href?: never;
}
type HrefProps = BaseProps & {
  email?: never;
  tel?: never;
  sms?: never;
  facetime?: never;
  href: string;
}
export type Props = EmailProps | TelProps | SmsProps | FacetimeProps | HrefProps;
const props = Astro.props;
const { id } = props;
// Find the active prop (email, tel, sms, facetime, or href)
const activeProp = Object.entries(props).find(([key, value]) => 
  key !== 'id' && value !== undefined
);
let attribute = '';
let value = '';
if (activeProp) {
  [attribute, value] = activeProp;
  const orgValue = value;
  value = Buffer.from(value).toString('base64');
}
---

<obfuscate-link
  id={id}
  {...{[attribute]: value}}
><slot /></obfuscate-link>Code language: JavaScript (javascript)

Finally, you can utilize both the Astro component and the Web component throughout your Astro project.


---
import ObfuscateLink from './ObfuscateLink.astro';
---

<div class="card">
  <p>
    Email: <ObfuscateLink email="info@example.com" />
  </p>
</div>Code language: JavaScript (javascript)

The complete code can be seen in this Gist:

https://gist.github.com/ivoba/222d5a49ad4542392772195c5e5ad032