Return

文章内嵌代码块-macOS Style

文章内嵌代码块-macOS Style
Table of Contents

如果我要持续技术学习类的文章写作,将在文章中放置大量代码。

但是 Astro 默认的代码块样式(Shiki)不够美观,且缺少功能性。

在此尝试实现了类 macOS 的视觉效果,并添加多种功能。

就以此作为个人博客的第一篇学习文章吧!

功能实现

  • 模拟 macOS 窗口栏

  • 语言类型提示

  • 复制按钮(手动去除 div 块带来的回车,实现紧密复制)

  • 下拉 / 收起代码块(已调整至合适视图)

  • 一定程度的抽象封装

需要注意的是,Astro v5 之后代码块行号记录不再能通过 config 显式开启。

原来只需要在 shikiConfig 中添加 lineNumbers: true

现在需要通过 CSS 来实现行号显示。

代码实现

  1. 容器与装饰

    /* 基础容器 */
    pre.astro-code {
      position: relative;
      overflow: hidden;
      margin-top: 1.5em;
      margin-bottom: 1.5em;
      padding: 0;
      max-width: 100%;
      box-sizing: border-box;
      border-radius: 8px;
      box-shadow: var(--box-shadow);
      font-size: 1rem;
      transition: max-height 0.3s ease-out;
    }
    /* 模拟 macOS 窗口栏 */
    pre.astro-code::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 2.5rem;
      background-color: #1e293b;
      background-image: 
        radial-gradient(circle at 1.5rem 1.25rem, #ff5f56 0.375rem, transparent 0.375rem),
        radial-gradient(circle at 2.75rem 1.25rem, #ffbd2e 0.375rem, transparent 0.375rem),
        radial-gradient(circle at 4rem 1.25rem, #27c93f 0.375rem, transparent 0.375rem);
      background-repeat: no-repeat;
      z-index: 1;
    }
    /* 语言提示 */
    pre.astro-code::after {
      content: attr(data-language);
      position: absolute;
      top: 0.375rem;
      right: 5.5rem;
      padding: 0.125rem 0.5rem;
      border-radius: 0.25rem;
      font-size: 1.25rem;
      font-weight: 600;
      text-transform: uppercase;
      z-index: 1;
      display: inline-block;
    }
  2. 图标与按钮系统

    /* [抽象基类] 布局核心:负责定位、尺寸与对齐 */
    pre.astro-code .astro-code-icon-base {
      position: absolute;
      top: 0.25rem;
      width: 2rem;
      height: 2rem;
      padding: 0.125rem;
      border-radius: 0.25rem;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    /* [交互组件] 按钮外观:负责点击反馈、背景与层级 */
    pre.astro-code .astro-code-icon-btn {
      border: none;
      background-color: transparent;
      cursor: pointer;
      z-index: 3;
      transition: background-color 0.2s;
      outline: none;
    }
    pre.astro-code .astro-code-icon-btn:hover {
      background-color: rgba(0, 0, 0, 0.5);
    }
    /* [实例] 下拉/收回按钮 */
    pre.astro-code .toggle-btn {
      right: 3.25rem;
    }
    /* [实例] 复制功能组 */
    pre.astro-code .copy-btn,
    pre.astro-code .copy-success {
      right: 1rem;
    }
    /* 复制成功状态特有样式 */
    pre.astro-code .copy-success {
      z-index: 4;
      opacity: 0;
      transition: opacity 0.2s;
      pointer-events: none;
    }
    pre.astro-code .copy-success.show {
      opacity: 1;
    }
  3. 代码内容与行号

    pre.astro-code > code {
      display: block;
      width: 100%;
      padding: 3.5rem 1.5rem 1.5rem 3rem;
      counter-reset: line;
      box-sizing: border-box;
      overflow: auto;
      max-height: 49rem;
      line-height: 0.75rem;
    }
    /* 折叠状态逻辑 */
    pre.astro-code.collapsed > code {
      max-height: 22rem;
    }
    /* Shiki 行容器 */
    .astro-code .line {
      display: block;
      position: relative;
      max-width: 100%;
      box-sizing: border-box;
      min-height: 0.75rem;
    }
    /* 自动行号生成 */
    .astro-code .line::before {
      content: counter(line);
      counter-increment: line;
      position: absolute;
      top: 0;
      left: -3.3rem;
      width: 2.5rem;
      text-align: right;
      color: inherit;
      opacity: 0.7;
      user-select: none;
      pointer-events: none;
    }