与 DaisyUI 集成

DaisyUI 是一个基于 Tailwind CSS 的组件库,提供了丰富的 UI 组件。本页面展示如何将 rehype-smart-links 与 DaisyUI 组件集成,为链接添加漂亮的样式和交互效果。

基础按钮链接

将链接转换为 DaisyUI 按钮样式:

DaisyUI 按钮样式链接

内部链接

外部链接

断开链接

JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        internalLinkClass: 'btn btn-primary',
        externalLinkClass: 'btn btn-secondary',
        brokenLinkClass: 'btn btn-error',
        externalLinkAttributes: {
          target: '_blank',
          rel: 'noopener noreferrer'
        }
      }
    ]]
  }
});

带图标的按钮

在 DaisyUI 按钮中添加图标:

带图标的DaisyUI按钮

内部链接

外部链接

断开链接

JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';
import { h } from 'hastscript';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        wrapperTemplate: (node, linkType) => {
          let icon;

          if (linkType === 'internal') {
            // 内部链接的信息图标
            icon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              class: 'h-5 w-5',
              fill: 'none',
              viewBox: '0 0 24 24',
              stroke: 'currentColor'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
              })
            ]);
            
            // 设置类并添加图标
            node.properties.className = ['btn', 'btn-primary', 'gap-2'];
            node.children = [icon, ...node.children];
          } 
          else if (linkType === 'external') {
            // 外部链接的箭头图标
            icon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              class: 'h-5 w-5',
              fill: 'none',
              viewBox: '0 0 24 24',
              stroke: 'currentColor'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14'
              })
            ]);
            
            // 设置类并添加图标
            node.properties.className = ['btn', 'btn-accent', 'gap-2'];
            node.properties.target = '_blank';
            node.properties.rel = 'noopener noreferrer';
            node.children = [icon, ...node.children];
          } 
          else if (linkType === 'broken') {
            // 失效链接的警告图标
            icon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              class: 'h-5 w-5',
              fill: 'none',
              viewBox: '0 0 24 24',
              stroke: 'currentColor'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z'
              })
            ]);
            
            // 设置类并添加图标
            node.properties.className = ['btn', 'btn-error', 'gap-2'];
            node.children = [icon, ...node.children];
          }
          
          return node;
        }
      }
    ]]
  }
});

链接卡片

将链接转换为 DaisyUI 卡片组件:

链接卡片

JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';
import { h } from 'hastscript';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        wrapperTemplate: (node, linkType, url) => {
          // 创建卡片容器
          const cardDiv = h('div', {
            class: linkType === 'broken' 
              ? 'card w-96 bg-base-300 shadow-xl' 
              : 'card w-96 bg-base-100 shadow-xl hover:shadow-2xl transition-shadow duration-300'
          });
          
          // 复制原始链接的属性到新的a元素
          const linkProps = { ...node.properties, class: 'card-body' };
          const cardLink = h('a', linkProps);
          
          // 根据链接类型创建不同内容
          let title, description, button;
          
          if (linkType === 'internal') {
            title = h('h2', { class: 'card-title' }, '关于我们');
            description = h('p', {}, '了解更多关于我们的团队和使命');
            button = h('button', { class: 'btn btn-primary' }, '查看');
          } 
          else if (linkType === 'external') {
            title = h('h2', { class: 'card-title' }, 'GitHub');
            description = h('p', {}, '访问我们的GitHub仓库');
            
            // 创建带有图标的按钮
            const externalIcon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              class: 'h-4 w-4 ml-1',
              fill: 'none',
              viewBox: '0 0 24 24',
              stroke: 'currentColor'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14'
              })
            ]);
            
            button = h('button', { class: 'btn btn-accent' }, ['访问 ', externalIcon]);
          } 
          else if (linkType === 'broken') {
            title = h('h2', { class: 'card-title text-error' }, '链接失效');
            description = h('p', {}, '此链接不存在或已被移除');
            button = h('button', { class: 'btn btn-outline btn-error' }, '链接已断开');
          }
          
          // 创建卡片动作区域
          const cardActions = h('div', { class: 'card-actions justify-end' }, [button]);
          
          // 将所有元素组合起来
          cardLink.children = [title, description, cardActions];
          cardDiv.children = [cardLink];
          
          return cardDiv;
        }
      }
    ]]
  }
});

标签徽章链接

使用 DaisyUI 的徽章组件美化链接:

徽章样式链接

内部链接

外部链接

断开链接

JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        internalLinkClass: 'badge badge-primary p-4',
        externalLinkClass: 'badge badge-secondary p-4',
        brokenLinkClass: 'badge badge-error p-4',
        externalLinkAttributes: {
          target: '_blank',
          rel: 'noopener noreferrer'
        }
      }
    ]]
  }
});

提示框链接

将链接包装在 DaisyUI 的提示框组件中:

提示框链接

内部链接

外部链接

断开链接

链接失效:无法访问
JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';
import { h } from 'hastscript';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        wrapperTemplate: (node, linkType) => {
          let alertType, icon, text;
          
          // 保存原始链接的属性和内容
          const linkProps = { ...node.properties, class: 'font-bold ml-1' };
          const linkContent = [...node.children];
          
          if (linkType === 'internal') {
            alertType = 'alert-info';
            text = '查看';
            icon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              fill: 'none',
              viewBox: '0 0 24 24',
              class: 'stroke-current shrink-0 w-6 h-6'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
              })
            ]);
          } 
          else if (linkType === 'external') {
            alertType = 'alert-success';
            text = '访问';
            icon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              class: 'stroke-current shrink-0 h-6 w-6',
              fill: 'none',
              viewBox: '0 0 24 24'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z'
              })
            ]);
            
            // 为外部链接添加属性
            linkProps.target = '_blank';
            linkProps.rel = 'noopener noreferrer';
          } 
          else if (linkType === 'broken') {
            alertType = 'alert-error';
            text = '链接失效:';
            icon = h('svg', {
              xmlns: 'http://www.w3.org/2000/svg',
              class: 'stroke-current shrink-0 h-6 w-6',
              fill: 'none',
              viewBox: '0 0 24 24'
            }, [
              h('path', {
                'stroke-linecap': 'round',
                'stroke-linejoin': 'round',
                'stroke-width': '2',
                d: 'M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z'
              })
            ]);
          }
          
          // 创建新的链接和包装元素
          const link = h('a', linkProps, linkContent);
          const textSpan = h('span', {}, text);
          const textDiv = h('div', {}, [textSpan, link]);
          const alert = h('div', { class: `alert ${alertType} shadow-lg` }, [icon, textDiv]);
          
          return alert;
        }
      }
    ]]
  }
});

自适应链接样式

根据不同主题和颜色方案调整链接样式:

自适应主题链接

内部链接

外部链接

断开链接

JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        internalLinkClass: 'link link-primary link-hover',
        externalLinkClass: 'link link-secondary link-hover',
        brokenLinkClass: 'link link-error link-hover',
        externalLinkAttributes: {
          target: '_blank',
          rel: 'noopener noreferrer'
        }
      }
    ]]
  }
});

综合案例

将 DaisyUI 的多个组件组合使用:

混合使用多种组件

内部链接

文档

这是一个内部文档链接

外部链接

外部

这是一个外部资源链接

断开链接

失效

这个链接已经失效或不存在

JS
// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeSmartLinks from 'rehype-smart-links';
import { h } from 'hastscript';

export default defineConfig({
  markdown: {
    rehypePlugins: [[
      rehypeSmartLinks, 
      {
        wrapperTemplate: (node, linkType) => {
          // 创建卡片基础结构
          const bgClass = linkType === 'broken' ? 'bg-base-300' : 'bg-base-100';
          const cardDiv = h('div', { class: `card ${bgClass} shadow-xl` });
          const cardBody = h('div', { class: 'card-body' });
          
          // 创建标题和徽章
          let badgeType, badgeText, linkText, btnClass, iconPath;
          
          if (linkType === 'internal') {
            badgeType = 'badge-primary';
            badgeText = '文档';
            linkText = '浏览文档';
            btnClass = 'btn-primary';
            iconPath = 'M9 5l7 7-7 7';
          } 
          else if (linkType === 'external') {
            badgeType = 'badge-secondary';
            badgeText = '外部';
            linkText = '访问资源';
            btnClass = 'btn-secondary';
            iconPath = 'M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14';
            
            // 为外部链接添加属性
            node.properties.target = '_blank';
            node.properties.rel = 'noopener noreferrer';
          } 
          else if (linkType === 'broken') {
            badgeType = 'badge-error';
            badgeText = '失效';
            linkText = '尝试访问';
            btnClass = 'btn-outline btn-error';
            iconPath = 'M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z';
          }
          
          // 创建各个元素
          const badge = h('span', { class: `badge ${badgeType}` }, badgeText);
          const cardTitle = h('h2', { class: 'card-title' }, [badge]);
          
          // 描述文本
          const descriptionText = linkType === 'internal'
            ? '这是一个内部文档链接'
            : linkType === 'external'
              ? '这是一个外部资源链接'
              : '这个链接已经失效或不存在';
          
          const description = h('p', {}, descriptionText);
          
          // 创建图标
          const svgAttrs = linkType === 'external'
            ? { xmlns: 'http://www.w3.org/2000/svg', width: '16', height: '16', fill: 'none', viewBox: '0 0 24 24', class: 'inline-block w-5 h-5 ml-2 stroke-current' }
            : { xmlns: 'http://www.w3.org/2000/svg', fill: 'none', viewBox: '0 0 24 24', class: 'inline-block w-5 h-5 ml-2 stroke-current' };
          
          const icon = h('svg', svgAttrs, [
            h('path', {
              'stroke-linecap': 'round',
              'stroke-linejoin': 'round',
              'stroke-width': '2',
              d: iconPath
            })
          ]);
          
          // 设置链接属性和内容
          node.properties.className = `btn ${btnClass}`;
          node.children = [linkText, ' ', icon];
          
          // 创建卡片动作区域
          const cardActions = h('div', { class: 'card-actions justify-end' }, [node]);
          
          // 组合所有元素
          cardBody.children = [cardTitle, description, cardActions];
          cardDiv.children = [cardBody];
          
          return cardDiv;
        }
      }
    ]]
  }
});

下一步

浏览更多示例:

相关链接 Astro Tailwind CSS DaisyUI
资源 GitHub NPM