npm package: @sakitam-gis/sprite-cli
Description: A modern TypeScript CLI tool for generating sprite sheets from SVG and PNG files with advanced optimization and metadata support
Author: sakitam-fdd
Latest version: 1.0.2

# @sakitam-gis/sprite-cli

[![npm version](https://img.shields.io/npm/v/@sakitam-gis/sprite-cli.svg)](https://www.npmjs.com/package/@sakitam-gis/sprite-cli)
[![npm downloads](https://img.shields.io/npm/dm/@sakitam-gis/sprite-cli.svg)](https://www.npmjs.com/package/@sakitam-gis/sprite-cli)
[![license](https://img.shields.io/npm/l/@sakitam-gis/sprite-cli.svg)](https://github.com/sakitam-gis/sprite-cli/blob/main/LICENSE.md)
[![Node.js CI](https://github.com/sakitam-gis/sprite-cli/workflows/Node.js%20CI/badge.svg)](https://github.com/sakitam-gis/sprite-cli/actions)

一个现代化的、功能强大的雪碧图生成工具，用于从 SVG 和 PNG 文件生成优化的雪碧图（sprite sheets）。使用 TypeScript 编写，具有完善的工程化配置和高级优化功能。

> 本项目基于 [@mapbox/spritezero](https://github.com/mapbox/spritezero) 核心功能，完全使用 TypeScript 重写，无需外部依赖，并添加了更多高级特性。

[English](./README.md) | [快速开始](./QUICK_START.md)

## ✨ 特性

### 🎨 图像支持
- ✅ **SVG 支持** - 原生支持矢量图形，自动优化
- ✅ **PNG 支持** - 支持光栅图像输入
- ✅ **多种像素比率** - 支持 1x、2x、3x 等 Retina 显示屏
- ✅ **智能去重** - unique 模式，自动识别相同图像

### ⚡️ 性能优化
- 🚀 **高效布局算法** - Shelf Best Height Fit，空间利用率 80-95%
- 🔥 **并发处理** - 多图像并行处理，提升性能
- 💾 **智能缓存** - SVG 解析缓存，避免重复计算
- 🗜️ **PNG 优化** - 使用 Sharp 进行颜色量化和压缩优化

### 📋 元数据支持
- 📐 **9-patch 元数据** - 支持 stretchX/Y 区域定义
- 📄 **内容区域** - 支持 content 区域定义
- 📝 **文本占位符** - 支持 placeholder 区域定义
- 🏷️ **自动提取** - 基于 Mapbox 规范自动提取元数据

### 🛠️ 开发体验
- 💪 **TypeScript 编写** - 完整的类型支持和 IDE 智能提示
- ⚙️ **现代化工具链** - ESLint、Prettier、Husky、Vitest
- 📦 **零配置使用** - 开箱即用的 CLI 工具
- ✅ **完善测试** - 50+ 测试用例，覆盖核心功能

## 📦 安装

### 全局安装

```bash
npm install -g @sakitam-gis/sprite-cli
# 或
pnpm add -g @sakitam-gis/sprite-cli
# 或
yarn global add @sakitam-gis/sprite-cli
```

### 本地安装

```bash
npm install --save-dev @sakitam-gis/sprite-cli
# 或
pnpm add -D @sakitam-gis/sprite-cli
# 或
yarn add -D @sakitam-gis/sprite-cli
```

## 🚀 快速开始

### 安装

```bash
# npm
npm install -g @sakitam-gis/sprite-cli

# pnpm (推荐)
pnpm add -g @sakitam-gis/sprite-cli

# yarn
yarn global add @sakitam-gis/sprite-cli
```

### 基本用法

```bash
sprite-maker [output] [input] [options]
```

### 示例

#### 1️⃣ 生成标准雪碧图（1x）

```bash
sprite-maker output/sprite icons/
```

生成：
- `output/sprite.png` - 雪碧图图片
- `output/sprite.json` - 布局信息（包含位置和元数据）

#### 2️⃣ 生成 Retina 雪碧图（2x）

```bash
sprite-maker output/sprite@2x icons/ --retina
# 或
sprite-maker output/sprite@2x icons/ --ratio=2
```

#### 3️⃣ 生成多种分辨率

```bash
sprite-maker output/sprite icons/            # 1x
sprite-maker output/sprite@2x icons/ --ratio=2    # 2x
sprite-maker output/sprite@3x icons/ --ratio=3    # 3x
```

#### 4️⃣ 使用 unique 模式（去重）

```bash
sprite-maker output/sprite icons/ --unique
```

#### 5️⃣ PNG 优化选项

```bash
# 调色板模式（减小文件大小）
sprite-maker output/sprite icons/ --palette --colors=128

# 自定义质量
sprite-maker output/sprite icons/ --quality=90
```

## 📖 详细文档

查看 [快速开始指南](./QUICK_START.md) 获取更多详细示例和高级用法。

## 🔧 CLI 选项

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `--retina` | 生成 2x 像素比率（等同于 --ratio=2） | `false` |
| `--ratio=<n>` | 指定像素比率（1x, 2x, 3x 等） | `1` |
| `--unique` | 去重模式，相同图像只存储一次 | `false` |
| `--colors=<n>` | PNG 颜色数量（2-256） | `256` |
| `--quality=<n>` | PNG 质量（0-100） | `80` |
| `--palette` | 使用调色板模式压缩 PNG | `false` |
| `--help, -h` | 显示帮助信息 | - |

## 🛠️ 开发

### 环境要求

- Node.js >= 18.0.0
- pnpm（推荐）或 npm / yarn

### 克隆项目

```bash
git clone <repository-url>
cd icon-cli
```

### 安装依赖

```bash
pnpm install
# 或
npm install
```

### 开发命令

```bash
# 开发模式（监听文件变化）
pnpm dev

# 构建
pnpm build

# 类型检查
pnpm type-check

# 代码检查
pnpm lint

# 修复代码问题
pnpm lint:fix

# 格式化代码
pnpm format

# 检查代码格式
pnpm format:check

# 运行测试
pnpm test

# 监听模式运行测试
pnpm test:watch

# 测试覆盖率
pnpm test:coverage
```

## 🏗️ 项目结构

```
.
├── src/
│   ├── cli.ts                  # CLI 入口文件
│   ├── types.ts                # TypeScript 类型定义
│   ├── utils.ts                # 工具函数
│   └── core/
│       ├── index.ts            # 核心模块导出
│       ├── layout.ts           # 布局算法（Shelf Best Height Fit）
│       ├── image.ts            # 图像渲染和 PNG 优化
│       ├── metadata.ts         # SVG 元数据提取
│       └── shelf-pack.ts       # ShelfPack 打包算法
├── test/
│   ├── cli.test.ts             # CLI 端到端测试
│   ├── layout-efficiency.test.ts # 布局效率测试
│   ├── sorting.test.ts         # 排序稳定性测试
│   ├── metadata.test.ts        # 元数据提取测试
│   ├── performance.test.ts     # 性能优化测试
│   ├── shelf-pack.test.ts      # ShelfPack 算法测试
│   ├── error-handling.test.ts  # 错误处理测试
│   └── fixture/                # 测试 fixtures
├── dist/                       # 编译输出目录
├── tsconfig.json               # TypeScript 配置
├── tsup.config.ts              # 构建配置（tsup）
├── vitest.config.ts            # 测试配置（vitest）
├── .eslintrc.cjs               # ESLint 配置
├── .prettierrc.json            # Prettier 配置
└── commitlint.config.cjs       # Commitlint 配置
```

## 🔧 工程化配置

本项目采用了现代化的工程化工具链：

### 代码质量

- **TypeScript** - 类型安全
- **ESLint** - 代码检查
- **Prettier** - 代码格式化
- **lint-staged** - Git 暂存区文件检查

### Git 规范

- **Husky** - Git hooks 管理
- **commitlint** - Commit 信息规范检查

Commit 信息格式：

```
<type>(<scope>): <subject>

type: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
```

示例：
```bash
git commit -m "feat: 添加新的命令行选项"
git commit -m "fix: 修复文件路径解析问题"
git commit -m "docs: 更新 README 文档"
```

### 构建和测试

- **tsup** - 快速的 TypeScript 构建工具
- **Vitest** - 现代化的单元测试框架

## 📝 输出格式

### JSON 布局文件

生成的 JSON 文件包含每个图标的位置、尺寸和元数据信息：

```json
{
  "icon-name": {
    "width": 24,
    "height": 24,
    "x": 0,
    "y": 0,
    "pixelRatio": 1,
    "metadata": {
      "stretchX": [[8, 16]],
      "stretchY": [[8, 16]],
      "content": [4, 4, 20, 20],
      "placeholder": [6, 6, 18, 18]
    }
  }
}
```

### 元数据说明

- `stretchX`: 水平拉伸区域（9-patch）
- `stretchY`: 垂直拉伸区域（9-patch）
- `content`: 内容区域边界 `[left, top, right, bottom]`
- `placeholder`: 文本占位符区域 `[left, top, right, bottom]`

### SVG 元数据标记

在 SVG 文件中使用特殊的 ID 来定义元数据：

```xml
<svg width="24" height="24">
  <!-- 定义水平拉伸区域 -->
  <path id="mapbox-stretch-x" d="M 8 0 L 16 0 L 16 24 L 8 24 Z"/>
  
  <!-- 定义垂直拉伸区域 -->
  <path id="mapbox-stretch-y" d="M 0 8 L 24 8 L 24 16 L 0 16 Z"/>
  
  <!-- 定义内容区域 -->
  <path id="mapbox-content" d="M 4 4 L 20 4 L 20 20 L 4 20 Z"/>
  
  <!-- 定义文本占位符 -->
  <path id="mapbox-text-placeholder" d="M 6 6 L 18 6 L 18 18 L 6 18 Z"/>
</svg>
```

### PNG 雪碧图

生成的 PNG 文件是一个包含所有图标的合成图片，经过高级优化：

- ✅ 自动颜色量化（可配置）
- ✅ 最大压缩级别（level 9）
- ✅ 自适应滤波
- ✅ 可选调色板模式

## 🤝 贡献

欢迎贡献代码！请确保：

1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'feat: 添加某个特性'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 开启 Pull Request

提交代码前，请确保：
- 通过所有测试 (`pnpm test`)
- 代码符合规范 (`pnpm lint`)
- 代码格式正确 (`pnpm format:check`)

## 📄 许可证

ISC License

## 🔍 核心算法

### Shelf Best Height Fit

本项目使用 Shelf Best Height Fit 算法进行 2D 矩形打包：

1. **排序优化** - 按高度降序 + ID 字母序排序
2. **智能打包** - 选择最合适的货架（shelf）放置图像
3. **空间复用** - 自动复用释放的空闲区域
4. **自动扩展** - 根据需要动态调整画布大小
5. **空间利用率** - 达到 80-95%（比简单算法提升 10-20%）

### 性能优化

- **SVG 缓存** - 缓存解析结果，避免重复计算
- **并发处理** - 使用 `Promise.all` 并行处理多个图像
- **惰性计算** - 按需提取元数据和优化

## 📊 性能测试

基准测试结果（361 个 SVG 图标）：

```
✓ 布局算法效率 > 80%
✓ SVG 缓存加速 > 2x
✓ 并发处理加速 > 3x
✓ 大批量处理 (361 icons) < 5s
```

## 🙏 致谢

- 原项目：[spritezero-cli](https://github.com/mapbox/spritezero-cli)
- 核心库：[@mapbox/spritezero](https://github.com/mapbox/spritezero)
- 打包算法：[ShelfPack](https://github.com/mapbox/shelf-pack)
- 图像处理：[Sharp](https://github.com/lovell/sharp)
- SVG 优化：[SVGO](https://github.com/svg/svgo)

## 📮 联系

- Issues: [GitHub Issues](https://github.com/sakitam-gis/sprite-cli/issues)
- Pull Requests: [GitHub PRs](https://github.com/sakitam-gis/sprite-cli/pulls)
- NPM: [@sakitam-gis/sprite-cli](https://www.npmjs.com/package/@sakitam-gis/sprite-cli)

## 📜 更新日志

查看 [CHANGELOG.md](./CHANGELOG.md) 了解版本更新历史。

## 🌟 Star History

[![Star History Chart](https://api.star-history.com/svg?repos=sakitam-gis/sprite-cli&type=Date)](https://star-history.com/#sakitam-gis/sprite-cli&Date)