react-beauty-link 1.1.3 → 1.1.5
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.
- package/dist/hooks/useBeautyLink.d.ts +1 -0
- package/dist/hooks/useBeautyLink.d.ts.map +1 -1
- package/dist/hooks/useBeautyLink.js +5 -4
- package/dist/hooks/useBeautyLink.js.map +1 -1
- package/dist/index.cjs +17 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +76 -72
- package/dist/index.js.map +1 -1
- package/dist/utils/loadNerdFonts.d.ts.map +1 -1
- package/dist/utils/loadNerdFonts.js +34 -21
- package/dist/utils/loadNerdFonts.js.map +1 -1
- package/package.json +1 -1
|
@@ -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;
|
|
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,EAkK3G,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) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBeautyLink.js","sourceRoot":"","sources":["../../src/hooks/useBeautyLink.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
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"),
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),x=require("react"),k={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 j(){if(typeof window>"u"||typeof document>"u"||b)return;const t="react-beauty-link-nerd-fonts";if(document.getElementById(t)){b=!0;return}try{const n=document.createElement("style");n.id=t,n.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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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(n),b=!0,typeof console<"u"&&console.debug&&console.debug("[react-beauty-link] Nerd Fonts loaded successfully")}catch(n){console.error("[react-beauty-link] Failed to load Nerd Fonts:",n)}}typeof window<"u"&&j();function v(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 S=(t,n="new-tab",l)=>{const s=/(https:\/\/[^\s]+)/g,[p,h]=x.useState({}),g=Array.from(t.matchAll(s)).map(e=>e[0]);x.useEffect(()=>{(async()=>{for(const o of g)if(!p[o]){const r=v(o);if(r&&k[r]){const i=o.split("/").pop()||o;h(f=>({...f,[o]:{title:decodeURIComponent(i),favicon:null}}));continue}try{console.log("Fetching metadata for:",o);const i=await N(o);console.log("Metadata received:",i),h(f=>({...f,[o]:i}))}catch(i){console.error("Failed to fetch metadata for",o,i),h(f=>({...f,[o]:{title:o,favicon:null}}))}}})()},[t,JSON.stringify(g)]);const c=[];let a=0,d;for(s.lastIndex=0;(d=s.exec(t))!==null;){const e=d[0],o=d.index;o>a&&c.push(t.substring(a,o));const r=p[e],i=r?.title?r.title.length>60?r.title.substring(0,60)+"...":r.title:e,f=r?.favicon,w=v(e),m=w?k[w]:null,F=()=>{switch(n){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"}}};c.push(u.jsxs("a",{href:e,...F(),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-${o}`)),a=o+e.length}return a<t.length&&c.push(t.substring(a)),c.length>0?c:[t]};async function N(t){try{const n=new URL(t),l=n.origin,s=[`https://api.allorigins.win/get?url=${encodeURIComponent(t)}`,`https://corsproxy.io/?${encodeURIComponent(t)}`];let p="",h=!1;for(const o of s)try{const r=await fetch(o,{signal:AbortSignal.timeout(1e4)});if(!r.ok)continue;const i=await r.json();p=i.contents||i,h=!0;break}catch(r){console.warn("Proxy failed:",o,r);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||t;a=a.trim();let d=`https://www.google.com/s2/favicons?domain=${n.hostname}&sz=32`;const e=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 e&&(e.startsWith("http")?d=e:e.startsWith("//")?d="https:"+e:e.startsWith("/")?d=l+e:d=l+"/"+e),{title:a,favicon:d}}catch(n){console.error("Error fetching metadata:",n);const l=new URL(t);return{title:l.hostname,favicon:`https://www.google.com/s2/favicons?domain=${l.hostname}&sz=32`}}}exports.loadNerdFonts=j;exports.useBeautyLink=S;
|
|
19
19
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 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","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","doc","title","favicon","faviconLink"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -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,5 +1,5 @@
|
|
|
1
|
-
import { jsxs as x, jsx as
|
|
2
|
-
import { useState as
|
|
1
|
+
import { jsxs as x, jsx as h } from "react/jsx-runtime";
|
|
2
|
+
import { useState as S, useEffect as j } from "react";
|
|
3
3
|
const k = {
|
|
4
4
|
// Documents
|
|
5
5
|
pdf: { icon: "", color: "#e74856" },
|
|
@@ -57,53 +57,56 @@ const k = {
|
|
|
57
57
|
};
|
|
58
58
|
let w = !1;
|
|
59
59
|
function C() {
|
|
60
|
-
if (
|
|
60
|
+
if (typeof window > "u" || typeof document > "u" || w)
|
|
61
61
|
return;
|
|
62
62
|
const t = "react-beauty-link-nerd-fonts";
|
|
63
63
|
if (document.getElementById(t)) {
|
|
64
64
|
w = !0;
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
font-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
67
|
+
try {
|
|
68
|
+
const n = document.createElement("style");
|
|
69
|
+
n.id = t, n.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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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(n), w = !0, typeof console < "u" && console.debug && console.debug("[react-beauty-link] Nerd Fonts loaded successfully");
|
|
87
|
+
} catch (n) {
|
|
88
|
+
console.error("[react-beauty-link] Failed to load Nerd Fonts:", n);
|
|
89
|
+
}
|
|
86
90
|
}
|
|
87
|
-
|
|
91
|
+
typeof window < "u" && C();
|
|
92
|
+
function v(t) {
|
|
88
93
|
try {
|
|
89
|
-
const l = new URL(t).pathname,
|
|
90
|
-
return
|
|
94
|
+
const l = new URL(t).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,
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
C();
|
|
99
|
-
}, []), v(() => {
|
|
100
|
+
const E = (t, n = "new-tab", l) => {
|
|
101
|
+
const s = /(https:\/\/[^\s]+)/g, [p, u] = S({}), g = Array.from(t.matchAll(s)).map((e) => e[0]);
|
|
102
|
+
j(() => {
|
|
100
103
|
(async () => {
|
|
101
|
-
for (const o of
|
|
104
|
+
for (const o of g)
|
|
102
105
|
if (!p[o]) {
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
106
|
+
const r = v(o);
|
|
107
|
+
if (r && k[r]) {
|
|
105
108
|
const i = o.split("/").pop() || o;
|
|
106
|
-
|
|
109
|
+
u((d) => ({
|
|
107
110
|
...d,
|
|
108
111
|
[o]: {
|
|
109
112
|
title: decodeURIComponent(i),
|
|
@@ -114,13 +117,13 @@ const E = (t, c = "new-tab", l) => {
|
|
|
114
117
|
}
|
|
115
118
|
try {
|
|
116
119
|
console.log("Fetching metadata for:", o);
|
|
117
|
-
const i = await
|
|
118
|
-
console.log("Metadata received:", i),
|
|
120
|
+
const i = await N(o);
|
|
121
|
+
console.log("Metadata received:", i), u((d) => ({
|
|
119
122
|
...d,
|
|
120
123
|
[o]: i
|
|
121
124
|
}));
|
|
122
125
|
} catch (i) {
|
|
123
|
-
console.error("Failed to fetch metadata for", o, i),
|
|
126
|
+
console.error("Failed to fetch metadata for", o, i), u((d) => ({
|
|
124
127
|
...d,
|
|
125
128
|
[o]: {
|
|
126
129
|
title: o,
|
|
@@ -130,14 +133,14 @@ const E = (t, c = "new-tab", l) => {
|
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
})();
|
|
133
|
-
}, [t, JSON.stringify(
|
|
134
|
-
const
|
|
135
|
-
let
|
|
136
|
-
for (
|
|
136
|
+
}, [t, JSON.stringify(g)]);
|
|
137
|
+
const c = [];
|
|
138
|
+
let a = 0, f;
|
|
139
|
+
for (s.lastIndex = 0; (f = s.exec(t)) !== null; ) {
|
|
137
140
|
const e = f[0], o = f.index;
|
|
138
|
-
o >
|
|
139
|
-
const
|
|
140
|
-
switch (
|
|
141
|
+
o > a && c.push(t.substring(a, o));
|
|
142
|
+
const r = p[e], i = r?.title ? r.title.length > 60 ? r.title.substring(0, 60) + "..." : r.title : e, d = r?.favicon, b = v(e), m = b ? k[b] : null, F = () => {
|
|
143
|
+
switch (n) {
|
|
141
144
|
case "new-window":
|
|
142
145
|
return {
|
|
143
146
|
target: "_blank",
|
|
@@ -157,7 +160,7 @@ const E = (t, c = "new-tab", l) => {
|
|
|
157
160
|
};
|
|
158
161
|
}
|
|
159
162
|
};
|
|
160
|
-
|
|
163
|
+
c.push(
|
|
161
164
|
/* @__PURE__ */ x(
|
|
162
165
|
"a",
|
|
163
166
|
{
|
|
@@ -171,13 +174,13 @@ const E = (t, c = "new-tab", l) => {
|
|
|
171
174
|
gap: "6px"
|
|
172
175
|
},
|
|
173
176
|
children: [
|
|
174
|
-
|
|
177
|
+
m ? /* @__PURE__ */ h(
|
|
175
178
|
"span",
|
|
176
179
|
{
|
|
177
180
|
style: {
|
|
178
181
|
fontFamily: '"Symbols Nerd Font Mono", "Symbols Nerd Font", "Nerd Font", "FiraCode Nerd Font", monospace',
|
|
179
182
|
fontSize: "16px",
|
|
180
|
-
color:
|
|
183
|
+
color: m.color,
|
|
181
184
|
lineHeight: 1,
|
|
182
185
|
display: "inline-block",
|
|
183
186
|
width: "16px",
|
|
@@ -185,9 +188,9 @@ const E = (t, c = "new-tab", l) => {
|
|
|
185
188
|
fontWeight: "normal"
|
|
186
189
|
},
|
|
187
190
|
"aria-hidden": "true",
|
|
188
|
-
children:
|
|
191
|
+
children: m.icon
|
|
189
192
|
}
|
|
190
|
-
) : d ? /* @__PURE__ */
|
|
193
|
+
) : d ? /* @__PURE__ */ h(
|
|
191
194
|
"img",
|
|
192
195
|
{
|
|
193
196
|
src: d,
|
|
@@ -210,51 +213,51 @@ const E = (t, c = "new-tab", l) => {
|
|
|
210
213
|
strokeLinecap: "round",
|
|
211
214
|
strokeLinejoin: "round",
|
|
212
215
|
children: [
|
|
213
|
-
/* @__PURE__ */
|
|
214
|
-
/* @__PURE__ */
|
|
216
|
+
/* @__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" }),
|
|
217
|
+
/* @__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
218
|
]
|
|
216
219
|
}
|
|
217
220
|
),
|
|
218
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ h("span", { children: i })
|
|
219
222
|
]
|
|
220
223
|
},
|
|
221
224
|
`link-${o}`
|
|
222
225
|
)
|
|
223
|
-
),
|
|
226
|
+
), a = o + e.length;
|
|
224
227
|
}
|
|
225
|
-
return
|
|
228
|
+
return a < t.length && c.push(t.substring(a)), c.length > 0 ? c : [t];
|
|
226
229
|
};
|
|
227
|
-
async function
|
|
230
|
+
async function N(t) {
|
|
228
231
|
try {
|
|
229
|
-
const
|
|
232
|
+
const n = new URL(t), l = n.origin, s = [
|
|
230
233
|
`https://api.allorigins.win/get?url=${encodeURIComponent(t)}`,
|
|
231
234
|
`https://corsproxy.io/?${encodeURIComponent(t)}`
|
|
232
235
|
];
|
|
233
|
-
let p = "",
|
|
234
|
-
for (const o of
|
|
236
|
+
let p = "", u = !1;
|
|
237
|
+
for (const o of s)
|
|
235
238
|
try {
|
|
236
|
-
const
|
|
239
|
+
const r = await fetch(o, {
|
|
237
240
|
signal: AbortSignal.timeout(1e4)
|
|
238
241
|
// 10 second timeout
|
|
239
242
|
});
|
|
240
|
-
if (!
|
|
241
|
-
const i = await
|
|
242
|
-
p = i.contents || i,
|
|
243
|
+
if (!r.ok) continue;
|
|
244
|
+
const i = await r.json();
|
|
245
|
+
p = i.contents || i, u = !0;
|
|
243
246
|
break;
|
|
244
|
-
} catch (
|
|
245
|
-
console.warn("Proxy failed:", o,
|
|
247
|
+
} catch (r) {
|
|
248
|
+
console.warn("Proxy failed:", o, r);
|
|
246
249
|
continue;
|
|
247
250
|
}
|
|
248
|
-
if (!
|
|
251
|
+
if (!u || !p)
|
|
249
252
|
throw new Error("All proxies failed");
|
|
250
|
-
const
|
|
251
|
-
let
|
|
252
|
-
|
|
253
|
-
let f = `https://www.google.com/s2/favicons?domain=${
|
|
254
|
-
const e =
|
|
255
|
-
return e && (e.startsWith("http") ? f = e : e.startsWith("//") ? f = "https:" + e : e.startsWith("/") ? f = l + e : f = l + "/" + e), { title:
|
|
256
|
-
} catch (
|
|
257
|
-
console.error("Error fetching metadata:",
|
|
253
|
+
const c = new DOMParser().parseFromString(p, "text/html");
|
|
254
|
+
let a = c.querySelector('meta[property="og:title"]')?.getAttribute("content") || c.querySelector('meta[name="twitter:title"]')?.getAttribute("content") || c.querySelector("title")?.textContent || t;
|
|
255
|
+
a = a.trim();
|
|
256
|
+
let f = `https://www.google.com/s2/favicons?domain=${n.hostname}&sz=32`;
|
|
257
|
+
const e = c.querySelector('link[rel="icon"]')?.getAttribute("href") || c.querySelector('link[rel="shortcut icon"]')?.getAttribute("href") || c.querySelector('link[rel="apple-touch-icon"]')?.getAttribute("href");
|
|
258
|
+
return e && (e.startsWith("http") ? f = e : e.startsWith("//") ? f = "https:" + e : e.startsWith("/") ? f = l + e : f = l + "/" + e), { title: a, favicon: f };
|
|
259
|
+
} catch (n) {
|
|
260
|
+
console.error("Error fetching metadata:", n);
|
|
258
261
|
const l = new URL(t);
|
|
259
262
|
return {
|
|
260
263
|
title: l.hostname,
|
|
@@ -263,6 +266,7 @@ async function M(t) {
|
|
|
263
266
|
}
|
|
264
267
|
}
|
|
265
268
|
export {
|
|
269
|
+
C as loadNerdFonts,
|
|
266
270
|
E as useBeautyLink
|
|
267
271
|
};
|
|
268
272
|
//# 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 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","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","doc","title","favicon","faviconLink"],"mappings":";;AAKO,MAAMA,IAAgD;AAAA;AAAA,EAEzD,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA;AAAA,EAG5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA;AAAA,EAG3B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA;AAAA,EAG7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA;AAAA,EAG7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA;AAAA,EAG5B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC7B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC3B,KAAO,EAAE,MAAM,MAAM,OAAO,UAAA;AAAA,EAC5B,IAAM,EAAE,MAAM,MAAM,OAAO,UAAA;AAC7B;AC/DF,IAAIC,IAAc;AAEX,SAASC,IAAgB;AAO9B,MALI,OAAO,SAAW,OAAe,OAAO,WAAa,OAKrDD;AACF;AAGF,QAAME,IAAU;AAGhB,MAAI,SAAS,eAAeA,CAAO,GAAG;AACpC,IAAAF,IAAc;AACd;AAAA,EACF;AAEA,MAAI;AACF,UAAMG,IAAQ,SAAS,cAAc,OAAO;AAC5C,IAAAA,EAAM,KAAKD,GACXC,EAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAmBpB,SAAS,KAAK,YAAYA,CAAK,GAC/BH,IAAc,IAGV,OAAO,UAAY,OAAe,QAAQ,SAC5C,QAAQ,MAAM,oDAAoD;AAAA,EAEtE,SAASI,GAAO;AACd,YAAQ,MAAM,kDAAkDA,CAAK;AAAA,EACvE;AACF;AChDI,OAAO,SAAW,OACpBH,EAAA;AAWF,SAASI,EAAiBC,GAA4B;AACpD,MAAI;AAEF,UAAMC,IADS,IAAI,IAAID,CAAG,EACF,UAClBE,IAAUD,EAAS,YAAY,GAAG;AACxC,WAAIC,MAAY,MAAMA,MAAYD,EAAS,SAAS,IAAU,OACvDA,EAAS,UAAUC,IAAU,CAAC,EAAE,YAAA;AAAA,EACzC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUO,MAAMC,IAAgB,CAACC,GAAcC,IAAqB,WAAWC,MAAsC;AAChH,QAAMC,IAAW,uBACX,CAACC,GAAcC,CAAe,IAAIC,EAAuC,CAAA,CAAE,GAE3EC,IAAO,MAAM,KAAKP,EAAK,SAASG,CAAQ,CAAC,EAAE,IAAI,CAAAK,MAASA,EAAM,CAAC,CAAC;AAEtE,EAAAC,EAAU,MAAM;AAyCd,KAxCyB,YAAY;AACnC,iBAAWb,KAAOW;AAChB,YAAI,CAACH,EAAaR,CAAG,GAAG;AACtB,gBAAMc,IAAYf,EAAiBC,CAAG;AAGtC,cAAIc,KAAarB,EAAgBqB,CAAS,GAAG;AAC3C,kBAAMC,IAAWf,EAAI,MAAM,GAAG,EAAE,SAASA;AACzC,YAAAS,EAAgB,CAAAO,OAAS;AAAA,cACvB,GAAGA;AAAA,cACH,CAAChB,CAAG,GAAG;AAAA,gBACL,OAAO,mBAAmBe,CAAQ;AAAA,gBAClC,SAAS;AAAA,cAAA;AAAA,YACX,EACA;AACF;AAAA,UACF;AAEA,cAAI;AACF,oBAAQ,IAAI,0BAA0Bf,CAAG;AACzC,kBAAMiB,IAAW,MAAMC,EAAkBlB,CAAG;AAC5C,oBAAQ,IAAI,sBAAsBiB,CAAQ,GAC1CR,EAAgB,CAAAO,OAAS;AAAA,cACvB,GAAGA;AAAA,cACH,CAAChB,CAAG,GAAGiB;AAAA,YAAA,EACP;AAAA,UACJ,SAASnB,GAAO;AACd,oBAAQ,MAAM,gCAAgCE,GAAKF,CAAK,GACxDW,EAAgB,CAAAO,OAAS;AAAA,cACvB,GAAGA;AAAA,cACH,CAAChB,CAAG,GAAG;AAAA,gBACL,OAAOA;AAAA,gBACP,SAAS;AAAA,cAAA;AAAA,YACX,EACA;AAAA,UACJ;AAAA,QACF;AAAA,IAEJ,GAEA;AAAA,EACF,GAAG,CAACI,GAAM,KAAK,UAAUO,CAAI,CAAC,CAAC;AAE/B,QAAMQ,IAAqB,CAAA;AAC3B,MAAIC,IAAY,GACZR;AAGJ,OADAL,EAAS,YAAY,IACbK,IAAQL,EAAS,KAAKH,CAAI,OAAO,QAAM;AAC7C,UAAMJ,IAAMY,EAAM,CAAC,GACbS,IAAaT,EAAM;AAEzB,IAAIS,IAAaD,KACfD,EAAM,KAAKf,EAAK,UAAUgB,GAAWC,CAAU,CAAC;AAGlD,UAAMJ,IAAWT,EAAaR,CAAG,GAC3BsB,IAAeL,GAAU,QAC1BA,EAAS,MAAM,SAAS,KAAKA,EAAS,MAAM,UAAU,GAAG,EAAE,IAAI,QAAQA,EAAS,QACjFjB,GAEEuB,IAAaN,GAAU,SACvBH,IAAYf,EAAiBC,CAAG,GAChCwB,IAAWV,IAAYrB,EAAgBqB,CAAS,IAAI,MAEpDW,IAAsB,MAAM;AAChC,cAAQpB,GAAA;AAAA,QACN,KAAK;AACH,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,KAAK;AAAA,YACL,SAAS,CAACqB,MAAwB;AAChC,cAAAA,EAAE,eAAA,GACF,OAAO,KAAK1B,GAAK,UAAU,0CAA0C;AAAA,YACvE;AAAA,UAAA;AAAA,QAEJ,KAAK;AACH,iBAAO;AAAA,YACL,QAAQ;AAAA,UAAA;AAAA,QAGZ;AACE,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,KAAK;AAAA,UAAA;AAAA,MACP;AAAA,IAEN;AAEA,IAAAmB,EAAM;AAAA,MACJ,gBAAAQ;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAM3B;AAAA,UACL,GAAGyB,EAAA;AAAA,UACJ,OAAO;AAAA,YACL,OAAOnB,KAAe;AAAA,YACtB,gBAAgB;AAAA,YAChB,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,KAAK;AAAA,UAAA;AAAA,UAGN,UAAA;AAAA,YAAAkB,IACC,gBAAAI;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO;AAAA,kBACL,YAAY;AAAA,kBACZ,UAAU;AAAA,kBACV,OAAOJ,EAAS;AAAA,kBAChB,YAAY;AAAA,kBACZ,SAAS;AAAA,kBACT,OAAO;AAAA,kBACP,WAAW;AAAA,kBACX,YAAY;AAAA,gBAAA;AAAA,gBAEd,eAAY;AAAA,gBAEX,UAAAA,EAAS;AAAA,cAAA;AAAA,YAAA,IAEVD,IACF,gBAAAK;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAKL;AAAA,gBACL,KAAI;AAAA,gBACJ,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAA;AAAA,gBAChC,SAAS,CAACG,MAAM;AACb,kBAAAA,EAAE,OAA4B,MAAM;AAAA,gBACvC;AAAA,cAAA;AAAA,YAAA,IAGF,gBAAAC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAM;AAAA,gBACN,OAAM;AAAA,gBACN,QAAO;AAAA,gBACP,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,aAAY;AAAA,gBACZ,eAAc;AAAA,gBACd,gBAAe;AAAA,gBAEf,UAAA;AAAA,kBAAA,gBAAAC,EAAC,QAAA,EAAK,GAAE,8DAAA,CAA6D;AAAA,kBACrE,gBAAAA,EAAC,QAAA,EAAK,GAAE,+DAAA,CAA8D;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAG1E,gBAAAA,EAAC,UAAM,UAAAN,EAAA,CAAa;AAAA,UAAA;AAAA,QAAA;AAAA,QApDf,QAAQD,CAAU;AAAA,MAAA;AAAA,IAqDzB,GAGFD,IAAYC,IAAarB,EAAI;AAAA,EAC/B;AAEA,SAAIoB,IAAYhB,EAAK,UACnBe,EAAM,KAAKf,EAAK,UAAUgB,CAAS,CAAC,GAG/BD,EAAM,SAAS,IAAIA,IAAQ,CAACf,CAAI;AACzC;AAKA,eAAec,EAAkBlB,GAAoC;AACnE,MAAI;AACF,UAAM6B,IAAS,IAAI,IAAI7B,CAAG,GACpB8B,IAASD,EAAO,QAEhBE,IAAU;AAAA,MACd,sCAAsC,mBAAmB/B,CAAG,CAAC;AAAA,MAC7D,yBAAyB,mBAAmBA,CAAG,CAAC;AAAA,IAAA;AAGlD,QAAIgC,IAAO,IACPC,IAAU;AAEd,eAAWC,KAAYH;AACrB,UAAI;AACF,cAAMI,IAAW,MAAM,MAAMD,GAAU;AAAA,UACrC,QAAQ,YAAY,QAAQ,GAAK;AAAA;AAAA,QAAA,CAClC;AAED,YAAI,CAACC,EAAS,GAAI;AAElB,cAAMC,IAAO,MAAMD,EAAS,KAAA;AAC5B,QAAAH,IAAOI,EAAK,YAAYA,GACxBH,IAAU;AACV;AAAA,MACF,SAASI,GAAK;AACZ,gBAAQ,KAAK,iBAAiBH,GAAUG,CAAG;AAC3C;AAAA,MACF;AAGF,QAAI,CAACJ,KAAW,CAACD;AACf,YAAM,IAAI,MAAM,oBAAoB;AAItC,UAAMM,IADS,IAAI,UAAA,EACA,gBAAgBN,GAAM,WAAW;AAEpD,QAAIO,IACFD,EAAI,cAAc,2BAA2B,GAAG,aAAa,SAAS,KACtEA,EAAI,cAAc,4BAA4B,GAAG,aAAa,SAAS,KACvEA,EAAI,cAAc,OAAO,GAAG,eAC5BtC;AAEF,IAAAuC,IAAQA,EAAM,KAAA;AAEd,QAAIC,IAAU,6CAA6CX,EAAO,QAAQ;AAE1E,UAAMY,IACJH,EAAI,cAAc,kBAAkB,GAAG,aAAa,MAAM,KAC1DA,EAAI,cAAc,2BAA2B,GAAG,aAAa,MAAM,KACnEA,EAAI,cAAc,8BAA8B,GAAG,aAAa,MAAM;AAExE,WAAIG,MACEA,EAAY,WAAW,MAAM,IAC/BD,IAAUC,IACDA,EAAY,WAAW,IAAI,IACpCD,IAAU,WAAWC,IACZA,EAAY,WAAW,GAAG,IACnCD,IAAUV,IAASW,IAEnBD,IAAUV,IAAS,MAAMW,IAItB,EAAE,OAAAF,GAAO,SAAAC,EAAA;AAAA,EAClB,SAAS1C,GAAO;AACd,YAAQ,MAAM,4BAA4BA,CAAK;AAC/C,UAAM+B,IAAS,IAAI,IAAI7B,CAAG;AAC1B,WAAO;AAAA,MACL,OAAO6B,EAAO;AAAA,MACd,SAAS,6CAA6CA,EAAO,QAAQ;AAAA,IAAA;AAAA,EAEzE;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadNerdFonts.d.ts","sourceRoot":"","sources":["../../src/utils/loadNerdFonts.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,
|
|
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
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
font-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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,
|
|
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