{"_id":"@aihop/ai-editor","name":"@aihop/ai-editor","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@aihop/ai-editor","version":"1.0.0","private":false,"license":"MIT","description":"A modern AI-powered, highly customizable rich text editor for Vue, based on Tiptap and shadcn-vue. 一个面向 Vue3 的现代化 AI 富文本编辑器。","author":{"name":"aihopv@gmail.com"},"homepage":"https://github.com/aihop","repository":{"type":"git","url":"git+https://github.com/aihop/AIEditor.git"},"scripts":{"dev":"vite","examples":"pnpm build:lib && pnpm --dir ./examples run dev","examples:dev":"pnpm --dir ./examples run dev","build:lib":"vite build","build:examples":"pnpm build:lib && pnpm --dir ./examples run build","preview":"vite preview","git-commit":"git-cz","type:check":"tsc --noEmit","format":"prettier --write .","format:check":"prettier --check .","lint":"eslint --ext .js,.jsx,.ts,.tsx,.vue src","lint:fix":"eslint --ext .js,.jsx,.ts,.tsx,.vue src --fix","push":"pnpm build:lib && pnpm publish --access public --no-git-checks","prepare":"husky"},"config":{"commitizen":{"path":"@commitlint/cz-commitlint"}},"keywords":["AI editor","WYSIWYG","vue","vue.js","typescript","tiptap","editor","shadcn ui","wysiwyg","rich text","markdown"],"main":"./lib/ai-editor.umd.js","module":"./lib/ai-editor.mjs","types":"./lib/index.d.ts","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/ai-editor.es.js","require":"./lib/ai-editor.umd.js"},"./style.css":{"import":"./lib/style.css","require":"./lib/style.css"}},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"sideEffects":false,"engines":{"node":">=18.0.0"},"dependencies":{"@tiptap/core":"^2.11.5","@tiptap/extension-blockquote":"^2.11.5","@tiptap/extension-bold":"^2.11.5","@tiptap/extension-bubble-menu":"^2.11.5","@tiptap/extension-bullet-list":"^2.11.5","@tiptap/extension-character-count":"^2.11.5","@tiptap/extension-code":"^2.11.5","@tiptap/extension-color":"^2.11.5","@tiptap/extension-document":"^2.11.5","@tiptap/extension-dropcursor":"^2.11.5","@tiptap/extension-focus":"^2.11.5","@tiptap/extension-font-family":"^2.11.5","@tiptap/extension-gapcursor":"^2.11.5","@tiptap/extension-hard-break":"^2.11.5","@tiptap/extension-heading":"^2.11.5","@tiptap/extension-highlight":"^2.11.5","@tiptap/extension-history":"^2.11.5","@tiptap/extension-horizontal-rule":"^2.11.5","@tiptap/extension-image":"^2.11.5","@tiptap/extension-italic":"^2.11.5","@tiptap/extension-link":"^2.11.5","@tiptap/extension-list-item":"^2.11.5","@tiptap/extension-ordered-list":"^2.11.5","@tiptap/extension-paragraph":"^2.11.5","@tiptap/extension-placeholder":"^2.11.5","@tiptap/extension-strike":"^2.11.5","@tiptap/extension-subscript":"^2.11.5","@tiptap/extension-superscript":"^2.11.5","@tiptap/extension-table":"^2.11.5","@tiptap/extension-table-cell":"^2.11.5","@tiptap/extension-table-header":"^2.11.5","@tiptap/extension-table-row":"^2.11.5","@tiptap/extension-task-item":"^2.11.5","@tiptap/extension-task-list":"^2.11.5","@tiptap/extension-text":"^2.11.5","@tiptap/extension-text-align":"^2.11.5","@tiptap/extension-text-style":"^2.11.5","@tiptap/extension-underline":"^2.11.5","@tiptap/pm":"^2.11.5","@tiptap/suggestion":"^2.11.5","@tiptap/vue-3":"^2.11.5","@vueuse/core":"^10.11.1","class-variance-authority":"^0.7.1","clsx":"^2.1.1","hotkeys-js":"^3.13.7","lucide-vue-next":"^0.477.0","marked":"^15.0.0","reka-ui":"^2.0.2","tippy.js":"^6.3.7","turndown":"^7.2.0"},"devDependencies":{"@commitlint/cli":"^19.3.0","@commitlint/config-conventional":"^19.2.2","@commitlint/cz-commitlint":"^19.2.0","@types/node":"^24.0.14","@typescript-eslint/eslint-plugin":"^7.9.0","@typescript-eslint/parser":"^7.9.0","@vitejs/plugin-vue":"^6.0.0","@vue/tsconfig":"^0.7.0","autoprefixer":"^10.4.19","commitizen":"^4.3.0","commitlint":"^19.3.0","eslint":"^8.12.0","eslint-config-prettier":"^9.1.0","eslint-plugin-import":"^2.29.1","eslint-plugin-prettier":"^5.1.3","eslint-plugin-vue":"^9.26.0","husky":"^9.0.11","lint-staged":"^15.2.2","lodash-unified":"^1.0.3","postcss-prefix-selector":"^2.1.1","prettier":"^3.2.5","prism-code-editor":"^4.0.0","rollup-plugin-visualizer":"^6.0.5","tailwind-merge":"^2.6.0","tailwindcss":"^3.4.3","tailwindcss-animate":"^1.0.7","typescript":"~5.8.3","vite":"^7.0.4","vite-plugin-dts":"^3.9.0","vue":"^3.5.17","vue-tsc":"^2.2.12"},"peerDependencies":{"vue":">= 3.0.0"},"gitHead":"64d688b583b5bdd17b85697f85e3bd5255ca31e1","_id":"@aihop/ai-editor@1.0.0","bugs":{"url":"https://github.com/aihop/AIEditor/issues"},"_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-5OCLFbj49ncRKF7XrOKXh9oVL5A+JcOFzBNODnBcQWBpFfauMx9eWQ4ZTVwixp5WkRnq8ZpWmGcIQrI1yHaxfA==","shasum":"dcae6365b849494a9f68494dbc1b2266fce6a352","tarball":"https://registry.npmjs.org/@aihop/ai-editor/-/ai-editor-1.0.0.tgz","fileCount":310,"unpackedSize":3488718,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICmiQiLVsL1J42XSE82QOizmenjpbio/nCSQt2lqg61rAiEAlWBuoLB2YEEo9Vh5Iakk1MQC/oFgblHtE8/dlxN3Uvk="}]},"_npmUser":{"name":"aihop","email":"aihopv@gmail.com"},"directories":{},"maintainers":[{"name":"aihop","email":"aihopv@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai-editor_1.0.0_1782277057895_0.22347582004950906"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-24T04:57:37.746Z","1.0.0":"2026-06-24T04:57:38.062Z","modified":"2026-06-24T04:57:38.250Z"},"maintainers":[{"name":"aihop","email":"aihopv@gmail.com"}],"description":"A modern AI-powered, highly customizable rich text editor for Vue, based on Tiptap and shadcn-vue. 一个面向 Vue3 的现代化 AI 富文本编辑器。","homepage":"https://github.com/aihop","keywords":["AI editor","WYSIWYG","vue","vue.js","typescript","tiptap","editor","shadcn ui","wysiwyg","rich text","markdown"],"repository":{"type":"git","url":"git+https://github.com/aihop/AIEditor.git"},"author":{"name":"aihopv@gmail.com"},"bugs":{"url":"https://github.com/aihop/AIEditor/issues"},"license":"MIT","readme":"# AiEditor\n\n一个面向 Vue 3 的现代化 AI 富文本编辑器，基于 [tiptap](https://tiptap.dev) 与 [shadcn-vue](https://www.shadcn-vue.com/) 构建，强调“高可定制 + 组件化 + 扩展驱动”。\n\n[![MIT 许可证](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)\n[![](https://img.shields.io/npm/v/ai-editor.svg?label=version)](https://www.npmjs.com/package/ai-editor)\n[![](https://img.shields.io/npm/dependency-version/ai-editor/peer/vue?color=vue)](https://www.npmjs.com/package/ai-editor)\n\n[English](./README.md) | 中文\n\n![应用截图](./screenshot/screenshot.png)\n\n## 亮点\n\n- ✨ AI 写作辅助（基于选区、快捷指令、流式输出、随时停止）\n- 📝 Markdown 预览、源码模式、查找替换\n- 🔤 常用富文本能力（标题、列表、引用、链接、颜色/高亮等）\n- 📊 表格 / 代码块 / 多栏布局 / Iframe\n- 🖼️ 图片与视频（提供上传扩展可选用）\n- 🌍 国际化（`en`、`zhHans`）+ 主题系统（暗黑模式、圆角、主题色）\n- 🧩 扩展式架构：通过 Tiptap Extensions 组合出你需要的编辑器\n- 🎭 TypeScript 友好\n\n## 安装\n\n```bash\npnpm add ai-editor\n# 或\nnpm i ai-editor\n# 或\nyarn add ai-editor\n```\n\n## 快速开始\n\n### 方式一：全局注册（推荐）\n\n```ts\n// main.ts\nimport { createApp } from 'vue'\nimport App from './App.vue'\nimport AiEditor from 'ai-editor'\nimport 'ai-editor/style.css'\n\ncreateApp(App).use(AiEditor).mount('#app')\n```\n\n```vue\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { BaseKit } from 'ai-editor'\n\nconst content = ref('')\nconst extensions = [\n  BaseKit.configure({\n    placeholder: {\n      placeholder: '开始写作...',\n    },\n  }),\n]\n</script>\n\n<template>\n  <ai-editor v-model=\"content\" :extensions=\"extensions\" />\n</template>\n```\n\n### 方式二：直接使用\n\n```vue\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { AiEditor, BaseKit } from 'ai-editor'\nimport 'ai-editor/style.css'\n\nconst content = ref('')\nconst extensions = [BaseKit.configure()]\n</script>\n\n<template>\n  <AiEditor v-model=\"content\" :extensions=\"extensions\" />\n</template>\n```\n\n## AI 接入\n\nAI 能力由 `AI` 扩展提供。你只需要提供一个 `completions()` 方法（可选：自定义快捷指令）。\n\n```ts\nimport { BaseKit, AI } from 'ai-editor'\n\nconst extensions = [\n  BaseKit.configure(),\n  AI.configure({\n    toolbar: true,\n    shortcuts: [],\n    completions: async (history, signal) => {\n      const resp = await fetch('/api/ai/chat', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ messages: history }),\n        signal,\n      })\n      if (!resp.ok || !resp.body) throw new Error('AI 请求失败')\n\n      const reader = resp.body.getReader()\n      const decoder = new TextDecoder()\n\n      async function* iterator() {\n        let buf = ''\n        while (true) {\n          const { value, done } = await reader.read()\n          if (done) return\n          buf += decoder.decode(value, { stream: true })\n          const lines = buf.split('\\n')\n          buf = lines.pop() ?? ''\n          for (const line of lines) {\n            const trimmed = line.trim()\n            if (!trimmed.startsWith('data:')) continue\n            const json = trimmed.slice('data:'.length).trim()\n            if (!json || json === '[DONE]') continue\n            yield JSON.parse(json)\n          }\n        }\n      }\n\n      return iterator()\n    },\n  }),\n]\n```\n\n说明：\n\n- `completions()` 需要返回一个 `AsyncIterable` 流式迭代器，chunk 结构遵循 OpenAI streaming：`chunk.choices[0].delta.content`。\n- 强烈建议把 Key 放在后端：前端只调用你自己的 `/api/ai/chat`。\n\n## 组件 Props 与事件\n\n### Props\n\n| 参数                 | 类型                                        | 默认值   | 说明                      |\n| -------------------- | ------------------------------------------- | -------- | ------------------------- |\n| modelValue           | `string \\| JSONContent`                     | -        | 输入内容                  |\n| output               | `'html' \\| 'json' \\| 'text'`                | `'html'` | 输出格式                  |\n| disabled             | `boolean`                                   | `false`  | 只读                      |\n| hideToolbar          | `boolean`                                   | `false`  | 隐藏 Toolbar              |\n| hideMenubar          | `boolean`                                   | `false`  | 隐藏 Menubar              |\n| hideBubble           | `boolean`                                   | `false`  | 隐藏气泡菜单              |\n| dark                 | `boolean`                                   | 跟随系统 | 强制暗黑模式              |\n| theme                | `Theme`                                     | `'zinc'` | 主题色预设                |\n| radius               | `BorderRadius`                              | `0.5`    | 圆角                      |\n| maxWidth             | `string \\| number`                          | -        | 内容最大宽度              |\n| minHeight            | `string \\| number`                          | -        | 内容最小高度              |\n| maxHeight            | `string \\| number`                          | -        | 内容最大高度              |\n| removeDefaultWrapper | `boolean`                                   | `false`  | 为空时移除 `<p></p>` 包裹 |\n| extensions           | `AnyExtension[]`                            | -        | Tiptap 扩展列表           |\n| editorClass          | `string \\| string[] \\| Record<string, any>` | -        | 容器 class                |\n| contentClass         | `string \\| string[] \\| Record<string, any>` | -        | 内容 class                |\n| customFullscreen     | `boolean`                                   | `false`  | 自定义全屏行为            |\n\n### Emits\n\n| 事件              | 参数                    | 说明         |\n| ----------------- | ----------------------- | ------------ |\n| update:modelValue | `string \\| JSONContent` | v-model 更新 |\n| change            | `{ editor, output }`    | 内容变化     |\n| enter             | -                       | 按下 Enter   |\n| fullscreenChange  | `boolean`               | 全屏切换     |\n\n## 国际化\n\n```ts\nimport { locale } from 'ai-editor'\n\nlocale.setLang('zhHans') // 'en' | 'zhHans'\n```\n\n## 主题\n\n- 通过 `<ai-editor />` 的 `theme` / `dark` / `radius` 控制主题\n- 或使用内置组件：`ThemeToggle`、`ThemePicker`\n\n## 开发\n\n```bash\npnpm install\npnpm dev\n```\n\n运行 examples（先构建 lib，再启动示例应用）：\n\n```bash\npnpm examples\n```\n\n## 许可证\n\n[MIT](https://choosealicense.com/licenses/mit/)\n","readmeFilename":"README.zh-CN.md","_rev":"1-02caee93659506f52d5867ec31f84230"}