Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
46c1d09
feat: 添加 NutUI React 到 Taro 的迁移技能文档和实现
alvinhui Aug 21, 2026
11cded4
feat: 添加 Skill 页面及导航链接,更新 CLI 文档以支持 NutUI-React 的新技能
alvinhui Aug 21, 2026
ab3a66e
feat: align versioning of nutui-react-cli and nutui-react-taro-cli wi…
alvinhui Aug 21, 2026
e595496
feat: add NutUI React and NutUI React Taro skills documentation, enha…
alvinhui Aug 21, 2026
41296d9
feat: add detailed documentation for migrating from NutUI React to Nu…
alvinhui Aug 21, 2026
8b37609
Merge branch 'jdf2e:feat_v4.x' into feat/react-to-taro
alvinhui Aug 21, 2026
eb20bc0
fix: update CLI usage instructions in documentation for NutUI React a…
alvinhui Aug 21, 2026
ca0cc9a
docs: enhance migration documentation for NutUI React to Taro, clarif…
alvinhui Aug 21, 2026
4e1c800
docs: add command for starting local stdio MCP server in NutUI React …
alvinhui Aug 21, 2026
2f5353d
docs: update CLI usage instructions to include --format json option f…
alvinhui Aug 21, 2026
35de83f
chore: 中文符号
alvinhui Aug 21, 2026
24fc00e
docs: refine migration documentation for NutUI React to Taro, improvi…
alvinhui Aug 21, 2026
560c5e3
docs: streamline descriptions in NutUI React and NutUI React Taro doc…
alvinhui Aug 21, 2026
376f741
docs: update NutUI React and NutUI React Taro documentation for impro…
alvinhui Aug 21, 2026
8a172b9
docs: add README and MCP documentation for NutUI React and NutUI Reac…
alvinhui Aug 25, 2026
4dd1040
docs: update title in MCP documentation for NutUI Taro, clarifying fo…
alvinhui Aug 25, 2026
9a2578d
docs: update installation instructions in NutUI React and Taro docume…
alvinhui Aug 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/nutui-react-cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

本包版本号自 `4.0.0` 起与组件包 `@nutui/nutui-react` 对齐,便于未来支持多版本查询。

## v4.0.0

`2026-08-21`

- :sparkles: 版本号对齐 `@nutui/nutui-react`(此前为独立的 `0.1.x`),同一大版本的 CLI 与组件库保持一致,为未来多版本支持奠定基础。
- :sparkles: 离线知识查询 CLI:`list` / `info` / `doc` / `demo` / `token`,元数据随包分发,无需网络与 API Key。
- :sparkles: 内置 stdio MCP Server(`mcp` 命令),暴露 5 个工具与 2 个 prompt,供 Claude Code / Cursor / VS Code / Codex 等 IDE 集成。
- :sparkles: 随包分发 Skill:`nutui-react`(编写 / 调试 NutUI React 代码时查询组件知识)、`nutui-react-to-taro`(将 H5 代码迁移到 Taro)。
- :sparkles: 每个 Skill 补充 `metadata.json`,声明版本、兼容性、触发词等元信息。
13 changes: 10 additions & 3 deletions packages/nutui-react-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,22 @@ args = ["-y", "@nutui/nutui-react-cli", "mcp"]

CLI 内置一份 [Skill 文件](./skills/nutui-react/SKILL.md)(遵循 Anthropic Agent Skills 规范),随 npm 包一起分发。CLI / MCP 提供的是「能力」,Skill 则约束 Agent「**什么时候、按什么顺序**」用这些能力——例如「写组件前先 `nutui-react info` 查 Props、再 `nutui-react demo` 拿示例」「定制样式用 `var(--nutui-*)` token 而非硬编码颜色」。

安装(skill 已随包 bundle,装好 CLI 后从本地路径装进当前项目):
安装(从 GitHub 仓库直接装进当前项目):

```bash
npm i -D @nutui/nutui-react-cli
npx skills add ./node_modules/@nutui/nutui-react-cli/skills/nutui-react
npx skills add jdf2e/nutui-react --skill nutui-react
```

兼容 Claude Code / Cursor / VS Code / Codex 等所有支持 [skills](https://github.com/vercel-labs/skills) 协议的 Agent。安装后,Agent 在遇到 NutUI React 相关任务时会自动遵循「先查后写」的流程。

### 迁移 Skill:H5 → Taro

本包额外内置一份 [迁移 Skill](./skills/nutui-react-to-taro/SKILL.md),用于把使用 `@nutui/nutui-react`(H5)的项目迁移到 `@nutui/nutui-react-taro`(Taro 跨端 / 小程序)。它编排「包名/原生标签/样式单位/事件类型」等规则化改写,并同时调用本包与 `@nutui/nutui-react-taro-cli` 的 `info` 交叉核对两端 Props 差异(少数组件如 Uploader / Image 两端属性不同),对 Web API、canvas 等无法机械转换的场景给出重写指引。

```bash
npx skills add jdf2e/nutui-react --skill nutui-react-to-taro
```

## 本地开发

```bash
Expand Down
62 changes: 62 additions & 0 deletions packages/nutui-react-cli/docs/mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# NutUI Knowledge

本篇介绍如何通过 Model Context Protocol (MCP) 在 AI 工具中使用 NutUI-React。

## 启动 MCP 服务

`nutui-react mcp` 启动一个通过 stdio 通信的本地 MCP 服务,暴露 5 个只读工具与 2 个提示词。该命令不应在终端直接裸跑,而应在 AI 工具中配置(见下方)。

### 工具

| 工具 | 说明 |
| --- | --- |
| `nutui_list` | 列出全部组件(可按分类筛选) |
| `nutui_info` | 获取组件的 Props 规格 |
| `nutui_doc` | 获取组件完整文档(`lang: zh\|en`) |
| `nutui_demo` | 获取组件 H5 示例列表 / 源码 |
| `nutui_token` | 查询 Design Token(全局 / 组件级) |

所有工具均为只读、无副作用、不访问外部网络。

### 提示词

| 提示词 | 说明 |
| --- | --- |
| `nutui-expert` | 把 Agent 定位为 NutUI-React 专家(先查后写) |
| `nutui-page-generator` | 基于 NutUI-React 组件生成完整可运行页面 |

## 配置

**Claude Code**(`.mcp.json` 或 `claude mcp add`)、**Cursor**(`.cursor/mcp.json`)、**VS Code**(`.vscode/mcp.json` 的 `servers` 字段)通用配置:

```json
{
"mcpServers": {
"nutui-react": {
"command": "npx",
"args": ["-y", "@nutui/nutui-react-cli", "mcp"]
}
}
}
```

**Codex**(`~/.codex/config.toml`):

```toml
[mcp_servers.nutui-react]
command = "npx"
args = ["-y", "@nutui/nutui-react-cli", "mcp"]
```

`npx -y` 免全局安装即可拉起;也可全局安装 CLI 后把 `command` 换成 `nutui-react`、`args` 换成 `["mcp"]`。

## 在 AI 工具中的使用

| 工具 | 配置 |
| --- | --- |
| **Claude Code** | 添加到 `.mcp.json`,或用 `claude mcp add` 命令 |
| **Cursor** | 添加到 `.cursor/mcp.json`,或设置 → MCP |
| **VS Code** | 添加到 `.vscode/mcp.json` 的 `servers` 字段 |
| **Codex** | 添加到 `~/.codex/config.toml` |

当这些工具在对话中可用时,Agent 会优先直接调用,而非再拼命令行字符串。
6 changes: 4 additions & 2 deletions packages/nutui-react-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nutui/nutui-react-cli",
"version": "0.1.1",
"version": "4.0.0",
"type": "module",
"description": "NutUI React 面向 AI Coding 的离线知识查询 CLI:list / info / doc / demo / token。",
"keywords": [
Expand All @@ -24,7 +24,9 @@
"files": [
"dist",
"data",
"skills"
"skills",
"README.md",
"docs"
],
"engines": {
"node": ">=18.12.0"
Expand Down
19 changes: 19 additions & 0 deletions packages/nutui-react-cli/skills/nutui-react-to-taro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# NutUI React to Taro Migration

`nutui-react-to-taro` 是把项目从 NutUI React(`@nutui/nutui-react`,H5)迁移到 NutUI React Taro(`@nutui/nutui-react-taro`,小程序 / 跨端)的 skill,面向 AI 编程智能体。两个包由同一套 codebase 构建,几乎每个组件在两端都同名、Props 也大体一致,因此迁移高度规则化。skill 借助源端与目标端两个离线 CLI 交叉核对 Props,把迁移拆成包名 / import 改写、原生标签 → Taro 组件替换、样式单位修正等机械步骤,并对少数两端 Props 不同的组件做人工判断,避免盲目查找替换产出在小程序上悄悄失效的代码。

## 安装

本 skill 同时依赖源端(H5)与目标端(Taro)两个 CLI,运行时通过 `npx` 免安装调用,无需预装:

```bash
npx skills add jdf2e/nutui-react --skill nutui-react-to-taro
```

## 适用场景

- **把 H5 项目迁移到小程序 / 跨端**:需要把使用 `@nutui/nutui-react` 的 H5 项目或页面整体迁移到 Taro(`@nutui/nutui-react-taro`)运行时时,按扫描盘点 → 机械改写 → 语义改写 → 验证的流程,系统性完成包名、import、标签与样式的替换。
- **配置 Taro + NutUI 运行环境**:迁移前先准备项目——安装 `@nutui/nutui-react-taro` 等依赖、在 `config/index.js` 开启 `@tarojs/plugin-html` 并设置设计尺寸、在应用入口引入全局样式,确保迁移后的代码能在 Taro 编译运行。
- **交叉核对两端组件 Props 差异**:改写每个组件前,用源端与目标端两个 CLI 对比 Props(如 Uploader、Image、InputNumber 等两端不一致的组件),删除或重映射 Taro 端不接受的属性,避免产出在小程序上悄悄失效的代码。
- **改写 Web-only API 与原生 DOM 逻辑**:把 `window` / `document` / `localStorage` / canvas 等浏览器专有写法逐处映射到 `@tarojs/taro` 或组件自身能力,识别 Taro 端无对应的组件(如 `Audio`),并对无法安全自动迁移处标记出来交用户复核。
- **替换原生标签与样式单位**:将 `<div>` / `<span>` / `<img>` 等原生 HTML 标签替换为 `@tarojs/components`(`View` / `Text` / `Image`),修正裸 px、逻辑属性(如 `marginInlineStart`)与触摸事件类型,必要时用 `pxTransform` 做跨设备缩放。
248 changes: 248 additions & 0 deletions packages/nutui-react-cli/skills/nutui-react-to-taro/SKILL.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
---
name: nutui-react-to-taro
description: >
Use when migrating a project (or a code snippet) from NutUI React
(@nutui/nutui-react, H5) to NutUI React Taro (@nutui/nutui-react-taro,
mini-program / cross-platform Taro). Trigger scenarios such as "migrate NutUI
React to Taro", "make this H5 NutUI page run inside a mini-program", or
converting H5 NutUI components to the Taro runtime. The two packages share the
same set of components, and the vast majority map one-to-one — so the real
work is package-name / import rewrites, native-tag → Taro-component
replacement, style-unit fixes, and cross-checking the few components whose
props differ across the two ends.
allowed-tools:
- Bash(nutui-react *)
- Bash(nutui-react-taro *)
- Bash(npx -y @nutui/nutui-react-cli *)
- Bash(npx -y @nutui/nutui-react-taro-cli *)
- Bash(which nutui-react)
- Bash(which nutui-react-taro)
---

# NutUI React (H5) → NutUI React Taro migration

You are responsible for migrating code from `@nutui/nutui-react` (H5) to
`@nutui/nutui-react-taro` (Taro mini-program / cross-platform). The two packages
are built from the **same codebase**, so nearly every component shares the same
name and largely the same props across both ends. This makes the migration
highly rule-based — but a few steps still require real judgment and cannot be
done with blind find-and-replace.

Two CLIs back this work; both are offline, with metadata shipped alongside the packages:

- `@nutui/nutui-react-cli` — **source-end** (H5) source of truth: `nutui-react info <C>`
- `@nutui/nutui-react-taro-cli` — **target-end** (Taro) source of truth: `nutui-react-taro info <C>`

If a CLI is not on PATH, invoke it via npx (no install needed):

```bash
which nutui-react || echo "use: npx -y @nutui/nutui-react-cli info <C> --format json"
which nutui-react-taro || echo "use: npx -y @nutui/nutui-react-taro-cli info <C> --format json"
```

**The most important habit: for every component you touch, diff its props with
both CLIs before rewriting.** Props are usually identical, but once they differ
(Uploader, Image, InputNumber, etc.) blindly copying them produces code that
silently fails on the mini-program. Always pass `--format json` and parse it.

## Migration flow

Execute the phases below in order. Do not skip the scan — it is what tells you which files are risky.

### Phase 0 — Environment setup (project config, do this first)

Migrated code can only run in Taro if the project is configured properly. The
authoritative source is NutUI's official "Getting Started" (start-react) docs.

1. **Install dependencies** (ask the user for consent before running the install):
- `@nutui/nutui-react-taro`, `@nutui/icons-react-taro`
- `@tarojs/plugin-html` — **its version must match the project's Taro version**
- `babel-plugin-import` (only if the project needs on-demand imports)
2. **Modify `config/index.js`** — enable the HTML plugin and set the design size
so NutUI (a 375-based library) scales correctly:
```js
config = {
plugins: ['@tarojs/plugin-html'],
designWidth(input) {
if (input?.file?.replace(/\\+/g, '/').indexOf('@nutui') > -1) return 375
return 750
},
deviceRatio: { 640: 2.34 / 2, 750: 1, 828: 1.81 / 2, 375: 2 / 1 },
}
```
3. **Import the global stylesheet at the app entry** (`app.tsx` / `app.ts`):
```js
import '@nutui/nutui-react-taro/dist/style.css'
```

You may edit `config/index.js` and the entry file directly. Confirm with the
user before installing dependencies.

### Phase 1 — Scan and inventory

Find all NutUI usage and flag high-risk files up front:

```bash
# which files import the H5 package
grep -rn "@nutui/nutui-react\b\|@nutui/icons-react\b" src --include=*.tsx --include=*.ts

# high-risk signals — these files need line-by-line human / AI judgment (see Phase 3):
grep -rln "\bAudio\b" src # Audio has no counterpart on the Taro end (see pitfalls)
grep -rln "document\.\|window\.\|localStorage\|URL.createObjectURL\|addEventListener" src
grep -rln "getElementById\|querySelector\|createElement\|canvas" src # canvas / DOM logic
```

List the components involved, then confirm each one exists on the Taro end:

```bash
nutui-react-taro list --format json # confirm component names / spot the Audio gap
```

### Phase 2 — Mechanical rewrite (rules ①–④)

Process each file with the rule table below. These are rule-based enough to do
quickly, but ② and ③ still need light judgment (see notes).

### Phase 3 — Semantic rewrite and props cross-check (rules ⑤–⑥)

For every high-risk file flagged in Phase 1, and every component you migrate:

```bash
# diff props: what the H5 end has vs. what the Taro end accepts
nutui-react info Uploader --format json
nutui-react-taro info Uploader --format json
# for components needing a semantic rewrite (e.g. Signature), read the full Taro doc first
nutui-react-taro doc Signature --format json
```

Rewrite Web-only APIs into Taro APIs, remove / replace props the Taro end does
not accept, and handle the pitfalls below.

### Phase 4 — Verification

- Build the Taro target and confirm it compiles: e.g.
`taro build --type weapp --watch` (or `--type h5`).
- Manually re-check every high-risk file — **a passing compile does not mean**
the canvas / Web API rewrites behave correctly.
- Report which files were fully auto-migrated and which need user review.

## Rule table (before → after)

### ① Package names and imports — pure replacement

```diff
- import { Button, Cell } from '@nutui/nutui-react'
+ import { Button, Cell } from '@nutui/nutui-react-taro'
- import { Dongdong } from '@nutui/icons-react'
+ import { Dongdong } from '@nutui/icons-react-taro'
```

### ② Native HTML tags → Taro components — replace + add import

Taro has no DOM. Replace native tags and add the corresponding import from `@tarojs/components`.

| H5 | Taro | Notes |
| --- | --- | --- |
| `<div>` | `<View>` | block-level container |
| `<p>` | `<View>` | |
| `<span>` | `<Text>` or `<View>` | **`<Text>` is for pure inline text only; use `<View>` if it contains child elements** |
| `<img>` | `<Image>` | |

```diff
+ import { View } from '@tarojs/components'
<Cell onClick={() => setIsVisible(!isVisible)}>
- <span>Basic usage</span>
- <div style={{ marginInlineStart: '10px', color: '#999' }}>{val}</div>
+ <View>Basic usage</View>
+ <View style={{ marginLeft: pxTransform(10), color: '#999' }}>{val}</View>
</Cell>
```

### ③ Style units — bare px and logical properties

- Bare numeric px must become strings: `margin: 8` → `margin: '8px'`.
- Mini-programs do not support logical properties: `marginInlineStart` →
`marginLeft`, `insetInlineStart` → `left`, etc.
- For values that need cross-device scaling, use `pxTransform(10)` imported from
`@nutui/nutui-react-taro` (returns an rpx-adapted length).

```diff
- const marginStyle = { margin: 8 }
+ const marginStyle = { margin: '8px' }
```

### ④ Touch event types

Mini-program touch events are not `MouseEvent`. Loosen the type and import
`ITouchEvent` from `@tarojs/components`.

```diff
+ import { ITouchEvent } from '@tarojs/components'
- const testClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {}
+ const testClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | ITouchEvent) => {}
```

### ⑤ Web-only API → Taro API — requires reasoning, rewrite case by case

The Taro runtime provides only a **limited emulation** of `window` / `document` /
DOM, and its coverage drifts by target version — **do not delete wholesale**.
Judge case by case: map to `@tarojs/taro` or the component's own capabilities
where possible; keep what the runtime genuinely supports (e.g. the async
`getBoundingClientRect`); delete only logic that truly cannot be migrated. Common
mappings:

| H5 pattern | Taro replacement |
| --- | --- |
| `alert` / popping a toast via DOM | `Taro.showToast(...)` (`import Taro from '@tarojs/taro'`) |
| `URL.createObjectURL(file)` | pick the matching Taro chooser/upload API by file type (`Taro.chooseMedia` for images/video; check the `@tarojs/taro` docs for other types), then use its temp path — don't force video / audio / generic files through image picking |
| `document.createElement` + manual DOM manipulation | prefer component props / ref; when you genuinely need to touch nodes use APIs like `Taro.createSelectorQuery`, don't blindly delete the logic |
| `window.location` / route navigation | `Taro.navigateTo` / `Taro.redirectTo` |
| `localStorage` | `Taro.setStorageSync` / `Taro.getStorageSync` |
| `addEventListener('scroll')` | Taro page / scroll events or component props |

### ⑥ Component prop differences — cross-check with both CLIs

The vast majority of props are identical, but some components genuinely differ.
**Never assume — diff.** Confirmed examples (verify live at migration time,
versions drift):

| Component | H5-only props | Taro-only props | Handling |
| --- | --- | --- | --- |
| `Uploader` | `accept`, `capture` | `mediaType`, `sizeType`, `sourceType`, `camera` | re-express the intent with Taro's file-picking props |
| `Image` | `fit`, `lazy`, `position`, `alt` | — | remove / remap (e.g. `fit` → check the CLI doc for `mode` semantics) |
| `InputNumber` | `select` | `type` | check the CLI doc |
| `Button` | — | (`openType`, `hoverClass` … are mini-program pass-through attrs) | add mini-program-specific props as needed |

## Pitfalls (blind replacement gets these wrong)

1. **`Audio` has no counterpart on the Taro end.** It only exists in the H5
package. When a file uses NutUI's `Audio`, stop and tell the user — suggest
`Taro.createInnerAudioContext()` or a custom solution. Do not invent an
import out of thin air.
2. **Do not blindly replace every `document`.** Some components accept it as-is
— e.g. `Popup`'s `portal={document.body}` **stays unchanged** on the Taro end
(the component handles it). Judge by component semantics / CLI doc, not by grep.
3. **Canvas-based components (e.g. `Signature`) are a semantic rewrite.** The H5
end often has hand-written DOM manipulation (`document.createElement('img')`,
appending to a node). On the Taro end, delete that DOM logic and use the
component's `canvasId` prop + ref methods. Read `nutui-react-taro doc
Signature` first.
4. **`<span>` → `<Text>` or `<View>`.** `<Text>` is inline and for pure text
only; wrapping child elements in `<Text>` breaks the layout. Use `<View>`
when there are nested elements.

## Core rules

1. **Before rewriting each component, cross-check its props with `nutui-react
info <C>` and `nutui-react-taro info <C>`.** This is the heart of the whole
migration — see rule ⑥.
2. **Always use `--format json`** — parse the structured output, do not regex
the text.
3. **Confirm the component exists on the Taro end** with `nutui-react-taro
list`; watch for the `Audio` gap.
4. **Rules ①–④ are mechanical; ⑤–⑥ and the pitfalls need judgment** — handle
the latter case by case, and flag anything that cannot be safely
auto-migrated for user review. Do not claim a file is fully migrated until
the Taro build compiles.
5. **Do the environment setup first** — migrating code is pointless if the
project cannot compile Taro + NutUI.
Loading
Loading