react-beauty-link 1.1.3 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ export type LinkTarget = 'new-tab' | 'new-window' | 'self';
5
5
  * with page titles and favicons
6
6
  * @param text - The input string containing potential URLs
7
7
  * @param target - How to open links: 'new-tab' (default), 'new-window', or 'self'
8
+ * @param customColor - Custom color for links (optional)
8
9
  * @returns An array of React nodes with text and links
9
10
  */
10
11
  export declare const useBeautyLink: (text: string, target?: LinkTarget, customColor?: string) => ReactNode[];
@@ -1 +1 @@
1
- {"version":3,"file":"useBeautyLink.d.ts","sourceRoot":"","sources":["../../src/hooks/useBeautyLink.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAe3D;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,SAAQ,UAAsB,EAAE,cAAc,MAAM,KAAG,SAAS,EAuK3G,CAAC"}
1
+ {"version":3,"file":"useBeautyLink.d.ts","sourceRoot":"","sources":["../../src/hooks/useBeautyLink.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAcvC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAe3D;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,SAAQ,UAAsB,EAAE,cAAc,MAAM,KAAG,SAAS,EAsK3G,CAAC"}
@@ -2,6 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from 'react';
3
3
  import { FILE_TYPE_ICONS } from '../utils/fileIcons';
4
4
  import { loadNerdFonts } from '../utils/loadNerdFonts';
5
+ // Load fonts immediately when module is imported (browser only, one-time)
6
+ if (typeof window !== 'undefined') {
7
+ loadNerdFonts();
8
+ }
5
9
  function getFileExtension(url) {
6
10
  try {
7
11
  const urlObj = new URL(url);
@@ -20,16 +24,13 @@ function getFileExtension(url) {
20
24
  * with page titles and favicons
21
25
  * @param text - The input string containing potential URLs
22
26
  * @param target - How to open links: 'new-tab' (default), 'new-window', or 'self'
27
+ * @param customColor - Custom color for links (optional)
23
28
  * @returns An array of React nodes with text and links
24
29
  */
25
30
  export const useBeautyLink = (text, target = 'new-tab', customColor) => {
26
31
  const urlRegex = /(https:\/\/[^\s]+)/g;
27
32
  const [linkMetadata, setLinkMetadata] = useState({});
28
33
  const urls = Array.from(text.matchAll(urlRegex)).map(match => match[0]);
29
- // Load Nerd Fonts once when hook is first used
30
- useEffect(() => {
31
- loadNerdFonts();
32
- }, []);
33
34
  useEffect(() => {
34
35
  const fetchAllMetadata = async () => {
35
36
  for (const url of urls) {
@@ -48,16 +49,20 @@ export const useBeautyLink = (text, target = 'new-tab', customColor) => {
48
49
  continue;
49
50
  }
50
51
  try {
51
- console.log('Fetching metadata for:', url);
52
52
  const metadata = await fetchLinkMetadata(url);
53
- console.log('Metadata received:', metadata);
53
+ if (process.env.NODE_ENV === 'development') {
54
+ console.debug('[react-beauty-link] Metadata fetched:', url);
55
+ }
54
56
  setLinkMetadata(prev => ({
55
57
  ...prev,
56
58
  [url]: metadata
57
59
  }));
58
60
  }
59
61
  catch (error) {
60
- console.error('Failed to fetch metadata for', url, error);
62
+ // Silently fall back to URL - this is expected behavior
63
+ if (process.env.NODE_ENV === 'development') {
64
+ console.debug('[react-beauty-link] Using URL fallback for:', url);
65
+ }
61
66
  setLinkMetadata(prev => ({
62
67
  ...prev,
63
68
  [url]: {
@@ -146,13 +151,14 @@ async function fetchLinkMetadata(url) {
146
151
  const proxies = [
147
152
  `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`,
148
153
  `https://corsproxy.io/?${encodeURIComponent(url)}`,
154
+ `https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(url)}`,
149
155
  ];
150
156
  let html = '';
151
157
  let success = false;
152
158
  for (const proxyUrl of proxies) {
153
159
  try {
154
160
  const response = await fetch(proxyUrl, {
155
- signal: AbortSignal.timeout(10000) // 10 second timeout
161
+ signal: AbortSignal.timeout(5000) // 5 second timeout (faster failover)
156
162
  });
157
163
  if (!response.ok)
158
164
  continue;
@@ -162,7 +168,11 @@ async function fetchLinkMetadata(url) {
162
168
  break;
163
169
  }
164
170
  catch (err) {
165
- console.warn('Proxy failed:', proxyUrl, err);
171
+ // Only log in development mode to reduce console noise
172
+ if (process.env.NODE_ENV === 'development') {
173
+ const errorName = err instanceof Error ? err.name : 'Unknown error';
174
+ console.debug('[react-beauty-link] Proxy failed:', proxyUrl.split('?')[0], errorName);
175
+ }
166
176
  continue;
167
177
  }
168
178
  }
@@ -197,7 +207,10 @@ async function fetchLinkMetadata(url) {
197
207
  return { title, favicon };
198
208
  }
199
209
  catch (error) {
200
- console.error('Error fetching metadata:', error);
210
+ // Graceful fallback - use hostname and Google favicon service
211
+ if (process.env.NODE_ENV === 'development') {
212
+ console.debug('[react-beauty-link] Metadata fetch failed, using fallback');
213
+ }
201
214
  const urlObj = new URL(url);
202
215
  return {
203
216
  title: urlObj.hostname,
@@ -1 +1 @@
1
- {"version":3,"file":"useBeautyLink.js","sourceRoot":"","sources":["../../src/hooks/useBeautyLink.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useBeautyLink.js","sourceRoot":"","sources":["../../src/hooks/useBeautyLink.tsx"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,19 +1,19 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),b=require("react"),v={pdf:{icon:"󰈦",color:"#e74856"},doc:{icon:"󰈬",color:"#2b579a"},docx:{icon:"󰈬",color:"#2b579a"},xls:{icon:"󰈛",color:"#207245"},xlsx:{icon:"󰈛",color:"#207245"},ppt:{icon:"󰈧",color:"#d24726"},pptx:{icon:"󰈧",color:"#d24726"},txt:{icon:"󰈙",color:"#6c757d"},zip:{icon:"󰗄",color:"#e89f1c"},rar:{icon:"󰗄",color:"#e89f1c"},"7z":{icon:"󰗄",color:"#e89f1c"},tar:{icon:"󰗄",color:"#e89f1c"},gz:{icon:"󰗄",color:"#e89f1c"},jpg:{icon:"󰈟",color:"#a855f7"},jpeg:{icon:"󰈟",color:"#a855f7"},png:{icon:"󰈟",color:"#a855f7"},gif:{icon:"󰈟",color:"#a855f7"},svg:{icon:"󰜡",color:"#f97316"},webp:{icon:"󰈟",color:"#a855f7"},mp4:{icon:"󰕧",color:"#ec4899"},avi:{icon:"󰕧",color:"#ec4899"},mov:{icon:"󰕧",color:"#ec4899"},mkv:{icon:"󰕧",color:"#ec4899"},webm:{icon:"󰕧",color:"#ec4899"},mp3:{icon:"󰈣",color:"#10b981"},wav:{icon:"󰈣",color:"#10b981"},flac:{icon:"󰈣",color:"#10b981"},ogg:{icon:"󰈣",color:"#10b981"},js:{icon:"󰌞",color:"#f0db4f"},ts:{icon:"󰛦",color:"#3178c6"},jsx:{icon:"󰜈",color:"#61dafb"},tsx:{icon:"󰜈",color:"#61dafb"},py:{icon:"󰌠",color:"#3776ab"},java:{icon:"󰬷",color:"#007396"},php:{icon:"󰌟",color:"#777bb4"},rb:{icon:"󰴭",color:"#cc342d"},go:{icon:"󰟓",color:"#00add8"},rs:{icon:"󱘗",color:"#dea584"},html:{icon:"󰌝",color:"#e34c26"},css:{icon:"󰌜",color:"#264de4"},json:{icon:"󰘦",color:"#f7df1e"},xml:{icon:"󰗀",color:"#ff6600"},yaml:{icon:"󰈙",color:"#cb171e"},yml:{icon:"󰈙",color:"#cb171e"},md:{icon:"󰍔",color:"#083fa1"},sql:{icon:"󰆼",color:"#00758f"},sh:{icon:"󰆍",color:"#89e051"}};let w=!1;function S(){if(w||typeof document>"u")return;const t="react-beauty-link-nerd-fonts";if(document.getElementById(t)){w=!0;return}const c=document.createElement("style");c.id=t,c.textContent=`
2
- /* react-beauty-link: Nerd Font Symbols */
3
- @font-face {
4
- font-family: 'Symbols Nerd Font';
5
- src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');
6
- font-weight: normal;
7
- font-style: normal;
8
- font-display: swap;
9
- }
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),x=require("react"),v={pdf:{icon:"󰈦",color:"#e74856"},doc:{icon:"󰈬",color:"#2b579a"},docx:{icon:"󰈬",color:"#2b579a"},xls:{icon:"󰈛",color:"#207245"},xlsx:{icon:"󰈛",color:"#207245"},ppt:{icon:"󰈧",color:"#d24726"},pptx:{icon:"󰈧",color:"#d24726"},txt:{icon:"󰈙",color:"#6c757d"},zip:{icon:"󰗄",color:"#e89f1c"},rar:{icon:"󰗄",color:"#e89f1c"},"7z":{icon:"󰗄",color:"#e89f1c"},tar:{icon:"󰗄",color:"#e89f1c"},gz:{icon:"󰗄",color:"#e89f1c"},jpg:{icon:"󰈟",color:"#a855f7"},jpeg:{icon:"󰈟",color:"#a855f7"},png:{icon:"󰈟",color:"#a855f7"},gif:{icon:"󰈟",color:"#a855f7"},svg:{icon:"󰜡",color:"#f97316"},webp:{icon:"󰈟",color:"#a855f7"},mp4:{icon:"󰕧",color:"#ec4899"},avi:{icon:"󰕧",color:"#ec4899"},mov:{icon:"󰕧",color:"#ec4899"},mkv:{icon:"󰕧",color:"#ec4899"},webm:{icon:"󰕧",color:"#ec4899"},mp3:{icon:"󰈣",color:"#10b981"},wav:{icon:"󰈣",color:"#10b981"},flac:{icon:"󰈣",color:"#10b981"},ogg:{icon:"󰈣",color:"#10b981"},js:{icon:"󰌞",color:"#f0db4f"},ts:{icon:"󰛦",color:"#3178c6"},jsx:{icon:"󰜈",color:"#61dafb"},tsx:{icon:"󰜈",color:"#61dafb"},py:{icon:"󰌠",color:"#3776ab"},java:{icon:"󰬷",color:"#007396"},php:{icon:"󰌟",color:"#777bb4"},rb:{icon:"󰴭",color:"#cc342d"},go:{icon:"󰟓",color:"#00add8"},rs:{icon:"󱘗",color:"#dea584"},html:{icon:"󰌝",color:"#e34c26"},css:{icon:"󰌜",color:"#264de4"},json:{icon:"󰘦",color:"#f7df1e"},xml:{icon:"󰗀",color:"#ff6600"},yaml:{icon:"󰈙",color:"#cb171e"},yml:{icon:"󰈙",color:"#cb171e"},md:{icon:"󰍔",color:"#083fa1"},sql:{icon:"󰆼",color:"#00758f"},sh:{icon:"󰆍",color:"#89e051"}};let b=!1;function N(){if(typeof window>"u"||typeof document>"u"||b)return;const o="react-beauty-link-nerd-fonts";if(document.getElementById(o)){b=!0;return}try{const r=document.createElement("style");r.id=o,r.textContent=`
2
+ /* react-beauty-link: Nerd Font Symbols */
3
+ @font-face {
4
+ font-family: 'Symbols Nerd Font';
5
+ src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');
6
+ font-weight: normal;
7
+ font-style: normal;
8
+ font-display: swap;
9
+ }
10
10
 
11
- @font-face {
12
- font-family: 'Symbols Nerd Font Mono';
13
- src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');
14
- font-weight: normal;
15
- font-style: normal;
16
- font-display: swap;
17
- }
18
- `,document.head.appendChild(c),w=!0}function k(t){try{const l=new URL(t).pathname,s=l.lastIndexOf(".");return s===-1||s===l.length-1?null:l.substring(s+1).toLowerCase()}catch{return null}}const F=(t,c="new-tab",l)=>{const s=/(https:\/\/[^\s]+)/g,[h,p]=b.useState({}),g=Array.from(t.matchAll(s)).map(e=>e[0]);b.useEffect(()=>{S()},[]),b.useEffect(()=>{(async()=>{for(const o of g)if(!h[o]){const n=k(o);if(n&&v[n]){const i=o.split("/").pop()||o;p(d=>({...d,[o]:{title:decodeURIComponent(i),favicon:null}}));continue}try{console.log("Fetching metadata for:",o);const i=await C(o);console.log("Metadata received:",i),p(d=>({...d,[o]:i}))}catch(i){console.error("Failed to fetch metadata for",o,i),p(d=>({...d,[o]:{title:o,favicon:null}}))}}})()},[t,JSON.stringify(g)]);const r=[];let a=0,f;for(s.lastIndex=0;(f=s.exec(t))!==null;){const e=f[0],o=f.index;o>a&&r.push(t.substring(a,o));const n=h[e],i=n?.title?n.title.length>60?n.title.substring(0,60)+"...":n.title:e,d=n?.favicon,x=k(e),m=x?v[x]:null,j=()=>{switch(c){case"new-window":return{target:"_blank",rel:"noopener noreferrer",onClick:y=>{y.preventDefault(),window.open(e,"_blank","noopener,noreferrer,width=800,height=600")}};case"self":return{target:"_self"};default:return{target:"_blank",rel:"noopener noreferrer"}}};r.push(u.jsxs("a",{href:e,...j(),style:{color:l||"#646cff",textDecoration:"underline",display:"inline-flex",alignItems:"center",gap:"6px"},children:[m?u.jsx("span",{style:{fontFamily:'"Symbols Nerd Font Mono", "Symbols Nerd Font", "Nerd Font", "FiraCode Nerd Font", monospace',fontSize:"16px",color:m.color,lineHeight:1,display:"inline-block",width:"16px",textAlign:"center",fontWeight:"normal"},"aria-hidden":"true",children:m.icon}):d?u.jsx("img",{src:d,alt:"",style:{width:"16px",height:"16px"},onError:y=>{y.target.src='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"%3E%3Cpath d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/%3E%3Cpath d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/%3E%3C/svg%3E'}}):u.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"}),u.jsx("path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"})]}),u.jsx("span",{children:i})]},`link-${o}`)),a=o+e.length}return a<t.length&&r.push(t.substring(a)),r.length>0?r:[t]};async function C(t){try{const c=new URL(t),l=c.origin,s=[`https://api.allorigins.win/get?url=${encodeURIComponent(t)}`,`https://corsproxy.io/?${encodeURIComponent(t)}`];let h="",p=!1;for(const o of s)try{const n=await fetch(o,{signal:AbortSignal.timeout(1e4)});if(!n.ok)continue;const i=await n.json();h=i.contents||i,p=!0;break}catch(n){console.warn("Proxy failed:",o,n);continue}if(!p||!h)throw new Error("All proxies failed");const r=new DOMParser().parseFromString(h,"text/html");let a=r.querySelector('meta[property="og:title"]')?.getAttribute("content")||r.querySelector('meta[name="twitter:title"]')?.getAttribute("content")||r.querySelector("title")?.textContent||t;a=a.trim();let f=`https://www.google.com/s2/favicons?domain=${c.hostname}&sz=32`;const e=r.querySelector('link[rel="icon"]')?.getAttribute("href")||r.querySelector('link[rel="shortcut icon"]')?.getAttribute("href")||r.querySelector('link[rel="apple-touch-icon"]')?.getAttribute("href");return e&&(e.startsWith("http")?f=e:e.startsWith("//")?f="https:"+e:e.startsWith("/")?f=l+e:f=l+"/"+e),{title:a,favicon:f}}catch(c){console.error("Error fetching metadata:",c);const l=new URL(t);return{title:l.hostname,favicon:`https://www.google.com/s2/favicons?domain=${l.hostname}&sz=32`}}}exports.useBeautyLink=F;
11
+ @font-face {
12
+ font-family: 'Symbols Nerd Font Mono';
13
+ src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');
14
+ font-weight: normal;
15
+ font-style: normal;
16
+ font-display: swap;
17
+ }
18
+ `,document.head.appendChild(r),b=!0,typeof console<"u"&&console.debug&&console.debug("[react-beauty-link] Nerd Fonts loaded successfully")}catch(r){console.error("[react-beauty-link] Failed to load Nerd Fonts:",r)}}typeof window<"u"&&N();function k(o){try{const l=new URL(o).pathname,s=l.lastIndexOf(".");return s===-1||s===l.length-1?null:l.substring(s+1).toLowerCase()}catch{return null}}const S=(o,r="new-tab",l)=>{const s=/(https:\/\/[^\s]+)/g,[p,h]=x.useState({}),g=Array.from(o.matchAll(s)).map(t=>t[0]);x.useEffect(()=>{(async()=>{for(const e of g)if(!p[e]){const n=k(e);if(n&&v[n]){const i=e.split("/").pop()||e;h(f=>({...f,[e]:{title:decodeURIComponent(i),favicon:null}}));continue}try{const i=await E(e);process.env.NODE_ENV==="development"&&console.debug("[react-beauty-link] Metadata fetched:",e),h(f=>({...f,[e]:i}))}catch{process.env.NODE_ENV==="development"&&console.debug("[react-beauty-link] Using URL fallback for:",e),h(f=>({...f,[e]:{title:e,favicon:null}}))}}})()},[o,JSON.stringify(g)]);const c=[];let a=0,d;for(s.lastIndex=0;(d=s.exec(o))!==null;){const t=d[0],e=d.index;e>a&&c.push(o.substring(a,e));const n=p[t],i=n?.title?n.title.length>60?n.title.substring(0,60)+"...":n.title:t,f=n?.favicon,w=k(t),m=w?v[w]:null,j=()=>{switch(r){case"new-window":return{target:"_blank",rel:"noopener noreferrer",onClick:y=>{y.preventDefault(),window.open(t,"_blank","noopener,noreferrer,width=800,height=600")}};case"self":return{target:"_self"};default:return{target:"_blank",rel:"noopener noreferrer"}}};c.push(u.jsxs("a",{href:t,...j(),style:{color:l||"#646cff",textDecoration:"underline",display:"inline-flex",alignItems:"center",gap:"6px"},children:[m?u.jsx("span",{style:{fontFamily:'"Symbols Nerd Font Mono", "Symbols Nerd Font", "Nerd Font", "FiraCode Nerd Font", monospace',fontSize:"16px",color:m.color,lineHeight:1,display:"inline-block",width:"16px",textAlign:"center",fontWeight:"normal"},"aria-hidden":"true",children:m.icon}):f?u.jsx("img",{src:f,alt:"",style:{width:"16px",height:"16px"},onError:y=>{y.target.src='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"%3E%3Cpath d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/%3E%3Cpath d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/%3E%3C/svg%3E'}}):u.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"}),u.jsx("path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"})]}),u.jsx("span",{children:i})]},`link-${e}`)),a=e+t.length}return a<o.length&&c.push(o.substring(a)),c.length>0?c:[o]};async function E(o){try{const r=new URL(o),l=r.origin,s=[`https://api.allorigins.win/get?url=${encodeURIComponent(o)}`,`https://corsproxy.io/?${encodeURIComponent(o)}`,`https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(o)}`];let p="",h=!1;for(const e of s)try{const n=await fetch(e,{signal:AbortSignal.timeout(5e3)});if(!n.ok)continue;const i=await n.json();p=i.contents||i,h=!0;break}catch(n){if(process.env.NODE_ENV==="development"){const i=n instanceof Error?n.name:"Unknown error";console.debug("[react-beauty-link] Proxy failed:",e.split("?")[0],i)}continue}if(!h||!p)throw new Error("All proxies failed");const c=new DOMParser().parseFromString(p,"text/html");let a=c.querySelector('meta[property="og:title"]')?.getAttribute("content")||c.querySelector('meta[name="twitter:title"]')?.getAttribute("content")||c.querySelector("title")?.textContent||o;a=a.trim();let d=`https://www.google.com/s2/favicons?domain=${r.hostname}&sz=32`;const t=c.querySelector('link[rel="icon"]')?.getAttribute("href")||c.querySelector('link[rel="shortcut icon"]')?.getAttribute("href")||c.querySelector('link[rel="apple-touch-icon"]')?.getAttribute("href");return t&&(t.startsWith("http")?d=t:t.startsWith("//")?d="https:"+t:t.startsWith("/")?d=l+t:d=l+"/"+t),{title:a,favicon:d}}catch{process.env.NODE_ENV==="development"&&console.debug("[react-beauty-link] Metadata fetch failed, using fallback");const l=new URL(o);return{title:l.hostname,favicon:`https://www.google.com/s2/favicons?domain=${l.hostname}&sz=32`}}}exports.loadNerdFonts=N;exports.useBeautyLink=S;
19
19
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils/fileIcons.ts","../src/utils/loadNerdFonts.ts","../src/hooks/useBeautyLink.tsx"],"sourcesContent":["interface FileTypeIcon {\n icon: string;\n color: string;\n }\n\nexport const FILE_TYPE_ICONS: Record<string, FileTypeIcon> = {\n // Documents\n 'pdf': { icon: '󰈦', color: '#e74856' },\n 'doc': { icon: '󰈬', color: '#2b579a' },\n 'docx': { icon: '󰈬', color: '#2b579a' },\n 'xls': { icon: '󰈛', color: '#207245' },\n 'xlsx': { icon: '󰈛', color: '#207245' },\n 'ppt': { icon: '󰈧', color: '#d24726' },\n 'pptx': { icon: '󰈧', color: '#d24726' },\n 'txt': { icon: '󰈙', color: '#6c757d' },\n \n // Archives\n 'zip': { icon: '󰗄', color: '#e89f1c' },\n 'rar': { icon: '󰗄', color: '#e89f1c' },\n '7z': { icon: '󰗄', color: '#e89f1c' },\n 'tar': { icon: '󰗄', color: '#e89f1c' },\n 'gz': { icon: '󰗄', color: '#e89f1c' },\n \n // Images\n 'jpg': { icon: '󰈟', color: '#a855f7' },\n 'jpeg': { icon: '󰈟', color: '#a855f7' },\n 'png': { icon: '󰈟', color: '#a855f7' },\n 'gif': { icon: '󰈟', color: '#a855f7' },\n 'svg': { icon: '󰜡', color: '#f97316' },\n 'webp': { icon: '󰈟', color: '#a855f7' },\n \n // Videos\n 'mp4': { icon: '󰕧', color: '#ec4899' },\n 'avi': { icon: '󰕧', color: '#ec4899' },\n 'mov': { icon: '󰕧', color: '#ec4899' },\n 'mkv': { icon: '󰕧', color: '#ec4899' },\n 'webm': { icon: '󰕧', color: '#ec4899' },\n \n // Audio\n 'mp3': { icon: '󰈣', color: '#10b981' },\n 'wav': { icon: '󰈣', color: '#10b981' },\n 'flac': { icon: '󰈣', color: '#10b981' },\n 'ogg': { icon: '󰈣', color: '#10b981' },\n \n // Code\n 'js': { icon: '󰌞', color: '#f0db4f' },\n 'ts': { icon: '󰛦', color: '#3178c6' },\n 'jsx': { icon: '󰜈', color: '#61dafb' },\n 'tsx': { icon: '󰜈', color: '#61dafb' },\n 'py': { icon: '󰌠', color: '#3776ab' },\n 'java': { icon: '󰬷', color: '#007396' },\n 'php': { icon: '󰌟', color: '#777bb4' },\n 'rb': { icon: '󰴭', color: '#cc342d' },\n 'go': { icon: '󰟓', color: '#00add8' },\n 'rs': { icon: '󱘗', color: '#dea584' },\n 'html': { icon: '󰌝', color: '#e34c26' },\n 'css': { icon: '󰌜', color: '#264de4' },\n 'json': { icon: '󰘦', color: '#f7df1e' },\n 'xml': { icon: '󰗀', color: '#ff6600' },\n 'yaml': { icon: '󰈙', color: '#cb171e' },\n 'yml': { icon: '󰈙', color: '#cb171e' },\n 'md': { icon: '󰍔', color: '#083fa1' },\n 'sql': { icon: '󰆼', color: '#00758f' },\n 'sh': { icon: '󰆍', color: '#89e051' },\n };","// Load Nerd Fonts dynamically for file type icons\nlet fontsLoaded = false;\n\nexport function loadNerdFonts() {\n // Only inject once\n if (fontsLoaded || typeof document === 'undefined') {\n return;\n }\n\n const styleId = 'react-beauty-link-nerd-fonts';\n \n // Check if already injected\n if (document.getElementById(styleId)) {\n fontsLoaded = true;\n return;\n }\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n /* react-beauty-link: Nerd Font Symbols */\n @font-face {\n font-family: 'Symbols Nerd Font';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n\n @font-face {\n font-family: 'Symbols Nerd Font Mono';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n `;\n\n document.head.appendChild(style);\n fontsLoaded = true;\n}\n","import { useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport { FILE_TYPE_ICONS } from '../utils/fileIcons';\nimport { loadNerdFonts } from '../utils/loadNerdFonts';\n\ninterface LinkMetadata {\n title: string;\n favicon: string | null;\n}\n\nexport type LinkTarget = 'new-tab' | 'new-window' | 'self';\n\n\nfunction getFileExtension(url: string): string | null {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n const lastDot = pathname.lastIndexOf('.');\n if (lastDot === -1 || lastDot === pathname.length - 1) return null;\n return pathname.substring(lastDot + 1).toLowerCase();\n } catch {\n return null;\n }\n}\n\n/**\n * Custom hook that converts HTTPS URLs in a string into clickable links\n * with page titles and favicons\n * @param text - The input string containing potential URLs\n * @param target - How to open links: 'new-tab' (default), 'new-window', or 'self'\n * @returns An array of React nodes with text and links\n */\nexport const useBeautyLink = (text: string, target: LinkTarget = 'new-tab', customColor?: string): ReactNode[] => {\n const urlRegex = /(https:\\/\\/[^\\s]+)/g;\n const [linkMetadata, setLinkMetadata] = useState<Record<string, LinkMetadata>>({});\n \n const urls = Array.from(text.matchAll(urlRegex)).map(match => match[0]);\n\n // Load Nerd Fonts once when hook is first used\n useEffect(() => {\n loadNerdFonts();\n }, []);\n\n useEffect(() => {\n const fetchAllMetadata = async () => {\n for (const url of urls) {\n if (!linkMetadata[url]) {\n const extension = getFileExtension(url);\n \n // If it's a file URL, skip metadata fetching and use filename\n if (extension && FILE_TYPE_ICONS[extension]) {\n const filename = url.split('/').pop() || url;\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: decodeURIComponent(filename),\n favicon: null\n }\n }));\n continue;\n }\n \n try {\n console.log('Fetching metadata for:', url);\n const metadata = await fetchLinkMetadata(url);\n console.log('Metadata received:', metadata);\n setLinkMetadata(prev => ({\n ...prev,\n [url]: metadata\n }));\n } catch (error) {\n console.error('Failed to fetch metadata for', url, error);\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: url,\n favicon: null\n }\n }));\n }\n }\n }\n };\n\n fetchAllMetadata();\n }, [text, JSON.stringify(urls)]);\n\n const parts: ReactNode[] = [];\n let lastIndex = 0;\n let match;\n\n urlRegex.lastIndex = 0;\n while ((match = urlRegex.exec(text)) !== null) {\n const url = match[0];\n const startIndex = match.index;\n\n if (startIndex > lastIndex) {\n parts.push(text.substring(lastIndex, startIndex));\n }\n\n const metadata = linkMetadata[url];\n const displayTitle = metadata?.title \n ? (metadata.title.length > 60 ? metadata.title.substring(0, 60) + '...' : metadata.title)\n : url;\n \n const faviconUrl = metadata?.favicon;\n const extension = getFileExtension(url);\n const fileIcon = extension ? FILE_TYPE_ICONS[extension] : null;\n\n const getTargetAttributes = () => {\n switch (target) {\n case 'new-window':\n return {\n target: '_blank',\n rel: 'noopener noreferrer',\n onClick: (e: React.MouseEvent) => {\n e.preventDefault();\n window.open(url, '_blank', 'noopener,noreferrer,width=800,height=600');\n }\n };\n case 'self':\n return {\n target: '_self'\n };\n case 'new-tab':\n default:\n return {\n target: '_blank',\n rel: 'noopener noreferrer'\n };\n }\n };\n\n parts.push(\n <a\n key={`link-${startIndex}`}\n href={url}\n {...getTargetAttributes()}\n style={{ \n color: customColor || '#646cff', \n textDecoration: 'underline',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px'\n }}\n >\n {fileIcon ? (\n <span \n style={{ \n fontFamily: '\"Symbols Nerd Font Mono\", \"Symbols Nerd Font\", \"Nerd Font\", \"FiraCode Nerd Font\", monospace',\n fontSize: '16px',\n color: fileIcon.color,\n lineHeight: 1,\n display: 'inline-block',\n width: '16px',\n textAlign: 'center',\n fontWeight: 'normal'\n }}\n aria-hidden=\"true\"\n >\n {fileIcon.icon}\n </span>\n ) : faviconUrl ? (\n <img \n src={faviconUrl} \n alt=\"\" \n style={{ width: '16px', height: '16px' }}\n onError={(e) => {\n (e.target as HTMLImageElement).src = 'data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"%3E%3Cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/%3E%3Cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/%3E%3C/svg%3E';\n }}\n />\n ) : (\n <svg \n xmlns=\"http://www.w3.org/2000/svg\" \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n stroke=\"currentColor\" \n strokeWidth=\"2\" \n strokeLinecap=\"round\" \n strokeLinejoin=\"round\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/>\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>\n </svg>\n )}\n <span>{displayTitle}</span>\n </a>\n );\n\n lastIndex = startIndex + url.length;\n }\n\n if (lastIndex < text.length) {\n parts.push(text.substring(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n};\n\n/**\n * Fetches metadata (title and favicon) for a given URL\n */\nasync function fetchLinkMetadata(url: string): Promise<LinkMetadata> {\n try {\n const urlObj = new URL(url);\n const origin = urlObj.origin;\n \n const proxies = [\n `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`,\n `https://corsproxy.io/?${encodeURIComponent(url)}`,\n ];\n \n let html = '';\n let success = false;\n \n for (const proxyUrl of proxies) {\n try {\n const response = await fetch(proxyUrl, { \n signal: AbortSignal.timeout(10000) // 10 second timeout\n });\n \n if (!response.ok) continue;\n \n const data = await response.json();\n html = data.contents || data;\n success = true;\n break;\n } catch (err) {\n console.warn('Proxy failed:', proxyUrl, err);\n continue;\n }\n }\n \n if (!success || !html) {\n throw new Error('All proxies failed');\n }\n \n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n \n let title = \n doc.querySelector('meta[property=\"og:title\"]')?.getAttribute('content') ||\n doc.querySelector('meta[name=\"twitter:title\"]')?.getAttribute('content') ||\n doc.querySelector('title')?.textContent ||\n url;\n \n title = title.trim();\n \n let favicon = `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`;\n \n const faviconLink = \n doc.querySelector('link[rel=\"icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"shortcut icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"apple-touch-icon\"]')?.getAttribute('href');\n \n if (faviconLink) {\n if (faviconLink.startsWith('http')) {\n favicon = faviconLink;\n } else if (faviconLink.startsWith('//')) {\n favicon = 'https:' + faviconLink;\n } else if (faviconLink.startsWith('/')) {\n favicon = origin + faviconLink;\n } else {\n favicon = origin + '/' + faviconLink;\n }\n }\n \n return { title, favicon };\n } catch (error) {\n console.error('Error fetching metadata:', error);\n const urlObj = new URL(url);\n return {\n title: urlObj.hostname,\n favicon: `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`\n };\n }\n}\n"],"names":["FILE_TYPE_ICONS","fontsLoaded","loadNerdFonts","styleId","style","getFileExtension","url","pathname","lastDot","useBeautyLink","text","target","customColor","urlRegex","linkMetadata","setLinkMetadata","useState","urls","match","useEffect","extension","filename","prev","metadata","fetchLinkMetadata","error","parts","lastIndex","startIndex","displayTitle","faviconUrl","fileIcon","getTargetAttributes","e","jsxs","jsx","urlObj","origin","proxies","html","success","proxyUrl","response","data","err","doc","title","favicon","faviconLink"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/fileIcons.ts","../src/utils/loadNerdFonts.ts","../src/hooks/useBeautyLink.tsx"],"sourcesContent":["interface FileTypeIcon {\n icon: string;\n color: string;\n }\n\nexport const FILE_TYPE_ICONS: Record<string, FileTypeIcon> = {\n // Documents\n 'pdf': { icon: '󰈦', color: '#e74856' },\n 'doc': { icon: '󰈬', color: '#2b579a' },\n 'docx': { icon: '󰈬', color: '#2b579a' },\n 'xls': { icon: '󰈛', color: '#207245' },\n 'xlsx': { icon: '󰈛', color: '#207245' },\n 'ppt': { icon: '󰈧', color: '#d24726' },\n 'pptx': { icon: '󰈧', color: '#d24726' },\n 'txt': { icon: '󰈙', color: '#6c757d' },\n \n // Archives\n 'zip': { icon: '󰗄', color: '#e89f1c' },\n 'rar': { icon: '󰗄', color: '#e89f1c' },\n '7z': { icon: '󰗄', color: '#e89f1c' },\n 'tar': { icon: '󰗄', color: '#e89f1c' },\n 'gz': { icon: '󰗄', color: '#e89f1c' },\n \n // Images\n 'jpg': { icon: '󰈟', color: '#a855f7' },\n 'jpeg': { icon: '󰈟', color: '#a855f7' },\n 'png': { icon: '󰈟', color: '#a855f7' },\n 'gif': { icon: '󰈟', color: '#a855f7' },\n 'svg': { icon: '󰜡', color: '#f97316' },\n 'webp': { icon: '󰈟', color: '#a855f7' },\n \n // Videos\n 'mp4': { icon: '󰕧', color: '#ec4899' },\n 'avi': { icon: '󰕧', color: '#ec4899' },\n 'mov': { icon: '󰕧', color: '#ec4899' },\n 'mkv': { icon: '󰕧', color: '#ec4899' },\n 'webm': { icon: '󰕧', color: '#ec4899' },\n \n // Audio\n 'mp3': { icon: '󰈣', color: '#10b981' },\n 'wav': { icon: '󰈣', color: '#10b981' },\n 'flac': { icon: '󰈣', color: '#10b981' },\n 'ogg': { icon: '󰈣', color: '#10b981' },\n \n // Code\n 'js': { icon: '󰌞', color: '#f0db4f' },\n 'ts': { icon: '󰛦', color: '#3178c6' },\n 'jsx': { icon: '󰜈', color: '#61dafb' },\n 'tsx': { icon: '󰜈', color: '#61dafb' },\n 'py': { icon: '󰌠', color: '#3776ab' },\n 'java': { icon: '󰬷', color: '#007396' },\n 'php': { icon: '󰌟', color: '#777bb4' },\n 'rb': { icon: '󰴭', color: '#cc342d' },\n 'go': { icon: '󰟓', color: '#00add8' },\n 'rs': { icon: '󱘗', color: '#dea584' },\n 'html': { icon: '󰌝', color: '#e34c26' },\n 'css': { icon: '󰌜', color: '#264de4' },\n 'json': { icon: '󰘦', color: '#f7df1e' },\n 'xml': { icon: '󰗀', color: '#ff6600' },\n 'yaml': { icon: '󰈙', color: '#cb171e' },\n 'yml': { icon: '󰈙', color: '#cb171e' },\n 'md': { icon: '󰍔', color: '#083fa1' },\n 'sql': { icon: '󰆼', color: '#00758f' },\n 'sh': { icon: '󰆍', color: '#89e051' },\n };","// Load Nerd Fonts dynamically for file type icons\nlet fontsLoaded = false;\n\nexport function loadNerdFonts() {\n // SSR check\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n // Only inject once\n if (fontsLoaded) {\n return;\n }\n\n const styleId = 'react-beauty-link-nerd-fonts';\n \n // Check if already injected\n if (document.getElementById(styleId)) {\n fontsLoaded = true;\n return;\n }\n\n try {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n /* react-beauty-link: Nerd Font Symbols */\n @font-face {\n font-family: 'Symbols Nerd Font';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n\n @font-face {\n font-family: 'Symbols Nerd Font Mono';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n `;\n\n document.head.appendChild(style);\n fontsLoaded = true;\n \n // Debug log (can be removed in production)\n if (typeof console !== 'undefined' && console.debug) {\n console.debug('[react-beauty-link] Nerd Fonts loaded successfully');\n }\n } catch (error) {\n console.error('[react-beauty-link] Failed to load Nerd Fonts:', error);\n }\n}\n","import { useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport { FILE_TYPE_ICONS } from '../utils/fileIcons';\nimport { loadNerdFonts } from '../utils/loadNerdFonts';\n\n// Load fonts immediately when module is imported (browser only, one-time)\nif (typeof window !== 'undefined') {\n loadNerdFonts();\n}\n\ninterface LinkMetadata {\n title: string;\n favicon: string | null;\n}\n\nexport type LinkTarget = 'new-tab' | 'new-window' | 'self';\n\n\nfunction getFileExtension(url: string): string | null {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n const lastDot = pathname.lastIndexOf('.');\n if (lastDot === -1 || lastDot === pathname.length - 1) return null;\n return pathname.substring(lastDot + 1).toLowerCase();\n } catch {\n return null;\n }\n}\n\n/**\n * Custom hook that converts HTTPS URLs in a string into clickable links\n * with page titles and favicons\n * @param text - The input string containing potential URLs\n * @param target - How to open links: 'new-tab' (default), 'new-window', or 'self'\n * @param customColor - Custom color for links (optional)\n * @returns An array of React nodes with text and links\n */\nexport const useBeautyLink = (text: string, target: LinkTarget = 'new-tab', customColor?: string): ReactNode[] => {\n const urlRegex = /(https:\\/\\/[^\\s]+)/g;\n const [linkMetadata, setLinkMetadata] = useState<Record<string, LinkMetadata>>({});\n \n const urls = Array.from(text.matchAll(urlRegex)).map(match => match[0]);\n\n useEffect(() => {\n const fetchAllMetadata = async () => {\n for (const url of urls) {\n if (!linkMetadata[url]) {\n const extension = getFileExtension(url);\n \n // If it's a file URL, skip metadata fetching and use filename\n if (extension && FILE_TYPE_ICONS[extension]) {\n const filename = url.split('/').pop() || url;\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: decodeURIComponent(filename),\n favicon: null\n }\n }));\n continue;\n }\n \n try {\n const metadata = await fetchLinkMetadata(url);\n if (process.env.NODE_ENV === 'development') {\n console.debug('[react-beauty-link] Metadata fetched:', url);\n }\n setLinkMetadata(prev => ({\n ...prev,\n [url]: metadata\n }));\n } catch (error) {\n // Silently fall back to URL - this is expected behavior\n if (process.env.NODE_ENV === 'development') {\n console.debug('[react-beauty-link] Using URL fallback for:', url);\n }\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: url,\n favicon: null\n }\n }));\n }\n }\n }\n };\n\n fetchAllMetadata();\n }, [text, JSON.stringify(urls)]);\n\n const parts: ReactNode[] = [];\n let lastIndex = 0;\n let match;\n\n urlRegex.lastIndex = 0;\n while ((match = urlRegex.exec(text)) !== null) {\n const url = match[0];\n const startIndex = match.index;\n\n if (startIndex > lastIndex) {\n parts.push(text.substring(lastIndex, startIndex));\n }\n\n const metadata = linkMetadata[url];\n const displayTitle = metadata?.title \n ? (metadata.title.length > 60 ? metadata.title.substring(0, 60) + '...' : metadata.title)\n : url;\n \n const faviconUrl = metadata?.favicon;\n const extension = getFileExtension(url);\n const fileIcon = extension ? FILE_TYPE_ICONS[extension] : null;\n\n const getTargetAttributes = () => {\n switch (target) {\n case 'new-window':\n return {\n target: '_blank',\n rel: 'noopener noreferrer',\n onClick: (e: React.MouseEvent) => {\n e.preventDefault();\n window.open(url, '_blank', 'noopener,noreferrer,width=800,height=600');\n }\n };\n case 'self':\n return {\n target: '_self'\n };\n case 'new-tab':\n default:\n return {\n target: '_blank',\n rel: 'noopener noreferrer'\n };\n }\n };\n\n parts.push(\n <a\n key={`link-${startIndex}`}\n href={url}\n {...getTargetAttributes()}\n style={{ \n color: customColor || '#646cff', \n textDecoration: 'underline',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px'\n }}\n >\n {fileIcon ? (\n <span \n style={{ \n fontFamily: '\"Symbols Nerd Font Mono\", \"Symbols Nerd Font\", \"Nerd Font\", \"FiraCode Nerd Font\", monospace',\n fontSize: '16px',\n color: fileIcon.color,\n lineHeight: 1,\n display: 'inline-block',\n width: '16px',\n textAlign: 'center',\n fontWeight: 'normal'\n }}\n aria-hidden=\"true\"\n >\n {fileIcon.icon}\n </span>\n ) : faviconUrl ? (\n <img \n src={faviconUrl} \n alt=\"\" \n style={{ width: '16px', height: '16px' }}\n onError={(e) => {\n (e.target as HTMLImageElement).src = 'data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"%3E%3Cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/%3E%3Cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/%3E%3C/svg%3E';\n }}\n />\n ) : (\n <svg \n xmlns=\"http://www.w3.org/2000/svg\" \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n stroke=\"currentColor\" \n strokeWidth=\"2\" \n strokeLinecap=\"round\" \n strokeLinejoin=\"round\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/>\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>\n </svg>\n )}\n <span>{displayTitle}</span>\n </a>\n );\n\n lastIndex = startIndex + url.length;\n }\n\n if (lastIndex < text.length) {\n parts.push(text.substring(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n};\n\n/**\n * Fetches metadata (title and favicon) for a given URL\n */\nasync function fetchLinkMetadata(url: string): Promise<LinkMetadata> {\n try {\n const urlObj = new URL(url);\n const origin = urlObj.origin;\n \n const proxies = [\n `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`,\n `https://corsproxy.io/?${encodeURIComponent(url)}`,\n `https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(url)}`,\n ];\n \n let html = '';\n let success = false;\n \n for (const proxyUrl of proxies) {\n try {\n const response = await fetch(proxyUrl, { \n signal: AbortSignal.timeout(5000) // 5 second timeout (faster failover)\n });\n \n if (!response.ok) continue;\n \n const data = await response.json();\n html = data.contents || data;\n success = true;\n break;\n } catch (err) {\n // Only log in development mode to reduce console noise\n if (process.env.NODE_ENV === 'development') {\n const errorName = err instanceof Error ? err.name : 'Unknown error';\n console.debug('[react-beauty-link] Proxy failed:', proxyUrl.split('?')[0], errorName);\n }\n continue;\n }\n }\n \n if (!success || !html) {\n throw new Error('All proxies failed');\n }\n \n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n \n let title = \n doc.querySelector('meta[property=\"og:title\"]')?.getAttribute('content') ||\n doc.querySelector('meta[name=\"twitter:title\"]')?.getAttribute('content') ||\n doc.querySelector('title')?.textContent ||\n url;\n \n title = title.trim();\n \n let favicon = `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`;\n \n const faviconLink = \n doc.querySelector('link[rel=\"icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"shortcut icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"apple-touch-icon\"]')?.getAttribute('href');\n \n if (faviconLink) {\n if (faviconLink.startsWith('http')) {\n favicon = faviconLink;\n } else if (faviconLink.startsWith('//')) {\n favicon = 'https:' + faviconLink;\n } else if (faviconLink.startsWith('/')) {\n favicon = origin + faviconLink;\n } else {\n favicon = origin + '/' + faviconLink;\n }\n }\n \n return { title, favicon };\n } catch (error) {\n // Graceful fallback - use hostname and Google favicon service\n if (process.env.NODE_ENV === 'development') {\n console.debug('[react-beauty-link] Metadata fetch failed, using fallback');\n }\n const urlObj = new URL(url);\n return {\n title: urlObj.hostname,\n favicon: `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`\n };\n }\n}\n"],"names":["FILE_TYPE_ICONS","fontsLoaded","loadNerdFonts","styleId","style","error","getFileExtension","url","pathname","lastDot","useBeautyLink","text","target","customColor","urlRegex","linkMetadata","setLinkMetadata","useState","urls","match","useEffect","extension","filename","prev","metadata","fetchLinkMetadata","parts","lastIndex","startIndex","displayTitle","faviconUrl","fileIcon","getTargetAttributes","e","jsxs","jsx","urlObj","origin","proxies","html","success","proxyUrl","response","data","err","errorName","doc","title","favicon","faviconLink"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { useBeautyLink, type LinkTarget } from './hooks/useBeautyLink';
2
+ export { loadNerdFonts } from './utils/loadNerdFonts';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { jsxs as x, jsx as u } from "react/jsx-runtime";
2
- import { useState as j, useEffect as v } from "react";
3
- const k = {
1
+ import { jsxs as x, jsx as h } from "react/jsx-runtime";
2
+ import { useState as E, useEffect as S } from "react";
3
+ const v = {
4
4
  // Documents
5
5
  pdf: { icon: "󰈦", color: "#e74856" },
6
6
  doc: { icon: "󰈬", color: "#2b579a" },
@@ -55,57 +55,60 @@ const k = {
55
55
  sql: { icon: "󰆼", color: "#00758f" },
56
56
  sh: { icon: "󰆍", color: "#89e051" }
57
57
  };
58
- let w = !1;
59
- function C() {
60
- if (w || typeof document > "u")
58
+ let b = !1;
59
+ function F() {
60
+ if (typeof window > "u" || typeof document > "u" || b)
61
61
  return;
62
- const t = "react-beauty-link-nerd-fonts";
63
- if (document.getElementById(t)) {
64
- w = !0;
62
+ const o = "react-beauty-link-nerd-fonts";
63
+ if (document.getElementById(o)) {
64
+ b = !0;
65
65
  return;
66
66
  }
67
- const c = document.createElement("style");
68
- c.id = t, c.textContent = `
69
- /* react-beauty-link: Nerd Font Symbols */
70
- @font-face {
71
- font-family: 'Symbols Nerd Font';
72
- src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');
73
- font-weight: normal;
74
- font-style: normal;
75
- font-display: swap;
76
- }
67
+ try {
68
+ const r = document.createElement("style");
69
+ r.id = o, r.textContent = `
70
+ /* react-beauty-link: Nerd Font Symbols */
71
+ @font-face {
72
+ font-family: 'Symbols Nerd Font';
73
+ src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');
74
+ font-weight: normal;
75
+ font-style: normal;
76
+ font-display: swap;
77
+ }
77
78
 
78
- @font-face {
79
- font-family: 'Symbols Nerd Font Mono';
80
- src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');
81
- font-weight: normal;
82
- font-style: normal;
83
- font-display: swap;
84
- }
85
- `, document.head.appendChild(c), w = !0;
79
+ @font-face {
80
+ font-family: 'Symbols Nerd Font Mono';
81
+ src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');
82
+ font-weight: normal;
83
+ font-style: normal;
84
+ font-display: swap;
85
+ }
86
+ `, document.head.appendChild(r), b = !0, typeof console < "u" && console.debug && console.debug("[react-beauty-link] Nerd Fonts loaded successfully");
87
+ } catch (r) {
88
+ console.error("[react-beauty-link] Failed to load Nerd Fonts:", r);
89
+ }
86
90
  }
87
- function S(t) {
91
+ typeof window < "u" && F();
92
+ function k(o) {
88
93
  try {
89
- const l = new URL(t).pathname, a = l.lastIndexOf(".");
90
- return a === -1 || a === l.length - 1 ? null : l.substring(a + 1).toLowerCase();
94
+ const l = new URL(o).pathname, s = l.lastIndexOf(".");
95
+ return s === -1 || s === l.length - 1 ? null : l.substring(s + 1).toLowerCase();
91
96
  } catch {
92
97
  return null;
93
98
  }
94
99
  }
95
- const E = (t, c = "new-tab", l) => {
96
- const a = /(https:\/\/[^\s]+)/g, [p, h] = j({}), m = Array.from(t.matchAll(a)).map((e) => e[0]);
97
- v(() => {
98
- C();
99
- }, []), v(() => {
100
+ const I = (o, r = "new-tab", l) => {
101
+ const s = /(https:\/\/[^\s]+)/g, [p, u] = E({}), m = Array.from(o.matchAll(s)).map((t) => t[0]);
102
+ S(() => {
100
103
  (async () => {
101
- for (const o of m)
102
- if (!p[o]) {
103
- const n = S(o);
104
- if (n && k[n]) {
105
- const i = o.split("/").pop() || o;
106
- h((d) => ({
107
- ...d,
108
- [o]: {
104
+ for (const e of m)
105
+ if (!p[e]) {
106
+ const n = k(e);
107
+ if (n && v[n]) {
108
+ const i = e.split("/").pop() || e;
109
+ u((f) => ({
110
+ ...f,
111
+ [e]: {
109
112
  title: decodeURIComponent(i),
110
113
  favicon: null
111
114
  }
@@ -113,37 +116,36 @@ const E = (t, c = "new-tab", l) => {
113
116
  continue;
114
117
  }
115
118
  try {
116
- console.log("Fetching metadata for:", o);
117
- const i = await M(o);
118
- console.log("Metadata received:", i), h((d) => ({
119
- ...d,
120
- [o]: i
119
+ const i = await j(e);
120
+ process.env.NODE_ENV === "development" && console.debug("[react-beauty-link] Metadata fetched:", e), u((f) => ({
121
+ ...f,
122
+ [e]: i
121
123
  }));
122
- } catch (i) {
123
- console.error("Failed to fetch metadata for", o, i), h((d) => ({
124
- ...d,
125
- [o]: {
126
- title: o,
124
+ } catch {
125
+ process.env.NODE_ENV === "development" && console.debug("[react-beauty-link] Using URL fallback for:", e), u((f) => ({
126
+ ...f,
127
+ [e]: {
128
+ title: e,
127
129
  favicon: null
128
130
  }
129
131
  }));
130
132
  }
131
133
  }
132
134
  })();
133
- }, [t, JSON.stringify(m)]);
134
- const r = [];
135
- let s = 0, f;
136
- for (a.lastIndex = 0; (f = a.exec(t)) !== null; ) {
137
- const e = f[0], o = f.index;
138
- o > s && r.push(t.substring(s, o));
139
- const n = p[e], i = n?.title ? n.title.length > 60 ? n.title.substring(0, 60) + "..." : n.title : e, d = n?.favicon, b = S(e), g = b ? k[b] : null, F = () => {
140
- switch (c) {
135
+ }, [o, JSON.stringify(m)]);
136
+ const c = [];
137
+ let a = 0, d;
138
+ for (s.lastIndex = 0; (d = s.exec(o)) !== null; ) {
139
+ const t = d[0], e = d.index;
140
+ e > a && c.push(o.substring(a, e));
141
+ const n = p[t], i = n?.title ? n.title.length > 60 ? n.title.substring(0, 60) + "..." : n.title : t, f = n?.favicon, w = k(t), g = w ? v[w] : null, N = () => {
142
+ switch (r) {
141
143
  case "new-window":
142
144
  return {
143
145
  target: "_blank",
144
146
  rel: "noopener noreferrer",
145
147
  onClick: (y) => {
146
- y.preventDefault(), window.open(e, "_blank", "noopener,noreferrer,width=800,height=600");
148
+ y.preventDefault(), window.open(t, "_blank", "noopener,noreferrer,width=800,height=600");
147
149
  }
148
150
  };
149
151
  case "self":
@@ -157,12 +159,12 @@ const E = (t, c = "new-tab", l) => {
157
159
  };
158
160
  }
159
161
  };
160
- r.push(
162
+ c.push(
161
163
  /* @__PURE__ */ x(
162
164
  "a",
163
165
  {
164
- href: e,
165
- ...F(),
166
+ href: t,
167
+ ...N(),
166
168
  style: {
167
169
  color: l || "#646cff",
168
170
  textDecoration: "underline",
@@ -171,7 +173,7 @@ const E = (t, c = "new-tab", l) => {
171
173
  gap: "6px"
172
174
  },
173
175
  children: [
174
- g ? /* @__PURE__ */ u(
176
+ g ? /* @__PURE__ */ h(
175
177
  "span",
176
178
  {
177
179
  style: {
@@ -187,10 +189,10 @@ const E = (t, c = "new-tab", l) => {
187
189
  "aria-hidden": "true",
188
190
  children: g.icon
189
191
  }
190
- ) : d ? /* @__PURE__ */ u(
192
+ ) : f ? /* @__PURE__ */ h(
191
193
  "img",
192
194
  {
193
- src: d,
195
+ src: f,
194
196
  alt: "",
195
197
  style: { width: "16px", height: "16px" },
196
198
  onError: (y) => {
@@ -210,52 +212,56 @@ const E = (t, c = "new-tab", l) => {
210
212
  strokeLinecap: "round",
211
213
  strokeLinejoin: "round",
212
214
  children: [
213
- /* @__PURE__ */ u("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
214
- /* @__PURE__ */ u("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
215
+ /* @__PURE__ */ h("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
216
+ /* @__PURE__ */ h("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
215
217
  ]
216
218
  }
217
219
  ),
218
- /* @__PURE__ */ u("span", { children: i })
220
+ /* @__PURE__ */ h("span", { children: i })
219
221
  ]
220
222
  },
221
- `link-${o}`
223
+ `link-${e}`
222
224
  )
223
- ), s = o + e.length;
225
+ ), a = e + t.length;
224
226
  }
225
- return s < t.length && r.push(t.substring(s)), r.length > 0 ? r : [t];
227
+ return a < o.length && c.push(o.substring(a)), c.length > 0 ? c : [o];
226
228
  };
227
- async function M(t) {
229
+ async function j(o) {
228
230
  try {
229
- const c = new URL(t), l = c.origin, a = [
230
- `https://api.allorigins.win/get?url=${encodeURIComponent(t)}`,
231
- `https://corsproxy.io/?${encodeURIComponent(t)}`
231
+ const r = new URL(o), l = r.origin, s = [
232
+ `https://api.allorigins.win/get?url=${encodeURIComponent(o)}`,
233
+ `https://corsproxy.io/?${encodeURIComponent(o)}`,
234
+ `https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(o)}`
232
235
  ];
233
- let p = "", h = !1;
234
- for (const o of a)
236
+ let p = "", u = !1;
237
+ for (const e of s)
235
238
  try {
236
- const n = await fetch(o, {
237
- signal: AbortSignal.timeout(1e4)
238
- // 10 second timeout
239
+ const n = await fetch(e, {
240
+ signal: AbortSignal.timeout(5e3)
241
+ // 5 second timeout (faster failover)
239
242
  });
240
243
  if (!n.ok) continue;
241
244
  const i = await n.json();
242
- p = i.contents || i, h = !0;
245
+ p = i.contents || i, u = !0;
243
246
  break;
244
247
  } catch (n) {
245
- console.warn("Proxy failed:", o, n);
248
+ if (process.env.NODE_ENV === "development") {
249
+ const i = n instanceof Error ? n.name : "Unknown error";
250
+ console.debug("[react-beauty-link] Proxy failed:", e.split("?")[0], i);
251
+ }
246
252
  continue;
247
253
  }
248
- if (!h || !p)
254
+ if (!u || !p)
249
255
  throw new Error("All proxies failed");
250
- const r = new DOMParser().parseFromString(p, "text/html");
251
- let s = r.querySelector('meta[property="og:title"]')?.getAttribute("content") || r.querySelector('meta[name="twitter:title"]')?.getAttribute("content") || r.querySelector("title")?.textContent || t;
252
- s = s.trim();
253
- let f = `https://www.google.com/s2/favicons?domain=${c.hostname}&sz=32`;
254
- const e = r.querySelector('link[rel="icon"]')?.getAttribute("href") || r.querySelector('link[rel="shortcut icon"]')?.getAttribute("href") || r.querySelector('link[rel="apple-touch-icon"]')?.getAttribute("href");
255
- return e && (e.startsWith("http") ? f = e : e.startsWith("//") ? f = "https:" + e : e.startsWith("/") ? f = l + e : f = l + "/" + e), { title: s, favicon: f };
256
- } catch (c) {
257
- console.error("Error fetching metadata:", c);
258
- const l = new URL(t);
256
+ const c = new DOMParser().parseFromString(p, "text/html");
257
+ let a = c.querySelector('meta[property="og:title"]')?.getAttribute("content") || c.querySelector('meta[name="twitter:title"]')?.getAttribute("content") || c.querySelector("title")?.textContent || o;
258
+ a = a.trim();
259
+ let d = `https://www.google.com/s2/favicons?domain=${r.hostname}&sz=32`;
260
+ const t = c.querySelector('link[rel="icon"]')?.getAttribute("href") || c.querySelector('link[rel="shortcut icon"]')?.getAttribute("href") || c.querySelector('link[rel="apple-touch-icon"]')?.getAttribute("href");
261
+ return t && (t.startsWith("http") ? d = t : t.startsWith("//") ? d = "https:" + t : t.startsWith("/") ? d = l + t : d = l + "/" + t), { title: a, favicon: d };
262
+ } catch {
263
+ process.env.NODE_ENV === "development" && console.debug("[react-beauty-link] Metadata fetch failed, using fallback");
264
+ const l = new URL(o);
259
265
  return {
260
266
  title: l.hostname,
261
267
  favicon: `https://www.google.com/s2/favicons?domain=${l.hostname}&sz=32`
@@ -263,6 +269,7 @@ async function M(t) {
263
269
  }
264
270
  }
265
271
  export {
266
- E as useBeautyLink
272
+ F as loadNerdFonts,
273
+ I as useBeautyLink
267
274
  };
268
275
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/fileIcons.ts","../src/utils/loadNerdFonts.ts","../src/hooks/useBeautyLink.tsx"],"sourcesContent":["interface FileTypeIcon {\n icon: string;\n color: string;\n }\n\nexport const FILE_TYPE_ICONS: Record<string, FileTypeIcon> = {\n // Documents\n 'pdf': { icon: '󰈦', color: '#e74856' },\n 'doc': { icon: '󰈬', color: '#2b579a' },\n 'docx': { icon: '󰈬', color: '#2b579a' },\n 'xls': { icon: '󰈛', color: '#207245' },\n 'xlsx': { icon: '󰈛', color: '#207245' },\n 'ppt': { icon: '󰈧', color: '#d24726' },\n 'pptx': { icon: '󰈧', color: '#d24726' },\n 'txt': { icon: '󰈙', color: '#6c757d' },\n \n // Archives\n 'zip': { icon: '󰗄', color: '#e89f1c' },\n 'rar': { icon: '󰗄', color: '#e89f1c' },\n '7z': { icon: '󰗄', color: '#e89f1c' },\n 'tar': { icon: '󰗄', color: '#e89f1c' },\n 'gz': { icon: '󰗄', color: '#e89f1c' },\n \n // Images\n 'jpg': { icon: '󰈟', color: '#a855f7' },\n 'jpeg': { icon: '󰈟', color: '#a855f7' },\n 'png': { icon: '󰈟', color: '#a855f7' },\n 'gif': { icon: '󰈟', color: '#a855f7' },\n 'svg': { icon: '󰜡', color: '#f97316' },\n 'webp': { icon: '󰈟', color: '#a855f7' },\n \n // Videos\n 'mp4': { icon: '󰕧', color: '#ec4899' },\n 'avi': { icon: '󰕧', color: '#ec4899' },\n 'mov': { icon: '󰕧', color: '#ec4899' },\n 'mkv': { icon: '󰕧', color: '#ec4899' },\n 'webm': { icon: '󰕧', color: '#ec4899' },\n \n // Audio\n 'mp3': { icon: '󰈣', color: '#10b981' },\n 'wav': { icon: '󰈣', color: '#10b981' },\n 'flac': { icon: '󰈣', color: '#10b981' },\n 'ogg': { icon: '󰈣', color: '#10b981' },\n \n // Code\n 'js': { icon: '󰌞', color: '#f0db4f' },\n 'ts': { icon: '󰛦', color: '#3178c6' },\n 'jsx': { icon: '󰜈', color: '#61dafb' },\n 'tsx': { icon: '󰜈', color: '#61dafb' },\n 'py': { icon: '󰌠', color: '#3776ab' },\n 'java': { icon: '󰬷', color: '#007396' },\n 'php': { icon: '󰌟', color: '#777bb4' },\n 'rb': { icon: '󰴭', color: '#cc342d' },\n 'go': { icon: '󰟓', color: '#00add8' },\n 'rs': { icon: '󱘗', color: '#dea584' },\n 'html': { icon: '󰌝', color: '#e34c26' },\n 'css': { icon: '󰌜', color: '#264de4' },\n 'json': { icon: '󰘦', color: '#f7df1e' },\n 'xml': { icon: '󰗀', color: '#ff6600' },\n 'yaml': { icon: '󰈙', color: '#cb171e' },\n 'yml': { icon: '󰈙', color: '#cb171e' },\n 'md': { icon: '󰍔', color: '#083fa1' },\n 'sql': { icon: '󰆼', color: '#00758f' },\n 'sh': { icon: '󰆍', color: '#89e051' },\n };","// Load Nerd Fonts dynamically for file type icons\nlet fontsLoaded = false;\n\nexport function loadNerdFonts() {\n // Only inject once\n if (fontsLoaded || typeof document === 'undefined') {\n return;\n }\n\n const styleId = 'react-beauty-link-nerd-fonts';\n \n // Check if already injected\n if (document.getElementById(styleId)) {\n fontsLoaded = true;\n return;\n }\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n /* react-beauty-link: Nerd Font Symbols */\n @font-face {\n font-family: 'Symbols Nerd Font';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n\n @font-face {\n font-family: 'Symbols Nerd Font Mono';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n `;\n\n document.head.appendChild(style);\n fontsLoaded = true;\n}\n","import { useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport { FILE_TYPE_ICONS } from '../utils/fileIcons';\nimport { loadNerdFonts } from '../utils/loadNerdFonts';\n\ninterface LinkMetadata {\n title: string;\n favicon: string | null;\n}\n\nexport type LinkTarget = 'new-tab' | 'new-window' | 'self';\n\n\nfunction getFileExtension(url: string): string | null {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n const lastDot = pathname.lastIndexOf('.');\n if (lastDot === -1 || lastDot === pathname.length - 1) return null;\n return pathname.substring(lastDot + 1).toLowerCase();\n } catch {\n return null;\n }\n}\n\n/**\n * Custom hook that converts HTTPS URLs in a string into clickable links\n * with page titles and favicons\n * @param text - The input string containing potential URLs\n * @param target - How to open links: 'new-tab' (default), 'new-window', or 'self'\n * @returns An array of React nodes with text and links\n */\nexport const useBeautyLink = (text: string, target: LinkTarget = 'new-tab', customColor?: string): ReactNode[] => {\n const urlRegex = /(https:\\/\\/[^\\s]+)/g;\n const [linkMetadata, setLinkMetadata] = useState<Record<string, LinkMetadata>>({});\n \n const urls = Array.from(text.matchAll(urlRegex)).map(match => match[0]);\n\n // Load Nerd Fonts once when hook is first used\n useEffect(() => {\n loadNerdFonts();\n }, []);\n\n useEffect(() => {\n const fetchAllMetadata = async () => {\n for (const url of urls) {\n if (!linkMetadata[url]) {\n const extension = getFileExtension(url);\n \n // If it's a file URL, skip metadata fetching and use filename\n if (extension && FILE_TYPE_ICONS[extension]) {\n const filename = url.split('/').pop() || url;\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: decodeURIComponent(filename),\n favicon: null\n }\n }));\n continue;\n }\n \n try {\n console.log('Fetching metadata for:', url);\n const metadata = await fetchLinkMetadata(url);\n console.log('Metadata received:', metadata);\n setLinkMetadata(prev => ({\n ...prev,\n [url]: metadata\n }));\n } catch (error) {\n console.error('Failed to fetch metadata for', url, error);\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: url,\n favicon: null\n }\n }));\n }\n }\n }\n };\n\n fetchAllMetadata();\n }, [text, JSON.stringify(urls)]);\n\n const parts: ReactNode[] = [];\n let lastIndex = 0;\n let match;\n\n urlRegex.lastIndex = 0;\n while ((match = urlRegex.exec(text)) !== null) {\n const url = match[0];\n const startIndex = match.index;\n\n if (startIndex > lastIndex) {\n parts.push(text.substring(lastIndex, startIndex));\n }\n\n const metadata = linkMetadata[url];\n const displayTitle = metadata?.title \n ? (metadata.title.length > 60 ? metadata.title.substring(0, 60) + '...' : metadata.title)\n : url;\n \n const faviconUrl = metadata?.favicon;\n const extension = getFileExtension(url);\n const fileIcon = extension ? FILE_TYPE_ICONS[extension] : null;\n\n const getTargetAttributes = () => {\n switch (target) {\n case 'new-window':\n return {\n target: '_blank',\n rel: 'noopener noreferrer',\n onClick: (e: React.MouseEvent) => {\n e.preventDefault();\n window.open(url, '_blank', 'noopener,noreferrer,width=800,height=600');\n }\n };\n case 'self':\n return {\n target: '_self'\n };\n case 'new-tab':\n default:\n return {\n target: '_blank',\n rel: 'noopener noreferrer'\n };\n }\n };\n\n parts.push(\n <a\n key={`link-${startIndex}`}\n href={url}\n {...getTargetAttributes()}\n style={{ \n color: customColor || '#646cff', \n textDecoration: 'underline',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px'\n }}\n >\n {fileIcon ? (\n <span \n style={{ \n fontFamily: '\"Symbols Nerd Font Mono\", \"Symbols Nerd Font\", \"Nerd Font\", \"FiraCode Nerd Font\", monospace',\n fontSize: '16px',\n color: fileIcon.color,\n lineHeight: 1,\n display: 'inline-block',\n width: '16px',\n textAlign: 'center',\n fontWeight: 'normal'\n }}\n aria-hidden=\"true\"\n >\n {fileIcon.icon}\n </span>\n ) : faviconUrl ? (\n <img \n src={faviconUrl} \n alt=\"\" \n style={{ width: '16px', height: '16px' }}\n onError={(e) => {\n (e.target as HTMLImageElement).src = 'data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"%3E%3Cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/%3E%3Cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/%3E%3C/svg%3E';\n }}\n />\n ) : (\n <svg \n xmlns=\"http://www.w3.org/2000/svg\" \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n stroke=\"currentColor\" \n strokeWidth=\"2\" \n strokeLinecap=\"round\" \n strokeLinejoin=\"round\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/>\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>\n </svg>\n )}\n <span>{displayTitle}</span>\n </a>\n );\n\n lastIndex = startIndex + url.length;\n }\n\n if (lastIndex < text.length) {\n parts.push(text.substring(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n};\n\n/**\n * Fetches metadata (title and favicon) for a given URL\n */\nasync function fetchLinkMetadata(url: string): Promise<LinkMetadata> {\n try {\n const urlObj = new URL(url);\n const origin = urlObj.origin;\n \n const proxies = [\n `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`,\n `https://corsproxy.io/?${encodeURIComponent(url)}`,\n ];\n \n let html = '';\n let success = false;\n \n for (const proxyUrl of proxies) {\n try {\n const response = await fetch(proxyUrl, { \n signal: AbortSignal.timeout(10000) // 10 second timeout\n });\n \n if (!response.ok) continue;\n \n const data = await response.json();\n html = data.contents || data;\n success = true;\n break;\n } catch (err) {\n console.warn('Proxy failed:', proxyUrl, err);\n continue;\n }\n }\n \n if (!success || !html) {\n throw new Error('All proxies failed');\n }\n \n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n \n let title = \n doc.querySelector('meta[property=\"og:title\"]')?.getAttribute('content') ||\n doc.querySelector('meta[name=\"twitter:title\"]')?.getAttribute('content') ||\n doc.querySelector('title')?.textContent ||\n url;\n \n title = title.trim();\n \n let favicon = `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`;\n \n const faviconLink = \n doc.querySelector('link[rel=\"icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"shortcut icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"apple-touch-icon\"]')?.getAttribute('href');\n \n if (faviconLink) {\n if (faviconLink.startsWith('http')) {\n favicon = faviconLink;\n } else if (faviconLink.startsWith('//')) {\n favicon = 'https:' + faviconLink;\n } else if (faviconLink.startsWith('/')) {\n favicon = origin + faviconLink;\n } else {\n favicon = origin + '/' + faviconLink;\n }\n }\n \n return { title, favicon };\n } catch (error) {\n console.error('Error fetching metadata:', error);\n const urlObj = new URL(url);\n return {\n title: urlObj.hostname,\n favicon: `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`\n };\n }\n}\n"],"names":["FILE_TYPE_ICONS","fontsLoaded","loadNerdFonts","styleId","style","getFileExtension","url","pathname","lastDot","useBeautyLink","text","target","customColor","urlRegex","linkMetadata","setLinkMetadata","useState","urls","match","useEffect","extension","filename","prev","metadata","fetchLinkMetadata","error","parts","lastIndex","startIndex","displayTitle","faviconUrl","fileIcon","getTargetAttributes","e","jsxs","jsx","urlObj","origin","proxies","html","success","proxyUrl","response","data","err","doc","title","favicon","faviconLink"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/fileIcons.ts","../src/utils/loadNerdFonts.ts","../src/hooks/useBeautyLink.tsx"],"sourcesContent":["interface FileTypeIcon {\n icon: string;\n color: string;\n }\n\nexport const FILE_TYPE_ICONS: Record<string, FileTypeIcon> = {\n // Documents\n 'pdf': { icon: '󰈦', color: '#e74856' },\n 'doc': { icon: '󰈬', color: '#2b579a' },\n 'docx': { icon: '󰈬', color: '#2b579a' },\n 'xls': { icon: '󰈛', color: '#207245' },\n 'xlsx': { icon: '󰈛', color: '#207245' },\n 'ppt': { icon: '󰈧', color: '#d24726' },\n 'pptx': { icon: '󰈧', color: '#d24726' },\n 'txt': { icon: '󰈙', color: '#6c757d' },\n \n // Archives\n 'zip': { icon: '󰗄', color: '#e89f1c' },\n 'rar': { icon: '󰗄', color: '#e89f1c' },\n '7z': { icon: '󰗄', color: '#e89f1c' },\n 'tar': { icon: '󰗄', color: '#e89f1c' },\n 'gz': { icon: '󰗄', color: '#e89f1c' },\n \n // Images\n 'jpg': { icon: '󰈟', color: '#a855f7' },\n 'jpeg': { icon: '󰈟', color: '#a855f7' },\n 'png': { icon: '󰈟', color: '#a855f7' },\n 'gif': { icon: '󰈟', color: '#a855f7' },\n 'svg': { icon: '󰜡', color: '#f97316' },\n 'webp': { icon: '󰈟', color: '#a855f7' },\n \n // Videos\n 'mp4': { icon: '󰕧', color: '#ec4899' },\n 'avi': { icon: '󰕧', color: '#ec4899' },\n 'mov': { icon: '󰕧', color: '#ec4899' },\n 'mkv': { icon: '󰕧', color: '#ec4899' },\n 'webm': { icon: '󰕧', color: '#ec4899' },\n \n // Audio\n 'mp3': { icon: '󰈣', color: '#10b981' },\n 'wav': { icon: '󰈣', color: '#10b981' },\n 'flac': { icon: '󰈣', color: '#10b981' },\n 'ogg': { icon: '󰈣', color: '#10b981' },\n \n // Code\n 'js': { icon: '󰌞', color: '#f0db4f' },\n 'ts': { icon: '󰛦', color: '#3178c6' },\n 'jsx': { icon: '󰜈', color: '#61dafb' },\n 'tsx': { icon: '󰜈', color: '#61dafb' },\n 'py': { icon: '󰌠', color: '#3776ab' },\n 'java': { icon: '󰬷', color: '#007396' },\n 'php': { icon: '󰌟', color: '#777bb4' },\n 'rb': { icon: '󰴭', color: '#cc342d' },\n 'go': { icon: '󰟓', color: '#00add8' },\n 'rs': { icon: '󱘗', color: '#dea584' },\n 'html': { icon: '󰌝', color: '#e34c26' },\n 'css': { icon: '󰌜', color: '#264de4' },\n 'json': { icon: '󰘦', color: '#f7df1e' },\n 'xml': { icon: '󰗀', color: '#ff6600' },\n 'yaml': { icon: '󰈙', color: '#cb171e' },\n 'yml': { icon: '󰈙', color: '#cb171e' },\n 'md': { icon: '󰍔', color: '#083fa1' },\n 'sql': { icon: '󰆼', color: '#00758f' },\n 'sh': { icon: '󰆍', color: '#89e051' },\n };","// Load Nerd Fonts dynamically for file type icons\nlet fontsLoaded = false;\n\nexport function loadNerdFonts() {\n // SSR check\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n // Only inject once\n if (fontsLoaded) {\n return;\n }\n\n const styleId = 'react-beauty-link-nerd-fonts';\n \n // Check if already injected\n if (document.getElementById(styleId)) {\n fontsLoaded = true;\n return;\n }\n\n try {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n /* react-beauty-link: Nerd Font Symbols */\n @font-face {\n font-family: 'Symbols Nerd Font';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n\n @font-face {\n font-family: 'Symbols Nerd Font Mono';\n src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n `;\n\n document.head.appendChild(style);\n fontsLoaded = true;\n \n // Debug log (can be removed in production)\n if (typeof console !== 'undefined' && console.debug) {\n console.debug('[react-beauty-link] Nerd Fonts loaded successfully');\n }\n } catch (error) {\n console.error('[react-beauty-link] Failed to load Nerd Fonts:', error);\n }\n}\n","import { useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport { FILE_TYPE_ICONS } from '../utils/fileIcons';\nimport { loadNerdFonts } from '../utils/loadNerdFonts';\n\n// Load fonts immediately when module is imported (browser only, one-time)\nif (typeof window !== 'undefined') {\n loadNerdFonts();\n}\n\ninterface LinkMetadata {\n title: string;\n favicon: string | null;\n}\n\nexport type LinkTarget = 'new-tab' | 'new-window' | 'self';\n\n\nfunction getFileExtension(url: string): string | null {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n const lastDot = pathname.lastIndexOf('.');\n if (lastDot === -1 || lastDot === pathname.length - 1) return null;\n return pathname.substring(lastDot + 1).toLowerCase();\n } catch {\n return null;\n }\n}\n\n/**\n * Custom hook that converts HTTPS URLs in a string into clickable links\n * with page titles and favicons\n * @param text - The input string containing potential URLs\n * @param target - How to open links: 'new-tab' (default), 'new-window', or 'self'\n * @param customColor - Custom color for links (optional)\n * @returns An array of React nodes with text and links\n */\nexport const useBeautyLink = (text: string, target: LinkTarget = 'new-tab', customColor?: string): ReactNode[] => {\n const urlRegex = /(https:\\/\\/[^\\s]+)/g;\n const [linkMetadata, setLinkMetadata] = useState<Record<string, LinkMetadata>>({});\n \n const urls = Array.from(text.matchAll(urlRegex)).map(match => match[0]);\n\n useEffect(() => {\n const fetchAllMetadata = async () => {\n for (const url of urls) {\n if (!linkMetadata[url]) {\n const extension = getFileExtension(url);\n \n // If it's a file URL, skip metadata fetching and use filename\n if (extension && FILE_TYPE_ICONS[extension]) {\n const filename = url.split('/').pop() || url;\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: decodeURIComponent(filename),\n favicon: null\n }\n }));\n continue;\n }\n \n try {\n const metadata = await fetchLinkMetadata(url);\n if (process.env.NODE_ENV === 'development') {\n console.debug('[react-beauty-link] Metadata fetched:', url);\n }\n setLinkMetadata(prev => ({\n ...prev,\n [url]: metadata\n }));\n } catch (error) {\n // Silently fall back to URL - this is expected behavior\n if (process.env.NODE_ENV === 'development') {\n console.debug('[react-beauty-link] Using URL fallback for:', url);\n }\n setLinkMetadata(prev => ({\n ...prev,\n [url]: {\n title: url,\n favicon: null\n }\n }));\n }\n }\n }\n };\n\n fetchAllMetadata();\n }, [text, JSON.stringify(urls)]);\n\n const parts: ReactNode[] = [];\n let lastIndex = 0;\n let match;\n\n urlRegex.lastIndex = 0;\n while ((match = urlRegex.exec(text)) !== null) {\n const url = match[0];\n const startIndex = match.index;\n\n if (startIndex > lastIndex) {\n parts.push(text.substring(lastIndex, startIndex));\n }\n\n const metadata = linkMetadata[url];\n const displayTitle = metadata?.title \n ? (metadata.title.length > 60 ? metadata.title.substring(0, 60) + '...' : metadata.title)\n : url;\n \n const faviconUrl = metadata?.favicon;\n const extension = getFileExtension(url);\n const fileIcon = extension ? FILE_TYPE_ICONS[extension] : null;\n\n const getTargetAttributes = () => {\n switch (target) {\n case 'new-window':\n return {\n target: '_blank',\n rel: 'noopener noreferrer',\n onClick: (e: React.MouseEvent) => {\n e.preventDefault();\n window.open(url, '_blank', 'noopener,noreferrer,width=800,height=600');\n }\n };\n case 'self':\n return {\n target: '_self'\n };\n case 'new-tab':\n default:\n return {\n target: '_blank',\n rel: 'noopener noreferrer'\n };\n }\n };\n\n parts.push(\n <a\n key={`link-${startIndex}`}\n href={url}\n {...getTargetAttributes()}\n style={{ \n color: customColor || '#646cff', \n textDecoration: 'underline',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px'\n }}\n >\n {fileIcon ? (\n <span \n style={{ \n fontFamily: '\"Symbols Nerd Font Mono\", \"Symbols Nerd Font\", \"Nerd Font\", \"FiraCode Nerd Font\", monospace',\n fontSize: '16px',\n color: fileIcon.color,\n lineHeight: 1,\n display: 'inline-block',\n width: '16px',\n textAlign: 'center',\n fontWeight: 'normal'\n }}\n aria-hidden=\"true\"\n >\n {fileIcon.icon}\n </span>\n ) : faviconUrl ? (\n <img \n src={faviconUrl} \n alt=\"\" \n style={{ width: '16px', height: '16px' }}\n onError={(e) => {\n (e.target as HTMLImageElement).src = 'data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"%3E%3Cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/%3E%3Cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/%3E%3C/svg%3E';\n }}\n />\n ) : (\n <svg \n xmlns=\"http://www.w3.org/2000/svg\" \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n stroke=\"currentColor\" \n strokeWidth=\"2\" \n strokeLinecap=\"round\" \n strokeLinejoin=\"round\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/>\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>\n </svg>\n )}\n <span>{displayTitle}</span>\n </a>\n );\n\n lastIndex = startIndex + url.length;\n }\n\n if (lastIndex < text.length) {\n parts.push(text.substring(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n};\n\n/**\n * Fetches metadata (title and favicon) for a given URL\n */\nasync function fetchLinkMetadata(url: string): Promise<LinkMetadata> {\n try {\n const urlObj = new URL(url);\n const origin = urlObj.origin;\n \n const proxies = [\n `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`,\n `https://corsproxy.io/?${encodeURIComponent(url)}`,\n `https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(url)}`,\n ];\n \n let html = '';\n let success = false;\n \n for (const proxyUrl of proxies) {\n try {\n const response = await fetch(proxyUrl, { \n signal: AbortSignal.timeout(5000) // 5 second timeout (faster failover)\n });\n \n if (!response.ok) continue;\n \n const data = await response.json();\n html = data.contents || data;\n success = true;\n break;\n } catch (err) {\n // Only log in development mode to reduce console noise\n if (process.env.NODE_ENV === 'development') {\n const errorName = err instanceof Error ? err.name : 'Unknown error';\n console.debug('[react-beauty-link] Proxy failed:', proxyUrl.split('?')[0], errorName);\n }\n continue;\n }\n }\n \n if (!success || !html) {\n throw new Error('All proxies failed');\n }\n \n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n \n let title = \n doc.querySelector('meta[property=\"og:title\"]')?.getAttribute('content') ||\n doc.querySelector('meta[name=\"twitter:title\"]')?.getAttribute('content') ||\n doc.querySelector('title')?.textContent ||\n url;\n \n title = title.trim();\n \n let favicon = `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`;\n \n const faviconLink = \n doc.querySelector('link[rel=\"icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"shortcut icon\"]')?.getAttribute('href') ||\n doc.querySelector('link[rel=\"apple-touch-icon\"]')?.getAttribute('href');\n \n if (faviconLink) {\n if (faviconLink.startsWith('http')) {\n favicon = faviconLink;\n } else if (faviconLink.startsWith('//')) {\n favicon = 'https:' + faviconLink;\n } else if (faviconLink.startsWith('/')) {\n favicon = origin + faviconLink;\n } else {\n favicon = origin + '/' + faviconLink;\n }\n }\n \n return { title, favicon };\n } catch (error) {\n // Graceful fallback - use hostname and Google favicon service\n if (process.env.NODE_ENV === 'development') {\n console.debug('[react-beauty-link] Metadata fetch failed, using fallback');\n }\n const urlObj = new URL(url);\n return {\n title: urlObj.hostname,\n favicon: `https://www.google.com/s2/favicons?domain=${urlObj.hostname}&sz=32`\n };\n }\n}\n"],"names":["FILE_TYPE_ICONS","fontsLoaded","loadNerdFonts","styleId","style","error","getFileExtension","url","pathname","lastDot","useBeautyLink","text","target","customColor","urlRegex","linkMetadata","setLinkMetadata","useState","urls","match","useEffect","extension","filename","prev","metadata","fetchLinkMetadata","parts","lastIndex","startIndex","displayTitle","faviconUrl","fileIcon","getTargetAttributes","e","jsxs","jsx","urlObj","origin","proxies","html","success","proxyUrl","response","data","err","errorName","doc","title","favicon","faviconLink"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadNerdFonts.d.ts","sourceRoot":"","sources":["../../src/utils/loadNerdFonts.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,SAqC5B"}
1
+ {"version":3,"file":"loadNerdFonts.d.ts","sourceRoot":"","sources":["../../src/utils/loadNerdFonts.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,SAmD5B"}
@@ -1,8 +1,12 @@
1
1
  // Load Nerd Fonts dynamically for file type icons
2
2
  let fontsLoaded = false;
3
3
  export function loadNerdFonts() {
4
+ // SSR check
5
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
6
+ return;
7
+ }
4
8
  // Only inject once
5
- if (fontsLoaded || typeof document === 'undefined') {
9
+ if (fontsLoaded) {
6
10
  return;
7
11
  }
8
12
  const styleId = 'react-beauty-link-nerd-fonts';
@@ -11,27 +15,36 @@ export function loadNerdFonts() {
11
15
  fontsLoaded = true;
12
16
  return;
13
17
  }
14
- const style = document.createElement('style');
15
- style.id = styleId;
16
- style.textContent = `
17
- /* react-beauty-link: Nerd Font Symbols */
18
- @font-face {
19
- font-family: 'Symbols Nerd Font';
20
- src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');
21
- font-weight: normal;
22
- font-style: normal;
23
- font-display: swap;
24
- }
18
+ try {
19
+ const style = document.createElement('style');
20
+ style.id = styleId;
21
+ style.textContent = `
22
+ /* react-beauty-link: Nerd Font Symbols */
23
+ @font-face {
24
+ font-family: 'Symbols Nerd Font';
25
+ src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFont-Regular.ttf') format('truetype');
26
+ font-weight: normal;
27
+ font-style: normal;
28
+ font-display: swap;
29
+ }
25
30
 
26
- @font-face {
27
- font-family: 'Symbols Nerd Font Mono';
28
- src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');
29
- font-weight: normal;
30
- font-style: normal;
31
- font-display: swap;
31
+ @font-face {
32
+ font-family: 'Symbols Nerd Font Mono';
33
+ src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@v3.1.1/patched-fonts/NerdFontsSymbolsOnly/SymbolsNerdFontMono-Regular.ttf') format('truetype');
34
+ font-weight: normal;
35
+ font-style: normal;
36
+ font-display: swap;
37
+ }
38
+ `;
39
+ document.head.appendChild(style);
40
+ fontsLoaded = true;
41
+ // Debug log (can be removed in production)
42
+ if (typeof console !== 'undefined' && console.debug) {
43
+ console.debug('[react-beauty-link] Nerd Fonts loaded successfully');
44
+ }
45
+ }
46
+ catch (error) {
47
+ console.error('[react-beauty-link] Failed to load Nerd Fonts:', error);
32
48
  }
33
- `;
34
- document.head.appendChild(style);
35
- fontsLoaded = true;
36
49
  }
37
50
  //# sourceMappingURL=loadNerdFonts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadNerdFonts.js","sourceRoot":"","sources":["../../src/utils/loadNerdFonts.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,UAAU,aAAa;IAC3B,mBAAmB;IACnB,IAAI,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACnD,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,8BAA8B,CAAC;IAE/C,4BAA4B;IAC5B,IAAI,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,WAAW,GAAG,IAAI,CAAC;QACnB,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC;IACnB,KAAK,CAAC,WAAW,GAAG;;;;;;;;;;;;;;;;;GAiBnB,CAAC;IAEF,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"loadNerdFonts.js","sourceRoot":"","sources":["../../src/utils/loadNerdFonts.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,UAAU,aAAa;IAC3B,YAAY;IACZ,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACrE,OAAO;IACT,CAAC;IAED,mBAAmB;IACnB,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,8BAA8B,CAAC;IAE/C,4BAA4B;IAC5B,IAAI,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,WAAW,GAAG,IAAI,CAAC;QACnB,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC;QACnB,KAAK,CAAC,WAAW,GAAG;;;;;;;;;;;;;;;;;KAiBnB,CAAC;QAEF,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACjC,WAAW,GAAG,IAAI,CAAC;QAEnB,2CAA2C;QAC3C,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACpD,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-beauty-link",
3
- "version": "1.1.3",
3
+ "version": "1.1.6",
4
4
  "description": "A React hook that converts URLs in text to beautiful clickable links with page titles and favicons",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",