MoreRSS

site icon李瑞豪修改

一名前端開發工程師,hugo-fixit 的創建者,經常在 菠菜眾長 1 和 FixIt2 上撰寫文章和文檔。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

李瑞豪的 RSS 预览

A Christmas Easter Egg by JavaScript.

2025-12-24 11:31:47

🎄 Santa Hat | FixIt

一个 JavaScript 实现的圣诞节小彩蛋。

简体中文 | 繁體中文 | English | Français | Русский язык | Español | हिन्दी | deutsch | 한국어 | しろうと

特性

santa-hat

  • 🎅 自动在圣诞节期间(12 月 20 日至 26 日)为网站 Logo 添加圣诞帽装饰
  • 🎯 自动检测当前日期,无需手动开关
  • 💫 轻量级实现,不影响网站性能

要求

  • FixIt v0.4.0 或更高版本。

安装组件

安装方式与 安装主题 相同,有多种安装方式,任选一种即可,这里介绍两种主流方式。

作为 Hugo 模块安装

首先确保你的项目本身是一个 Hugo 模块

然后将此主题组件添加到你的 hugo.toml 配置文件中:

[module]

[[module.imports]]
path = "github.com/hugo-fixit/FixIt"

[[module.imports]]
path = "github.com/hugo-fixit/cmpt-santa-hat"

在 Hugo 的第一次启动时,它将下载所需的文件。

要更新到模块的最新版本,请运行:

hugo mod get -u
hugo mod tidy

作为 Git 子模块安装

FixIt 和此 git 存储库克隆到你的主题文件夹中,并将其作为网站目录的子模块添加。

git submodule add https://github.com/hugo-fixit/FixIt.git themes/FixIt
git submodule add https://github.com/hugo-fixit/cmpt-santa-hat.git themes/cmpt-santa-hat

接下来编辑项目的 hugo.toml 并将此主题组件添加到你的主题中:

theme = ["FixIt", "cmpt-santa-hat"]

配置

为了通过 FixIt 主题在 layouts/_partials/custom.html 文件中开放的 自定义块santa-hat.fixit.html 注入到 custom-assets 中,你需要填写以下必要配置:

[params]

[params.customPartials]
# ... other partials
assets = [
 "inject/santa-hat.fixit.html",
]
# ... other partials

样式控制

  • Logo 尺寸推荐:32x32 像素。
  • CSS 变量:
    • --fi-santa-hat-offset:控制圣诞帽相对于 Logo 的平移偏移,默认值 8px 2px
    • --fi-santa-hat-shadow:控制帽子阴影的 RGB 值,默认值 0, 0, 0,暗色模式下会自动切换为 255, 255, 255

Command line tool for generating a changelog from git tags and commit history

2025-08-30 23:40:19

auto-changelog-plus

中文 | English

从 git 提交历史自动生成 changelog 的命令行工具。

基于 auto-changelog约定式提交 规范。

npm version

📦 安装

npm install -g auto-changelog-plus

🚀 用法

在 git 仓库根目录运行 auto-changelog-plus 或者 acp。工具会在后台运行 git log 来解析提交历史。

Usage: auto-changelog-plus [options]

Options:
 -o, --output [file] # output file, default: CHANGELOG.md
 -c, --config [file] # config file location, default: .auto-changelog
 -t, --template [template] # specify template to use [compact, keepachangelog, json], default: compact
 -r, --remote [remote] # specify git remote to use for links, default: origin
 -p, --package # use version from package.json as latest release
 -v, --latest-version [version] # use specified version as latest release
 -u, --unreleased # include section for unreleased changes
 -l, --commit-limit [count] # number of commits to display per release, default: 3
 -b, --backfill-limit [count] # number of commits to backfill empty releases with, default: 3
 --commit-url [url] # override url for commits, use {id} for commit id
 --issue-url [url] # override url for issues, use {id} for issue id
 --merge-url [url] # override url for merges, use {id} for merge id
 --compare-url [url] # override url for compares, use {from} and {to} for tags
 --issue-pattern [regex] # override regex pattern for issues in commit messages
 --breaking-pattern [regex] # regex pattern for breaking change commits
 --merge-pattern [regex] # add custom regex pattern for merge commits
 --commit-pattern [regex] # pattern to include when parsing commits
 --ignore-commit-pattern [regex] # pattern to ignore when parsing commits
 --tag-pattern [regex] # override regex pattern for version tags
 --tag-prefix [prefix] # prefix used in version tags, default: v
 --starting-version [tag] # specify earliest version to include in changelog
 --starting-date [yyyy-mm-dd] # specify earliest date to include in changelog
 --ending-version [tag] # specify latest version to include in changelog
 --sort-commits [property] # sort commits by property [relevance, date, date-desc, subject, subject-desc], default: relevance
 --release-summary # display tagged commit message body as release summary
 --unreleased-only # only output unreleased changes
 --hide-empty-releases # hide empty releases
 --hide-credit # hide auto-changelog credit
 --handlebars-setup [file] # handlebars setup file
 --append-git-log [string] # string to append to git log command
 --append-git-tag [string] # string to append to git tag command
 --prepend # prepend changelog to output file
 --stdout # output changelog to stdout
 -V, --version # output the version number
 -h, --help # output usage information

以下是一些常见的使用示例:

# 在当前目录写入日志到 CHANGELOG.md
auto-changelog-plus

# 使用 keepachangelog 模板写入日志到 HISTORY.md
auto-changelog-plus --output HISTORY.md --template keepachangelog

# 禁用提交限制,渲染每个发布的所有提交
auto-changelog-plus --commit-limit false

执行 auto-changelog-plus -h 获取帮助或者参考 auto-changelog 文档。

📝 约定式提交

基于 约定式提交 规范,支持以下类型的提交:

  • feat: 新功能
  • fix: 修复问题
  • perf: 性能优化
  • refactor: 代码重构
  • docs: 文档变更
  • test: 测试相关
  • style: 代码格式调整
  • chore: 构建过程或辅助工具的变动
  • build: 构建系统变动
  • ci: 持续集成配置变动
  • revert: 代码回滚
  • 支持 scope:feat(api):, fix(ui):
  • 支持 emoji::sparkles: feat:, ✨ feat:
  • 支持 Breaking Changes:feat!:, feat(scope)!:, BREAKING CHANGE: 等格式
  • 自动忽略 WIP 提交:wip:, Wip: 等临时提交不会包含在变更日志中

⚙️ 自动化使用

auto-changelog-plus 安装到开发依赖:

npm install auto-changelog-plus --save-dev
# 或
yarn add auto-changelog-plus --dev
# 或
pnpm add -D auto-changelog-plus

在你的 package.jsonversion 脚本中添加 auto-changelog-plus -p && git add CHANGELOG.md

{
 "name": "my-awesome-package",
 "version": "1.0.0",
 "devDependencies": {
 "auto-changelog-plus": "*"
 },
 "scripts": {
 "version": "auto-changelog-plus -p && git add CHANGELOG.md"
 }
}

使用 -p--packagepackage.json 中的 version 用作最新发布,这样以前发布和现在之间的所有提交都成为该发布的一部分。基本上任何通常被解析为 Unreleased 的内容现在都会出现在 package.jsonversion 下。

现在每次运行 npm version 时,changelog 将自动更新并成为版本提交的一部分。

在不是 NPM 包的项目中,可以使用 npxpnpx 来运行 auto-changelog-plus,例如:

npx auto-changelog-plus
# 或
pnpx auto-changelog-plus

在 GitHub Actions 中,你可以使用以下工作流来自动生成发布说明:

name: Release for new tag

on:
 push:
 tags:
 - 'v*.*.*'
 workflow_dispatch:

jobs:
 release:
 runs-on: ubuntu-latest
 steps:
 - name: Checkout repository
 uses: actions/checkout@v5
 with:
 fetch-depth: 0 # Fetch all history for generating release notes

 - name: Setup Node.js
 uses: actions/setup-node@v5
 with:
 node-version: 'lts/*'

 - name: Generate release notes
 run: |
 npx auto-changelog-plus --starting-version ${{ github.ref_name }}
 sed -i '1,4d' CHANGELOG.md

 - name: GitHub Release
 uses: softprops/action-gh-release@v2
 with:
 draft: true
 body_path: CHANGELOG.md

🔄 和 auto-changelog 的区别

auto-changelog-plusauto-changelog 的上层封装,完全兼容 auto-changelog 的所有用法和配置。

主要改进:

  • 优化默认模板:更好地适配 约定式提交 规范
  • 调整默认配置:提供更合理的开箱即用体验
  • 扩展模板功能:提供额外的模板辅助函数

如果你正在使用 auto-changelog,可以直接替换为 auto-changelog-plus,无需修改任何配置。

📄 许可证

MIT

让 Mermaid 图表自动跟随系统深浅色

2025-08-16 12:37:49

featured image

Mermaid 是目前最流行的「文本即图表」渲染库,但它对「系统深浅色自动切换」的支持一直暧昧不明。官方 Roadmap 里偶有提及,却始终没有一个简单、稳定、文档化的 API。
不过社区里已有大量站点(mermaid.live、Obsidian、Notion-like 产品等)实现了丝滑的 Light/Dark 自适应。本文把目前能落地的三条路线一次性梳理出来,并给出最小可运行示例,方便你按需取用。

背景:Mermaid 主题机制与痛点

flowchart LR
 A(["Start"])
 A --> B{"Decision"}
 B -->|Yes| C["Option A"]
 B -->|No| D["Option B"]

Mermaid 在初始化时通过 theme 字段选定配色,例如:

mermaid.initialize({ theme: 'dark' });

但这条配置 只在首次渲染时生效。当用户在操作系统层面切到 Light/Dark,或者网页本身提供手动开关时,Mermaid 并不会自动重绘。这就导致:

  • 暗黑系统 + 浅色图表 ⇒ 刺眼
  • 浅色系统 + 暗黑图表 ⇒ 同样刺眼

社区 Issue #2644 早在 2022 年就提出希望官方支持 prefers-color-scheme,但至今(2025-08)仍未合入主干。

顺便提一下,主题的切换一般都有两种主流方式:

  1. 利用 prefers-color-scheme 感知系统级别主题变化,matchMedia('(prefers-color-scheme: dark)')change 事件。
  2. 通过 dark class 手动切换,这种方式通常会在 html/body 上设置一个 class 或者 data-theme="dark" 这样。

方案 1️⃣ Reinitialize

切换主题,重新 initialize + 重绘,这是目前来看大多数人的做法。

思路:

  1. 备份原始的 Mermaid code
  2. 设置 startOnLoad: false 避免 Mermaid 自动渲染,然后使用 mermaid.initialize({ theme: theme }) + mermaid.run() 完成初始化。
  3. 重新渲染时移除 data-processed,替换 .mermaid 的内容为原始 Mermaid code,使用 mermaid.initialize({ theme: newTheme }) + mermaid.run() 重新渲染

这份做法在 Issue #1945 里有完整代码,下面给出精简版:

优点是:

  • 利用现有官方 API

缺点是:

  • 每次切换都需要重新渲染,大图会闪一下
  • 如果页面里图表很多,性能损耗不可忽视
  • 还有异步处理带来的一系列问题

方案 2️⃣ CSS 滤镜

作为支持 prefers-color-scheme 和手动切换的一种简单的解决方案,可以使用 CSS 反转滤镜(inverthue-rotate 等)来实现。

例如:

[data-theme='dark'] .mermaid {
 filter: invert(0.88);
}

@media (prefers-color-scheme: dark) {
 :root:not([data-theme='light']) .mermaid {
 filter: invert(0.88);
 }
}

这条技巧是我在 Issue #2644 中看到的。

优点是:

  • 一行 CSS,无 JS
  • 不重新渲染,零延迟

缺点是:

  • 只是「反色」,并非官方暗黑主题
  • 对于红色、绿色等语义色会完全失真
  • 如果背景不是纯黑纯白,观感会很奇怪

由于太过简单,效果也很粗糙,适合做 Demo 或内部工具,不建议面向终端用户。

方案 3️⃣ 配置热替换

mermaid.live 站点能在用户切主题时瞬间完成切换,且颜色完全与官方暗黑主题对齐。从 源码 和 DevTools 推测,它大概做了三件事:

  1. 自己维护一份 themeCSS 字符串(而非仅用名字 'dark'
  2. prefers-color-scheme 变化时,直接把新的 CSS 注入到 <svg> 里的 <style> 节点
  3. 通过 mermaid.render('id', code) 拿到 SVG string 后,用正则替换掉旧 <style>,再 DOMParser 塞回页面

Issue #2644 中有提到,在 mermaid.live 中,目前是根据配色方案在配置中切换主题。

优点:

  • 无闪烁
  • 完全复用官方配色

缺点:

  • 需要内部维护主题 CSS,Mermaid 每升级一次都要同步
  • 实现细节依赖私有 API,官方一旦改动就会崩

如果你极度追求体验,可以照着源码抄一份,但要做好长期维护的心理准备。

#2644 中提到,在 mermaid.live 中,目前正在根据配色方案在配置中切换主题。这种方案暂时未找到更多的细节披露。我又懒得去深扒 mermaid.live 的实现细节。

方案 4️⃣ Reinitialize + CSS 结合

在我的实践中,FixIt 主题 是通过 data-theme 的方式手动切换网站主题的,我一开始走的思路和方案 1️⃣总体一致,为了处理这个方案的缺点,我多次迭代,有了最终的版本:

首先通过 type=module 引入 Mermaid:

import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.js';
import zenuml from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml/dist/mermaid-zenuml.esm.min.mjs';
await mermaid.registerExternalDiagrams([zenuml]);
mermaid.startOnLoad = false;
window.mermaid = mermaid;

然后在主题的切换逻辑中处理:

initMermaid() {
 if (!this.config.mermaid) return;

 const themes = this.config.mermaid.themes ?? ['default', 'dark'];
 let processing = false;
 let delayTask = null;

 const loadMermaid = async () => {
 processing = true;
 // https://mermaid.js.org/config/schema-docs/config.html
 window.mermaid.initialize({
 startOnLoad: false,
 darkMode: this.isDark,
 theme: this.isDark ? themes[1] : themes[0],
 securityLevel: this.config.mermaid.securityLevel,
 look: this.config.mermaid.look,
 fontFamily: this.config.mermaid.fontFamily,
 altFontFamily: this.config.mermaid.fontFamily
 });
 await window.mermaid.run({
 querySelector: '.mermaid',
 suppressErrors: true,
 });
 processing = false;
 if (delayTask && typeof delayTask === 'function') {
 delayTask();
 delayTask = null;
 // console.log('Delayed task executed');
 }
 };

 const reloadMermaid = async () => {
 await this.util.forEach(document.querySelectorAll('.mermaid[data-processed]'), (el) => {
 el.removeAttribute('data-processed');
 el.parentElement.replaceChild(el.nextElementSibling.content.cloneNode(true), el);
 });
 await loadMermaid();
 };

 const waitForMermaid = () => {
 return new Promise((resolve) => {
 const timer = setInterval(() => {
 if (window.mermaid && window.mermaid.initialize) {
 clearInterval(timer);
 resolve();
 }
 }, 100);
 });
 };

 waitForMermaid().then(() => {
 loadMermaid();
 this.switchThemeEventSet.add(() => {
 if (processing) {
 console.warn('Mermaid is still processing, delaying the reload.');
 delayTask = reloadMermaid;
 return;
 }
 // console.log('reload immediately');
 reloadMermaid().catch(console.error);
 });

 this.beforeprintEventSet.add(() => {
 // Optionally set theme to 'neutral' for printing if required
 });
 })
}

为了缓解闪屏问题,利用 CSS 增加一个 Loading 效果,过度一下。

.mermaid {
 position: relative;
 overflow: hidden !important;

 &[data-processed] {
 text-align: center;
 }

 &:not([data-processed])::before {
 content: '';
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 backdrop-filter: blur(0.5rem);
 background-position: center;
 background-repeat: no-repeat;
 background-image: var(#{$rootPrefix}loading-img);
 background-size: 60px;
 }

 svg {
 max-width: 100%;
 height: auto; 
 }
}

说实话,虽然勉强达到了目的,这里的 delayTaskwaitForMermaid() 算得上妥妥的 Dirty Hack。也属实是无奈之举。


睡觉前我灵光乍现,为了避免每次切换主题时都要重新渲染 Mermaid 图表,我尝试一开始直接把 Mermaid 的 Light 和 Dark 主题的两个图都渲染了,然后由 data-theme 控制显示哪个图表。

尝试后发现 Mermaid 在渲染图时,如果这个元素是 display: none; 则会报错。

于是,我改成初始化时只渲染 Light/Dark SVG,等到主题切换时才渲染 Dark/Light SVG,并隐藏另一个 SVG。

这样同一个图只需要渲染两次,后续多次主题切换,就能够通过 CSS 非常丝滑的控制切换了,狠狠戳这里查看效果

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Mermaid Light/Dark Mode switching</title>
 <style>
 .diagrams-container {
 display: flex;
 justify-content: space-evenly;
 }
 .mermaid-container {
 .mermaid-dark {
 display: none;
 }

 [data-theme="dark"] & {
 .mermaid {
 display: none;
 }
 .mermaid-dark {
 display: block;
 }
 }
 }
 </style>
</head>
<body>
 <script>
 function toggleTheme() {
 const currentTheme = document.body.dataset.theme;
 const newTheme = currentTheme === 'dark' ? 'default' : 'dark';
 document.body.dataset.theme = newTheme;
 }
 </script>
 <button id="toggler">切换主题</button>
 <div class="diagrams-container">
 <div class="mermaid-container">
 <pre class="mermaid">graph TD;
 A[开始] --> B{是否完成?};
 B -- 是 --> C[结束];
 B -- 否 --> D[继续];
 D --> B;
 </pre>
 <pre class="mermaid-dark">graph TD;
 A[开始] --> B{是否完成?};
 B -- 是 --> C[结束];
 B -- 否 --> D[继续];
 D --> B;
 </pre>
 </div>
 </div>

 <script type="module">
 import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';

 async function loadMermaid(theme) {
 const isDark = theme === 'dark';
 const querySelector = isDark ? '.mermaid-dark' : '.mermaid';
 mermaid.initialize({ startOnLoad: false, darkMode: isDark, theme });
 // Mermaid run 函数内部会跳过 data-processed 的元素,所以这样不会重复渲染
 await mermaid.run({ querySelector });
 }

 await loadMermaid('default')

 document.getElementById('toggler').addEventListener('click', () => {
 const currentTheme = document.body.dataset.theme || 'default';
 const newTheme = currentTheme === 'dark' ? 'default' : 'dark';
 document.body.dataset.theme = newTheme;
 loadMermaid(newTheme);
 });
 </script>
</body>
</html>

小结与选型建议

毋庸置疑,想要完美的体验,方案 3️⃣ 是最优选择, 方案 4️⃣ 作为方案 1️⃣ 的升级版,整体体验也相对较好。

方案 实现成本 体验 是否官方可维护
Reinitialize 中等(闪屏)
CSS invert 极低
mermaid.live 热替换 极佳
Reinitialize + CSS 较好
  • 内部文档 / 博客 / 小工具 ⇒ 方案 4️⃣
  • 赶时间的 MVP ⇒ 方案 2️⃣
  • 面向 C 端、对体验极端敏感 ⇒ 方案 3️⃣,但要准备长期跟进

黑盒出关・三把钥匙定江湖

2025-08-05 11:31:52

featured image

江湖传言,西土浏览器界有隐世高人,名曰“原生老祖”。老祖膝下三徒,各执一柄钥匙,开得了黑盒,锁得住乾坤。今日大话,诸位英雄且把耳洞放大,听我一一道来!

第一折・黑盒现世

昔日,React 少侠仗虚拟 DOM 之剑,Vue 剑仙携响应式绫罗,双雄争霸,血溅前端。

忽一日,电闪雷鸣,Chrome 山、Firefox 谷、Safari 崖三地同时金光乍现——一只乌漆嘛黑的小盒破空而出,盒上无门无派,只刻八字:

不拜山头,自成一派。

盒盖一开,三股真气冲天而起,惊得 React 剑锋一抖,Vue 绫罗乱颤。众修士齐呼:

“此乃何物?”

盒中悠悠传出一声:

“Web Components——浏览器亲儿子,江湖诨号:黑盒扫地僧。”


第二折・三把钥匙镇山门

铸兵符・Custom Elements

凡得此符者,可铸自家神兵。

<my-dog food="hotpot" mood="happy"></my-dog>

今日起,标签随你姓,语义随你编,浏览器照单全收,不查户口。

影分身・Shadow DOM

此术一开,样式、DOM、事件皆入黑屋,外头 CSS 千军万马,休想踏进半步。

“兄弟,你的 !important 呢?”
“抱歉,进了影分身,天王老子也得排队。”

袖里乾坤・HTML Templates & Slots

袖中一抖,模板千军万马;插槽轻点,内容各就各位。

无需编译,无需打包,一颗 <template> 漂洋过海,落地即插即用。

这是真正意义上的“一次编写,到处运行”——比 Java 当年喊的口号还真。


第三折・风云再起

黑盒既出,江湖格局瞬变:

  • 微前端:Vue2、Vue3、React18、Angular 同屏共舞,互不打脸。
  • 设计系统:按钮、输入框、LOGO 化身“原子暗器”,任何门派伸手即取。
  • 长尾奇袭:Chrome 插件、VS Code 插件、微信小程序、低代码山寨,皆呼“真香”。
  • 长寿秘籍:框架蜜月三年,黑盒随浏览器升级十年,npm 弃坑它不弃。

第四折・范式转移・浏览器登堂入室

当日头西斜,江湖忽然风起。众侠回头一看,浏览器老馆主身披龙袍、脚踏赤霄,一步跨上金銮殿。

旧朝遗诏:从“虚拟机”到“原生执政”

过去二十年,前端史是一部“夺权史”:

  • jQuery 夺的是 DOM 的刀;
  • Angular 夺的是模块的印;
  • React 夺的是渲染的剑;
  • Vue 夺的是状态的符。

四把大印加身,浏览器反成“空壳天子”。

而今,老馆主一声令下:“朕即框架,诸卿退班!”

三权分立:新标准下的江湖秩序

权柄 归属 职责 口号
立法权 WHATWG/W3C 写圣旨(HTML、CSS、DOM 标准) “凡入典章,万世不易。”
执法权 浏览器内核 掌御林军(渲染管线、沙箱、安全) “有朕一日,天下无刀兵。”
行政权 开发者 & 工具链 管民生(DX、脚手架、调试器) “百姓只用敲锣,不必造炮。”

Web Components 正是老馆主钦点的 “锦衣卫”

去框架化的三重暗涌

  1. 编译终点迁移

    昨日:Babel/Vite → React/Vue 运行时;

    今日:Babel/Vite → Web Components 原生指令。

    框架退居“DX 大臣”,不再染指最终字节码。

  2. 生态颗粒度下沉

    UI 库不再打包成“全家桶”,而是 CDN 单文件组件:

    https://unpkg.com/@ui/button.js

    按需即取,HTTP 缓存即版本管理,npm install 沦为可选项。

  3. 生命周期归一

    React 的 useEffect、Vue 的 onMounted、Svelte 的 onMount

    最终都得翻译成同一套浏览器生命周期:

    connectedCallbackdisconnectedCallbackattributeChangedCallback

    框架语法糖越甜,底层 API 越收敛,直至“糖衣”可有可无。

未来图景:十年后的登基大典

  • 2027:浏览器内置 signals 提案落地,状态管理回归原生;
  • 2029:CSS @scope + @state 双剑合璧,Shadow DOM 自带响应式;
  • 2031:HTTP/4 多路复用 + Import Map 2.0,让“一行 <script type=importmap> 即 CDN 全图”成为标配。

届时,开发者只需写:

<my-app></my-app>
<script type="module" src="app.js"></script>

框架?

“哦,那是旧朝遗老,偶尔进宫讲史罢了。”

老馆主抚须长笑:
“昔日你们借我地基起高楼,今日我把高楼收归国有。

范式逆流,不是革命,是回家。”


尾声・血雨腥风

“老衲不挑框架,不拒工具,但有一语相赠:
十年之后,你迁移的是框架,还是我?”

江湖血雨腥风,黑盒已开。

要么守着旧山门,十年后再为迁移埋单;

要么此刻随扫地僧下山,让代码像 HTML 一样长青。

下回分解

“5 分钟,一指定乾坤——纯原生撸一只可复用计数器,再扔进 React、Vue、Svelte 乱炖!”


注意

哈哈哈哈哈哈哈,以抖机灵的形式简单聊了一下 Web Components 的发展历程和未来趋势。

我对 Web Components 充满了浓厚的兴趣,决定花点时间研究研究。
剩余的内容在 Web Components 系列文章 将会持续更新,敬请期待!

Code Playground

2025-08-04 11:37:24

以下是常见的在线代码演示和开发环境服务,适合不同场景使用:

名称 特点与适用场景 网址
CodeSandbox 支持前后端全栈开发,内置 Docker,支持 React、Vue、Node、Python 等,适合复杂项目 https://codesandbox.io
CodePen 专注于前端小效果演示,社区活跃,适合分享和展示 HTML/CSS/JS 片段 https://codepen.io
JSFiddle 轻量级前端代码片段运行环境,适合快速测试和分享小 demo https://jsfiddle.net
JS Bin 类似 JSFiddle,支持实时协作和分享,适合调试和教学 https://jsbin.com
Playcode.io 无需登录即可运行 JS/TS,界面类似本地 IDE,适合快速原型开发 https://playcode.io
Replit 支持多语言(如 Python、Java、C++),适合教育用途和全栈开发 https://replit.com
StackBlitz 基于浏览器的全栈 IDE,支持 Node、React、Angular 等框架,自动部署到 Vercel,适合快速原型和教程 https://stackblitz.com
Gitpod 基于 VS Code 的云端 IDE,适合 GitHub 项目快速启动和协作 https://gitpod.io
码上掘金 国内版轻量 Playground,支持 React、Vue 等框架,适合中文用户 https://code.juejin.cn

A custom web component that embeds caniuse.com browser compatibility data for a specific feature.

2025-07-22 11:40:45

<caniuse-embed> 元素

npm version License

English | 简体中文

一个轻量级、可定制的 Web 组件,用于嵌入 caniuse.com 的特定 Web 功能的浏览器兼容性数据。使用 Lit 构建,设计为可无缝集成到任何 Web 项目中。

🌟 在线演示

caniuse 示例

baseline 示例

✨ 特性

  • 🎯 轻松集成:即插即用的 Web 组件,适用于任何框架或原生 HTML
  • 🎨 主题支持:自动、浅色和深色主题,适应您的设计
  • 📱 响应式:根据内容自动调整高度
  • 轻量级:使用 Lit 构建,最小化包体积
  • 🛠️ 可定制:配置数据源、时间范围和外观
  • 🔒 类型安全:完整的 TypeScript 支持和全面的类型定义

🚀 快速开始

CDN(推荐)

在您的 HTML 中添加脚本标签:

<script src="https://unpkg.com/@cell-x/caniuse-embed-element/dist/caniuse-embed-element.iife.js"></script>

然后使用组件:

<caniuse-embed feature="css-grid"></caniuse-embed>

NPM 安装

npm install @cell-x/caniuse-embed-element
import '@cell-x/caniuse-embed-element'

📖 使用示例

基本用法

<caniuse-embed feature="css-grid"></caniuse-embed>

使用 Baseline 支持

显示功能的浏览器兼容性基线信息:

<caniuse-embed feature="css-grid" baseline></caniuse-embed>

自定义配置

<caniuse-embed
 feature="flexbox"
 theme="dark"
 past="3"
 future="2"
 baseline
 origin="https://caniuse.lruihao.cn"
></caniuse-embed>

FRAMEWORK_INTEGRATION.md

框架集成

以下是使用 Vue.js 的示例。更多框架集成示例,请参阅 FRAMEWORK_INTEGRATION.md

<script setup>
import '@cell-x/caniuse-embed-element'
</script>

<template>
 <div>
 <caniuse-embed
 feature="css-grid"
 theme="dark"
 :past="3"
 :future="2"
 />
 </div>
</template>

⚙️ API 参考

属性

属性 类型 默认值 描述
feature string '' 必需。caniuse 功能标识符(例如 ‘css-grid’, ‘flexbox’)
past 0 - 5 2 显示过去浏览器版本的数量
future 0 - 3 1 显示未来浏览器版本的数量
baseline boolean false 显示基线浏览器兼容性状态(如果可用)
origin string 'https://caniuse.lruihao.cn' caniuse 嵌入服务的基础 URL
theme 'auto' | 'light' | 'dark' 'auto' 嵌入内容的颜色主题
loading 'eager' | 'lazy' 'lazy' iframe 的加载策略(立即加载或延迟加载)
meta string 自动生成 嵌入实例的唯一标识符

关于 Baseline

baseline 属性显示 Web 功能的 Baseline 浏览器兼容性状态。启用后,它会显示功能是否:

  • 广泛可用 - 所有主流浏览器都支持
  • 新近可用 - 最近在主流浏览器中可用
  • 有限可用 - 尚未在所有主流浏览器中可用

这提供了功能采用情况的快速视觉指示器,帮助开发者在使用 Web 平台功能时做出明智的决策。

查找功能名称

功能名称对应于 caniuse.com 上使用的标识符。您可以在以下位置找到它们:

常见功能示例

  • css-grid - CSS 网格布局
  • flexbox - 弹性盒子布局
  • arrow-functions - 箭头函数
  • webp - WebP 图片格式
  • css-variables - CSS 自定义属性
  • async-functions - Async/Await 函数

CSS 类

  • .ciu-embed-iframe - 嵌入的 iframe 元素
  • .ciu-embed-empty - 未指定功能时的空状态

🌐 浏览器支持

此 Web 组件适用于支持以下特性的所有现代浏览器:

  • Custom Elements v1
  • Shadow DOM v1
  • ES2015+ 特性

🔧 开发

前置要求

  • Node.js 20+
  • pnpm 10+

设置

# 克隆仓库
git clone https://github.com/Lruihao/caniuse-embed-element.git
cd caniuse-embed-element

# 安装依赖
pnpm install

# 启动开发服务器
pnpm dev

构建

# 构建所有格式
pnpm build:all

# 构建特定格式
pnpm build:lib # ES 模块和类型
pnpm build:iife # 用于 CDN 的 IIFE 格式
pnpm build # 演示构建

脚本

  • pnpm dev - 启动开发服务器
  • pnpm build - 构建演示
  • pnpm build:lib - 构建库(ES 模块 + 类型)
  • pnpm build:iife - 构建 CDN 的 IIFE 包
  • pnpm build:all - 构建所有格式
  • pnpm lint - 运行 ESLint
  • pnpm preview - 预览构建的演示

📦 发行版

该包提供多种构建格式:

  • ES 模块dist/)- 用于现代打包工具
  • IIFE 包dist/caniuse-embed-element.iife.js)- 用于 CDN
  • TypeScript 定义dist/types/)- 用于 TypeScript 项目

🤝 贡献

欢迎贡献!请随时提交 Pull Request。对于重大更改,请先开 issue 讨论您想要更改的内容。

  1. Fork 仓库
  2. 创建您的功能分支(git checkout -b feature/amazing-feature
  3. 提交您的更改(git commit -m 'Add some amazing feature'
  4. 推送到分支(git push origin feature/amazing-feature
  5. 打开 Pull Request LICENSE

📄 许可证

本项目采用 MIT 许可证。详情请参阅 LICENSE 文件。

🙏 致谢


Lruihao 用 ❤️ 制作