xhs-minitool-creator 1.0.0 → 1.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 +106 -51
- package/bin/create.mjs +5 -5
- package/package.json +1 -1
- package/src/pack.mjs +35 -4
- package/src/vite-preset.mjs +1 -1
- package/template/_gitignore +1 -1
- package/template/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,88 +1,143 @@
|
|
|
1
1
|
# xhs-minitool-creator
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
一个命令行工具,帮你创建、打包、检查**小红书小工具**项目。
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- **默认即合规**:Vite 预设内置 `build.target: ['es2017', 'chrome61']`,从源头避免 ES2020 语法泄漏导致的真机白屏
|
|
7
|
-
- **以官方规范为准**:内置官方打包规范 Skill(`minitool-zip-builder`)v1.6.0,校验规则与之一致
|
|
5
|
+
你只需要会最基本的终端操作:输入一条命令,就得到一个可以直接上传小红书的工具页面。不需要懂打包配置,不需要懂 zip 格式,也不需要提前了解小红书的开发规范——它都帮你处理好了。
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 快速上手(3 步)
|
|
10
|
+
|
|
11
|
+
> 前提:电脑上装好 [Node.js](https://nodejs.org)(18.17 或更新版本)。装好后在终端输入 `node -v` 能显示版本号即可。
|
|
12
|
+
|
|
13
|
+
### 第 1 步:创建项目
|
|
14
|
+
|
|
15
|
+
在终端里输入(把 `my-tool` 换成你喜欢的名字,只能用小写字母、数字和短横线):
|
|
10
16
|
|
|
11
17
|
```bash
|
|
12
|
-
# 创建项目(交互式)
|
|
13
18
|
npx xhs-minitool-creator my-tool
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
输入后它会问你几个简单的问题(页面标题、描述等),**不想回答就一路按回车**,全部用默认值即可。
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
npx xhs-minitool-creator my-tool --yes --title "我的工具" --theme "#ff2442"
|
|
23
|
+
### 第 2 步:进入项目并安装依赖
|
|
17
24
|
|
|
25
|
+
```bash
|
|
18
26
|
cd my-tool
|
|
19
27
|
npm install
|
|
20
|
-
npm run dev # 本地预览
|
|
21
|
-
npm run build # 构建 + 打包,输出 my-tool-xhs-tool.zip
|
|
22
|
-
npm run validate # 静态校验
|
|
23
28
|
```
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
第一次会下载一些文件,等待几十秒。
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
### 第 3 步:打包
|
|
28
33
|
|
|
34
|
+
```bash
|
|
35
|
+
npm run build
|
|
29
36
|
```
|
|
30
|
-
|
|
31
|
-
xhs-minitool
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
|
|
38
|
+
完成后,项目目录下会多出一个 `my-tool-xhs-minitool.zip`。**把这个 zip 上传到小红书创作服务平台,你的小工具就上线了。**
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 日常使用
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run dev # 本地预览:改代码时边改边看效果
|
|
46
|
+
npm run build # 打包:生成可上传的 zip
|
|
47
|
+
npm run validate # 体检:检查有没有违反平台规则的地方
|
|
36
48
|
```
|
|
37
49
|
|
|
38
|
-
|
|
50
|
+
改完代码后,重新执行 `npm run build`,把新生成的 zip 再传一次即可更新。
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 常见问题
|
|
55
|
+
|
|
56
|
+
**我需要会写代码吗?**
|
|
57
|
+
|
|
58
|
+
会用就行。它生成的项目自带一个能跑通的示例页面(输入名字、显示计数),你可以直接照葫芦画瓢改文字、改颜色。想做得更复杂,可以基于示例继续加代码,或让 AI 按项目里自带的开发规范(`.agents/` 目录)帮你改。
|
|
59
|
+
|
|
60
|
+
**打包时报错了怎么办?**
|
|
61
|
+
|
|
62
|
+
执行 `npm run validate`,它会告诉你哪里不合规、怎么改。大多数问题(比如引用了网络图片)它都能直接指出。
|
|
63
|
+
|
|
64
|
+
**zip 最大能多大?**
|
|
65
|
+
|
|
66
|
+
平台硬性上限 10 MB,建议控制在 2 MB 以内。图片尽量压缩后再放进去。打包时工具会自动汇报体积。
|
|
67
|
+
|
|
68
|
+
**为什么不能直接引用网络图片?**
|
|
69
|
+
|
|
70
|
+
小红书小工具在离线环境运行,网络图片、网络请求都会被禁止。把图片下载下来放进 `public/` 目录即可。
|
|
71
|
+
|
|
72
|
+
**这个工具和小红书官方是什么关系?**
|
|
73
|
+
|
|
74
|
+
没有隶属关系。它只是把小红书的官方开发规范内置进来帮你自动检查,规范原文就在项目 `.agents/skills/` 目录里,会随官方更新。
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 命令速查
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
npx xhs-minitool-creator <名字> 创建项目(默认)
|
|
82
|
+
npx xhs-minitool-creator <名字> --yes 跳过提问,全部用默认值
|
|
83
|
+
npx xhs-minitool-creator <名字> --title "我的工具" 指定页面标题
|
|
84
|
+
npx xhs-minitool-creator <名字> --theme "#ff2442" 指定主题色
|
|
85
|
+
```
|
|
39
86
|
|
|
40
87
|
| 选项 | 说明 |
|
|
41
88
|
| --- | --- |
|
|
42
|
-
|
|
|
43
|
-
| `--title
|
|
44
|
-
| `--desc
|
|
45
|
-
| `--icon
|
|
46
|
-
| `--theme
|
|
89
|
+
| `--yes` | 跳过提问,全部用默认值 |
|
|
90
|
+
| `--title` | 页面标题 |
|
|
91
|
+
| `--desc` | 项目描述 |
|
|
92
|
+
| `--icon` | 首页图标字符(默认「工」) |
|
|
93
|
+
| `--theme` | 主题色(默认 `#ff2442`) |
|
|
47
94
|
|
|
48
|
-
|
|
95
|
+
---
|
|
49
96
|
|
|
50
|
-
|
|
51
|
-
import { defineMinitoolConfig } from 'xhs-minitool-creator/vite';
|
|
52
|
-
import { pack } from 'xhs-minitool-creator';
|
|
53
|
-
import { validateDir } from 'xhs-minitool-creator/validate';
|
|
54
|
-
```
|
|
97
|
+
## 进阶
|
|
55
98
|
|
|
56
|
-
|
|
99
|
+
### 项目里自带什么?
|
|
57
100
|
|
|
58
|
-
|
|
101
|
+
创建出的项目包含:
|
|
59
102
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
103
|
+
- 一个开箱即用的示例页面(单页多视图,适配平台顶部导航栏与安全区)
|
|
104
|
+
- 已配置好的构建工具(Vite),**默认输出到 `xhs-minitool/` 目录**
|
|
105
|
+
- 打包与检查命令(纯 Node 实现,Windows / macOS / Linux 都能用)
|
|
106
|
+
- 官方开发规范 `minitool-zip-builder`(放在 `.agents/skills/`,给 AI 或人参考)
|
|
64
107
|
|
|
65
|
-
|
|
108
|
+
### 更新官方开发规范
|
|
66
109
|
|
|
67
|
-
|
|
68
|
-
2. 校验为纯 Node 静态扫描,规则对齐官方 Skill v1.6.0(含 10 MiB 硬上限、经典脚本约束、ES2017 基线)
|
|
69
|
-
3. 预设显式声明 `build.target: ['es2017', 'chrome61']`
|
|
70
|
-
4. 提供 `skill` 子命令查看版本并手动更新
|
|
110
|
+
官方规范会持续更新,且没有自动更新入口。做法:
|
|
71
111
|
|
|
72
|
-
|
|
112
|
+
1. 从官方渠道拿到最新规范包的下载地址(`.skill` 文件)
|
|
113
|
+
2. 在项目目录执行:
|
|
73
114
|
|
|
74
|
-
|
|
115
|
+
```bash
|
|
116
|
+
npx xhs-minitool-creator skill update --url <地址>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 检查命令的更多用法
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx xhs-minitool-creator validate ./xhs-minitool # 检查构建产物目录
|
|
123
|
+
npx xhs-minitool-creator validate ./xxx-xhs-minitool.zip # 检查已打包的 zip
|
|
124
|
+
npx xhs-minitool-creator pack --outDir <目录> # 指定产物目录再打包
|
|
125
|
+
```
|
|
75
126
|
|
|
76
|
-
|
|
77
|
-
|
|
127
|
+
### 编程式使用
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
import { defineMinitoolConfig } from 'xhs-minitool-creator/vite';
|
|
131
|
+
import { pack, validateDir } from 'xhs-minitool-creator';
|
|
132
|
+
```
|
|
78
133
|
|
|
79
|
-
|
|
134
|
+
---
|
|
80
135
|
|
|
81
|
-
##
|
|
136
|
+
## 说明
|
|
82
137
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
138
|
+
- 打包时若检测到系统自带 `zip` 命令(macOS 自带)会优先使用;没有则自动改用内置打包器,结果一致
|
|
139
|
+
- 静态检查无法替代真机验证,上线前请务必在小红书真机预览
|
|
140
|
+
- 平台规则可能随时调整,关键决策以小红书创作服务平台实时规则为准
|
|
86
141
|
|
|
87
142
|
## License
|
|
88
143
|
|
package/bin/create.mjs
CHANGED
|
@@ -40,8 +40,8 @@ create 选项:
|
|
|
40
40
|
--theme <颜色> 主题色(默认 #ff2442)
|
|
41
41
|
|
|
42
42
|
pack 选项:
|
|
43
|
-
--outDir <目录> 构建产物目录(默认 xhs-
|
|
44
|
-
--zipName <文件名> 输出 zip 名(默认 <包名>-xhs-
|
|
43
|
+
--outDir <目录> 构建产物目录(默认 xhs-minitool)
|
|
44
|
+
--zipName <文件名> 输出 zip 名(默认 <包名>-xhs-minitool.zip)
|
|
45
45
|
--strict 警告也视为失败
|
|
46
46
|
|
|
47
47
|
其他:
|
|
@@ -215,7 +215,7 @@ async function doCreate(name, vars) {
|
|
|
215
215
|
console.log(` cd ${name}`);
|
|
216
216
|
console.log(' npm install');
|
|
217
217
|
console.log(' npm run dev # 本地预览');
|
|
218
|
-
console.log(' npm run build # 构建 + 打包(输出 <项目名>-xhs-
|
|
218
|
+
console.log(' npm run build # 构建 + 打包(输出 <项目名>-xhs-minitool.zip)');
|
|
219
219
|
console.log(' npm run validate # 静态校验');
|
|
220
220
|
console.log('\n上传入口:小红书创作服务平台(以平台实时规则为准)');
|
|
221
221
|
}
|
|
@@ -224,7 +224,7 @@ async function doCreate(name, vars) {
|
|
|
224
224
|
|
|
225
225
|
function cmdPack(flags) {
|
|
226
226
|
const code = pack({
|
|
227
|
-
outDir: flags.outDir || 'xhs-
|
|
227
|
+
outDir: flags.outDir || 'xhs-minitool',
|
|
228
228
|
zipName: flags.zipName,
|
|
229
229
|
strict: flags.strict !== undefined ? flags.strict : true,
|
|
230
230
|
});
|
|
@@ -234,7 +234,7 @@ function cmdPack(flags) {
|
|
|
234
234
|
function cmdValidate(args, flags) {
|
|
235
235
|
const target = args._[0];
|
|
236
236
|
if (!target) {
|
|
237
|
-
fail('请指定要校验的目录或 zip,例如:xhs-minitool-creator validate ./xhs-
|
|
237
|
+
fail('请指定要校验的目录或 zip,例如:xhs-minitool-creator validate ./xhs-minitool');
|
|
238
238
|
}
|
|
239
239
|
const strict = flags.strict !== undefined ? flags.strict : true;
|
|
240
240
|
|
package/package.json
CHANGED
package/src/pack.mjs
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
14
14
|
import { dirname, extname, join, relative, resolve } from 'node:path';
|
|
15
|
+
import { spawnSync } from 'node:child_process';
|
|
15
16
|
import { createZip, listZipEntries } from './zip.mjs';
|
|
16
17
|
import { ALLOWED_EXT, validateDir, validateZip, formatIssues } from './validate.mjs';
|
|
17
18
|
|
|
@@ -109,6 +110,37 @@ function readPackageName(cwd) {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
/** 系统 zip 命令是否可用(macOS 自带;多数 Linux 需自行安装;Windows 无) */
|
|
114
|
+
function systemZipAvailable() {
|
|
115
|
+
const probe = spawnSync('zip', ['-v'], { stdio: 'ignore' });
|
|
116
|
+
return !probe.error && probe.status === 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 打 zip:优先使用系统 zip 命令(行为与平台工具一致),
|
|
121
|
+
* 不可用时回退到纯 Node 实现(零依赖,跨平台兜底)。
|
|
122
|
+
* 两种路径产物都会被自实现读取器校验结构。
|
|
123
|
+
*/
|
|
124
|
+
function makeZip(outDir, zipPath, entries) {
|
|
125
|
+
if (systemZipAvailable()) {
|
|
126
|
+
if (existsSync(zipPath)) rmSync(zipPath, { force: true });
|
|
127
|
+
const result = spawnSync('zip', ['-r', zipPath, '.', '-x', '*.DS_Store'], {
|
|
128
|
+
cwd: outDir,
|
|
129
|
+
encoding: 'utf8',
|
|
130
|
+
});
|
|
131
|
+
if (result.status !== 0) {
|
|
132
|
+
throw new Error(`系统 zip 打包失败:${result.stderr || result.stdout || 'unknown'}`);
|
|
133
|
+
}
|
|
134
|
+
console.log(' · 使用系统 zip 命令打包');
|
|
135
|
+
return readFileSync(zipPath);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log(' · 未检测到系统 zip,使用内置打包器');
|
|
139
|
+
const zipBuf = createZip(entries);
|
|
140
|
+
writeFileSync(zipPath, zipBuf);
|
|
141
|
+
return zipBuf;
|
|
142
|
+
}
|
|
143
|
+
|
|
112
144
|
/**
|
|
113
145
|
* @param {{
|
|
114
146
|
* cwd?: string, outDir?: string, zipName?: string, publicDir?: string,
|
|
@@ -117,8 +149,8 @@ function readPackageName(cwd) {
|
|
|
117
149
|
*/
|
|
118
150
|
export function pack(options = {}) {
|
|
119
151
|
const cwd = resolve(options.cwd || process.cwd());
|
|
120
|
-
const outDir = resolve(cwd, options.outDir || 'xhs-
|
|
121
|
-
const zipName = options.zipName || `${readPackageName(cwd)}-xhs-
|
|
152
|
+
const outDir = resolve(cwd, options.outDir || 'xhs-minitool');
|
|
153
|
+
const zipName = options.zipName || `${readPackageName(cwd)}-xhs-minitool.zip`;
|
|
122
154
|
const zipPath = resolve(cwd, zipName);
|
|
123
155
|
const publicDir = resolve(cwd, options.publicDir || 'public');
|
|
124
156
|
|
|
@@ -144,8 +176,7 @@ export function pack(options = {}) {
|
|
|
144
176
|
throw new Error('产物根目录缺少 index.html');
|
|
145
177
|
}
|
|
146
178
|
|
|
147
|
-
const zipBuf =
|
|
148
|
-
writeFileSync(zipPath, zipBuf);
|
|
179
|
+
const zipBuf = makeZip(outDir, zipPath, entries);
|
|
149
180
|
|
|
150
181
|
// 自检:确认 zip 结构正确(根含 index.html、无禁止文件)
|
|
151
182
|
const listed = listZipEntries(zipBuf).map((e) => e.name);
|
package/src/vite-preset.mjs
CHANGED
package/template/_gitignore
CHANGED