cuxml 1.0.6 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,140 +1,253 @@
1
- # cuxml
1
+ # CUXML
2
2
 
3
- CU: `'Can Use'` or `'customUI'`, whatever……
3
+ > CU: `'Can Use'` or `'customUI'`, whatever……
4
4
 
5
- ## What is it?
5
+ [![npm version](https://badge.fury.io/js/cuxml.svg)](https://www.npmjs.com/package/cuxml)
6
+ [![License](https://img.shields.io/npm/l/cuxml.svg)](LICENSE)
6
7
 
7
- 1. 可以将 customUI XML 设置的回调函数转成 JavaScript 函数,以便于在 WPS Office JS插件中使用,当然只是些简单的模版,复杂的还是需要自己写。
8
- > Can convert the callback functions of customUI XML settings to JavaScript functions, so that they can be used in WPS Office JS plug-ins. Of course, it is just some simple templates, and complex ones need to be written by yourself.
8
+ **CUXML** 是一个专为 WPS Office JS 插件开发者设计的工具,用于处理 RibbonUI XML 文件。它可以显著简化开发流程,让你更专注于业务逻辑。
9
9
 
10
- 3. 根据 CustomUI Ribbon 元素的布局规则和标准,帮助你快速粗略地检查 XML 文件是否符合规范。[simple types](https://learn.microsoft.com/en-us/openspecs/office_standards/ms-customui/869c8c9a-45f8-4119-b068-f61e76d04322)
11
- > According to the layout rules and standards of CustomUI Ribbon elements, help you quickly and roughly check whether the XML file conforms to the specification.
10
+ ## 特性
12
11
 
13
- >Only the namespace of Simple types in the http://schemas.microsoft.com/office/2006/01/customui are supported. It's may be support for customUI 2007/2010…… also.
12
+ - 🔄 **XML JavaScript 转换** - 自动将 RibbonUI XML 的回调函数配置转换为 JavaScript 代码
13
+ - 🔍 **XML 合规性检查** - 全面检查 XML 文件是否符合 CustomUI 规范
14
+ - 👀 **文件监视** - 监视 XML 文件变化,自动重新转换
15
+ - 📦 **模块化 API** - 提供完整的编程接口,支持同步和异步调用
16
+ - 🔌 **MCP 支持** - 可作为 MCP 插件集成到 AI 工具链中
14
17
 
15
- ## 示例 Example
18
+ ## 📦 安装
16
19
 
17
- XML file:
20
+ ```bash
21
+ npm install -g cuxml
22
+ ```
18
23
 
19
- ```xml
20
- <group id="test1" label="test1" getVisible="onthing"></group>
24
+ ## 🚀 快速开始
25
+
26
+ ### 命令行使用
27
+
28
+ #### 转换 XML 文件
29
+
30
+ ```bash
31
+ # 基本用法(不指定输出路径时,自动生成 {input}_temp.js)
32
+ cuxml -i ./ribbon.xml # 输出到 ./ribbon_temp.js
33
+
34
+ # 指定输出路径
35
+ cuxml -i ./ribbon.xml -o ./ribbon.js
36
+
37
+ # 监视模式(文件变化时自动转换)
38
+ cuxml -i ./ribbon.xml -w # 输出到 ./ribbon_temp.js
39
+
40
+ # 使用默认输入路径(当前目录下的 ribbon.xml)
41
+ cuxml # 需要在当前目录有 ribbon.xml 文件
21
42
  ```
22
43
 
23
- 输出到 JS 文件:
44
+ #### 检查 XML 文件
24
45
 
25
- > Out callback function to JS file:
46
+ ```bash
47
+ cuxml check ./ribbon.xml
48
+
49
+ # 显示详细信息
50
+ cuxml check ./ribbon.xml -v
51
+ ```
52
+
53
+ #### 查看帮助
26
54
 
27
55
  ```bash
28
- cuxml callback test.xml test.js -w
56
+ cuxml -h
57
+ cuxml check -h
58
+ cuxml convert -h
29
59
  ```
30
60
 
31
- 不出意外的话,你会得到这样的结果:
32
- > normally, you will get the result:
33
-
34
- ```js
35
- /**
36
- * @param {RibbonUI} ctrl 你不需要关心这个参数,它代表一个菜单控件元素对象。比如 button、group 等。
37
- * @note
38
- * - 这是控件的回调函数,你不应该调用这个函数。
39
- * - 通用模版而已,你可以根据需要自行修改。
40
- * - 这里的回调函数都是异步的,你不应该在这里写长耗时同步的代码,否则可能会导致 UI 卡死。(AI 说的)
41
- *
42
- * Time: Fri Apr 14 2023 01:43:09 GMT+0800 (China Standard Time)
43
- */
44
- function onthing(ctrl){
45
-
46
- // 以下代码只是通用模版,你可以根据需要自行修改
47
- // 通过 ctrl.Id 来判断当前元素
48
- // use ctrl.Id to judge the current element
49
-
50
- switch(ctrl.Id){
51
- // xmlPath: customUI[0]>ribbon[0]>tabs[0]>tab[0]>group[2]
52
- case "test1":
61
+ ### API 使用
62
+
63
+ ```javascript
64
+ const cuxml = require('cuxml');
65
+
66
+ // 转换 XML JavaScript
67
+ cuxml.convert('./ribbon.xml', './ribbon.js')
68
+ .then(result => console.log(result))
69
+ .catch(error => console.error(error));
70
+
71
+ // 同步转换
72
+ const result = cuxml.convertSync('./ribbon.xml', './ribbon.js');
73
+
74
+ // 检查 XML 文件
75
+ cuxml.check('./ribbon.xml')
76
+ .then(result => console.log(result));
77
+
78
+ // 同步检查
79
+ const checkResult = cuxml.checkSync('./ribbon.xml');
80
+
81
+ // 检查 XML 字符串
82
+ cuxml.check('<customUI xmlns="...">...</customUI>');
83
+
84
+ // 监视文件变化
85
+ const watcher = cuxml.watch('./ribbon.xml', './ribbon.js');
86
+ // 停止监视: watcher.close();
87
+
88
+ // 格式化检查结果
89
+ const detailedResult = cuxml.checkSync('./ribbon.xml', { detailed: true });
90
+ console.log(cuxml.formatCheckResult(detailedResult));
91
+ ```
92
+
93
+ ### MCP 插件
94
+
95
+ CUXML 可以作为 MCP (Model Context Protocol) 插件使用:
96
+
97
+ ```javascript
98
+ // 安装 MCP SDK
99
+ npm install @modelcontextprotocol/sdk
100
+
101
+ // 配置 MCP 服务器
102
+ {
103
+ "mcpServers": {
104
+ "cuxml": {
105
+ "command": "node",
106
+ "args": ["./node_modules/cuxml/src/mcp.js"]
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ## 📖 详细文档
113
+
114
+ 完整的使用文档和技术细节请参考:[CUXML Agent 文档](./test/agent_new.md)
115
+
116
+ ## 🔧 功能说明
117
+
118
+ ### XML 到 JavaScript 转换
119
+
120
+ 将 RibbonUI XML 文件中的回调函数配置自动转换为 JavaScript 函数代码:
121
+
122
+ - 智能解析 XML 中的回调函数属性
123
+ - 生成标准化的 JavaScript 函数模板
124
+ - 支持自动函数名处理(带 `.` 连接符的属性名会被截取)
125
+ - 自动处理函数名:`onClick.button1` → `button1`
126
+
127
+ **示例:**
128
+
129
+ ```xml
130
+ <button id="myButton" onAction="handleClick" label="点击我"/>
131
+ ```
132
+
133
+ 生成:
134
+
135
+ ```javascript
136
+ function handleClick(ctrl) {
137
+ switch (ctrl.Id) {
138
+ case "myButton":
139
+ // TODO: 实现控件逻辑
53
140
  break;
54
141
  default:
55
142
  break;
56
- };
57
-
58
- // 避免 UI 报错,总是返回 true
59
- // Need return true
60
-
143
+ }
61
144
  return true;
62
145
  }
146
+ ```
63
147
 
148
+ ### XML 合规性检查
149
+
150
+ 全面检查 XML 文件是否符合 CustomUI 规范:
151
+
152
+ - ✅ XML 语法规范性
153
+ - ✅ ID 唯一性检查(防止重复 ID)
154
+ - ✅ 属性冲突检测(如 `label` 和 `getLabel` 不能同时存在)
155
+ - ✅ 标签嵌套合规性
156
+ - ✅ 属性值类型验证
157
+ - ✅ 元素不支持的属性检测
158
+
159
+ ## 📁 项目结构
160
+
161
+ ```
162
+ cuxml/
163
+ ├── src/
164
+ │ ├── api.js # API 模块
165
+ │ ├── checker.js # XML 检查器
166
+ │ ├── cli.js # CLI 工具
167
+ │ ├── converter.js # 转换器
168
+ │ ├── mcp.js # MCP 插件
169
+ │ ├── parser.js # XML 解析器
170
+ │ └── templates.js # 模板生成器
171
+ ├── lib/
172
+ │ ├── simpleTypes.json # Simple Types 配置
173
+ │ ├── clashAttributes.json # 冲突属性配置
174
+ │ ├── StDelegate.json # 回调函数属性配置
175
+ │ └── cbfTypes.json # Callback 函数类型配置
176
+ ├── test/ # 测试文件和示例
177
+ ├── index.js # 主入口
178
+ └── package.json
64
179
  ```
65
180
 
66
- # Command
67
-
68
- 1. Run in Your WPS Office JS Plugin Project directory.
69
-
70
- ```bash
71
- npx cuxml # if support npx
72
- ```
73
- or
74
- ```bash
75
- node ./node_modules/cuxml/index.js # last choice……
76
- ```
77
- > 更多命令行参数请查看 --help 选项.
78
- > More command line parameters, please check the --help option.
79
-
80
- ## 注意
81
-
82
- **输出结果到文件时,保险起见,最好输出到临时文件,避免覆盖你已经写好的文件。**
83
-
84
- ## 最新更新
85
-
86
- 1. check, 仅输出有'问题'的 Element。
87
- 2. callback :
88
- + id 为空的 Element 会被忽略。
89
- + 匹配属性的回调函数返回值类型,在注释中标明。
90
- + JS 函数的注释中,添加了回调函数对应的 XML 元素属性。
91
- + 生成的 JS 函数只有一个参数,即 RibbonUI 对象。**不必添加多余的参数,目前 WPS Office Client 传参数时只有一个!**
92
- ```js
93
- // RibbonUI 对象成员大概如下:
94
- {
95
- Id: "test1", // 当前元素的 id 属性
96
- content:{...},
97
- Tag: "",// 如果你在 XML 中设置了 tag 属性,这里就会有值。
98
- }
99
- ```
100
-
101
- ## Bug
102
-
103
- 1. 可预见的: 如果 XML 中的回调函数名称带有" `.` "连接符,生成的 JS 代码会有语法错误。
104
- > Predictable: If the callback function name in XML contains a "`.`" connection symbol, the generated JS code will have a syntax error.
105
-
106
- 这种情况,cuxml 可能不适合用来批量生成 JS 回调函数。
107
- > In this case, cuxml may not be suitable for generating JS callback functions in batches.
108
-
109
- example:
110
- ```xml
111
- <group id="test1" label="test1" getVisible="on.thing"></group>
112
- ```
113
- > output:
114
- ```js
115
- function on.thing(ctrl){
116
- // ...
117
- }
118
- ```
181
+ ## 🎯 最佳实践
182
+
183
+ ### 1. 文件组织
184
+
185
+ ```
186
+ project/
187
+ ├── src/
188
+ │ └── ribbon.xml # RibbonUI 配置文件
189
+ ├── gen/
190
+ │ └── ribbon_callbacks.js # 自动生成的回调函数
191
+ ├── main.js # 主逻辑文件
192
+ └── package.json
193
+ ```
194
+
195
+ ### 2. 开发工作流
196
+
197
+ ```bash
198
+ # 开发阶段:使用监视模式,实时更新
199
+ cuxml -i src/ribbon.xml -o gen/ribbon_callbacks.js -w
200
+
201
+ # 构建阶段:生成并验证
202
+ cuxml check src/ribbon.xml && cuxml -i src/ribbon.xml -o gen/ribbon_callbacks.js
203
+ ```
204
+
205
+ ### 3. 错误处理
206
+
207
+ ```javascript
208
+ const cuxml = require('cuxml');
209
+
210
+ try {
211
+ cuxml.check('./ribbon.xml');
212
+ cuxml.convert('./ribbon.xml', './ribbon.js');
213
+ console.log('✅ 转换成功!');
214
+ } catch (error) {
215
+ console.error('❌ 转换失败:', error.message);
216
+ // 处理错误
217
+ }
218
+ ```
219
+
220
+ ## 🔗 相关资源
221
+
222
+ - [Microsoft CustomUI 规范](https://learn.microsoft.com/en-us/openspecs/office_standards/ms-customui/574eeee8-7a03-406a-b95f-f9e51e53dd9d)
223
+ - [Simple Types 参考](https://learn.microsoft.com/en-us/openspecs/office_standards/ms-customui/869c8c9a-45f8-4119-b068-f61e76d04322)
224
+ - [WPS Office 开发文档](https://wps.cn/developer/)
225
+ - [CUXML Agent 文档](./test/agent_new.md) - 完整的使用文档
226
+
227
+ ## 🤝 贡献
228
+
229
+ 欢迎贡献!请随时提交 Issue 或 Pull Request。
230
+
231
+ ## 📄 许可证
232
+
233
+ [ISC](LICENSE)
234
+
235
+ ## 📊 版本历史
119
236
 
120
- 是的, 我们能解决这个问题,但是,JS 函数的调用和声明方式是多变的,比如:
237
+ ### v2.0.0 (2026-02-14)
121
238
 
122
- ```xml
123
- <group id="test1" label="test1" getVisible="onthing"></group>
124
- ```
239
+ **重大更新:完全重构**
125
240
 
126
- ```js
127
- // cuxml 能将其转换为 function nothing(ctrl){};
128
- // 实际上也许你偏向于这种写法: let nothing = function(ctrl){};
129
- // 又或者它实际可能是:sync function nothing(ctrl){};
130
- ```
131
-
132
- 类似以下的写法,cuxml 可能无法准确的转换
241
+ - ✨ 全新的模块化架构
242
+ - 完整的 API 模块(支持同步和异步)
243
+ - 统一的 CLI 命令(`cuxml`)
244
+ - MCP 协议支持
245
+ - ✨ 完整的 JSDoc 文档
246
+ - ✨ 改进的错误处理和日志输出
247
+ - 🔧 优化项目结构
248
+ - 🐛 修复多个已知问题
133
249
 
134
- ```xml
135
- <group id="test1" getVisible="myRibbon.nothing"></group>
136
- <group id="test1" getVisible="a.b.c.nothing"></group>
137
- <group id="test1" getVisible="new nothing"></group>
138
- ```
250
+ ### v1.0.x
139
251
 
140
- 所以……如果你需要将 XML 中的诸如以上的回调函数转换为 JS 函数,也许你得自己写一些代码了。
252
+ - 初始版本
253
+ - 基本的 XML 转换和检查功能
package/index.js CHANGED
@@ -1,39 +1,17 @@
1
1
  #!/usr/bin/env node
2
- const Command = require('commander').Command;
3
- const program = new Command();
4
- const pkg = require('./package.json')
5
2
 
3
+ /**
4
+ * CUXML - WPS Office RibbonUI XML 处理工具
5
+ *
6
+ * 主入口文件,根据调用方式决定是作为 CLI 还是库使用
7
+ */
6
8
 
7
- program
8
- .name('cxml')
9
- .description(pkg.description)
10
- .version(pkg.version);
11
- program.command('check')
12
- .description('检查 XML 文件是否符合规范(CustomUI for MS Office 2006/2007……)仅输出有问题的 Element。')
13
- .argument('<xmlFile>', '要检查的 XML 文件')
14
- .argument('[outFile]', '输出检查结果到文件 [outFile]')
15
- .option('-w, --watch', '监视 <xmlFile> 文件')
16
- .action((xmlFile, outFile, options) => {
17
- console.log(JSON.stringify([options, xmlFile, outFile]));
18
- require('./cxml_w.js')(xmlFile, outFile, options)
19
- });
20
- program.command('callback')
21
- .description('生成 XML 中 CustomUI 元素设置的回调属性为 JavaScript Function 并写入 <jsFile>')
22
- .argument('<xmlFile>', 'customUI XML 文件')
23
- .argument('<jsFile>', '要写入的 JavaScript 文件')
24
- .option('-w, --write', '写入方式: 覆盖 JS 文件 <jsFile>')
25
- .option('-a, --append', '写入方式: 追加到 <jsFile> 文件末尾')
26
- .option('-watch, --watch', '监视 <xmlFile> 文件, 当文件发生变化时自动更新 <jsFile>,写入模式为覆盖')
27
- .action((xmlFile, jsFile, options) => {
28
- //console.log(JSON.stringify([options, xmlFile, jsFile]));
29
- if(options.watch){
30
- let w = require('chokidar').watch(xmlFile);
31
- w.on('change', (p,s) => {
32
- let xmlFile = p;
33
- require('./xml2cbFn.js')(xmlFile, jsFile, {write: true});
34
- })
35
- }else{
36
- require('./xml2cbFn.js')(xmlFile, jsFile, options);
37
- }
38
- });
39
- program.parse();
9
+ const CUXMLAPI = require('./src/api');
10
+
11
+ // 导出 API 供其他模块使用
12
+ module.exports = CUXMLAPI;
13
+
14
+ // 如果直接执行此文件,启动 CLI
15
+ if (require.main === module) {
16
+ require('./src/cli');
17
+ }
@@ -1,7 +1,7 @@
1
1
  [
2
2
  {
3
3
  "n": "getVisible",
4
- "t": "boolean"
4
+ "t": "string"
5
5
  },
6
6
  {
7
7
  "n": "getDescription",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  {
11
11
  "n": "getEnabled",
12
- "t": "boolean"
12
+ "t": "string"
13
13
  },
14
14
  {
15
15
  "n": "getImage",
@@ -29,15 +29,15 @@
29
29
  },
30
30
  {
31
31
  "n": "getShowImage",
32
- "t": "boolean"
32
+ "t": "string"
33
33
  },
34
34
  {
35
35
  "n": "getShowLabel",
36
- "t": "boolean"
36
+ "t": "string"
37
37
  },
38
38
  {
39
39
  "n": "getSize",
40
- "t": "number"
40
+ "t": "string"
41
41
  },
42
42
  {
43
43
  "n": "getSupertip",
@@ -45,15 +45,15 @@
45
45
  },
46
46
  {
47
47
  "n": "onAction",
48
- "t": "void"
48
+ "t": "string"
49
49
  },
50
50
  {
51
51
  "n": "getPressed",
52
- "t": "boolean"
52
+ "t": "string"
53
53
  },
54
54
  {
55
55
  "n": "getItemCount",
56
- "t": "number"
56
+ "t": "string"
57
57
  },
58
58
  {
59
59
  "n": "getItemID",
@@ -81,7 +81,7 @@
81
81
  },
82
82
  {
83
83
  "n": "onChange",
84
- "t": "void"
84
+ "t": "string"
85
85
  },
86
86
  {
87
87
  "n": "loadImage",
@@ -89,7 +89,7 @@
89
89
  },
90
90
  {
91
91
  "n": "onLoad",
92
- "t": "void"
92
+ "t": "string"
93
93
  },
94
94
  {
95
95
  "n": "getSelectedItemID",
@@ -97,7 +97,7 @@
97
97
  },
98
98
  {
99
99
  "n": "getSelectedItemIndex",
100
- "t": "number"
100
+ "t": "string"
101
101
  },
102
102
  {
103
103
  "n": "getContent",
@@ -105,11 +105,11 @@
105
105
  },
106
106
  {
107
107
  "n": "getItemHeight",
108
- "t": "number"
108
+ "t": "string"
109
109
  },
110
110
  {
111
111
  "n": "getItemWidth",
112
- "t": "number"
112
+ "t": "string"
113
113
  },
114
114
  {
115
115
  "n": "getTitle",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cuxml",
3
- "version": "1.0.6",
3
+ "version": "2.1.0",
4
4
  "description": "A tool to help use ribbon UI for your WPS Office Client JS add-in project.",
5
5
  "keywords": [
6
6
  "wps office",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "author": "",
19
19
  "license": "ISC",
20
- "homepage": "https://github.com/YYago/cuxml",
20
+ "homepage": "https://github.com/YYago/cuxml/README.md",
21
21
  "bugs": {
22
22
  "url": "https://github.com/YYago/cuxml/issues"
23
23
  },