MoreRSS

site iconsugar | 粥里有勺糖修改

99年,西南石油大学,热爱开源。前端,美团,阿里。运营视野修炼周刊。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

sugar | 粥里有勺糖的 RSS 预览

开发一个美观的 VitePress 图片预览插件

2026-01-10 15:15:07

开发一个美观的 VitePress 图片预览插件

前言

笔者维护的 VitePress 博客主题已经集成了非常多的功能,为便于在主题之外复用,因此有计划将其一部分功能分离出来,形成独立的插件。

现在又有AI加持,再已经有通用插件模板前提下,使用AI就能完成95%的插件工作量!

分离的 图片预览插件,效果如下:

组件样式实现参考了 Element Plus Image Viewer

接下来先简单介绍一下用法,再快速讲解核心原理。

插件开发基于之前创建的一个通用模板,vitepress-plugin-slot-inject-template,在模板的基础上,插件95%的代码由 Gemini 3.0 生成。

如何使用

只需要 2 步:

  1. 安装插件
sh
pnpm add vitepress-plugin-image-preview
  1. 配置插件

引入插件在 .vitepress/config.mts VitePress 配置文件中

ts
import { defineConfig } from 'vitepress'
import { ImagePreviewPlugin } from 'vitepress-plugin-image-preview'

export default defineConfig({
  vite: {
    plugins: [
      ImagePreviewPlugin()
    ]
  }
})

实现原理

这里只阐述关键点,细节与之前的公告插件类似,这里不做赘述。

VitePress 默认主题 Layout.vue 组件预设的一些插槽,只需将实现自定义组件注入到对应插槽为止即可。

所有的 slotsVitePress 文档里也有介绍

注入自定义组件

利用插件的 transform 钩子,将我们的 <ImagePreview /> 组件插入到 Layout.vue 的特定插槽位置

图片预览组件我这里使用的是 doc-beforepage-top 两个插槽。

使用 alias 保证引入组件的路径正确映射。

ts
// 仅包含关键代码
const componentName = 'ImagePreview'
const componentFile = `${componentName}.vue`
const aliasComponentFile = `${getDirname()}/components/${componentFile}`
function ImagePreviewPlugin(options = {}) {
  return {
    // 添加alias
    config: () => {
      return {
        resolve: {
          alias: {
            [`./${componentFile}`]: aliasComponentFile
          }
        }
      }
    },
    transform(code, id) {
      // 筛选出 Layout.vue
      if (id.endsWith('vitepress/dist/client/theme-default/Layout.vue')) {
        let transformResult = code

        // 插入组件
        const slots = [options.slots || ['doc-before', 'page-top']].flat()
        for (const slot of slots) {
          const slotPosition = `<slot name="${slot}" />`
          // 添加 ClientOnly 目的是避免组件在SSG的时候被渲染
          transformResult = transformResult.replace(slotPosition, `${slotPosition}\n<ClientOnly><${componentName} /></ClientOnly>`)
        }

        // 导入组件
        const setupPosition = '<script setup lang="ts">'
        transformResult = transformResult.replace(setupPosition, `${setupPosition}\nimport ${componentName} from './${componentFile}'`)
        return transformResult
      }
    },
  }
}

插件配置传递

采用虚拟模块的方式传递配置。

组件中导入配置:

ts
import options from 'virtual:image-preview-options'

插件中处理虚拟模块:

ts
const virtualModuleId = 'virtual:image-preview-options'
const resolvedVirtualModuleId = `\0${virtualModuleId}`
function ImagePreviewPlugin(options = {}) {
  return {
    // 省略其它无关代码...
    resolveId(id) {
      if (id === virtualModuleId) {
        return resolvedVirtualModuleId
      }
    },
    load(this, id) {
      if (id === resolvedVirtualModuleId) {
        return `export default ${stringify(options)}`
      }
    },
  }
}

核心交互实现

图片预览的核心逻辑在于监听图片的点击事件,获取图片列表,并显示预览遮罩。

  1. 事件监听:在 onMounted时,给内容的容器注册点击事件,在点击的时候获取容器中所有的图片元素,然后做后续操作。
ts
onMounted(() => {
  const wrapperId = imagePreviewOptions?.wrapperId || '#VPContent'
  const docDomContainer = document.querySelector(wrapperId)
  docDomContainer?.addEventListener('click', previewImage)
})

function previewImage(e: Event) {
  const target = e.target as HTMLElement
  const currentTarget = e.currentTarget as HTMLElement
  if (target.tagName.toLowerCase() === 'img') {
    const selector = imagePreviewOptions?.selector || '.content-container .main img,.VPPage img'
    const imgs = currentTarget.querySelectorAll<HTMLImageElement>(selector)
    const idx = Array.from(imgs).findIndex(el => el === target)
    const urls = Array.from(imgs).map(el => el.src)
    // 省略其它逻辑
  }
}
  1. 预览组件:参考了 Element Plus 的 图片预览组件的样式与功能,这部分完全由 AI 实现(Gemini 3.0),还原度非常高。

插件模板介绍

在开发插件的过程中,笔者把此类基于 slot 位置注入的插件分离了一个模板 vitepress-plugin-slot-inject-template

有相关诉求的朋友,可以基于此模板,配合 AI 快速的开发各种基于插槽就可以实现的组件能力。

最后

插件完整源码 vitepress-plugin-image-preview

最后再感叹一句,AI 太牛逼了,效率起飞。

欢迎评论区交流&指导。

心外“天花板”手术经历

2026-01-07 15:05:40

心外“天花板”手术经历

终于闯过最难的一关了,身体里的大患彻底刨除。

25年12月25日进行的胸腹主替换手术,时长约6小时,由心外顶尖医生"孙立忠"主刀,顺利拿下;近期状态恢复得还行,在这里记录分享一下相关细节。

病情回顾

25年2月4日,突发胸&背&腰痛,急诊去医院做了增强CT;确诊为主动脉夹层B型,整个降主动脉几乎完全撕裂。

当时我就在想是不是要做胸腹主置换了,工作了几年生活刚好起来就发难了

为什么跑上海来做手术

最开始发病,急诊去了四川华西,但由于病情复杂,华西并没有给到可靠的治疗方案,给予常规止痛降血压治疗了1周,就给转到疗养医院(急性期内不让下床,让躺一个月)。

托朋友先去了北京安贞,找了朱俊明医生(顶尖的心外医生),得到的结论也是做胸腹主置换,让先床上躺够时间,等待血肿吸收。

于是在25年3月9日,就动身去了北京,线下面诊了医生,医生看过当下身体情况后,不是特别乐观,现在的状态不是很能支持这个手术,让考虑清楚再来找他。(安贞住院得排差不多1个月起的队)

3月14日的时候又突发心悸,120又拉到医院做了检查,病情又有所进展。

没招了,只好去最后一个选择了,上海德达医院,另一位心外科大佬“孙立忠”在这里坐镇。

"上海德达心血管医院" ,在心血管领域算是最后一站了,很多其他医院不收的复杂病例的都往这里跑。

这家医院是私立医院,有一些自主定价的额外费用不在医保范围内。

孙院长给了一个相对安全折中的治疗方案,难以操作的部分先通过介入处理,剩余部分再外科手术处理。

于是3月和9月做了两次介入,年底来复查的时候,未处置的部分进展过于迅速,就安排做外科手术,处理剩余病变部分。

术前

  1. 一顿检查+各项指标评估

常规的化验、各种超声、增强CT、脑部磁共振。

刚好也赶上年底病人相对较少,第四天就安排手术了!

  1. 术前身体准备

备皮(头部以下,剃光光);灌肠(使用开塞露Plus😱)。

  1. 术前谈话告知风险

小概率会截瘫;术中大出血。

手术当日

手术排在了第二台,上午没有排上,就安排了静脉补液。

下午大概 1:30 进的手术室,准备阶段我还清醒着,配合完整左右手的穿刺,还有背部脊柱侧的穿刺,说是术中必要的时候补充脑脊液。

这三针搞完,就准备推麻药了,医生告知准备睡觉了,松了一口气,不用醒着受罪了(非常有经验了,今年第三次全麻)。这次数了一下大概30次心跳左右就睡过去了。

晚上 7:30 左右手术结束,整个过程耗时6小时。

医生给到的答复是手术很成功,但肋间动脉质量差没缝合上,不过腰间的侧支循环供血比较好(前2次支架后长出了许多侧枝),有可能会起作用,不至于截瘫,一切要等我醒了之后活动一下才知道。

ICU观察

ICU 里一共呆了3天,第四天早上转入普通病房。

① 第一天:

大概是第二天早上被ICU护士唤醒的,醒来后第一时间就是感受一下腿脚哈哈。幸亏还是好的,护士也松了一口气。

身体状态如下:

醒了之后嘴里插着呼吸管,左右手都被绑着,避免抓挠呼吸管;护士说下午才能拔,这期间就没法说话,拔完4小时才能少量饮水,下午拔完呼吸管后,喉咙肿痛,声音沙哑。

下午家属进来探视的时候,我问护士可不可以喝点有味道的甜水,让家属买,护士说他这有冰红茶,说可以喝一点点。(一共喝了3次,每次10ml)

最难受的就是吸痰了,不过这次痰少,只吸了几次。

除了呼吸管,身上还有引流管,鼻子里有胃管,脖子/手/脚上都有穿刺的针。

痛其实还好,没啥感觉,第一天听护士说给了吗啡,还有一个止痛泵,会不停地提供止痛药,也可以在痛的厉害的时候自己手动按。

不过这药有致幻效果🍄,眼睛一闭上就各种幻象,睡觉也是不断地梦,人睡得浑浑噩噩的。

② 第二天

早上在超声复查身体的时候,胸腔右侧有许多积液,后背又挨了一小刀,穿刺引流。

今天的护士隔一段时间就给我翻一下身,然后使劲的拍背让咳痰。(哎哟,要了老命了)

③ 第三天

由于一直没有通气(放屁),今天给了一个促进肠道的药,中午晚上吃了两次,我感觉肚子里已经有气了,醒着的时候就不停地用手揉,累了就睡。

没通气就不能吃东西,水的话一小时也只能喝几十毫升

这两天脑脊液量差不多达标了,晚上把背上脑脊液引流的针拔了,需要平躺6小时,没搞好的话说会引起头疼。

④ 第四天

一大早ICU 医生看了一下状态指标都还可以,就吩咐护士把身上能拔的管子和针都拔了,留了左腹部引流和脖子上输液的针,然后转到了普通病房,

普通病房休养

12月29日早上转回的普通病房。

护士交接的时候发现,背上有比较严重的压疮,在ICU里躺太久,皮肤压伤了,建议尽量侧着躺,背上搞了一些贴贴保护。

早上给伤口消毒的时候才看见伤口长啥样:

  1. 腹股沟有一处:伤口像个 T 字形,大概 6cm 左右,问了一下是用于建立体外循环的。
  2. 胸腹主置换的刀口:从左背到左腹部完整的一刀,大概 4&50cm

普通病房的床睡着非常不舒服,第一天有止痛泵还好,给人能整得迷迷糊糊的睡。

第二天止痛泵就用完了,白天没精神的时候就睡,伤口不算特别痛,但是两侧肩膀和左腰非常的酸胀,怎么躺都难受,只有特别疲惫的时候才能睡着,醒了就一身酸痛。

医生给搞了点膏药贴在几个痛处

第3/4天的时候状态稍微好点,肩膀不再酸胀了,偶尔床边坐坐,其它时间除了上厕所都是在床上躺着,在床上转辗反侧,滚来滚去。

第五天早上早床边坐了一会儿,突然腹股沟处的伤口刺痛,我赶紧上床准备躺一会儿,定睛一看伤口周围肿胀起来了,皮肤被撑得鼓鼓的。赶紧叫护士让医生过来看看。

医生来摸了一下,说有搏动,不排除“假性动脉瘤”的可能,如果确认是的话就得拉到手术室搞了。赶紧让超声来看看,由于当天还在元旦假期,只有一个超声医生值班,轮到我检查已经是过来好几个小时了。看完说里面没有血流信号,就把危险的情况排除了,说可能是血肿,内部伤口渗液,说会自行吸收。

次日就没下床活动了,担心给血肿搞大;早上医生查房,主任医生摸了一下说有可能是淋巴漏了,血管都是缝合过的不可能漏。

第七天早上查房发现腹部的伤口一直没有结痂,有脂肪液化的现象,说要挤出来,然后就由医生单独用手挤压伤口然后消毒,脂肪液化预估要挤好几天。

第八天继续搞脂肪液化的问题,但出现了小插曲,医生在用力挤的时候,我突然感觉腹股沟有一股热流,感觉什么东西破了一样,然后看到之前肿胀的位置变得更大了,给医生吓一跳,赶紧让超声第一时间来看什么情况。

让超声医生仔细看一下到底有没有血流,最后还是没有血流信号,不过下面的动/静脉都有一定程度受压,医生说得搞一下给里面东西抽出来看看到底是什么。

于是叫护士拿了一堆不同规格的针筒过来,先用 1ml 的扎了下去,抽出来是黄色的液体,医生松了一口气,确定就是淋巴液。

然后换成 10ml 的,这个针头明细感觉大一些,扎下去有明细疼痛,抽完后又准备换20ml的,我说哎要不就10ml的抽,20ml的扎着会更痛。医生赶紧说别担心,这次只换针筒不换针头,不用再挨一针,连着抽了2个20ml后,鼓包就消下去了,剩下的一点说让自行吸收,避免针头探太深,扎到动脉。

抽完就加压包扎了一下,说压几天,避免持续渗液。

第九天脂肪液化还是存在,导致伤口没法结痂一直渗液。今天医生说重新缝合一下这部分,然后就在病房里一顿操作,局部麻醉,先把原来的伤口剪开,然后消毒清理后,重新缝合,缝了6针,非常的紧实能感觉到,肚皮都绷紧了的感觉。

整个操作过程除了打麻药痛,缝合就是有感觉,但不痛,麻药劲儿过了之后才开始渐渐有点感觉,皮肤表面缝合的线至少要14天才能拆。

最后

现在整体状态还不错,能够坐起来玩玩手机和电脑了(第一时间就把本篇小作文码了出来),快的话估计最多还有1周就会叫出院了,伤口拆线估计得回家自己找医院拆了。

又双叒住院了

2025-12-23 12:13:05

又双叒住院了

上周六 ✈️ 到上海来复查一下身体情况,做了一些检查。

周一上午找了专家面诊,给了治疗建议,尽快手术处理,拖着就是定时炸弹,回家也是提心吊胆的。

来之前有做心理准备,只是比预期来得早一点。

周一下午就办了入院,这次是个大手术了,医生保守估计住院天数在20天左右。

这几天就搞各种检查,快的话这周就能把手术排上。

希望一切顺利!


大伙儿也多关注一下身体的健康情况,有问题及时就医。

视野修炼第128期 | Bun 被收购

2025-12-07 17:55:47

视野修炼第128期 | Bun 被收购

欢迎来到第 128 期的【视野修炼 - 技术周刊】,下面是本期的精选内容简介

下面开始本期内容的介绍ღ( ´・ᴗ・` )比心

🔥强烈推荐

1. Anthropic 收购 Bun

Anthropic 是 Claude 大模型背后的公司。

Bun 作者发布的阐述博客内容中翻:Bun 被 Anthropic 收购

2. Mole - Mac 垃圾清理工具

一个终端工具,功能很丰富!

分析:

清理:

系统状态:

所有指令

3. React 高危漏洞

React Server Components(RSC)出现了一个最高级别(CVSS 10) 的安全漏洞。

攻击者可以直接在目标服务器上执行恶意代码。

笔者没有跑 Next.js 应用,没有受到影响。

更多信息↓:

  1. Cloudflare 本周又挂掉:因防御 React Server Components 漏洞,Cloudflare 遭遇 25 分钟服务故障

  2. bug 如何产生和修复看这里: React Server Components RCE 漏洞分析

钻了原型链漏洞,修复只需加上 hasOwnProperty 就行!

  1. 鱼皮阐述受到攻击:Next.js高危漏洞致服务器被黑,我已中招!

  2. 如何发现和利用漏洞插件:Next.js无条件RCE漏洞 - 浏览器插件

https://github.com/mrknow001/RSC_Detector

🔧开源工具&技术资讯

4. code996

code996 是一个分析工具,它可以统计 Git 项目的 commit 时间分布,进而推导出项目的编码工作强度。

sh
npx code996

5. Vite 8 发布 Beta

由 Rolldown 驱动。

6. 基于Web本地化的图片编辑器

7. Gitmal - Git 仓库变成静态站点

8. GitHub 分享卡片生成

支持多种样式定制。

⭐️强力推荐关注

周刊部分内容来源如下渠道,推荐大家关注。

视野修炼第127期 | Valdi

2025-11-16 17:40:58

视野修炼第127期 | Valdi

欢迎来到第 127 期的【视野修炼 - 技术周刊】,下面是本期的精选内容简介

下面开始本期内容的介绍ღ( ´・ᴗ・` )比心

🔥强烈推荐

1. tasuku - 极简 Node 任务处理

js
import task from 'tasuku'

task('Task 1', async () => {
  await someAsyncTask()
})

task('Task 2', async () => {
  await someAsyncTask()
})

task('Task 3', async () => {
  await someAsyncTask()
})

在做 CLI 的时候可以用上,尤其需要处理多个异步任务时。

还支持嵌套,多状态展示等。

感觉和 @clack/prompts 和非常搭配。

收藏 ⭐️!

2. fkill - 强制终止进程

进程大杀器,支持多种终止进程的方式👍🏻,跨平台可用。

js
import fkill from 'fkill'

await fkill(1337)
console.log('Killed process')

fkill('Safari')
fkill(':8080')

fkill([1337, 'Safari', ':8080'])

也支持 CLI 调用。

sh
npm install --global fkill-cli

fkill 1337
fkill Safari
fkill :8080

还支持 交互式 CLI。

赶紧装上。

3. FileMock

免费的测试文件生成器,支持视频/图片/音乐/文档等多种格式。

收藏⭐️,基本覆盖了常见的文件格式!

🔧开源工具&技术资讯

4. Valdi - 新的跨平台 UI 框架

使用 TypeScript&TSX 编写 UI,可以直接编译成 iOS、Android 和 macOS 上 由 Native 渲染的视图应用,无 JS 中间层。

笔者拉仓库试了一下 Demo,效果如下。

感觉还行,就是才刚开源,文档还不是特别友好,项目初始化流程不是特别标准。

5. JavaScript 引擎大全

包含上百种 JS 引擎的基本信息 ES 支持程度,性能等对比信息。

📚教程&文章

6. 使用 Error.cause 进行错误处理

使用 Error.cause 处理错误,保留更清晰的堆栈跟踪信息。

js
function fetchUserData() {
  try {
    JSON.parse('{ broken: true }') // ← This will fail
  }
  catch (parseError) {
    throw new Error('Failed to fetch user data', { cause: parseError })
  }
}

try {
  fetchUserData()
}
catch (err) {
  console.error(err.message) // "Failed to fetch user data"
  console.error(err.cause) // [SyntaxError: Unexpected token b in JSON]
  console.error(err.cause instanceof SyntaxError) // true
}

🤖AI工具&资讯

7. GitHub Repo Visibility Analyzer

这个免费的工具可以对你的仓库进行分析,提供主题标签建议和其他推荐的行动项,帮助开发者更容易地找到你的项目。

提升你在 GitHub 搜索、Google 和大型语言模型(LLMs)中的仓库可见性。

⭐️强力推荐关注

周刊部分内容来源如下渠道,推荐大家关注。

视野修炼第126期 | TypeScript #1

2025-11-08 19:48:20

视野修炼第126期 | TypeScript #1

欢迎来到第 126 期的【视野修炼 - 技术周刊】,下面是本期的精选内容简介

养了一段时间身体,又断更了 2 月 😄。

🔥强烈推荐

1. 🤫spoilerjs

一个框架无关的 Web 组件,用于创建带有粒子动画效果的隐藏文字内容。

html
<h1>
  Beautiful
  <spoiler-span>
    spoiler effects
  </spoiler-span>|
</h1>

⭐️!

2. 🏆 TypeScript 跃升至 #1 - GitHub 上最常用的语言

2025 年 8 月,TypeScript 超越了 Python 和 JavaScript,TypeScript 现在是 GitHub 上最常用的语言 。

3. 中国法定假日查询库

做复杂日历组件必备!收藏+1。

🔧开源工具&技术资讯

4. type-flag - 类型化命令行参数解析

sh
my-script --name John --age 20
ts
import { typeFlag } from 'type-flag'

const parsed = typeFlag({
  name: String,
  age: {
    type: Number,
    alias: 'a'
  }
})

console.log(parsed.flags.name) // 'John'
console.log(parsed.flags.age) // 20

5. Node v24 已经是最新的LTS 版本

6. TypingSVG

生成由 SVG 驱动的打字动画。

Typing SVG

7. 腾讯 TDesign 组件库的 uniapp 适配

先收藏,uni-app 开发小程序可以考虑考虑。

8. Dayflow - 每日的电脑使用分析

开源的 macOS 桌面应用,可以生成电脑屏幕一天的时间占用。它每秒截一次屏,然后交给 AI 分析,生成你一天活动的时间线。

本地使用阿里开源的 qwen 模型。

支持以视频的形式回顾屏幕历史。

windows 上印象也也有类似的工具(待我翻翻吃灰的收藏夹 再贴上来)。

9. image-dimensions

获取图片的尺寸信息,支持现代的js运行环境(浏览器、Node.js、Bun、Deno等)

js
import { imageDimensionsFromStream } from 'image-dimensions'

// example1
const url = 'https://sindresorhus.com/unicorn'

const { body } = await fetch(url)

console.log(await imageDimensionsFromStream(body))

// example2
const data = getImage()

console.log(imageDimensionsFromData(data))
// => {width: 1920, height: 1080, type: 'png'}

10. Biome v2.3

Biome 是一个适用于 JavaScript、TypeScript、JSX等快速格式化工具,与 Prettier 有高达 97% 的兼容覆盖率,同时也是一个高性能的 linter。

现在支持 Vue、Svelte 和 Astro lint和格式化了!

11. Vercel 支持 Bun 运行时

12. emoji-regex

提供匹配表情符号的正则

js
const emojiRegex = require('emoji-regex')

const regex = emojiRegex()

for (const match of text.matchAll(regex)) {
  const emoji = match[0]
}

⭐️!

⭐️强力推荐关注

周刊部分内容来源如下渠道,推荐大家关注。