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 🙏

© 2024 – Pkg Stats / Ryan Hefner

smart-compose

v4.0.3

Published

Smart Compose 是一个轻量级的 JavaScript 库,可以将任何给定的 `textarea` 或 `contenteditable` 元素转换为具有智能补全功能的编辑器。

Downloads

118

Readme

Smart Compose

Smart Compose 是一个轻量级的 JavaScript 库,可以将任何给定的 textareacontenteditable 元素转换为具有智能补全功能的编辑器。

功能特点

  • 支持 textareacontenteditable 元素
  • 实时文本补全建议
  • 自定义 API 端点
  • 可配置的防抖时间
  • 自动调整文本区域高度
  • 支持自定义样式和回调函数
  • 响应式设计,支持窗口大小变化
  • 焦点状态样式
  • 占位符文本支持

项目架构

Smart Compose 采用模块化和面向对象的架构设计。以下是项目的整体结构概览:

| 文件/文件夹 | 描述 | | ---------------------- | --------------------------------------------------- | | src/ | 源代码目录 | | ├── SmartCompose/ | Smart Compose 核心代码 | | │ ├── index.ts | 主入口文件,包含 SmartCompose 类和 enhance 方法 | | │ ├── utils/ | 工具函数目录 | | │ │ ├── api.ts | API 相关工具函数 | | │ │ ├── domUtils.ts | DOM 操作相关工具函数 | | │ │ └── textUtils.ts | 文本处理相关工具函数 | | │ ├── constants.ts | 全局常量 | | │ ├── handlers.ts | 元素处理器,处理不同类型可编辑元素的逻辑 | | │ ├── styles.ts | 样式定义和管理 | | │ └── types.ts | 类型定义文件 | | ├── __tests__/ | 测试文件目录 | | ├── App.css | 开发环境:应用程序样式文件 | | ├── App.tsx | 开发环境:主应用程序组件 | | ├── index.ts | 项目入口文件 | | ├── main.tsx | 开发环境:主渲染文件 | | └── vite-env.d.ts | Vite 环境声明文件 | | .github/ | GitHub 相关配置文件目录 | | .husky/ | Husky git hooks 配置目录 | | dist/ | 构建输出目录 | | githubExtension/ | GitHub 扩展测试相关代码 | | node_modules/ | 项目依赖包目录 | | tiptapTest/ | TipTap 编辑器测试相关代码 | | .eslint.config.js | ESLint 配置文件 | | .gitignore | Git 忽略文件配置 | | .npmignore | npm 发布忽略文件配置 | | index.html | 开发环境:项目 HTML 入口文件 | | package.json | 项目依赖和脚本配置 | | pnpm-lock.yaml | pnpm 依赖锁定文件 | | README.md | 项目说明文档 | | tsconfig.dev.json | 开发环境 TypeScript 配置 | | tsconfig.json | 生产环境 TypeScript 配置 | | tsconfig.node.json | Node.js 环境 TypeScript 配置 | | tsconfig.tsbuildinfo | TypeScript 构建信息文件 | | vite.config.ts | Vite 配置文件 | | vite.dev.config.ts | Vite 开发环境配置文件 |

实现思路

  1. 创建一个新的 div:包裹层(wrapper),包含原始的编辑器元素(textareacontenteditable)和一个新创建的 div:的补全层(completion)。

  2. 补全层位于编辑器元素下方,用于显示补全建议。它的内容由用户输入的文本和智能补全的建议组成。

  3. 将编辑器元素的背景设置为透明,允许补全层的内容透过显示。

  4. 精确调整补全层的样式(字体、大小、行高等),使其与编辑器元素的文本完全对齐。

  5. 实时监听编辑器的输入事件,并相应更新补全层的内容:

    • 用户输入的文本保持不变
    • 根据 API 返回的建议更新补全部分
  6. 实现光标跟踪机制,确保补全建议始终出现在光标位置之后,而不仅仅是在文本末尾。

  7. 添加用户交互逻辑,如按 Tab 键接受补全建议。

  8. 优化渲染性能,使用防抖(debounce)技术减少 API 调用频率,避免频繁的 DOM 操作。

  9. 实现响应式设计,确保在窗口大小变化时保持对齐。

数据流

用户输入 → 触发输入事件 → 防抖处理 → 调用 API 获取补全建议 → 更新补全层内容 → 用户接受建议 → 更新编辑器内容

待改进

  1. 如果在已输入内容中间输入,生成的联想还是会在末尾
  2. 输入和删除时会闪烁

安装

npm install smart-compose
yarn add smart-compose
pnpm add smart-compose

开发

克隆仓库并安装依赖:

git clone https://github.com/dadafawang/smart-compose
cd smart-compose
pnpm install

运行开发服务器:

pnpm dev

运行测试:

pnpm test

构建库:

pnpm build

使用方法

作为模块使用

import SmartCompose from 'smart-compose'

const textarea = document.querySelector('#myTextarea')
const apiEndpoint = 'https://your-api-endpoint.com/smart-compose'

const smartCompose = SmartCompose.enhance(textarea, apiEndpoint, {
  debounceTime: 300,
  placeholder: '在此处描述问题...',
  onComplete: (result) => {
    console.log('补全完成:', result)
  },
  onChange: (text) => {
    console.log('内容变化:', text)
  }
})

在 GitHub Issues 测试

因为 GitHub 有内容安全策略(Content Security Policy,CSP)设置,不允许向 http://localhost:8000 发送请求。 所以对于在 GitHub Issues 的测试,我使用 Chrome 扩展(Chrome 扩展可以绕过网站的 CSP 限制)。 当然,您可以自由选择测试的方法,比如像使用代理等。

  1. 进入当前项目根目录的 githubExtension 文件夹,安装依赖并构建扩展生成 dist 文件夹(扩展的主要脚本内容写在 src/content.js 文件中)
cd githubExtension/
pnpm install
pnpm build
  1. 打开 Chrome 浏览器,进入扩展管理页面(chrome://extensions/),启用 "开发者模式";点击 "加载已解压的扩展程序",选择 githubExtension 文件夹下构建后的 dist 文件夹

  2. 打开一个 GitHub 仓库的 Issues 页面,点击 "New issue" 创建新的 issue,扩展会自动激活

  3. 如果遇到问题,可以打开 Chrome 开发者工具查看控制台输出

  4. 如果需要卸载扩展,可以在 Chrome 扩展管理页面中找到该扩展并点击"删除"

作为浏览器脚本使用

<div contenteditable="true"></div>

<script src="https://unpkg.com/smart-compose@latest/dist/js/smart-compose.umd.js"></script>
<script>
  const editor = document.querySelector('[contenteditable="true"]')
  const apiEndpoint = 'https://your-api-endpoint.com/smart-compose'

  const smartCompose = SmartCompose.enhance(editor, apiEndpoint, {
    debounceTime: 300,
    placeholder: '开始输入...',
    onComplete: (result) => {
      console.log('补全完成:', result)
    },
    onChange: (text) => {
      console.log('内容变化:', text)
    }
  })
</script>

在 TipTap 测试

  1. 打开 https://tiptap.dev/docs/examples/basics/default-text-editor

  2. 打开浏览器开发者工具(F12),切换到 console 标签页

  3. 在根目录下运行:pnpm build 构建当前项目,并复制打包后的 dist/js/smart-compose.umd.js 到控制台运行

  4. 复制以下测试代码粘贴到控制台运行(为了复制方便,以下测试代码也已备份到根目录下的 tiptapTest/index.js 内)

window.initTipTapSmartCompose = function () {
  const apiEndpoint = 'http://localhost:8000/api/smartCompose'

  function findEditor() {
    let editor = document.querySelector('[contenteditable="true"]')
    if (!editor) {
      editor = document.getElementsByClassName('tiptap')[0]
    }
    return editor
  }

  const editor = findEditor()

  if (editor) {
    // 如果已存在实例,先销毁它
    if (
      window.TipTapSmartComposeInstance &&
      typeof window.TipTapSmartComposeInstance.destroy === 'function'
    ) {
      window.TipTapSmartComposeInstance.destroy()
      console.log('已销毁旧的 GitHub SmartCompose 实例')
    }

    const smartCompose = SmartCompose.enhance(editor, apiEndpoint, {
      debounceTime: 300,
      placeholder: '开始输入...',
      onComplete: (result) => {
        console.log('补全完成:', result)
      },
      onChange: (text) => {
        console.log('内容变化:', text)
      }
    })

    // 在实例化后立即为 completion 元素添加 tiptap 类名
    const completionElements = document.getElementsByClassName(
      'smart-compose-completion'
    )
    Array.from(completionElements).forEach((element) => {
      element.classList.add('tiptap')
    })

    console.log('新的 TipTap SmartCompose 实例已创建:', smartCompose)

    // 在页面卸载时销毁 SmartCompose 实例
    window.addEventListener('beforeunload', () => {
      smartCompose.destroy()
      console.log('TipTap SmartCompose 实例已销毁')
    })

    window.TipTapSmartComposeInstance = smartCompose
  } else {
    console.error('未找到合适的 TipTap 编辑器元素')
  }
}

// 初始化SmartCompose
window.initTipTapSmartCompose()
  1. 如果页面刷新或需要重新初始化,在控制台中运行
window.initTipTapSmartCompose()

API

SmartCompose.enhance(element, apiEndpoint, options)

将给定的元素转换为智能补全编辑器。

参数:

  • element: HTMLTextAreaElement | HTMLElement - 要增强的 textareacontenteditable 元素
  • apiEndpoint: string - 用于获取补全建议的 API 端点
  • options: SmartComposeOptions - 配置选项(可选)

返回值: SmartCompose 实例

SmartComposeOptions

| 选项 | 类型 | 默认值 | 是否必填 | 描述 | | -------------- | ---------- | ------ | -------- | ----------------------------- | | debounceTime | number | 300 | 可选 | 输入防抖时间(毫秒) | | initialValue | string | - | 可选 | 编辑器的初始文本 | | className | string | - | 可选 | 应用于编辑器的额外 CSS 类名 | | placeholder | string | - | 可选 | 编辑器的占位符文本 | | style | object | - | 可选 | 应用于容器的内联样式 | | onComplete | function | - | 可选 | 应用补全建议时的回调函数 | | onChange | function | - | 可选 | 输入文本变化时的回调函数 |

实例方法

  • onComplete(callback: (result: CompletionResult) => void): 设置应用补全建议时的回调函数
  • onChange(callback: (value: string) => void): 设置输入文本变化时的回调函数
  • destroy(): 销毁 SmartCompose 实例,移除所有事件监听器和 DOM 修改

示例:

const smartCompose = SmartCompose.enhance(element, apiEndpoint)

// 设置补全回调
smartCompose.onComplete((result) => {
  console.log('补全已应用:', result)
})

// 设置变更回调
smartCompose.onChange((value) => {
  console.log('输入已更改:', value)
})

// 销毁实例
smartCompose.destroy()

这些方法允许你在实例创建后动态设置回调函数,或者在不再需要 SmartCompose 功能时清理资源。