73 lines
2.3 KiB
JavaScript
73 lines
2.3 KiB
JavaScript
|
|
/**
|
||
|
|
* @fileoverview Link Preview Component for Rantii
|
||
|
|
* @author retoor <retoor@molodetz.nl>
|
||
|
|
* @description Displays link previews with domain info
|
||
|
|
* @keywords link, preview, url, external, domain
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { BaseComponent } from './base-component.js';
|
||
|
|
import { getDomain, sanitizeUrl } from '../utils/url.js';
|
||
|
|
|
||
|
|
class LinkPreview extends BaseComponent {
|
||
|
|
static get observedAttributes() {
|
||
|
|
return ['url', 'title'];
|
||
|
|
}
|
||
|
|
|
||
|
|
init() {
|
||
|
|
this.render();
|
||
|
|
}
|
||
|
|
|
||
|
|
render() {
|
||
|
|
const url = this.getAttr('url');
|
||
|
|
const title = this.getAttr('title');
|
||
|
|
|
||
|
|
if (!url) {
|
||
|
|
this.setHtml('');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const safeUrl = sanitizeUrl(url);
|
||
|
|
if (!safeUrl) {
|
||
|
|
this.setHtml('');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const domain = getDomain(safeUrl);
|
||
|
|
const displayTitle = title || safeUrl;
|
||
|
|
|
||
|
|
this.addClass('link-preview');
|
||
|
|
|
||
|
|
this.setHtml(`
|
||
|
|
<a href="${safeUrl}" class="link-card" target="_blank" rel="noopener noreferrer">
|
||
|
|
<div class="link-icon">
|
||
|
|
<svg viewBox="0 0 24 24" width="20" height="20">
|
||
|
|
<path fill="currentColor" d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
<div class="link-info">
|
||
|
|
<span class="link-title">${this.truncate(displayTitle, 60)}</span>
|
||
|
|
<span class="link-domain">${domain}</span>
|
||
|
|
</div>
|
||
|
|
<div class="link-external">
|
||
|
|
<svg viewBox="0 0 24 24" width="16" height="16">
|
||
|
|
<path fill="currentColor" d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
</a>
|
||
|
|
`);
|
||
|
|
}
|
||
|
|
|
||
|
|
truncate(text, length) {
|
||
|
|
if (text.length <= length) return text;
|
||
|
|
return text.substring(0, length) + '...';
|
||
|
|
}
|
||
|
|
|
||
|
|
onAttributeChanged(name, oldValue, newValue) {
|
||
|
|
this.render();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
customElements.define('link-preview', LinkPreview);
|
||
|
|
|
||
|
|
export { LinkPreview };
|