npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@will1123/lx-ui-utils

v1.0.11

Published

LX UI - 灵曦平台 AI 组件库通用工具函数库

Downloads

1,970

Readme

@will1123/lx-ui-utils

LX UI 通用工具函数库,提供常用的工具函数和 AI 相关功能。

特性

  • 🚀 TypeScript 支持 - 完整的类型定义
  • 📦 Tree-Shaking 支持 - 按需引入,减少打包体积
  • 🔐 内置认证 - 支持 Token 认证
  • 🔧 AI 相关工具 - SSE、深度思考提取、Markdown 渲染

安装

npm install @will1123/lx-ui-utils
# 或
yarn add @will1123/lx-ui-utils
# 或
pnpm add @will1123/lx-ui-utils

使用方法

全量导入

import { sse, extractThinking, createMarkdownRender, bindMarkdownCodeBoxEvents } from '@will1123/lx-ui-utils'

按需导入(推荐)

import { sse } from '@will1123/lx-ui-utils'
import { extractThinking } from '@will1123/lx-ui-utils'
import {
  createMarkdownRender,
  getMarkdownCodeTheme,
  setMarkdownCodeTheme,
  toggleMarkdownCodeTheme,
  updateMarkdownCodeBlocksTheme,
  bindMarkdownCodeBoxEvents
} from '@will1123/lx-ui-utils'
import { copyToClipboard, isDom } from '@will1123/lx-ui-utils'

API 文档

SSE (Server-Sent Events)

基于 @microsoft/fetch-event-source 封装的 SSE 请求,支持流式响应、自动重连和页面可见性控制。

类型定义

interface SSEConfig {
  url: string                          // 请求 URL
  method?: 'GET' | 'POST'              // 请求方法,默认 POST
  headers?: Record<string, string>     // 请求头
  body?: object                        // 请求体(对象类型)
  signal?: AbortSignal                 // 用于取消请求
  token?: string                       // 认证 Token
  openWhenHidden?: boolean             // 页面隐藏时是否保持连接,默认 true
}

interface SSEHandlers {
  onOpen?: (response: Response) => void | Promise<void>       // 连接打开时触发
  onMessage?: (message: EventSourceMessage) => void            // 接收到消息时触发
  onClose?: () => void                                          // 连接关闭时触发
  onError?: (error: Error) => void                              // 发生错误时触发
}

使用示例

import { sse } from '@will1123/lx-ui-utils'

// 基础用法(默认 POST)
await sse({
  url: 'https://api.example.com/stream',
  body: { prompt: '你好' }
}, {
  onMessage(msg) {
    console.log('收到消息:', msg)
  }
})

// 使用 Token 认证
await sse({
  url: 'https://api.example.com/stream',
  token: 'Bearer your-token-here',
  body: { prompt: '你好' }
}, {
  onOpen(response) {
    console.log('连接已打开,状态:', response.status)
  },

  onMessage(msg) {
    // msg 是原始对象,包含 data、event、id 等字段
    console.log('收到消息:', msg.data)
  },

  onClose() {
    console.log('连接已关闭')
  },

  onError(err) {
    console.error('连接错误:', err)
  }
})

// GET 请求
await sse({
  url: 'https://api.example.com/stream',
  method: 'GET'
}, {
  onMessage(msg) {
    console.log(msg.data)
  }
})

// 取消请求
const ctrl = new AbortController()
await sse({
  url: 'https://api.example.com/stream',
  signal: ctrl.signal
}, {
  onMessage(msg) {
    console.log(msg.data)
  }
})

// 取消请求
ctrl.abort()

深度思考提取

从 AI 响应中提取深度思考内容。

类型定义

interface ThinkingExtractConfig {
  tagName?: string              // 思考标签名称,默认 'think'
  mode?: 'full' | 'end-tag-only'  // 解析模式
}

interface ThinkingResult {
  thinking: string              // 提取的思考内容
  content: string               // 实际回答内容
}

使用示例

import { extractThinking } from '@will1123/lx-ui-utils'

// 模式 1:完整标签(默认)
const text1 = `这是思考内容
这是回答内容`

const result1 = extractThinking(text1)
console.log(result1.thinking) // "这是思考内容"
console.log(result1.content)  // "这是回答内容"

// 模式 2:仅结束标签
const text2 = '这是思考内容这是回答内容'

const result2 = extractThinking(text2, { mode: 'end-tag-only' })
console.log(result2.thinking) // "这是思考内容"
console.log(result2.content)  // "这是回答内容"

// 模式 3:没有标签
const text3 = '全部是正文内容'

const result3 = extractThinking(text3)
console.log(result3.thinking) // ""
console.log(result3.content)  // "全部是正文内容"

Markdown 渲染

基于 Marked.js 的增强 Markdown 渲染器,支持代码高亮、主题切换、自定义样式和 KaTeX 数学公式。

特性

  • 链接增强 - 自动添加 target="_blank"
  • 表格优化 - 自动包装在可滚动容器中
  • 代码增强 - 显示语言标签、复制按钮、主题切换
  • 主题系统 - 支持 dark/light 主题切换,基于 localStorage
  • 代码高亮 - 集成 highlight.js,支持 190+ 语言
  • GFM 支持 - 表格、任务列表、删除线等
  • 类名前缀 - 所有生成的类名带 lx-ui 前缀,避免冲突
  • KaTeX 公式 - 支持数学公式渲染(可选)

类型定义

type CodeTheme = 'dark' | 'light'

interface CreateMarkdownRenderConfig {
  codeBoxToolEnable?: boolean  // 代码块工具栏是否启用,默认 true
  katexEnable?: boolean         // 是否启用 KaTeX 公式支持,默认 true
  katexOptions?: KatexOptions   // KaTeX 配置选项
}

使用步骤

1. 引入代码高亮样式(必需)

选择一个 highlight.js 主题并引入:

// 暗色主题(推荐)
import 'highlight.js/styles/base16/outrun-dark.min.css'
import 'highlight.js/styles/atom-one-dark.min.css'
import 'highlight.js/styles/github-dark.min.css'

// 亮色主题
import 'highlight.js/styles/github.min.css'
import 'highlight.js/styles/base16/solarflare-light.min.css'

// 查看所有主题:https://highlightjs.org/examples
// 主题文件位置:node_modules/highlight.js/styles/
2. 引入 KaTeX 样式(必需,默认启用公式支持)
// KaTeX 样式(必需,默认启用公式支持)
import 'katex/dist/katex.min.css'
3. 创建渲染器
import { createMarkdownRender } from '@will1123/lx-ui-utils'

// 创建渲染器(默认启用工具栏和 KaTeX 公式支持)
const renderer = createMarkdownRender({
  codeBoxToolEnable: true,
  katexEnable: true,
  katexOptions: {
    throwOnError: false,
    strict: false
  }
})

// 创建渲染器(禁用工具栏)
const simpleRenderer = createMarkdownRender({
  codeBoxToolEnable: false
})

// 创建渲染器(禁用公式支持)
const noKatexRenderer = createMarkdownRender({
  codeBoxToolEnable: true,
  katexEnable: false
})
4. 渲染 Markdown
const markdown = `# 标题

这是一段**粗体**和*斜体*文字。

## 数学公式

### 行内公式
爱因斯坦质能方程:$E = mc^2$

### 块级公式
$$
\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}
$$

## 代码示例

\`\`\`javascript
function greet(name) {
  console.log(\`Hello, \${name}!\`)
  return true
}
\`\`\`

## 表格

| 列1 | 列2 | 列3 |
|-----|-----|-----|
| A   | B   | C   |
| D   | E   | F   |

## 任务列表

- [ ] 未完成任务
- [x] 已完成任务

[链接](https://example.com)
`

// 渲染(异步)
const html = await renderer.parse(markdown)
console.log(html)

KaTeX 公式语法

支持两种公式语法:

行内公式 - 使用单个 $ 包裹:

爱因斯坦方程:$E = mc^2$

块级公式 - 使用双个 $$ 包裹:

$$
\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}
$$

注意事项

  • 行内公式不能包含换行符
  • 块级公式可以跨多行
  • 如果公式渲染失败,会保留原始公式文本
  • KaTeX 公式支持默认启用,无需配置即可使用
  • 如需禁用公式支持,设置 katexEnable: false

生成的 HTML 结构 - KaTeX 公式

行内公式

<span class="lx-ui-katex-inline">
  <!-- KaTeX 生成的 HTML -->
</span>

块级公式

<div class="lx-ui-katex-block">
  <!-- KaTeX 生成的 HTML -->
</div>

主题管理

import { getMarkdownCodeTheme, setMarkdownCodeTheme, toggleMarkdownCodeTheme, updateMarkdownCodeBlocksTheme } from '@will1123/lx-ui-utils'

// 获取当前主题
const theme = getMarkdownCodeTheme()  // 'dark' | 'light'

// 设置主题
setMarkdownCodeTheme('light')

// 切换主题(只更新 localStorage,不更新 DOM)
const newTheme = toggleMarkdownCodeTheme()

// 更新 DOM 中所有代码块的主题(方式 1:只传主题)
updateMarkdownCodeBlocksTheme('dark')

// 更新指定容器内代码块的主题(方式 2:传容器和主题)
const container = document.querySelector('#markdown-container')
updateMarkdownCodeBlocksTheme(container, 'light')

注意

  • toggleMarkdownCodeTheme() 只切换 localStorage 中的主题,不会更新 DOM
  • updateMarkdownCodeBlocksTheme() 用于更新 DOM 中代码块的 data-theme 属性
  • bindMarkdownCodeBoxEvents() 内部会自动调用这两个函数
  • updateMarkdownCodeBlocksTheme() 支持两种调用方式:
    • 只传主题字符串:updateMarkdownCodeBlocksTheme('dark') - 更新 document.body 中的所有代码块
    • 传容器和主题:updateMarkdownCodeBlocksTheme(container, 'light') - 更新指定容器内的代码块

绑定代码块工具栏事件(推荐)

bindMarkdownCodeBoxEvents 用于处理代码块工具栏的交互事件(复制、主题切换、折叠)。

类型定义
interface CodeBoxEventsConfig {
  onCopySuccess?: (text: string) => void    // 复制成功回调
  onCopyError?: (error: Error) => void      // 复制失败回调
  onThemeChange?: (theme: CodeTheme) => void // 主题切换回调
}

// 函数重载
function bindMarkdownCodeBoxEvents(): () => void
function bindMarkdownCodeBoxEvents(config: CodeBoxEventsConfig): () => void
function bindMarkdownCodeBoxEvents(container: HTMLElement | Document): () => void
function bindMarkdownCodeBoxEvents(
  container: HTMLElement | Document,
  config: CodeBoxEventsConfig
): () => void
使用步骤

1. 不传参数(默认 document.body)

import { bindMarkdownCodeBoxEvents } from '@will1123/lx-ui-utils'

const unbind = bindMarkdownCodeBoxEvents()

// 组件销毁时解绑
onUnmounted(() => unbind())

2. 只传 config(默认 document.body)

const unbind = bindMarkdownCodeBoxEvents({
  onCopySuccess: (text) => console.log('已复制:', text),
  onCopyError: (error) => console.error('复制失败:', error),
  onThemeChange: (theme) => console.log('主题切换为:', theme)
})

3. 只传 container(使用默认配置)

const container = document.querySelector('#markdown-container')
const unbind = bindMarkdownCodeBoxEvents(container)

4. 传 container 和 config

const container = document.querySelector('#markdown-container')
const unbind = bindMarkdownCodeBoxEvents(container, {
  onCopySuccess: (text) => console.log('已复制:', text),
  onThemeChange: (theme) => console.log('主题切换为:', theme)
})

5. Vue 组件完整示例

<template>
  <div>
    <div v-html="html" class="markdown-content"></div>
  </div>
</template>

<script>
import { createMarkdownRender, bindMarkdownCodeBoxEvents } from '@will1123/lx-ui-utils'

export default {
  data() {
    return {
      renderer: null,
      html: '',
      unbindEvents: null
    }
  },
  async mounted() {
    // 创建渲染器
    this.renderer = createMarkdownRender({
      codeBoxToolEnable: true
    })

    // 渲染 Markdown
    this.html = await this.renderer.parse(this.markdown)

    // 绑定事件(只传 config,默认 container 为 document.body)
    this.unbindEvents = bindMarkdownCodeBoxEvents({
      onCopySuccess: (text) => {
        this.$message.success('已复制到剪贴板')
      },
      onCopyError: (error) => {
        this.$message.error('复制失败')
      },
      onThemeChange: (theme) => {
        console.log('主题已切换为:', theme)
        // 主题切换会自动更新所有代码块的 data-theme
        // 无需重新渲染
      }
    })
  },
  beforeDestroy() {
    // 清理:解绑事件
    this.unbindEvents?.()
  },
  methods: {
    async render() {
      this.html = await this.renderer.parse(this.markdown)
    }
  }
}
</script>
功能说明

1. 复制按钮

  • 点击复制按钮自动复制代码到剪贴板
  • 内部使用 copyToClipboard 工具函数
  • 触发 onCopySuccessonCopyError 回调

2. 主题切换按钮

  • 点击主题按钮切换 dark/light 主题
  • 自动执行两步操作
    1. 调用 toggleMarkdownCodeTheme() 切换 localStorage 中的主题
    2. 调用 updateMarkdownCodeBlocksTheme() 更新指定容器内所有代码块的 data-theme 属性
  • 无需重新渲染 - 切换即时生效,性能更好
  • 触发 onThemeChange 回调
  • 容器隔离 - 只更新绑定容器内的代码块,不影响其他区域

3. 折叠按钮

  • 点击折叠按钮展开/收起代码块
  • 纯前端操作,无需重新渲染
注意事项
  • 事件委托:使用事件委托,动态添加的代码块也会生效
  • 清理函数:返回的清理函数必须在组件销毁时调用,避免内存泄漏
  • 职责分离:
    • toggleMarkdownCodeTheme() - 只负责切换 localStorage 中的主题
    • updateMarkdownCodeBlocksTheme() - 只负责更新 DOM 中代码块的 data-theme
    • bindMarkdownCodeBoxEvents() - 内部自动调用这两个函数完成完整流程
  • 函数重载:bindMarkdownCodeBoxEvents() 支持多种调用方式(不传参数、只传 config、只传 container、两个都传)
  • 容器隔离:指定 container 后,主题切换只影响该容器内的代码块,适合多实例场景
  • 兼容性:复制功能支持所有现代浏览器和 IE11+

生成的 HTML 结构

链接 - 自动添加 target="_blank"

<a target="_blank" href="...">链接文本</a>

表格 - 包装在可滚动容器中:

<div class="lx-ui-table-wrapper">
  <div class="lx-ui-table-box">
    <table>...</table>
  </div>
</div>

代码块(启用工具栏)

<div class="lx-ui-code-box-wrapper">
  <div class="lx-ui-code-box" data-theme="dark">
    <div class="lx-ui-code-box-header">
      <div class="lx-ui-code-box-header-left">
        <span class="lx-ui-code-language">javascript</span>
        <i class="lx-ui-icon-fold"></i>
      </div>
      <div class="lx-ui-code-box-header-right">
        <i class="lx-ui-icon-copy" title="复制"></i>
        <i class="lx-ui-icon-theme" title="切换主题"></i>
      </div>
    </div>
    <div class="lx-ui-code-box-content">
      <pre><code class="hljs language-javascript">...</code></pre>
    </div>
  </div>
</div>

代码块(禁用工具栏)

<div class="lx-ui-code-box-wrapper">
  <div class="lx-ui-code-box" data-theme="dark">
    <div class="lx-ui-code-box-header">
      <div class="lx-ui-code-box-header-left">
        <span class="lx-ui-code-language">javascript</span>
      </div>
    </div>
    <div class="lx-ui-code-box-content">
      <pre><code class="hljs language-javascript">...</code></pre>
    </div>
  </div>
</div>

CSS 样式指南

你需要自行实现以下 CSS 类的样式(所有类名都带 lx-ui 前缀以避免冲突):

/* 表格容器 */
.lx-ui-table-wrapper {
  overflow-x: auto;
}

.lx-ui-table-box {
  /* 表格内层容器 */
}

/* 代码块容器 */
.lx-ui-code-box-wrapper {
  margin-bottom: 20px;
}

.lx-ui-code-box {
  border-radius: 4px;
  overflow: hidden;
}

/* 代码主题 */
.lx-ui-code-box[data-theme="dark"] {
  background: #1e1e1e;
  color: #d4d4d4;
}

.lx-ui-code-box[data-theme="light"] {
  background: #f5f5f5;
  color: #333;
}

/* 代码块工具栏 */
.lx-ui-code-box-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
}

.lx-ui-code-box-header-left,
.lx-ui-code-box-header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.lx-ui-code-language {
  font-size: 12px;
  font-weight: 500;
}

.lx-ui-code-box-content {
  padding: 12px;
  overflow-x: auto;
}

/* 工具栏图标 */
.lx-ui-icon-copy,
.lx-ui-icon-theme,
.lx-ui-icon-fold {
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.2s;
}

.lx-ui-icon-copy:hover,
.lx-ui-icon-theme:hover,
.lx-ui-icon-fold:hover {
  opacity: 1;
}

/* KaTeX 公式样式(默认启用公式支持) */
.lx-ui-katex-inline {
  padding: 0 4px;
  font-size: 1.05em;
}

.lx-ui-katex-block {
  margin: 20px 0;
  padding: 15px;
  overflow-x: auto;
  text-align: center;
  background: #f5f7fa;
  border-radius: 4px;
}

完整示例

<template>
  <div class="markdown-content" v-html="html"></div>
</template>

<script>
import { createMarkdownRender } from '@will1123/lx-ui-utils'
import 'highlight.js/styles/base16/outrun-dark.min.css'
import 'katex/dist/katex.min.css'

export default {
  data() {
    return {
      renderer: null,
      html: ''
    }
  },
  async mounted() {
    // 创建渲染器(启用 KaTeX 公式支持)
    this.renderer = createMarkdownRender({
      codeBoxToolEnable: true,
      katexEnable: true
    })

    // 渲染 Markdown
    const markdown = `# Hello World\n\n\`\`\`javascript\nconsole.log('Hello')\n\`\`\``
    this.html = await this.renderer.parse(markdown)
  }
}
</script>

<style scoped>
/* 实现样式 */
.markdown-content :deep(.lx-ui-code-box) {
  background: #1e1e1e;
  border-radius: 4px;
}

.markdown-content :deep(.lx-ui-code-box-header) {
  display: flex;
  justify-content: space-between;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.05);
}

.markdown-content :deep(.lx-ui-icon-copy) {
  cursor: pointer;
  opacity: 0.7;
}

.markdown-content :deep(.lx-ui-icon-copy:hover) {
  opacity: 1;
}
</style>

核心优势

SSE 功能

  • 简洁 API - 默认 POST 请求,内置 Token 认证支持
  • 页面可见性 - 自动处理页面隐藏/显示(Page Visibility API)
  • 自动解析 - 无需手动解析 SSE 消息格式
  • 生产级 - 基于 Microsoft 维护的 @microsoft/fetch-event-source
  • 代码精简 - 相比手动实现减少 70% 代码量

深度思考提取

  • 灵活解析 - 支持完整标签和仅结束标签两种模式
  • 类型安全 - 完整的 TypeScript 类型定义
  • 简洁 API - 一个函数完成所有解析逻辑

Markdown 渲染

  • 增强功能 - 链接自动新窗口、表格可滚动、代码块工具栏
  • 主题系统 - dark/light 主题切换,基于 localStorage 持久化
  • 代码高亮 - 集成 highlight.js,支持 190+ 语言
  • 标准兼容 - 基于 Marked.js,99% CommonMark 兼容
  • GFM 支持 - 表格、任务列表、删除线等
  • 类名安全 - 所有生成的类名带 lx-ui 前缀,避免冲突
  • 按需样式 - 不提供 CSS 文件,用户自行实现样式
  • KaTeX 公式 - 支持 LaTeX 数学公式渲染(可选)

Helper Functions

通用工具函数,可在任何场景使用。

复制到剪贴板

copyToClipboard 是一个通用的复制文本到剪贴板的工具函数。

类型定义
function copyToClipboard(text: string): Promise<boolean>
使用示例
import { copyToClipboard } from '@will1123/lx-ui-utils'

// 基础用法
const success = await copyToClipboard('Hello World')
if (success) {
  console.log('复制成功')
} else {
  console.log('复制失败')
}

// 复制代码
const code = 'console.log("Hello World")'
await copyToClipboard(code)

// 复制 HTML 内容
const html = '<div>Hello</div>'
await copyToClipboard(html)
特性
  • 现代 API - 优先使用 Clipboard API
  • 自动降级 - 不支持时自动降级到 document.execCommand
  • SSR 安全 - 服务端渲染环境自动返回 false
  • 返回值 - 返回 Promise,成功返回 true,失败返回 false
  • 兼容性好 - 支持所有主流浏览器(包括 IE11+)
  • 通用性 - 可在任何场景使用,不限于 Markdown

判断 DOM 元素

isDom 用于判断值是否为 DOM 元素(HTMLElement 或 Document)。

类型定义
function isDom(val: unknown): val is HTMLElement | Document
使用示例
import { isDom } from '@will1123/lx-ui-utils'

// 判断各种值
isDom(document.body)        // true
isDom(document)             // true
isDom(document.querySelector('div'))  // true (如果找到元素)

isDom({})                  // false
isDom('div')               // false
isDom(null)                // false
isDom(undefined)           // false
isDom(123)                 // false

// 在函数重载中使用
function processInput(input: unknown) {
  if (isDom(input)) {
    // input 在这里被识别为 HTMLElement | Document
    input.addEventListener('click', handler)
  } else {
    console.log('不是 DOM 元素')
  }
}
特性
  • 类型守卫 - TypeScript 类型守卫,可缩小类型范围
  • 精确判断 - 使用 instanceof 判断,支持所有 DOM 元素
  • SSR 安全 - 服务端渲染环境也能正常工作
  • 辅助开发 - 常用于函数重载、参数验证等场景

构建

# 安装依赖
yarn install

# 构建 utils 包
yarn workspace @will1123/lx-ui-utils build

许可证

MIT