feat: refactor to Dart CLI tool v2.1.0
This commit is contained in:
parent
6ca3e12d4e
commit
b33e0b91a7
|
|
@ -0,0 +1,11 @@
|
||||||
|
## 2.1.0
|
||||||
|
|
||||||
|
- Feat: 支持配置 `font_package` 以支持从其他包加载字体。
|
||||||
|
- Refactor: 优化生成的代码结构,使用私有工厂方法减少代码体积。
|
||||||
|
- Refactor: 统一 `fontFamily` 常量定义。
|
||||||
|
|
||||||
|
## 2.0.0
|
||||||
|
|
||||||
|
- Feat: 重构为 Dart CLI 工具。
|
||||||
|
- Feat: 支持 YAML 配置文件。
|
||||||
|
- Feat: 优化代码生成逻辑。
|
||||||
485
README.md
485
README.md
|
|
@ -1,339 +1,202 @@
|
||||||
# YX Icon Fonts
|
# YX Icon Fonts
|
||||||
|
|
||||||
学习官OA系统图标字体库,基于iconfont.ttf和iconfont.json生成的Flutter图标库。
|
从 iconfont.json 生成 Flutter IconData 常量的 Dart CLI 工具。
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
- 🎨 包含50+个精心设计的图标
|
- 🎨 解析 iconfont.cn 导出的 JSON 文件
|
||||||
- 📱 支持Flutter应用
|
- 📝 生成类型安全的 Flutter IconData 常量
|
||||||
- 🎯 类型安全的图标使用
|
- ⚙️ YAML 配置文件支持
|
||||||
- 📦 轻量级,无额外依赖
|
- 🏗️ 自定义类名和输出路径
|
||||||
- 🔧 易于集成和使用
|
- 📚 自动生成文档注释
|
||||||
- ⚡ 自动化生成脚本
|
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
在您的`pubspec.yaml`文件中添加依赖:
|
在您的 Flutter 项目的 `pubspec.yaml` 中添加为开发依赖:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dev_dependencies:
|
||||||
yx_icon_fonts: ^1.0.0
|
yx_icon_fonts:
|
||||||
|
git:
|
||||||
|
url: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
||||||
|
ref: v2.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
然后运行:
|
然后运行:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
flutter pub get
|
dart pub get
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用方法
|
## 快速开始
|
||||||
|
|
||||||
### 基本用法
|
### 1. 初始化配置文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dart run yx_icon_fonts init
|
||||||
|
```
|
||||||
|
|
||||||
|
这将在项目根目录创建 `icon_generator_config.yaml` 配置模板。
|
||||||
|
|
||||||
|
### 2. 准备资源文件
|
||||||
|
|
||||||
|
从 [iconfont.cn](https://www.iconfont.cn/) 下载您的图标项目,将以下文件放到项目中:
|
||||||
|
|
||||||
|
- `iconfont.ttf` - 字体文件
|
||||||
|
- `iconfont.json` - 图标配置文件
|
||||||
|
|
||||||
|
### 3. 配置 pubspec.yaml
|
||||||
|
|
||||||
|
在 `pubspec.yaml` 中注册字体:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
flutter:
|
||||||
|
fonts:
|
||||||
|
- family: iconfont
|
||||||
|
fonts:
|
||||||
|
- asset: assets/fonts/iconfont.ttf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 编辑配置文件
|
||||||
|
|
||||||
|
修改 `icon_generator_config.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
input:
|
||||||
|
font_file: "assets/fonts/iconfont.ttf"
|
||||||
|
json_file: "assets/fonts/iconfont.json"
|
||||||
|
font_family: "iconfont"
|
||||||
|
|
||||||
|
output:
|
||||||
|
file_path: "lib/generated/icons.dart"
|
||||||
|
class_name: "AppIcons"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 生成代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dart run yx_icon_fonts generate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. 使用生成的图标
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:flutter/material.dart';
|
import 'package:your_app/generated/icons.dart';
|
||||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
|
||||||
|
|
||||||
class MyWidget extends StatelessWidget {
|
// 在 Widget 中使用
|
||||||
@override
|
Icon(AppIcons.iconHome, size: 24, color: Colors.blue)
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Icon(
|
// 在 IconButton 中使用
|
||||||
YXIconFonts.iconMsgContacts,
|
IconButton(
|
||||||
size: 24,
|
icon: Icon(AppIcons.iconSettings),
|
||||||
color: Colors.blue,
|
onPressed: () {},
|
||||||
);
|
)
|
||||||
}
|
```
|
||||||
|
|
||||||
|
## 命令参考
|
||||||
|
|
||||||
|
### help - 显示帮助
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dart run yx_icon_fonts help
|
||||||
|
```
|
||||||
|
|
||||||
|
### init - 初始化配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 创建配置文件
|
||||||
|
dart run yx_icon_fonts init
|
||||||
|
|
||||||
|
# 强制覆盖已存在的配置文件
|
||||||
|
dart run yx_icon_fonts init --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### generate - 生成代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用默认配置文件
|
||||||
|
dart run yx_icon_fonts generate
|
||||||
|
|
||||||
|
# 指定配置文件
|
||||||
|
dart run yx_icon_fonts generate --config my_config.yaml
|
||||||
|
|
||||||
|
# 详细输出
|
||||||
|
dart run yx_icon_fonts generate --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置选项
|
||||||
|
|
||||||
|
完整的配置选项请参考 [icon_generator_config.template.yaml](./icon_generator_config.template.yaml)。
|
||||||
|
|
||||||
|
### generator 配置
|
||||||
|
|
||||||
|
| 选项 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| name | string | "Icon Generator" | 生成器名称,用于代码注释 |
|
||||||
|
| version | string | "1.0" | 版本号 |
|
||||||
|
| author | string | "" | 作者信息 |
|
||||||
|
|
||||||
|
### input 配置
|
||||||
|
|
||||||
|
| 选项 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| font_file | string | "assets/fonts/iconfont.ttf" | 字体文件路径 |
|
||||||
|
| json_file | string | "assets/fonts/iconfont.json" | JSON 配置文件路径 |
|
||||||
|
| font_family | string | "iconfont" | 字体家族名称 |
|
||||||
|
|
||||||
|
### output 配置
|
||||||
|
|
||||||
|
| 选项 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| file_path | string | "lib/generated/icons.dart" | 输出文件路径 |
|
||||||
|
| class_name | string | "AppIcons" | 生成的类名 |
|
||||||
|
| generate_docs | bool | true | 是否生成文档注释 |
|
||||||
|
| use_const_constructor | bool | true | 是否使用 const 构造函数 |
|
||||||
|
|
||||||
|
## 生成的代码示例
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 此文件由 yx_icon_fonts 自动生成,请勿手动修改
|
||||||
|
// 生成时间: 2025-01-01 12:00
|
||||||
|
// 图标数量: 50
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
/// MyApp Icons 图标常量
|
||||||
|
class AppIcons {
|
||||||
|
AppIcons._();
|
||||||
|
|
||||||
|
// 统一的 IconData 构造方法
|
||||||
|
static const _icon = _IconDataFactory._();
|
||||||
|
|
||||||
|
/// icon_home (U+E600)
|
||||||
|
static final IconData iconHome = _icon(0xe600);
|
||||||
|
|
||||||
|
// ... 更多图标
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 内部 IconData 工厂类
|
||||||
|
class _IconDataFactory {
|
||||||
|
const _IconDataFactory._();
|
||||||
|
|
||||||
|
static const String _fontFamily = 'iconfont';
|
||||||
|
|
||||||
|
IconData call(int codePoint) => IconData(codePoint, fontFamily: _fontFamily);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用YXIcon组件
|
## 从 v1.x 迁移
|
||||||
|
|
||||||
```dart
|
v2.0 版本将 yx_icon_fonts 从 Flutter 库转换为了 CLI 工具。主要变化:
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
|
||||||
|
|
||||||
class MyWidget extends StatelessWidget {
|
1. **安装方式变化**:从 `dependencies` 改为 `dev_dependencies`
|
||||||
@override
|
2. **资源文件位置**:字体和 JSON 文件现在放在使用项目中,而非库中
|
||||||
Widget build(BuildContext context) {
|
3. **配置方式**:使用 YAML 配置文件,支持自定义类名和路径
|
||||||
return YXIcon(
|
|
||||||
YXIconFonts.iconMsgContacts,
|
|
||||||
size: 24,
|
|
||||||
color: Colors.blue,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 在AppBar中使用
|
## License
|
||||||
|
|
||||||
```dart
|
MIT License
|
||||||
AppBar(
|
|
||||||
title: Text('我的应用'),
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(YXIconFonts.iconMsgSearch),
|
|
||||||
onPressed: () {
|
|
||||||
// 搜索操作
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 可用图标
|
|
||||||
|
|
||||||
### 消息相关图标
|
|
||||||
- `YXIconFonts.iconMsgContacts` - 联系人
|
|
||||||
- `YXIconFonts.iconMsgViedo` - 视频
|
|
||||||
- `YXIconFonts.iconMsgSearch` - 搜索
|
|
||||||
- `YXIconFonts.iconMsgCall` - 通话
|
|
||||||
- `YXIconFonts.iconMsgPhoto` - 照片
|
|
||||||
- `YXIconFonts.iconMsgImg` - 图片
|
|
||||||
- `YXIconFonts.iconMsgFile` - 文件
|
|
||||||
|
|
||||||
### 箭头相关图标
|
|
||||||
- `YXIconFonts.icon32Arrowright` - 右箭头32
|
|
||||||
- `YXIconFonts.icon44Arrowleft` - 左箭头44
|
|
||||||
- `YXIconFonts.icon44Arrowright` - 右箭头44
|
|
||||||
- `YXIconFonts.icon24Arrowleft` - 左箭头24
|
|
||||||
- `YXIconFonts.icon24Arrowdown` - 下箭头24
|
|
||||||
- `YXIconFonts.icon44Arrowright1` - 右箭头44(1)
|
|
||||||
|
|
||||||
### 编辑相关图标
|
|
||||||
- `YXIconFonts.icon44Edit` - 编辑44
|
|
||||||
- `YXIconFonts.icon24Edit` - 编辑24
|
|
||||||
- `YXIconFonts.icon36Editline` - 编辑线36
|
|
||||||
|
|
||||||
### 个人中心相关图标
|
|
||||||
- `YXIconFonts.icon44MePassword` - 密码
|
|
||||||
- `YXIconFonts.icon44MeHelp` - 帮助
|
|
||||||
- `YXIconFonts.icon44MeVersion` - 版本
|
|
||||||
- `YXIconFonts.icon44MePrivacy` - 隐私
|
|
||||||
- `YXIconFonts.icon44MeUser` - 用户
|
|
||||||
- `YXIconFonts.icon44MeSafe` - 安全
|
|
||||||
- `YXIconFonts.icon44MePhone` - 手机
|
|
||||||
|
|
||||||
### 功能图标
|
|
||||||
- `YXIconFonts.icon32Filter` - 筛选
|
|
||||||
- `YXIconFonts.icon36Question` - 问题
|
|
||||||
- `YXIconFonts.icon36Onlysee` - 仅查看
|
|
||||||
- `YXIconFonts.icon36Hint` - 提示
|
|
||||||
- `YXIconFonts.icon24Switch` - 切换
|
|
||||||
|
|
||||||
### 操作图标
|
|
||||||
- `YXIconFonts.icon44Delete` - 删除44
|
|
||||||
- `YXIconFonts.icon36Delete` - 删除36
|
|
||||||
- `YXIconFonts.icon24Delete` - 删除24
|
|
||||||
- `YXIconFonts.icon44More` - 更多
|
|
||||||
- `YXIconFonts.icon44More2` - 更多2
|
|
||||||
- `YXIconFonts.icon24Copy` - 复制
|
|
||||||
- `YXIconFonts.icon44Share` - 分享
|
|
||||||
- `YXIconFonts.icon44Calendar` - 日历
|
|
||||||
|
|
||||||
### 添加相关图标
|
|
||||||
- `YXIconFonts.icon24Add` - 添加24
|
|
||||||
- `YXIconFonts.icon24Plus` - 加号
|
|
||||||
- `YXIconFonts.icon44Add` - 添加44
|
|
||||||
- `YXIconFonts.icon32Add` - 添加32
|
|
||||||
|
|
||||||
### 消息功能图标
|
|
||||||
- `YXIconFonts.icon56Msgadd` - 消息添加
|
|
||||||
- `YXIconFonts.icon56Msgface` - 消息表情
|
|
||||||
- `YXIconFonts.icon56Msgvoice` - 消息语音
|
|
||||||
|
|
||||||
### 其他图标
|
|
||||||
- `YXIconFonts.icon36Team` - 团队
|
|
||||||
- `YXIconFonts.icon32Student` - 学生
|
|
||||||
- `YXIconFonts.icon44Keyboard` - 键盘
|
|
||||||
- `YXIconFonts.icon24Minus` - 减号
|
|
||||||
- `YXIconFonts.icon44Quitlite` - 退出轻量
|
|
||||||
- `YXIconFonts.icon32Quit` - 退出32
|
|
||||||
- `YXIconFonts.icon44Quit` - 退出44
|
|
||||||
|
|
||||||
## 示例
|
|
||||||
|
|
||||||
运行示例应用查看所有图标:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd example
|
|
||||||
flutter run
|
|
||||||
```
|
|
||||||
|
|
||||||
## 自定义
|
|
||||||
|
|
||||||
### 修改图标大小
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Icon(
|
|
||||||
YXIconFonts.iconMsgContacts,
|
|
||||||
size: 48, // 自定义大小
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 修改图标颜色
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Icon(
|
|
||||||
YXIconFonts.iconMsgContacts,
|
|
||||||
color: Colors.red, // 自定义颜色
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 在主题中使用
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Theme(
|
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
iconTheme: IconThemeData(
|
|
||||||
color: Colors.blue,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Icon(YXIconFonts.iconMsgContacts),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 开发
|
|
||||||
|
|
||||||
### 自动化生成脚本
|
|
||||||
|
|
||||||
项目提供了 `generate.sh` 脚本来自动化图标数据的生成过程。
|
|
||||||
|
|
||||||
#### 脚本功能
|
|
||||||
|
|
||||||
- 🔄 自动生成图标数据文件 (`lib/src/yx_icon_fonts_data.dart`)
|
|
||||||
- 📝 自动生成示例文件 (`example/lib/icons.dart`)
|
|
||||||
- ✅ 错误检查和验证
|
|
||||||
- 🎨 彩色输出和进度提示
|
|
||||||
|
|
||||||
#### 使用方法
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 生成所有文件(默认)
|
|
||||||
./generate.sh
|
|
||||||
|
|
||||||
# 只生成图标数据
|
|
||||||
./generate.sh icons
|
|
||||||
|
|
||||||
# 只生成示例文件
|
|
||||||
./generate.sh example
|
|
||||||
|
|
||||||
# 显示帮助信息
|
|
||||||
./generate.sh help
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 脚本选项
|
|
||||||
|
|
||||||
| 选项 | 功能 | 生成文件 |
|
|
||||||
|------|------|----------|
|
|
||||||
| `all` (默认) | 生成所有文件 | `lib/src/yx_icon_fonts_data.dart` + `example/lib/icons.dart` |
|
|
||||||
| `icons` | 只生成图标数据 | `lib/src/yx_icon_fonts_data.dart` |
|
|
||||||
| `example` | 只生成示例文件 | `example/lib/icons.dart` |
|
|
||||||
| `help` | 显示帮助信息 | - |
|
|
||||||
|
|
||||||
#### 使用示例
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 首次使用,确保脚本有执行权限
|
|
||||||
chmod +x generate.sh
|
|
||||||
|
|
||||||
# 生成所有文件
|
|
||||||
./generate.sh
|
|
||||||
|
|
||||||
# 只更新图标数据(当修改了 iconfont.json 时)
|
|
||||||
./generate.sh icons
|
|
||||||
|
|
||||||
# 只更新示例文件(当修改了图标数据时)
|
|
||||||
./generate.sh example
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 脚本输出示例
|
|
||||||
|
|
||||||
```
|
|
||||||
ℹ️ 开始生成所有文件...
|
|
||||||
|
|
||||||
ℹ️ 正在生成图标数据...
|
|
||||||
✅ 图标数据生成完成
|
|
||||||
|
|
||||||
ℹ️ 正在生成示例文件...
|
|
||||||
✅ 示例文件生成完成
|
|
||||||
|
|
||||||
✅ 所有文件生成完成!
|
|
||||||
```
|
|
||||||
|
|
||||||
### 项目结构
|
|
||||||
|
|
||||||
```
|
|
||||||
yx_icon_fonts/
|
|
||||||
├── lib/
|
|
||||||
│ ├── yx_icon_fonts.dart # 主库文件
|
|
||||||
│ ├── main.dart # 库入口文件
|
|
||||||
│ └── src/
|
|
||||||
│ ├── yx_icon_data.dart # 图标数据类
|
|
||||||
│ ├── yx_icon.dart # 图标组件
|
|
||||||
│ └── yx_icon_fonts_data.dart # 图标常量定义(自动生成)
|
|
||||||
├── fonts/
|
|
||||||
│ └── iconfont.ttf # 字体文件
|
|
||||||
├── scripts/
|
|
||||||
│ ├── generate_icons.dart # 图标数据生成脚本
|
|
||||||
│ ├── generate_example.dart # 示例文件生成脚本
|
|
||||||
│ └── utils.dart # 共享工具函数
|
|
||||||
├── example/
|
|
||||||
│ └── lib/
|
|
||||||
│ ├── main.dart # 示例应用
|
|
||||||
│ └── icons.dart # 示例图标文件(自动生成)
|
|
||||||
├── generate.sh # 自动化生成脚本
|
|
||||||
├── iconfont.json # 图标配置数据
|
|
||||||
├── pubspec.yaml # 包配置
|
|
||||||
└── README.md # 项目文档
|
|
||||||
```
|
|
||||||
|
|
||||||
### 更新图标
|
|
||||||
|
|
||||||
1. 替换 `fonts/iconfont.ttf` 文件
|
|
||||||
2. 更新 `iconfont.json` 文件
|
|
||||||
3. 运行生成脚本:
|
|
||||||
```bash
|
|
||||||
./generate.sh icons
|
|
||||||
```
|
|
||||||
4. 更新版本号
|
|
||||||
|
|
||||||
### 开发工作流
|
|
||||||
|
|
||||||
1. **修改图标源文件**:
|
|
||||||
- 更新 `fonts/iconfont.ttf`
|
|
||||||
- 更新 `iconfont.json`
|
|
||||||
|
|
||||||
2. **生成代码**:
|
|
||||||
```bash
|
|
||||||
./generate.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **测试**:
|
|
||||||
```bash
|
|
||||||
flutter analyze
|
|
||||||
flutter test
|
|
||||||
cd example && flutter run
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **发布**:
|
|
||||||
```bash
|
|
||||||
flutter pub publish
|
|
||||||
```
|
|
||||||
|
|
||||||
## 许可证
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
## 贡献
|
|
||||||
|
|
||||||
欢迎提交Issue和Pull Request!
|
|
||||||
|
|
||||||
## 更新日志
|
|
||||||
|
|
||||||
### 1.0.0
|
|
||||||
- 初始版本
|
|
||||||
- 包含50+个图标
|
|
||||||
- 支持Flutter 3.0+
|
|
||||||
- 添加自动化生成脚本
|
|
||||||
- 优化项目结构和文档
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
include: package:lints/recommended.yaml
|
include: package:very_good_analysis/analysis_options.yaml
|
||||||
|
|
||||||
analyzer:
|
analyzer:
|
||||||
exclude:
|
exclude:
|
||||||
- temp_font_awesome/**
|
- temp_font_awesome/**
|
||||||
- temp_font_awesome/**/*
|
- temp_font_awesome/**/*
|
||||||
|
- generate/**
|
||||||
|
- example/**
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
# 允许在生成的代码中使用常量标识符命名
|
||||||
|
constant_identifier_names: false
|
||||||
|
# 允许单行过长(生成的代码可能较长)
|
||||||
|
lines_longer_than_80_chars: false
|
||||||
|
# 允许公共成员不写文档
|
||||||
|
public_member_api_docs: false
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/usr/bin/env dart
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||||
|
|
||||||
|
/// YX Icon Fonts CLI 工具主入口
|
||||||
|
///
|
||||||
|
/// 这是一个图标字体代码生成工具,可以:
|
||||||
|
/// - 解析 iconfont.json 文件
|
||||||
|
/// - 生成 Flutter IconData 常量
|
||||||
|
/// - 支持自定义类名和输出路径
|
||||||
|
///
|
||||||
|
/// 使用方法:
|
||||||
|
/// `dart run yx_icon_fonts <command> [options]`
|
||||||
|
///
|
||||||
|
/// 可用命令:
|
||||||
|
/// - generate: 生成代码文件
|
||||||
|
/// - init: 初始化配置文件
|
||||||
|
/// - help: 显示帮助信息
|
||||||
|
/// - version: 显示版本信息
|
||||||
|
Future<void> main(List<String> arguments) async {
|
||||||
|
setupLogging(level: Level.ALL);
|
||||||
|
|
||||||
|
// 检查是否有参数
|
||||||
|
var resolvedArgs = arguments;
|
||||||
|
if (resolvedArgs.isEmpty) {
|
||||||
|
_showWelcome();
|
||||||
|
resolvedArgs = ['help'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查特殊命令
|
||||||
|
if (resolvedArgs.contains('--version') || resolvedArgs.contains('-v')) {
|
||||||
|
_showVersion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 CLI 运行器
|
||||||
|
final cli = IconFontsCLI();
|
||||||
|
final exitCode = await cli.run(resolvedArgs);
|
||||||
|
|
||||||
|
// 设置退出代码
|
||||||
|
exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示欢迎信息
|
||||||
|
void _showWelcome() {
|
||||||
|
appLogger
|
||||||
|
..info('🎨 欢迎使用 YX Icon Fonts CLI 工具!')
|
||||||
|
..info('这是一个强大的图标字体代码生成工具,可以帮助您:')
|
||||||
|
..info(' 📋 解析 iconfont.json 文件')
|
||||||
|
..info(' 🛠️ 生成 Flutter IconData 常量')
|
||||||
|
..info(' 📁 自定义输出路径和类名')
|
||||||
|
..info('使用 --help 查看详细帮助信息');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示版本信息
|
||||||
|
void _showVersion() {
|
||||||
|
appLogger
|
||||||
|
..info('🎨 YX Icon Fonts CLI v2.0.0')
|
||||||
|
..info('构建信息:')
|
||||||
|
..info(' - Dart SDK: ${Platform.version}')
|
||||||
|
..info(' - 平台: ${Platform.operatingSystem}')
|
||||||
|
..info('特性:')
|
||||||
|
..info(' ✨ YAML 配置文件支持')
|
||||||
|
..info(' 🏗️ 模块化架构设计')
|
||||||
|
..info(' 🚀 快速代码生成')
|
||||||
|
..info(' 📝 自定义类名和路径')
|
||||||
|
..info('更多信息请访问: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter');
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env dart
|
||||||
|
// YX Icon Fonts CLI 主入口
|
||||||
|
// 这是包的默认可执行文件入口点
|
||||||
|
// 当用户运行 `dart run yx_icon_fonts` 时会执行此文件
|
||||||
|
|
||||||
|
import 'main.dart' as entry;
|
||||||
|
|
||||||
|
void main(List<String> arguments) => entry.main(arguments);
|
||||||
|
|
@ -0,0 +1,541 @@
|
||||||
|
{
|
||||||
|
"id": "4944890",
|
||||||
|
"name": "劝学APP-学习官OA系统",
|
||||||
|
"font_family": "iconfont",
|
||||||
|
"css_prefix_text": "",
|
||||||
|
"description": "劝学APP-学习官OA系统图标",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "46349152",
|
||||||
|
"name": "icon_32_clean",
|
||||||
|
"font_class": "icon_32_clean",
|
||||||
|
"unicode": "e660",
|
||||||
|
"unicode_decimal": 58976
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46348938",
|
||||||
|
"name": "icon_36_viewhistory",
|
||||||
|
"font_class": "icon_36_viewhistory",
|
||||||
|
"unicode": "e65f",
|
||||||
|
"unicode_decimal": 58975
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46205256",
|
||||||
|
"name": "icon_36_revoke",
|
||||||
|
"font_class": "icon_36_revoke",
|
||||||
|
"unicode": "e65e",
|
||||||
|
"unicode_decimal": 58974
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46077069",
|
||||||
|
"name": "icon_30_edit",
|
||||||
|
"font_class": "icon_30_edit",
|
||||||
|
"unicode": "e65b",
|
||||||
|
"unicode_decimal": 58971
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46077068",
|
||||||
|
"name": "icon_24_copy2",
|
||||||
|
"font_class": "icon_24_copy2",
|
||||||
|
"unicode": "e65c",
|
||||||
|
"unicode_decimal": 58972
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46077067",
|
||||||
|
"name": "icon_30_delete",
|
||||||
|
"font_class": "icon_30_delete",
|
||||||
|
"unicode": "e65d",
|
||||||
|
"unicode_decimal": 58973
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46077053",
|
||||||
|
"name": "icon_36_add",
|
||||||
|
"font_class": "icon_36_add",
|
||||||
|
"unicode": "e65a",
|
||||||
|
"unicode_decimal": 58970
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46076927",
|
||||||
|
"name": "icon_32_location",
|
||||||
|
"font_class": "icon_32_location",
|
||||||
|
"unicode": "e659",
|
||||||
|
"unicode_decimal": 58969
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "46076827",
|
||||||
|
"name": "icon_24_mypoints",
|
||||||
|
"font_class": "icon_24_mypoints",
|
||||||
|
"unicode": "e657",
|
||||||
|
"unicode_decimal": 58967
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45986664",
|
||||||
|
"name": "icon_44_me_about",
|
||||||
|
"font_class": "icon_44_me_about",
|
||||||
|
"unicode": "e656",
|
||||||
|
"unicode_decimal": 58966
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45986657",
|
||||||
|
"name": "icon_44_me_pointsmall",
|
||||||
|
"font_class": "icon_44_me_pointsmall",
|
||||||
|
"unicode": "e658",
|
||||||
|
"unicode_decimal": 58968
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45876267",
|
||||||
|
"name": "icon_44_search",
|
||||||
|
"font_class": "icon_44_search",
|
||||||
|
"unicode": "e655",
|
||||||
|
"unicode_decimal": 58965
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45855059",
|
||||||
|
"name": "icon_36_clear_people",
|
||||||
|
"font_class": "icon_36_clear_people",
|
||||||
|
"unicode": "e654",
|
||||||
|
"unicode_decimal": 58964
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45530506",
|
||||||
|
"name": "icon_44_me_log_out",
|
||||||
|
"font_class": "icon_44_me_log_out",
|
||||||
|
"unicode": "e652",
|
||||||
|
"unicode_decimal": 58962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45530507",
|
||||||
|
"name": "icon_44_me_switch",
|
||||||
|
"font_class": "icon_44_me_switch",
|
||||||
|
"unicode": "e653",
|
||||||
|
"unicode_decimal": 58963
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45513436",
|
||||||
|
"name": "icon_44_wechat_share_white",
|
||||||
|
"font_class": "icon_44_wechat_share_white",
|
||||||
|
"unicode": "e651",
|
||||||
|
"unicode_decimal": 58961
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45513173",
|
||||||
|
"name": "icon_32_publish",
|
||||||
|
"font_class": "icon_32_publish",
|
||||||
|
"unicode": "e64e",
|
||||||
|
"unicode_decimal": 58958
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45513174",
|
||||||
|
"name": "icon_32_close",
|
||||||
|
"font_class": "icon_32_close",
|
||||||
|
"unicode": "e64f",
|
||||||
|
"unicode_decimal": 58959
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45513172",
|
||||||
|
"name": "icon_32_output",
|
||||||
|
"font_class": "icon_32_output",
|
||||||
|
"unicode": "e650",
|
||||||
|
"unicode_decimal": 58960
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45500127",
|
||||||
|
"name": "icon_24_download",
|
||||||
|
"font_class": "icon_24_download",
|
||||||
|
"unicode": "e64d",
|
||||||
|
"unicode_decimal": 58957
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45492400",
|
||||||
|
"name": "icon_voice_pause",
|
||||||
|
"font_class": "icon_voice_pause",
|
||||||
|
"unicode": "e64b",
|
||||||
|
"unicode_decimal": 58955
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45492399",
|
||||||
|
"name": "icon_voice",
|
||||||
|
"font_class": "icon_voice",
|
||||||
|
"unicode": "e64c",
|
||||||
|
"unicode_decimal": 58956
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45263171",
|
||||||
|
"name": "icon_subtract",
|
||||||
|
"font_class": "icon_subtract",
|
||||||
|
"unicode": "e64a",
|
||||||
|
"unicode_decimal": 58954
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45214203",
|
||||||
|
"name": "icon_44_edit",
|
||||||
|
"font_class": "icon_44_edit",
|
||||||
|
"unicode": "e648",
|
||||||
|
"unicode_decimal": 58952
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45214202",
|
||||||
|
"name": "icon_44_delete",
|
||||||
|
"font_class": "icon_44_delete",
|
||||||
|
"unicode": "e649",
|
||||||
|
"unicode_decimal": 58953
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45160662",
|
||||||
|
"name": "icon_44_cancel_account",
|
||||||
|
"font_class": "icon_44_cancel_account",
|
||||||
|
"unicode": "e647",
|
||||||
|
"unicode_decimal": 58951
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45103313",
|
||||||
|
"name": "icon_24_search",
|
||||||
|
"font_class": "icon_24_search",
|
||||||
|
"unicode": "e646",
|
||||||
|
"unicode_decimal": 58950
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "45037865",
|
||||||
|
"name": "icon_24_up",
|
||||||
|
"font_class": "icon_24_up",
|
||||||
|
"unicode": "e645",
|
||||||
|
"unicode_decimal": 58949
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44661359",
|
||||||
|
"name": "icon_msg_contacts",
|
||||||
|
"font_class": "icon_msg_contacts",
|
||||||
|
"unicode": "e644",
|
||||||
|
"unicode_decimal": 58948
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44659960",
|
||||||
|
"name": "icon_msg_video",
|
||||||
|
"font_class": "icon_msg_video",
|
||||||
|
"unicode": "e63e",
|
||||||
|
"unicode_decimal": 58942
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44659959",
|
||||||
|
"name": "icon_msg_search",
|
||||||
|
"font_class": "icon_msg_search",
|
||||||
|
"unicode": "e63f",
|
||||||
|
"unicode_decimal": 58943
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44659958",
|
||||||
|
"name": "icon_msg_call",
|
||||||
|
"font_class": "icon_msg_call",
|
||||||
|
"unicode": "e640",
|
||||||
|
"unicode_decimal": 58944
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44659956",
|
||||||
|
"name": "icon_msg_photo",
|
||||||
|
"font_class": "icon_msg_photo",
|
||||||
|
"unicode": "e641",
|
||||||
|
"unicode_decimal": 58945
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44659957",
|
||||||
|
"name": "icon_msg_img",
|
||||||
|
"font_class": "icon_msg_img",
|
||||||
|
"unicode": "e642",
|
||||||
|
"unicode_decimal": 58946
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44659955",
|
||||||
|
"name": "icon_msg_file",
|
||||||
|
"font_class": "icon_msg_file",
|
||||||
|
"unicode": "e643",
|
||||||
|
"unicode_decimal": 58947
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625643",
|
||||||
|
"name": "icon_32_arrow_right",
|
||||||
|
"font_class": "icon_32_arrow_right",
|
||||||
|
"unicode": "e61d",
|
||||||
|
"unicode_decimal": 58909
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625452",
|
||||||
|
"name": "icon_44_me_password",
|
||||||
|
"font_class": "icon_44_me_password",
|
||||||
|
"unicode": "e639",
|
||||||
|
"unicode_decimal": 58937
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625448",
|
||||||
|
"name": "icon_44_me_help",
|
||||||
|
"font_class": "icon_44_me_help",
|
||||||
|
"unicode": "e63a",
|
||||||
|
"unicode_decimal": 58938
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625447",
|
||||||
|
"name": "icon_24_minus",
|
||||||
|
"font_class": "icon_24_minus",
|
||||||
|
"unicode": "e63b",
|
||||||
|
"unicode_decimal": 58939
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625450",
|
||||||
|
"name": "icon_36_team",
|
||||||
|
"font_class": "icon_36_team",
|
||||||
|
"unicode": "e63c",
|
||||||
|
"unicode_decimal": 58940
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625446",
|
||||||
|
"name": "icon_32_filter",
|
||||||
|
"font_class": "icon_32_filter",
|
||||||
|
"unicode": "e63d",
|
||||||
|
"unicode_decimal": 58941
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625458",
|
||||||
|
"name": "icon_44_quit_lite",
|
||||||
|
"font_class": "icon_44_quit_lite",
|
||||||
|
"unicode": "e631",
|
||||||
|
"unicode_decimal": 58929
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625459",
|
||||||
|
"name": "icon_44_me_version",
|
||||||
|
"font_class": "icon_44_me_version",
|
||||||
|
"unicode": "e632",
|
||||||
|
"unicode_decimal": 58930
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625456",
|
||||||
|
"name": "icon_36_question",
|
||||||
|
"font_class": "icon_36_question",
|
||||||
|
"unicode": "e633",
|
||||||
|
"unicode_decimal": 58931
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625457",
|
||||||
|
"name": "icon_44_me_privacy",
|
||||||
|
"font_class": "icon_44_me_privacy",
|
||||||
|
"unicode": "e634",
|
||||||
|
"unicode_decimal": 58932
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625455",
|
||||||
|
"name": "icon_44_more2",
|
||||||
|
"font_class": "icon_44_more2",
|
||||||
|
"unicode": "e635",
|
||||||
|
"unicode_decimal": 58933
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625453",
|
||||||
|
"name": "icon_36_only_see",
|
||||||
|
"font_class": "icon_36_only_see",
|
||||||
|
"unicode": "e636",
|
||||||
|
"unicode_decimal": 58934
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625454",
|
||||||
|
"name": "icon_44_me_user",
|
||||||
|
"font_class": "icon_44_me_user",
|
||||||
|
"unicode": "e637",
|
||||||
|
"unicode_decimal": 58935
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625461",
|
||||||
|
"name": "icon_44_me_safe",
|
||||||
|
"font_class": "icon_44_me_safe",
|
||||||
|
"unicode": "e62c",
|
||||||
|
"unicode_decimal": 58924
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625460",
|
||||||
|
"name": "icon_44_me_phone",
|
||||||
|
"font_class": "icon_44_me_phone",
|
||||||
|
"unicode": "e62d",
|
||||||
|
"unicode_decimal": 58925
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625445",
|
||||||
|
"name": "icon_24_copy",
|
||||||
|
"font_class": "icon_24_copy",
|
||||||
|
"unicode": "e62e",
|
||||||
|
"unicode_decimal": 58926
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44625444",
|
||||||
|
"name": "icon_32_quit",
|
||||||
|
"font_class": "icon_32_quit",
|
||||||
|
"unicode": "e630",
|
||||||
|
"unicode_decimal": 58928
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572509",
|
||||||
|
"name": "icon_44_calendar",
|
||||||
|
"font_class": "icon_44_calendar",
|
||||||
|
"unicode": "e626",
|
||||||
|
"unicode_decimal": 58918
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572496",
|
||||||
|
"name": "icon_32_student",
|
||||||
|
"font_class": "icon_32_student",
|
||||||
|
"unicode": "e627",
|
||||||
|
"unicode_decimal": 58919
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572501",
|
||||||
|
"name": "icon_36_delete",
|
||||||
|
"font_class": "icon_36_delete",
|
||||||
|
"unicode": "e628",
|
||||||
|
"unicode_decimal": 58920
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572505",
|
||||||
|
"name": "icon_44_more",
|
||||||
|
"font_class": "icon_44_more",
|
||||||
|
"unicode": "e629",
|
||||||
|
"unicode_decimal": 58921
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572502",
|
||||||
|
"name": "icon_44_arrow_left",
|
||||||
|
"font_class": "icon_44_arrow_left",
|
||||||
|
"unicode": "e62a",
|
||||||
|
"unicode_decimal": 58922
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572499",
|
||||||
|
"name": "icon_36_edit_line",
|
||||||
|
"font_class": "icon_36_edit_line",
|
||||||
|
"unicode": "e62b",
|
||||||
|
"unicode_decimal": 58923
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572515",
|
||||||
|
"name": "icon_44_arrow_right",
|
||||||
|
"font_class": "icon_44_arrow_right",
|
||||||
|
"unicode": "e622",
|
||||||
|
"unicode_decimal": 58914
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572507",
|
||||||
|
"name": "icon_24_delete",
|
||||||
|
"font_class": "icon_24_delete",
|
||||||
|
"unicode": "e623",
|
||||||
|
"unicode_decimal": 58915
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572513",
|
||||||
|
"name": "icon_56_msg_add",
|
||||||
|
"font_class": "icon_56_msg_add",
|
||||||
|
"unicode": "e624",
|
||||||
|
"unicode_decimal": 58916
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572511",
|
||||||
|
"name": "icon_56_msg_face",
|
||||||
|
"font_class": "icon_56_msg_face",
|
||||||
|
"unicode": "e625",
|
||||||
|
"unicode_decimal": 58917
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572516",
|
||||||
|
"name": "icon_56_msg_voice",
|
||||||
|
"font_class": "icon_56_msg_voice",
|
||||||
|
"unicode": "e616",
|
||||||
|
"unicode_decimal": 58902
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572514",
|
||||||
|
"name": "icon_44_share",
|
||||||
|
"font_class": "icon_44_share",
|
||||||
|
"unicode": "e615",
|
||||||
|
"unicode_decimal": 58901
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572500",
|
||||||
|
"name": "icon_36_hint",
|
||||||
|
"font_class": "icon_36_hint",
|
||||||
|
"unicode": "e613",
|
||||||
|
"unicode_decimal": 58899
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572510",
|
||||||
|
"name": "icon_24_add",
|
||||||
|
"font_class": "icon_24_add",
|
||||||
|
"unicode": "e617",
|
||||||
|
"unicode_decimal": 58903
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572512",
|
||||||
|
"name": "icon_24_plus",
|
||||||
|
"font_class": "icon_24_plus",
|
||||||
|
"unicode": "e618",
|
||||||
|
"unicode_decimal": 58904
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572508",
|
||||||
|
"name": "icon_44_keyboard",
|
||||||
|
"font_class": "icon_44_keyboard",
|
||||||
|
"unicode": "e614",
|
||||||
|
"unicode_decimal": 58900
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572506",
|
||||||
|
"name": "icon_44_quit",
|
||||||
|
"font_class": "icon_44_quit",
|
||||||
|
"unicode": "e619",
|
||||||
|
"unicode_decimal": 58905
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572504",
|
||||||
|
"name": "icon_44_add",
|
||||||
|
"font_class": "icon_44_add",
|
||||||
|
"unicode": "e61a",
|
||||||
|
"unicode_decimal": 58906
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572495",
|
||||||
|
"name": "icon_24_switch",
|
||||||
|
"font_class": "icon_24_switch",
|
||||||
|
"unicode": "e61b",
|
||||||
|
"unicode_decimal": 58907
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572503",
|
||||||
|
"name": "icon_44_arrow_down_line",
|
||||||
|
"font_class": "icon_44_arrow_down_line",
|
||||||
|
"unicode": "e61c",
|
||||||
|
"unicode_decimal": 58908
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572493",
|
||||||
|
"name": "icon_24_arrow_right",
|
||||||
|
"font_class": "icon_24_arrow_right",
|
||||||
|
"unicode": "e61e",
|
||||||
|
"unicode_decimal": 58910
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572498",
|
||||||
|
"name": "icon_32_add",
|
||||||
|
"font_class": "icon_32_add",
|
||||||
|
"unicode": "e61f",
|
||||||
|
"unicode_decimal": 58911
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572494",
|
||||||
|
"name": "icon_24_edit",
|
||||||
|
"font_class": "icon_24_edit",
|
||||||
|
"unicode": "e620",
|
||||||
|
"unicode_decimal": 58912
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44572492",
|
||||||
|
"name": "icon_24_arrow_down",
|
||||||
|
"font_class": "icon_24_arrow_down",
|
||||||
|
"unicode": "e621",
|
||||||
|
"unicode_decimal": 58913
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,23 @@
|
||||||
|
# 图标字体生成器配置文件
|
||||||
|
# 用于生成 Flutter IconData 常量
|
||||||
|
|
||||||
|
generator:
|
||||||
|
name: "Example App Icons"
|
||||||
|
version: "1.0"
|
||||||
|
author: "Example"
|
||||||
|
|
||||||
|
input:
|
||||||
|
# 字体文件路径
|
||||||
|
font_file: "assets/fonts/iconfont.ttf"
|
||||||
|
# JSON 配置文件路径
|
||||||
|
json_file: "assets/fonts/iconfont.json"
|
||||||
|
# 字体家族名称
|
||||||
|
font_family: "iconfont"
|
||||||
|
|
||||||
|
output:
|
||||||
|
# 生成的 Dart 文件路径
|
||||||
|
file_path: "lib/generated/icons.dart"
|
||||||
|
# 生成的类名
|
||||||
|
class_name: "AppIcons"
|
||||||
|
# 是否生成文档注释
|
||||||
|
generate_docs: true
|
||||||
|
|
@ -1,24 +1,9 @@
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
/// 示例图标类
|
/// 示例图标模型
|
||||||
///
|
class ExampleIcon {
|
||||||
/// 用于在示例应用中展示图标
|
const ExampleIcon(this.iconData, this.title);
|
||||||
class ExampleIcon implements Comparable {
|
|
||||||
final IconData iconData;
|
final IconData iconData;
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
ExampleIcon(this.iconData, this.title);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => 'ExampleIcon{iconData: $iconData, title: $title}';
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
identical(this, other) || other is ExampleIcon && runtimeType == other.runtimeType && iconData == other.iconData && title == other.title;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => iconData.hashCode ^ title.hashCode;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int compareTo(other) => title.compareTo(other.title);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,261 @@
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 此文件由 yx_icon_fonts 自动生成,请勿手动修改
|
||||||
|
// 生成时间: 2025-12-17 11:07
|
||||||
|
// 图标数量: 76
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
/// Example App Icons 图标常量
|
||||||
|
///
|
||||||
|
/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用
|
||||||
|
///
|
||||||
|
/// 示例:
|
||||||
|
/// ```dart
|
||||||
|
/// Icon(AppIcons.iconName, size: 24)
|
||||||
|
/// ```
|
||||||
|
class AppIcons {
|
||||||
|
AppIcons._();
|
||||||
|
|
||||||
|
// 统一的 IconData 构造方法
|
||||||
|
static const _icon = _IconDataFactory._();
|
||||||
|
|
||||||
|
/// icon_32_clean (U+E660)
|
||||||
|
static final IconData icon32Clean = _icon(0xe660);
|
||||||
|
|
||||||
|
/// icon_36_viewhistory (U+E65F)
|
||||||
|
static final IconData icon36Viewhistory = _icon(0xe65f);
|
||||||
|
|
||||||
|
/// icon_36_revoke (U+E65E)
|
||||||
|
static final IconData icon36Revoke = _icon(0xe65e);
|
||||||
|
|
||||||
|
/// icon_30_edit (U+E65B)
|
||||||
|
static final IconData icon30Edit = _icon(0xe65b);
|
||||||
|
|
||||||
|
/// icon_24_copy2 (U+E65C)
|
||||||
|
static final IconData icon24Copy2 = _icon(0xe65c);
|
||||||
|
|
||||||
|
/// icon_30_delete (U+E65D)
|
||||||
|
static final IconData icon30Delete = _icon(0xe65d);
|
||||||
|
|
||||||
|
/// icon_36_add (U+E65A)
|
||||||
|
static final IconData icon36Add = _icon(0xe65a);
|
||||||
|
|
||||||
|
/// icon_32_location (U+E659)
|
||||||
|
static final IconData icon32Location = _icon(0xe659);
|
||||||
|
|
||||||
|
/// icon_24_mypoints (U+E657)
|
||||||
|
static final IconData icon24Mypoints = _icon(0xe657);
|
||||||
|
|
||||||
|
/// icon_44_me_about (U+E656)
|
||||||
|
static final IconData icon44MeAbout = _icon(0xe656);
|
||||||
|
|
||||||
|
/// icon_44_me_pointsmall (U+E658)
|
||||||
|
static final IconData icon44MePointsmall = _icon(0xe658);
|
||||||
|
|
||||||
|
/// icon_44_search (U+E655)
|
||||||
|
static final IconData icon44Search = _icon(0xe655);
|
||||||
|
|
||||||
|
/// icon_36_clear_people (U+E654)
|
||||||
|
static final IconData icon36ClearPeople = _icon(0xe654);
|
||||||
|
|
||||||
|
/// icon_44_me_log_out (U+E652)
|
||||||
|
static final IconData icon44MeLogOut = _icon(0xe652);
|
||||||
|
|
||||||
|
/// icon_44_me_switch (U+E653)
|
||||||
|
static final IconData icon44MeSwitch = _icon(0xe653);
|
||||||
|
|
||||||
|
/// icon_44_wechat_share_white (U+E651)
|
||||||
|
static final IconData icon44WechatShareWhite = _icon(0xe651);
|
||||||
|
|
||||||
|
/// icon_32_publish (U+E64E)
|
||||||
|
static final IconData icon32Publish = _icon(0xe64e);
|
||||||
|
|
||||||
|
/// icon_32_close (U+E64F)
|
||||||
|
static final IconData icon32Close = _icon(0xe64f);
|
||||||
|
|
||||||
|
/// icon_32_output (U+E650)
|
||||||
|
static final IconData icon32Output = _icon(0xe650);
|
||||||
|
|
||||||
|
/// icon_24_download (U+E64D)
|
||||||
|
static final IconData icon24Download = _icon(0xe64d);
|
||||||
|
|
||||||
|
/// icon_voice_pause (U+E64B)
|
||||||
|
static final IconData iconVoicePause = _icon(0xe64b);
|
||||||
|
|
||||||
|
/// icon_voice (U+E64C)
|
||||||
|
static final IconData iconVoice = _icon(0xe64c);
|
||||||
|
|
||||||
|
/// icon_subtract (U+E64A)
|
||||||
|
static final IconData iconSubtract = _icon(0xe64a);
|
||||||
|
|
||||||
|
/// icon_44_edit (U+E648)
|
||||||
|
static final IconData icon44Edit = _icon(0xe648);
|
||||||
|
|
||||||
|
/// icon_44_delete (U+E649)
|
||||||
|
static final IconData icon44Delete = _icon(0xe649);
|
||||||
|
|
||||||
|
/// icon_44_cancel_account (U+E647)
|
||||||
|
static final IconData icon44CancelAccount = _icon(0xe647);
|
||||||
|
|
||||||
|
/// icon_24_search (U+E646)
|
||||||
|
static final IconData icon24Search = _icon(0xe646);
|
||||||
|
|
||||||
|
/// icon_24_up (U+E645)
|
||||||
|
static final IconData icon24Up = _icon(0xe645);
|
||||||
|
|
||||||
|
/// icon_msg_contacts (U+E644)
|
||||||
|
static final IconData iconMsgContacts = _icon(0xe644);
|
||||||
|
|
||||||
|
/// icon_msg_video (U+E63E)
|
||||||
|
static final IconData iconMsgVideo = _icon(0xe63e);
|
||||||
|
|
||||||
|
/// icon_msg_search (U+E63F)
|
||||||
|
static final IconData iconMsgSearch = _icon(0xe63f);
|
||||||
|
|
||||||
|
/// icon_msg_call (U+E640)
|
||||||
|
static final IconData iconMsgCall = _icon(0xe640);
|
||||||
|
|
||||||
|
/// icon_msg_photo (U+E641)
|
||||||
|
static final IconData iconMsgPhoto = _icon(0xe641);
|
||||||
|
|
||||||
|
/// icon_msg_img (U+E642)
|
||||||
|
static final IconData iconMsgImg = _icon(0xe642);
|
||||||
|
|
||||||
|
/// icon_msg_file (U+E643)
|
||||||
|
static final IconData iconMsgFile = _icon(0xe643);
|
||||||
|
|
||||||
|
/// icon_32_arrow_right (U+E61D)
|
||||||
|
static final IconData icon32ArrowRight = _icon(0xe61d);
|
||||||
|
|
||||||
|
/// icon_44_me_password (U+E639)
|
||||||
|
static final IconData icon44MePassword = _icon(0xe639);
|
||||||
|
|
||||||
|
/// icon_44_me_help (U+E63A)
|
||||||
|
static final IconData icon44MeHelp = _icon(0xe63a);
|
||||||
|
|
||||||
|
/// icon_24_minus (U+E63B)
|
||||||
|
static final IconData icon24Minus = _icon(0xe63b);
|
||||||
|
|
||||||
|
/// icon_36_team (U+E63C)
|
||||||
|
static final IconData icon36Team = _icon(0xe63c);
|
||||||
|
|
||||||
|
/// icon_32_filter (U+E63D)
|
||||||
|
static final IconData icon32Filter = _icon(0xe63d);
|
||||||
|
|
||||||
|
/// icon_44_quit_lite (U+E631)
|
||||||
|
static final IconData icon44QuitLite = _icon(0xe631);
|
||||||
|
|
||||||
|
/// icon_44_me_version (U+E632)
|
||||||
|
static final IconData icon44MeVersion = _icon(0xe632);
|
||||||
|
|
||||||
|
/// icon_36_question (U+E633)
|
||||||
|
static final IconData icon36Question = _icon(0xe633);
|
||||||
|
|
||||||
|
/// icon_44_me_privacy (U+E634)
|
||||||
|
static final IconData icon44MePrivacy = _icon(0xe634);
|
||||||
|
|
||||||
|
/// icon_44_more2 (U+E635)
|
||||||
|
static final IconData icon44More2 = _icon(0xe635);
|
||||||
|
|
||||||
|
/// icon_36_only_see (U+E636)
|
||||||
|
static final IconData icon36OnlySee = _icon(0xe636);
|
||||||
|
|
||||||
|
/// icon_44_me_user (U+E637)
|
||||||
|
static final IconData icon44MeUser = _icon(0xe637);
|
||||||
|
|
||||||
|
/// icon_44_me_safe (U+E62C)
|
||||||
|
static final IconData icon44MeSafe = _icon(0xe62c);
|
||||||
|
|
||||||
|
/// icon_44_me_phone (U+E62D)
|
||||||
|
static final IconData icon44MePhone = _icon(0xe62d);
|
||||||
|
|
||||||
|
/// icon_24_copy (U+E62E)
|
||||||
|
static final IconData icon24Copy = _icon(0xe62e);
|
||||||
|
|
||||||
|
/// icon_32_quit (U+E630)
|
||||||
|
static final IconData icon32Quit = _icon(0xe630);
|
||||||
|
|
||||||
|
/// icon_44_calendar (U+E626)
|
||||||
|
static final IconData icon44Calendar = _icon(0xe626);
|
||||||
|
|
||||||
|
/// icon_32_student (U+E627)
|
||||||
|
static final IconData icon32Student = _icon(0xe627);
|
||||||
|
|
||||||
|
/// icon_36_delete (U+E628)
|
||||||
|
static final IconData icon36Delete = _icon(0xe628);
|
||||||
|
|
||||||
|
/// icon_44_more (U+E629)
|
||||||
|
static final IconData icon44More = _icon(0xe629);
|
||||||
|
|
||||||
|
/// icon_44_arrow_left (U+E62A)
|
||||||
|
static final IconData icon44ArrowLeft = _icon(0xe62a);
|
||||||
|
|
||||||
|
/// icon_36_edit_line (U+E62B)
|
||||||
|
static final IconData icon36EditLine = _icon(0xe62b);
|
||||||
|
|
||||||
|
/// icon_44_arrow_right (U+E622)
|
||||||
|
static final IconData icon44ArrowRight = _icon(0xe622);
|
||||||
|
|
||||||
|
/// icon_24_delete (U+E623)
|
||||||
|
static final IconData icon24Delete = _icon(0xe623);
|
||||||
|
|
||||||
|
/// icon_56_msg_add (U+E624)
|
||||||
|
static final IconData icon56MsgAdd = _icon(0xe624);
|
||||||
|
|
||||||
|
/// icon_56_msg_face (U+E625)
|
||||||
|
static final IconData icon56MsgFace = _icon(0xe625);
|
||||||
|
|
||||||
|
/// icon_56_msg_voice (U+E616)
|
||||||
|
static final IconData icon56MsgVoice = _icon(0xe616);
|
||||||
|
|
||||||
|
/// icon_44_share (U+E615)
|
||||||
|
static final IconData icon44Share = _icon(0xe615);
|
||||||
|
|
||||||
|
/// icon_36_hint (U+E613)
|
||||||
|
static final IconData icon36Hint = _icon(0xe613);
|
||||||
|
|
||||||
|
/// icon_24_add (U+E617)
|
||||||
|
static final IconData icon24Add = _icon(0xe617);
|
||||||
|
|
||||||
|
/// icon_24_plus (U+E618)
|
||||||
|
static final IconData icon24Plus = _icon(0xe618);
|
||||||
|
|
||||||
|
/// icon_44_keyboard (U+E614)
|
||||||
|
static final IconData icon44Keyboard = _icon(0xe614);
|
||||||
|
|
||||||
|
/// icon_44_quit (U+E619)
|
||||||
|
static final IconData icon44Quit = _icon(0xe619);
|
||||||
|
|
||||||
|
/// icon_44_add (U+E61A)
|
||||||
|
static final IconData icon44Add = _icon(0xe61a);
|
||||||
|
|
||||||
|
/// icon_24_switch (U+E61B)
|
||||||
|
static final IconData icon24Switch = _icon(0xe61b);
|
||||||
|
|
||||||
|
/// icon_44_arrow_down_line (U+E61C)
|
||||||
|
static final IconData icon44ArrowDownLine = _icon(0xe61c);
|
||||||
|
|
||||||
|
/// icon_24_arrow_right (U+E61E)
|
||||||
|
static final IconData icon24ArrowRight = _icon(0xe61e);
|
||||||
|
|
||||||
|
/// icon_32_add (U+E61F)
|
||||||
|
static final IconData icon32Add = _icon(0xe61f);
|
||||||
|
|
||||||
|
/// icon_24_edit (U+E620)
|
||||||
|
static final IconData icon24Edit = _icon(0xe620);
|
||||||
|
|
||||||
|
/// icon_24_arrow_down (U+E621)
|
||||||
|
static final IconData icon24ArrowDown = _icon(0xe621);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 内部 IconData 工厂类
|
||||||
|
class _IconDataFactory {
|
||||||
|
const _IconDataFactory._();
|
||||||
|
|
||||||
|
static const String _fontFamily = 'iconfont';
|
||||||
|
|
||||||
|
IconData call(int codePoint) => IconData(codePoint, fontFamily: _fontFamily);
|
||||||
|
}
|
||||||
|
|
@ -1,113 +1,112 @@
|
||||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
|
||||||
import 'package:yx_icon_fonts_example/example_icon.dart';
|
import 'package:yx_icon_fonts_example/example_icon.dart';
|
||||||
|
import 'package:yx_icon_fonts_example/generated/icons.dart';
|
||||||
|
|
||||||
// 此文件由脚本自动生成!
|
// 此文件用于示例展示,使用生成的 AppIcons 类
|
||||||
|
|
||||||
final icons = <ExampleIcon>[
|
final icons = <ExampleIcon>[
|
||||||
// 其他图标
|
// 其他图标
|
||||||
ExampleIcon(YXIconFonts.icon32Clean, 'icon 32 clean'),
|
ExampleIcon(AppIcons.icon32Clean, 'icon 32 clean'),
|
||||||
ExampleIcon(YXIconFonts.icon36Viewhistory, 'icon 36 viewhistory'),
|
ExampleIcon(AppIcons.icon36Viewhistory, 'icon 36 viewhistory'),
|
||||||
ExampleIcon(YXIconFonts.icon36Revoke, 'icon 36 revoke'),
|
ExampleIcon(AppIcons.icon36Revoke, 'icon 36 revoke'),
|
||||||
ExampleIcon(YXIconFonts.icon32Location, 'icon 32 location'),
|
ExampleIcon(AppIcons.icon32Location, 'icon 32 location'),
|
||||||
ExampleIcon(YXIconFonts.icon24Mypoints, 'icon 24 mypoints'),
|
ExampleIcon(AppIcons.icon24Mypoints, 'icon 24 mypoints'),
|
||||||
ExampleIcon(YXIconFonts.icon44Search, 'icon 44 search'),
|
ExampleIcon(AppIcons.icon44Search, 'icon 44 search'),
|
||||||
ExampleIcon(YXIconFonts.icon36ClearPeople, 'icon 36 clear people'),
|
ExampleIcon(AppIcons.icon36ClearPeople, 'icon 36 clear people'),
|
||||||
ExampleIcon(YXIconFonts.icon32Publish, 'icon 32 publish'),
|
ExampleIcon(AppIcons.icon32Publish, 'icon 32 publish'),
|
||||||
ExampleIcon(YXIconFonts.icon32Close, 'icon 32 close'),
|
ExampleIcon(AppIcons.icon32Close, 'icon 32 close'),
|
||||||
ExampleIcon(YXIconFonts.icon32Output, 'icon 32 output'),
|
ExampleIcon(AppIcons.icon32Output, 'icon 32 output'),
|
||||||
ExampleIcon(YXIconFonts.icon24Download, 'icon 24 download'),
|
ExampleIcon(AppIcons.icon24Download, 'icon 24 download'),
|
||||||
ExampleIcon(YXIconFonts.iconVoicePause, 'icon voice pause'),
|
ExampleIcon(AppIcons.iconVoicePause, 'icon voice pause'),
|
||||||
ExampleIcon(YXIconFonts.iconVoice, 'icon voice'),
|
ExampleIcon(AppIcons.iconVoice, 'icon voice'),
|
||||||
ExampleIcon(YXIconFonts.iconSubtract, 'icon subtract'),
|
ExampleIcon(AppIcons.iconSubtract, 'icon subtract'),
|
||||||
ExampleIcon(YXIconFonts.icon44CancelAccount, 'icon 44 cancel account'),
|
ExampleIcon(AppIcons.icon44CancelAccount, 'icon 44 cancel account'),
|
||||||
ExampleIcon(YXIconFonts.icon24Search, 'icon 24 search'),
|
ExampleIcon(AppIcons.icon24Search, 'icon 24 search'),
|
||||||
ExampleIcon(YXIconFonts.icon24Up, 'icon 24 up'),
|
ExampleIcon(AppIcons.icon24Up, 'icon 24 up'),
|
||||||
ExampleIcon(YXIconFonts.icon24Minus, 'icon 24 minus'),
|
ExampleIcon(AppIcons.icon24Minus, 'icon 24 minus'),
|
||||||
ExampleIcon(YXIconFonts.icon36OnlySee, 'icon 36 only see'),
|
ExampleIcon(AppIcons.icon36OnlySee, 'icon 36 only see'),
|
||||||
ExampleIcon(YXIconFonts.icon24Plus, 'icon 24 plus'),
|
ExampleIcon(AppIcons.icon24Plus, 'icon 24 plus'),
|
||||||
|
|
||||||
// 编辑相关图标
|
// 编辑相关图标
|
||||||
ExampleIcon(YXIconFonts.icon30Edit, 'icon 30 edit'),
|
ExampleIcon(AppIcons.icon30Edit, 'icon 30 edit'),
|
||||||
ExampleIcon(YXIconFonts.icon44Edit, 'icon 44 edit'),
|
ExampleIcon(AppIcons.icon44Edit, 'icon 44 edit'),
|
||||||
ExampleIcon(YXIconFonts.icon36EditLine, 'icon 36 edit line'),
|
ExampleIcon(AppIcons.icon36EditLine, 'icon 36 edit line'),
|
||||||
ExampleIcon(YXIconFonts.icon24Edit, 'icon 24 edit'),
|
ExampleIcon(AppIcons.icon24Edit, 'icon 24 edit'),
|
||||||
|
|
||||||
// 复制相关图标
|
// 复制相关图标
|
||||||
ExampleIcon(YXIconFonts.icon24Copy2, 'icon 24 copy2'),
|
ExampleIcon(AppIcons.icon24Copy2, 'icon 24 copy2'),
|
||||||
ExampleIcon(YXIconFonts.icon24Copy, 'icon 24 copy'),
|
ExampleIcon(AppIcons.icon24Copy, 'icon 24 copy'),
|
||||||
|
|
||||||
// 删除相关图标
|
// 删除相关图标
|
||||||
ExampleIcon(YXIconFonts.icon30Delete, 'icon 30 delete'),
|
ExampleIcon(AppIcons.icon30Delete, 'icon 30 delete'),
|
||||||
ExampleIcon(YXIconFonts.icon44Delete, 'icon 44 delete'),
|
ExampleIcon(AppIcons.icon44Delete, 'icon 44 delete'),
|
||||||
ExampleIcon(YXIconFonts.icon36Delete, 'icon 36 delete'),
|
ExampleIcon(AppIcons.icon36Delete, 'icon 36 delete'),
|
||||||
ExampleIcon(YXIconFonts.icon24Delete, 'icon 24 delete'),
|
ExampleIcon(AppIcons.icon24Delete, 'icon 24 delete'),
|
||||||
|
|
||||||
// 添加相关图标
|
// 添加相关图标
|
||||||
ExampleIcon(YXIconFonts.icon36Add, 'icon 36 add'),
|
ExampleIcon(AppIcons.icon36Add, 'icon 36 add'),
|
||||||
ExampleIcon(YXIconFonts.icon24Add, 'icon 24 add'),
|
ExampleIcon(AppIcons.icon24Add, 'icon 24 add'),
|
||||||
ExampleIcon(YXIconFonts.icon44Add, 'icon 44 add'),
|
ExampleIcon(AppIcons.icon44Add, 'icon 44 add'),
|
||||||
ExampleIcon(YXIconFonts.icon32Add, 'icon 32 add'),
|
ExampleIcon(AppIcons.icon32Add, 'icon 32 add'),
|
||||||
|
|
||||||
// 个人中心相关图标
|
// 个人中心相关图标
|
||||||
ExampleIcon(YXIconFonts.icon44MeAbout, 'icon 44 me about'),
|
ExampleIcon(AppIcons.icon44MeAbout, 'icon 44 me about'),
|
||||||
ExampleIcon(YXIconFonts.icon44MePointsmall, 'icon 44 me pointsmall'),
|
ExampleIcon(AppIcons.icon44MePointsmall, 'icon 44 me pointsmall'),
|
||||||
ExampleIcon(YXIconFonts.icon44MeLogOut, 'icon 44 me log out'),
|
ExampleIcon(AppIcons.icon44MeLogOut, 'icon 44 me log out'),
|
||||||
ExampleIcon(YXIconFonts.icon44MeSwitch, 'icon 44 me switch'),
|
ExampleIcon(AppIcons.icon44MeSwitch, 'icon 44 me switch'),
|
||||||
ExampleIcon(YXIconFonts.icon44MePassword, 'icon 44 me password'),
|
ExampleIcon(AppIcons.icon44MePassword, 'icon 44 me password'),
|
||||||
ExampleIcon(YXIconFonts.icon44MeHelp, 'icon 44 me help'),
|
ExampleIcon(AppIcons.icon44MeHelp, 'icon 44 me help'),
|
||||||
ExampleIcon(YXIconFonts.icon44MeVersion, 'icon 44 me version'),
|
ExampleIcon(AppIcons.icon44MeVersion, 'icon 44 me version'),
|
||||||
ExampleIcon(YXIconFonts.icon44MePrivacy, 'icon 44 me privacy'),
|
ExampleIcon(AppIcons.icon44MePrivacy, 'icon 44 me privacy'),
|
||||||
ExampleIcon(YXIconFonts.icon44MeUser, 'icon 44 me user'),
|
ExampleIcon(AppIcons.icon44MeUser, 'icon 44 me user'),
|
||||||
ExampleIcon(YXIconFonts.icon44MeSafe, 'icon 44 me safe'),
|
ExampleIcon(AppIcons.icon44MeSafe, 'icon 44 me safe'),
|
||||||
ExampleIcon(YXIconFonts.icon44MePhone, 'icon 44 me phone'),
|
ExampleIcon(AppIcons.icon44MePhone, 'icon 44 me phone'),
|
||||||
|
|
||||||
// 分享相关图标
|
// 分享相关图标
|
||||||
ExampleIcon(YXIconFonts.icon44WechatShareWhite, 'icon 44 wechat share white'),
|
ExampleIcon(AppIcons.icon44WechatShareWhite, 'icon 44 wechat share white'),
|
||||||
ExampleIcon(YXIconFonts.icon44Share, 'icon 44 share'),
|
ExampleIcon(AppIcons.icon44Share, 'icon 44 share'),
|
||||||
|
|
||||||
// 消息相关图标
|
// 消息相关图标
|
||||||
ExampleIcon(YXIconFonts.iconMsgContacts, 'icon msg contacts'),
|
ExampleIcon(AppIcons.iconMsgContacts, 'icon msg contacts'),
|
||||||
ExampleIcon(YXIconFonts.iconMsgVideo, 'icon msg video'),
|
ExampleIcon(AppIcons.iconMsgVideo, 'icon msg video'),
|
||||||
ExampleIcon(YXIconFonts.iconMsgSearch, 'icon msg search'),
|
ExampleIcon(AppIcons.iconMsgSearch, 'icon msg search'),
|
||||||
ExampleIcon(YXIconFonts.iconMsgCall, 'icon msg call'),
|
ExampleIcon(AppIcons.iconMsgCall, 'icon msg call'),
|
||||||
ExampleIcon(YXIconFonts.iconMsgPhoto, 'icon msg photo'),
|
ExampleIcon(AppIcons.iconMsgPhoto, 'icon msg photo'),
|
||||||
ExampleIcon(YXIconFonts.iconMsgImg, 'icon msg img'),
|
ExampleIcon(AppIcons.iconMsgImg, 'icon msg img'),
|
||||||
ExampleIcon(YXIconFonts.iconMsgFile, 'icon msg file'),
|
ExampleIcon(AppIcons.iconMsgFile, 'icon msg file'),
|
||||||
ExampleIcon(YXIconFonts.icon56MsgAdd, 'icon 56 msg add'),
|
ExampleIcon(AppIcons.icon56MsgAdd, 'icon 56 msg add'),
|
||||||
ExampleIcon(YXIconFonts.icon56MsgFace, 'icon 56 msg face'),
|
ExampleIcon(AppIcons.icon56MsgFace, 'icon 56 msg face'),
|
||||||
ExampleIcon(YXIconFonts.icon56MsgVoice, 'icon 56 msg voice'),
|
ExampleIcon(AppIcons.icon56MsgVoice, 'icon 56 msg voice'),
|
||||||
|
|
||||||
// 箭头相关图标
|
// 箭头相关图标
|
||||||
ExampleIcon(YXIconFonts.icon32ArrowRight, 'icon 32 arrow right'),
|
ExampleIcon(AppIcons.icon32ArrowRight, 'icon 32 arrow right'),
|
||||||
ExampleIcon(YXIconFonts.icon44ArrowLeft, 'icon 44 arrow left'),
|
ExampleIcon(AppIcons.icon44ArrowLeft, 'icon 44 arrow left'),
|
||||||
ExampleIcon(YXIconFonts.icon44ArrowRight, 'icon 44 arrow right'),
|
ExampleIcon(AppIcons.icon44ArrowRight, 'icon 44 arrow right'),
|
||||||
ExampleIcon(YXIconFonts.icon44ArrowDownLine, 'icon 44 arrow down line'),
|
ExampleIcon(AppIcons.icon44ArrowDownLine, 'icon 44 arrow down line'),
|
||||||
ExampleIcon(YXIconFonts.icon24ArrowRight, 'icon 24 arrow right'),
|
ExampleIcon(AppIcons.icon24ArrowRight, 'icon 24 arrow right'),
|
||||||
ExampleIcon(YXIconFonts.icon24ArrowDown, 'icon 24 arrow down'),
|
ExampleIcon(AppIcons.icon24ArrowDown, 'icon 24 arrow down'),
|
||||||
|
|
||||||
// 团队和用户相关图标
|
// 团队和用户相关图标
|
||||||
ExampleIcon(YXIconFonts.icon36Team, 'icon 36 team'),
|
ExampleIcon(AppIcons.icon36Team, 'icon 36 team'),
|
||||||
ExampleIcon(YXIconFonts.icon32Student, 'icon 32 student'),
|
ExampleIcon(AppIcons.icon32Student, 'icon 32 student'),
|
||||||
|
|
||||||
// 功能图标
|
// 功能图标
|
||||||
ExampleIcon(YXIconFonts.icon32Filter, 'icon 32 filter'),
|
ExampleIcon(AppIcons.icon32Filter, 'icon 32 filter'),
|
||||||
ExampleIcon(YXIconFonts.icon36Question, 'icon 36 question'),
|
ExampleIcon(AppIcons.icon36Question, 'icon 36 question'),
|
||||||
ExampleIcon(YXIconFonts.icon36Hint, 'icon 36 hint'),
|
ExampleIcon(AppIcons.icon36Hint, 'icon 36 hint'),
|
||||||
ExampleIcon(YXIconFonts.icon24Switch, 'icon 24 switch'),
|
ExampleIcon(AppIcons.icon24Switch, 'icon 24 switch'),
|
||||||
|
|
||||||
// 退出相关图标
|
// 退出相关图标
|
||||||
ExampleIcon(YXIconFonts.icon44QuitLite, 'icon 44 quit lite'),
|
ExampleIcon(AppIcons.icon44QuitLite, 'icon 44 quit lite'),
|
||||||
ExampleIcon(YXIconFonts.icon32Quit, 'icon 32 quit'),
|
ExampleIcon(AppIcons.icon32Quit, 'icon 32 quit'),
|
||||||
ExampleIcon(YXIconFonts.icon44Quit, 'icon 44 quit'),
|
ExampleIcon(AppIcons.icon44Quit, 'icon 44 quit'),
|
||||||
|
|
||||||
// 更多和菜单相关图标
|
// 更多和菜单相关图标
|
||||||
ExampleIcon(YXIconFonts.icon44More2, 'icon 44 more2'),
|
ExampleIcon(AppIcons.icon44More2, 'icon 44 more2'),
|
||||||
ExampleIcon(YXIconFonts.icon44More, 'icon 44 more'),
|
ExampleIcon(AppIcons.icon44More, 'icon 44 more'),
|
||||||
|
|
||||||
// 日历相关图标
|
// 日历相关图标
|
||||||
ExampleIcon(YXIconFonts.icon44Calendar, 'icon 44 calendar'),
|
ExampleIcon(AppIcons.icon44Calendar, 'icon 44 calendar'),
|
||||||
|
|
||||||
// 键盘相关图标
|
// 键盘相关图标
|
||||||
ExampleIcon(YXIconFonts.icon44Keyboard, 'icon 44 keyboard'),
|
ExampleIcon(AppIcons.icon44Keyboard, 'icon 44 keyboard'),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
|
||||||
import 'package:yx_icon_fonts_example/icons.dart';
|
import 'package:yx_icon_fonts_example/icons.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
@ -35,12 +34,18 @@ class YXIconFontsGalleryHome extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||||
var _searchTerm = "";
|
var _searchTerm = '';
|
||||||
var _isSearching = false;
|
var _isSearching = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final filteredIcons = icons.where((icon) => _searchTerm.isEmpty || icon.title.toLowerCase().contains(_searchTerm.toLowerCase())).toList();
|
final filteredIcons = icons
|
||||||
|
.where(
|
||||||
|
(icon) =>
|
||||||
|
_searchTerm.isEmpty ||
|
||||||
|
icon.title.toLowerCase().contains(_searchTerm.toLowerCase()),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: _isSearching ? _searchBar(context) : _titleBar(),
|
appBar: _isSearching ? _searchBar(context) : _titleBar(),
|
||||||
|
|
@ -69,7 +74,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Hero(
|
child: Hero(
|
||||||
tag: icon,
|
tag: icon,
|
||||||
child: YXIcon(
|
child: Icon(
|
||||||
icon.iconData,
|
icon.iconData,
|
||||||
size: 100,
|
size: 100,
|
||||||
),
|
),
|
||||||
|
|
@ -83,7 +88,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Hero(tag: icon, child: YXIcon(icon.iconData)),
|
Hero(tag: icon, child: Icon(icon.iconData)),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(top: 16.0),
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
@ -92,7 +97,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -103,7 +108,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isSearching = !_isSearching;
|
_isSearching = !_isSearching;
|
||||||
if (!_isSearching) _searchTerm = "";
|
if (!_isSearching) _searchTerm = '';
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Icon(_isSearching ? Icons.close : Icons.search),
|
child: Icon(_isSearching ? Icons.close : Icons.search),
|
||||||
|
|
@ -133,7 +138,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isSearching = false;
|
_isSearching = false;
|
||||||
_searchTerm = "";
|
_searchTerm = '';
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,14 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.0"
|
||||||
|
logging:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -200,13 +208,21 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.0.2"
|
version: "15.0.2"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
yx_icon_fonts:
|
yx_icon_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.5"
|
version: "2.0.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.8.0-0 <4.0.0"
|
dart: ">=3.8.0-0 <4.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
flutter: ">=3.18.0-18.0.pre.54"
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,20 @@ environment:
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_lints: ^3.0.0
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
# CLI 代码生成工具
|
||||||
yx_icon_fonts:
|
yx_icon_fonts:
|
||||||
path: ../
|
path: ../
|
||||||
|
|
||||||
dev_dependencies:
|
|
||||||
flutter_test:
|
|
||||||
sdk: flutter
|
|
||||||
flutter_lints: ^3.0.0
|
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
||||||
|
# 字体配置
|
||||||
|
fonts:
|
||||||
|
- family: iconfont
|
||||||
|
fonts:
|
||||||
|
- asset: assets/fonts/iconfont.ttf
|
||||||
158
generate.sh
158
generate.sh
|
|
@ -1,158 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# YX Icon Fonts 生成脚本
|
|
||||||
# 用于生成图标数据和示例文件
|
|
||||||
|
|
||||||
set -e # 遇到错误时退出
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 打印带颜色的消息
|
|
||||||
print_info() {
|
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查 Dart 是否安装
|
|
||||||
check_dart() {
|
|
||||||
if ! command -v dart &> /dev/null; then
|
|
||||||
print_error "Dart 未安装或不在 PATH 中"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查必要文件是否存在
|
|
||||||
check_files() {
|
|
||||||
if [ ! -f "iconfont.json" ]; then
|
|
||||||
print_error "找不到 iconfont.json 文件"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "scripts/generate_icons.dart" ]; then
|
|
||||||
print_error "找不到 scripts/generate_icons.dart 文件"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "scripts/generate_example.dart" ]; then
|
|
||||||
print_error "找不到 scripts/generate_example.dart 文件"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "scripts/generate_wrapper.dart" ]; then
|
|
||||||
print_error "找不到 scripts/generate_wrapper.dart 文件"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 生成图标数据
|
|
||||||
generate_icons() {
|
|
||||||
print_info "正在生成图标数据..."
|
|
||||||
dart scripts/generate_icons.dart
|
|
||||||
print_success "图标数据生成完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 生成示例文件
|
|
||||||
generate_example() {
|
|
||||||
print_info "正在生成示例文件..."
|
|
||||||
dart scripts/generate_example.dart
|
|
||||||
print_success "示例文件生成完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 生成外部封装文件
|
|
||||||
generate_wrapper() {
|
|
||||||
print_info "正在生成外部封装文件..."
|
|
||||||
dart scripts/generate_wrapper.dart
|
|
||||||
print_success "外部封装文件生成完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 生成所有文件
|
|
||||||
generate_all() {
|
|
||||||
print_info "开始生成所有文件..."
|
|
||||||
echo
|
|
||||||
|
|
||||||
generate_icons
|
|
||||||
echo
|
|
||||||
generate_wrapper
|
|
||||||
echo
|
|
||||||
generate_example
|
|
||||||
echo
|
|
||||||
|
|
||||||
print_success "所有文件生成完成!"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 显示帮助信息
|
|
||||||
show_help() {
|
|
||||||
echo "YX Icon Fonts 生成脚本"
|
|
||||||
echo
|
|
||||||
echo "用法: $0 [选项]"
|
|
||||||
echo
|
|
||||||
echo "选项:"
|
|
||||||
echo " icons 只生成图标数据 (lib/src/yx_icon_fonts_data.dart)"
|
|
||||||
echo " wrapper 只生成外部封装文件 (generate/icons.dart)"
|
|
||||||
echo " example 只生成示例文件 (example/lib/icons.dart)"
|
|
||||||
echo " all 生成所有文件 (默认)"
|
|
||||||
echo " help 显示此帮助信息"
|
|
||||||
echo
|
|
||||||
echo "示例:"
|
|
||||||
echo " $0 # 生成所有文件"
|
|
||||||
echo " $0 icons # 只生成图标数据"
|
|
||||||
echo " $0 wrapper # 只生成外部封装文件"
|
|
||||||
echo " $0 example # 只生成示例文件"
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主函数
|
|
||||||
main() {
|
|
||||||
local action=${1:-all}
|
|
||||||
|
|
||||||
case $action in
|
|
||||||
"icons")
|
|
||||||
check_dart
|
|
||||||
check_files
|
|
||||||
generate_icons
|
|
||||||
;;
|
|
||||||
"wrapper")
|
|
||||||
check_dart
|
|
||||||
check_files
|
|
||||||
generate_wrapper
|
|
||||||
;;
|
|
||||||
"example")
|
|
||||||
check_dart
|
|
||||||
check_files
|
|
||||||
generate_example
|
|
||||||
;;
|
|
||||||
"all")
|
|
||||||
check_dart
|
|
||||||
check_files
|
|
||||||
generate_all
|
|
||||||
;;
|
|
||||||
"help"|"-h"|"--help")
|
|
||||||
show_help
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
print_error "未知选项: $action"
|
|
||||||
echo
|
|
||||||
show_help
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# 运行主函数
|
|
||||||
main "$@"
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
# 图标字体生成器配置文件模板
|
||||||
|
# 复制此文件到您的项目根目录,重命名为 icon_generator_config.yaml
|
||||||
|
# 并根据需要修改配置
|
||||||
|
|
||||||
|
# 生成器信息
|
||||||
|
generator:
|
||||||
|
# 项目名称(用于生成的代码注释)
|
||||||
|
name: "MyApp Icons"
|
||||||
|
# 版本
|
||||||
|
version: "1.0"
|
||||||
|
# 作者
|
||||||
|
author: "Your Name"
|
||||||
|
|
||||||
|
# 输入配置
|
||||||
|
input:
|
||||||
|
# 字体文件路径(相对于项目根目录)
|
||||||
|
# 这个文件从 iconfont.cn 下载
|
||||||
|
font_file: "assets/fonts/iconfont.ttf"
|
||||||
|
|
||||||
|
# JSON 配置文件路径(从 iconfont.cn 下载)
|
||||||
|
# 包含所有图标的 unicode 编码和名称
|
||||||
|
json_file: "assets/fonts/iconfont.json"
|
||||||
|
|
||||||
|
# 字体家族名称
|
||||||
|
# 需要与 pubspec.yaml 中 flutter.fonts 配置的 family 一致
|
||||||
|
# 例如:
|
||||||
|
# flutter:
|
||||||
|
# fonts:
|
||||||
|
# - family: iconfont
|
||||||
|
# fonts:
|
||||||
|
# - asset: assets/fonts/iconfont.ttf
|
||||||
|
font_family: "iconfont"
|
||||||
|
|
||||||
|
# 字体包名(可选)
|
||||||
|
# 如果字体文件位于另一个 package 中,请指定包名
|
||||||
|
# font_package: "my_icons_package"
|
||||||
|
|
||||||
|
# 输出配置
|
||||||
|
output:
|
||||||
|
# 生成的 Dart 文件路径
|
||||||
|
# 建议放在 lib/generated/ 目录下,并添加到 .gitignore
|
||||||
|
file_path: "lib/generated/icons.dart"
|
||||||
|
|
||||||
|
# 生成的类名
|
||||||
|
# 使用时: Icon(AppIcons.iconName, size: 24)
|
||||||
|
class_name: "AppIcons"
|
||||||
|
|
||||||
|
# 是否生成文档注释
|
||||||
|
# 设为 true 会为每个图标生成 Unicode 说明
|
||||||
|
generate_docs: true
|
||||||
|
|
||||||
|
# 是否使用 const 构造函数
|
||||||
|
use_const_constructor: true
|
||||||
|
|
||||||
|
# 包导入路径(可选)
|
||||||
|
# 如果需要在生成的文件中添加特定的 package 导入
|
||||||
|
# package_import: "package:my_app/common/icons.dart"
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
runApp(const MainApp());
|
|
||||||
}
|
|
||||||
|
|
||||||
class MainApp extends StatelessWidget {
|
|
||||||
const MainApp({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const MaterialApp(
|
|
||||||
home: Scaffold(
|
|
||||||
body: Center(
|
|
||||||
child: Text('Hello World!'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/commands/base_command.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/commands/generate_command.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/commands/init_command.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/string_helper.dart';
|
||||||
|
|
||||||
|
/// YX Icon Fonts CLI 应用程序
|
||||||
|
///
|
||||||
|
/// 使用命令模式架构的 CLI 工具
|
||||||
|
class IconFontsCLI {
|
||||||
|
IconFontsCLI() {
|
||||||
|
_registerCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final Logger _logger = Logger('IconFontsCLI');
|
||||||
|
final Map<String, BaseCommand> _commands = {};
|
||||||
|
|
||||||
|
/// 注册所有命令
|
||||||
|
void _registerCommands() {
|
||||||
|
_registerCommand(GenerateCommand());
|
||||||
|
_registerCommand(InitCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 注册单个命令
|
||||||
|
void _registerCommand(BaseCommand command) {
|
||||||
|
_commands[command.name] = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 运行 CLI 应用程序
|
||||||
|
Future<int> run(List<String> arguments) async {
|
||||||
|
try {
|
||||||
|
_showBanner();
|
||||||
|
|
||||||
|
if (arguments.isEmpty ||
|
||||||
|
arguments.first == 'help' ||
|
||||||
|
arguments.first == '--help') {
|
||||||
|
_showHelp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final commandName = arguments.first;
|
||||||
|
final commandArgs =
|
||||||
|
arguments.length > 1 ? arguments.sublist(1) : <String>[];
|
||||||
|
|
||||||
|
// 检查特殊命令
|
||||||
|
if (commandName == 'version' || commandName == '--version') {
|
||||||
|
_showVersion();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找并执行命令
|
||||||
|
final command = _commands[commandName];
|
||||||
|
if (command == null) {
|
||||||
|
_logger
|
||||||
|
..severe('❌ 未知命令: $commandName')
|
||||||
|
..info('');
|
||||||
|
_showAvailableCommands();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查命令帮助
|
||||||
|
if (commandArgs.contains('--help') || commandArgs.contains('-h')) {
|
||||||
|
command.showHelp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行命令
|
||||||
|
final stopwatch = Stopwatch()..start();
|
||||||
|
final exitCode = await command.execute(commandArgs);
|
||||||
|
stopwatch.stop();
|
||||||
|
|
||||||
|
// 显示执行时间
|
||||||
|
if (exitCode == 0) {
|
||||||
|
_logger
|
||||||
|
..info('')
|
||||||
|
..info(
|
||||||
|
'⏱️ 总耗时: ${StringHelper.formatDuration(stopwatch.elapsed)}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
} on Exception catch (error, stackTrace) {
|
||||||
|
_logger
|
||||||
|
..severe('❌ 应用程序错误: $error')
|
||||||
|
..severe('堆栈跟踪: $stackTrace');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示应用程序横幅
|
||||||
|
void _showBanner() {
|
||||||
|
_logger
|
||||||
|
..info('')
|
||||||
|
..info('🎨 YX Icon Fonts 代码生成器 v2.0')
|
||||||
|
..info('=====================================')
|
||||||
|
..info('从 iconfont.json 生成 Flutter IconData 常量')
|
||||||
|
..info('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示帮助信息
|
||||||
|
void _showHelp() {
|
||||||
|
_logger
|
||||||
|
..info('用法: dart run yx_icon_fonts <命令> [选项]')
|
||||||
|
..info('')
|
||||||
|
..info('支持 YAML 配置文件,可自定义输出路径和类名。')
|
||||||
|
..info('');
|
||||||
|
_showAvailableCommands();
|
||||||
|
_showGlobalOptions();
|
||||||
|
_showExamples();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示可用命令
|
||||||
|
void _showAvailableCommands() {
|
||||||
|
_logger
|
||||||
|
..info('📋 可用命令:')
|
||||||
|
..info('');
|
||||||
|
|
||||||
|
for (final command in _commands.values) {
|
||||||
|
_logger.info(' ${command.name.padRight(12)} ${command.description}');
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger
|
||||||
|
..info(' help 显示帮助信息')
|
||||||
|
..info(' version 显示版本信息')
|
||||||
|
..info('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示全局选项
|
||||||
|
void _showGlobalOptions() {
|
||||||
|
_logger
|
||||||
|
..info('🔧 全局选项:')
|
||||||
|
..info(' -h, --help 显示帮助信息')
|
||||||
|
..info(' --version 显示版本信息')
|
||||||
|
..info('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示使用示例
|
||||||
|
void _showExamples() {
|
||||||
|
_logger
|
||||||
|
..info('💡 使用示例:')
|
||||||
|
..info('')
|
||||||
|
..info(' # 初始化配置文件')
|
||||||
|
..info(' dart run yx_icon_fonts init')
|
||||||
|
..info('')
|
||||||
|
..info(' # 生成图标代码')
|
||||||
|
..info(' dart run yx_icon_fonts generate')
|
||||||
|
..info('')
|
||||||
|
..info(' # 使用指定配置文件')
|
||||||
|
..info(' dart run yx_icon_fonts generate --config my_config.yaml')
|
||||||
|
..info('')
|
||||||
|
..info(' # 查看命令帮助')
|
||||||
|
..info(' dart run yx_icon_fonts generate --help')
|
||||||
|
..info('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示版本信息
|
||||||
|
void _showVersion() {
|
||||||
|
_logger
|
||||||
|
..info('YX Icon Fonts CLI v2.0.0')
|
||||||
|
..info('构建于: ${DateTime.now().toIso8601String()}')
|
||||||
|
..info('Dart SDK: ${Platform.version}')
|
||||||
|
..info('')
|
||||||
|
..info('功能特性:')
|
||||||
|
..info('- 🎨 从 iconfont.json 生成代码')
|
||||||
|
..info('- 📝 YAML 配置文件支持')
|
||||||
|
..info('- 🏗️ 自定义类名和输出路径')
|
||||||
|
..info('- 📚 自动生成文档注释')
|
||||||
|
..info('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
/// 命令基类
|
||||||
|
///
|
||||||
|
/// 所有 CLI 命令都应继承此类
|
||||||
|
abstract class BaseCommand {
|
||||||
|
/// 命令名称
|
||||||
|
String get name;
|
||||||
|
|
||||||
|
/// 命令描述
|
||||||
|
String get description;
|
||||||
|
|
||||||
|
/// 日志器
|
||||||
|
Logger get logger => Logger(name);
|
||||||
|
|
||||||
|
/// 执行命令
|
||||||
|
///
|
||||||
|
/// 返回退出码:0 表示成功,非 0 表示失败
|
||||||
|
Future<int> execute(List<String> arguments);
|
||||||
|
|
||||||
|
/// 显示帮助信息
|
||||||
|
void showHelp() {
|
||||||
|
logger
|
||||||
|
..info('命令: $name')
|
||||||
|
..info('描述: $description')
|
||||||
|
..info('')
|
||||||
|
..info('用法: dart run yx_icon_fonts $name [选项]')
|
||||||
|
..info('')
|
||||||
|
..info('选项:');
|
||||||
|
showOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示命令选项
|
||||||
|
void showOptions() {
|
||||||
|
logger.info(' -h, --help 显示帮助信息');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 解析参数中的选项值
|
||||||
|
String? getOption(List<String> arguments, String name, {String? shortName}) {
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
final arg = arguments[i];
|
||||||
|
if (arg == '--$name' || (shortName != null && arg == '-$shortName')) {
|
||||||
|
if (i + 1 < arguments.length) {
|
||||||
|
return arguments[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arg.startsWith('--$name=')) {
|
||||||
|
return arg.substring('--$name='.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查参数中是否有指定标志
|
||||||
|
bool hasFlag(List<String> arguments, String name, {String? shortName}) {
|
||||||
|
for (final arg in arguments) {
|
||||||
|
if (arg == '--$name' || (shortName != null && arg == '-$shortName')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import 'package:yx_icon_fonts/src/commands/base_command.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/config/config_loader.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/generator/icon_generator.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/logger.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/string_helper.dart';
|
||||||
|
|
||||||
|
/// 生成命令
|
||||||
|
///
|
||||||
|
/// 从配置文件读取配置,生成图标常量代码
|
||||||
|
class GenerateCommand extends BaseCommand {
|
||||||
|
@override
|
||||||
|
String get name => 'generate';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get description => '从 iconfont.json 生成 Flutter IconData 常量';
|
||||||
|
|
||||||
|
@override
|
||||||
|
void showOptions() {
|
||||||
|
super.showOptions();
|
||||||
|
logger
|
||||||
|
..info(' -c, --config <path> 指定配置文件路径 '
|
||||||
|
'(默认: icon_generator_config.yaml)')
|
||||||
|
..info(' -v, --verbose 显示详细输出');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> execute(List<String> arguments) async {
|
||||||
|
try {
|
||||||
|
// 解析参数
|
||||||
|
final configPath = getOption(arguments, 'config', shortName: 'c');
|
||||||
|
final verbose = hasFlag(arguments, 'verbose', shortName: 'v');
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
appLogger.info('🔍 详细模式已启用');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载配置
|
||||||
|
appLogger.progress('正在加载配置...');
|
||||||
|
final config = ConfigLoader.load(configPath: configPath);
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
appLogger
|
||||||
|
..info('📋 配置信息:')
|
||||||
|
..info(' - 输入文件: ${config.input.jsonFile}')
|
||||||
|
..info(' - 字体家族: ${config.input.fontFamily}')
|
||||||
|
..info(' - 输出文件: ${config.output.filePath}')
|
||||||
|
..info(' - 类名: ${config.output.className}');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行生成
|
||||||
|
final generator = IconGenerator(config: config);
|
||||||
|
final result = await generator.generate();
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
appLogger
|
||||||
|
..success('代码生成成功!')
|
||||||
|
..info('')
|
||||||
|
..info('📁 输出文件: ${result.outputPath}')
|
||||||
|
..stats('共生成 ${result.iconCount} 个图标常量');
|
||||||
|
|
||||||
|
if (result.duration != null) {
|
||||||
|
appLogger.info(
|
||||||
|
'⏱️ 耗时: ${StringHelper.formatDuration(result.duration!)}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
appLogger.severe('❌ 生成失败: ${result.error}');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} on ConfigNotFoundException catch (e) {
|
||||||
|
appLogger
|
||||||
|
..severe('❌ ${e.message}')
|
||||||
|
..info('')
|
||||||
|
..info('💡 提示: 运行 "dart run yx_icon_fonts init" 创建配置文件');
|
||||||
|
return 1;
|
||||||
|
} on Exception catch (e) {
|
||||||
|
appLogger.severe('❌ 发生错误: $e');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:yx_icon_fonts/src/commands/base_command.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/config/config_loader.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/logger.dart';
|
||||||
|
|
||||||
|
/// 初始化命令
|
||||||
|
///
|
||||||
|
/// 在当前目录创建配置文件模板
|
||||||
|
class InitCommand extends BaseCommand {
|
||||||
|
@override
|
||||||
|
String get name => 'init';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get description => '创建配置文件模板';
|
||||||
|
|
||||||
|
@override
|
||||||
|
void showOptions() {
|
||||||
|
super.showOptions();
|
||||||
|
logger
|
||||||
|
..info(' -f, --force 强制覆盖已存在的配置文件')
|
||||||
|
..info(' -o, --output <path> 指定配置文件输出路径');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> execute(List<String> arguments) async {
|
||||||
|
try {
|
||||||
|
final force = hasFlag(arguments, 'force', shortName: 'f');
|
||||||
|
final outputPath = getOption(arguments, 'output', shortName: 'o');
|
||||||
|
|
||||||
|
final configPath = outputPath ??
|
||||||
|
path.join(
|
||||||
|
Directory.current.path,
|
||||||
|
ConfigLoader.defaultConfigFileName,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查文件是否已存在
|
||||||
|
if (File(configPath).existsSync() && !force) {
|
||||||
|
appLogger
|
||||||
|
..warning('⚠️ 配置文件已存在: $configPath')
|
||||||
|
..info('')
|
||||||
|
..info('💡 使用 --force 选项覆盖现有文件');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入配置模板
|
||||||
|
appLogger.progress('正在创建配置文件...');
|
||||||
|
File(configPath).writeAsStringSync(_configTemplate);
|
||||||
|
|
||||||
|
appLogger
|
||||||
|
..success('配置文件创建成功!')
|
||||||
|
..info('')
|
||||||
|
..info('📁 配置文件: $configPath')
|
||||||
|
..info('')
|
||||||
|
..info('📝 下一步:')
|
||||||
|
..info(' 1. 编辑配置文件,设置输入输出路径')
|
||||||
|
..info(' 2. 运行 "dart run yx_icon_fonts generate" 生成代码');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} on Exception catch (e) {
|
||||||
|
appLogger.severe('❌ 发生错误: $e');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 配置文件模板
|
||||||
|
static const String _configTemplate = '''
|
||||||
|
# 图标字体生成器配置文件
|
||||||
|
# 由 yx_icon_fonts init 命令生成
|
||||||
|
|
||||||
|
# 生成器信息
|
||||||
|
generator:
|
||||||
|
name: "MyApp Icons"
|
||||||
|
version: "1.0"
|
||||||
|
author: "Your Name"
|
||||||
|
|
||||||
|
# 输入配置
|
||||||
|
input:
|
||||||
|
# 字体文件路径(相对于项目根目录)
|
||||||
|
font_file: "assets/fonts/iconfont.ttf"
|
||||||
|
|
||||||
|
# JSON 配置文件路径(从 iconfont.cn 下载)
|
||||||
|
json_file: "assets/fonts/iconfont.json"
|
||||||
|
|
||||||
|
# 字体家族名称(与 pubspec.yaml 中配置的一致)
|
||||||
|
font_family: "iconfont"
|
||||||
|
|
||||||
|
# 字体包名(可选)
|
||||||
|
# 如果字体文件位于另一个 package 中,请指定包名
|
||||||
|
# font_package: "my_icons_package"
|
||||||
|
|
||||||
|
# 输出配置
|
||||||
|
output:
|
||||||
|
# 生成的 Dart 文件路径
|
||||||
|
file_path: "lib/generated/icons.dart"
|
||||||
|
|
||||||
|
# 生成的类名
|
||||||
|
class_name: "AppIcons"
|
||||||
|
|
||||||
|
# 是否生成文档注释
|
||||||
|
generate_docs: true
|
||||||
|
|
||||||
|
# 是否使用 const 构造函数
|
||||||
|
use_const_constructor: true
|
||||||
|
''';
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:yaml/yaml.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/config/generator_config.dart';
|
||||||
|
|
||||||
|
/// 配置加载器
|
||||||
|
///
|
||||||
|
/// 负责从 YAML 文件加载配置
|
||||||
|
class ConfigLoader {
|
||||||
|
/// 默认配置文件名
|
||||||
|
static const String defaultConfigFileName = 'icon_generator_config.yaml';
|
||||||
|
|
||||||
|
/// 加载配置文件
|
||||||
|
///
|
||||||
|
/// [configPath] 配置文件路径,如果为 null 则使用默认路径
|
||||||
|
/// [workingDir] 工作目录,默认为当前目录
|
||||||
|
static GeneratorConfig load({
|
||||||
|
String? configPath,
|
||||||
|
String? workingDir,
|
||||||
|
}) {
|
||||||
|
final directory = workingDir ?? Directory.current.path;
|
||||||
|
final filePath = configPath ?? path.join(directory, defaultConfigFileName);
|
||||||
|
final file = File(filePath);
|
||||||
|
|
||||||
|
if (!file.existsSync()) {
|
||||||
|
throw ConfigNotFoundException(
|
||||||
|
'配置文件不存在: $filePath\n'
|
||||||
|
'请运行 "dart run yx_icon_fonts init" 创建配置文件',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final content = file.readAsStringSync();
|
||||||
|
final yamlMap = loadYaml(content) as YamlMap?;
|
||||||
|
|
||||||
|
if (yamlMap == null) {
|
||||||
|
throw ConfigParseException('配置文件为空或格式错误');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 YamlMap 转换为 Map<String, dynamic>
|
||||||
|
final map = _convertYamlMap(yamlMap);
|
||||||
|
return GeneratorConfig.fromMap(map);
|
||||||
|
} on YamlException catch (e) {
|
||||||
|
throw ConfigParseException('YAML 解析错误: ${e.message}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查配置文件是否存在
|
||||||
|
static bool exists({String? configPath, String? workingDir}) {
|
||||||
|
final directory = workingDir ?? Directory.current.path;
|
||||||
|
final filePath = configPath ?? path.join(directory, defaultConfigFileName);
|
||||||
|
return File(filePath).existsSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 将 YamlMap 递归转换为 Map<String, dynamic>
|
||||||
|
static Map<String, dynamic> _convertYamlMap(YamlMap yamlMap) {
|
||||||
|
final result = <String, dynamic>{};
|
||||||
|
for (final key in yamlMap.keys) {
|
||||||
|
final value = yamlMap[key];
|
||||||
|
if (value is YamlMap) {
|
||||||
|
result[key.toString()] = _convertYamlMap(value);
|
||||||
|
} else if (value is YamlList) {
|
||||||
|
result[key.toString()] = _convertYamlList(value);
|
||||||
|
} else {
|
||||||
|
result[key.toString()] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 将 YamlList 递归转换为 List<dynamic>
|
||||||
|
static List<dynamic> _convertYamlList(YamlList yamlList) {
|
||||||
|
return yamlList.map((item) {
|
||||||
|
if (item is YamlMap) {
|
||||||
|
return _convertYamlMap(item);
|
||||||
|
} else if (item is YamlList) {
|
||||||
|
return _convertYamlList(item);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 配置文件未找到异常
|
||||||
|
class ConfigNotFoundException implements Exception {
|
||||||
|
ConfigNotFoundException(this.message);
|
||||||
|
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'ConfigNotFoundException: $message';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 配置解析异常
|
||||||
|
class ConfigParseException implements Exception {
|
||||||
|
ConfigParseException(this.message);
|
||||||
|
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'ConfigParseException: $message';
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
// 配置模型类
|
||||||
|
//
|
||||||
|
// 定义图标生成器的配置结构
|
||||||
|
|
||||||
|
/// 总配置类
|
||||||
|
class GeneratorConfig {
|
||||||
|
const GeneratorConfig({
|
||||||
|
required this.generator,
|
||||||
|
required this.input,
|
||||||
|
required this.output,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 从 Map 创建配置
|
||||||
|
factory GeneratorConfig.fromMap(Map<String, dynamic> map) {
|
||||||
|
return GeneratorConfig(
|
||||||
|
generator: GeneratorInfo.fromMap(
|
||||||
|
map['generator'] as Map<String, dynamic>? ?? {},
|
||||||
|
),
|
||||||
|
input: InputConfig.fromMap(
|
||||||
|
map['input'] as Map<String, dynamic>? ?? {},
|
||||||
|
),
|
||||||
|
output: OutputConfig.fromMap(
|
||||||
|
map['output'] as Map<String, dynamic>? ?? {},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建默认配置
|
||||||
|
factory GeneratorConfig.defaults() {
|
||||||
|
return GeneratorConfig(
|
||||||
|
generator: GeneratorInfo.defaults(),
|
||||||
|
input: InputConfig.defaults(),
|
||||||
|
output: OutputConfig.defaults(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 生成器信息
|
||||||
|
final GeneratorInfo generator;
|
||||||
|
|
||||||
|
/// 输入配置
|
||||||
|
final InputConfig input;
|
||||||
|
|
||||||
|
/// 输出配置
|
||||||
|
final OutputConfig output;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'GeneratorConfig(generator: $generator, input: $input, '
|
||||||
|
'output: $output)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 生成器信息
|
||||||
|
class GeneratorInfo {
|
||||||
|
const GeneratorInfo({
|
||||||
|
required this.name,
|
||||||
|
this.version = '1.0',
|
||||||
|
this.author = '',
|
||||||
|
});
|
||||||
|
|
||||||
|
factory GeneratorInfo.fromMap(Map<String, dynamic> map) {
|
||||||
|
return GeneratorInfo(
|
||||||
|
name: map['name'] as String? ?? 'Icon Generator',
|
||||||
|
version: map['version'] as String? ?? '1.0',
|
||||||
|
author: map['author'] as String? ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory GeneratorInfo.defaults() {
|
||||||
|
return const GeneratorInfo(name: 'Icon Generator');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 生成器名称
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
/// 版本
|
||||||
|
final String version;
|
||||||
|
|
||||||
|
/// 作者
|
||||||
|
final String author;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GeneratorInfo(name: $name, version: $version)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 输入配置
|
||||||
|
class InputConfig {
|
||||||
|
const InputConfig({
|
||||||
|
required this.fontFile,
|
||||||
|
required this.jsonFile,
|
||||||
|
required this.fontFamily,
|
||||||
|
this.fontPackage,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory InputConfig.fromMap(Map<String, dynamic> map) {
|
||||||
|
return InputConfig(
|
||||||
|
fontFile: map['font_file'] as String? ?? 'assets/fonts/iconfont.ttf',
|
||||||
|
jsonFile: map['json_file'] as String? ?? 'assets/fonts/iconfont.json',
|
||||||
|
fontFamily: map['font_family'] as String? ?? 'iconfont',
|
||||||
|
fontPackage: map['font_package'] as String?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory InputConfig.defaults() {
|
||||||
|
return const InputConfig(
|
||||||
|
fontFile: 'assets/fonts/iconfont.ttf',
|
||||||
|
jsonFile: 'assets/fonts/iconfont.json',
|
||||||
|
fontFamily: 'iconfont',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 字体文件路径(相对于项目根目录)
|
||||||
|
final String fontFile;
|
||||||
|
|
||||||
|
/// JSON 配置文件路径
|
||||||
|
final String jsonFile;
|
||||||
|
|
||||||
|
/// 字体家族名称
|
||||||
|
final String fontFamily;
|
||||||
|
|
||||||
|
/// 字体包名
|
||||||
|
final String? fontPackage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'InputConfig(fontFile: $fontFile, jsonFile: $jsonFile, '
|
||||||
|
'fontFamily: $fontFamily, fontPackage: $fontPackage)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 输出配置
|
||||||
|
class OutputConfig {
|
||||||
|
const OutputConfig({
|
||||||
|
required this.filePath,
|
||||||
|
required this.className,
|
||||||
|
this.generateDocs = true,
|
||||||
|
this.useConstConstructor = true,
|
||||||
|
this.packageImport,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory OutputConfig.fromMap(Map<String, dynamic> map) {
|
||||||
|
return OutputConfig(
|
||||||
|
filePath: map['file_path'] as String? ?? 'lib/generated/icons.dart',
|
||||||
|
className: map['class_name'] as String? ?? 'AppIcons',
|
||||||
|
generateDocs: map['generate_docs'] as bool? ?? true,
|
||||||
|
useConstConstructor: map['use_const_constructor'] as bool? ?? true,
|
||||||
|
packageImport: map['package_import'] as String?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory OutputConfig.defaults() {
|
||||||
|
return const OutputConfig(
|
||||||
|
filePath: 'lib/generated/icons.dart',
|
||||||
|
className: 'AppIcons',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 生成的 Dart 文件路径
|
||||||
|
final String filePath;
|
||||||
|
|
||||||
|
/// 生成的类名
|
||||||
|
final String className;
|
||||||
|
|
||||||
|
/// 是否生成文档注释
|
||||||
|
final bool generateDocs;
|
||||||
|
|
||||||
|
/// 是否使用 const 构造函数
|
||||||
|
final bool useConstConstructor;
|
||||||
|
|
||||||
|
/// 包导入路径(可选,用于生成 part of 指令)
|
||||||
|
final String? packageImport;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'OutputConfig(filePath: $filePath, className: $className, '
|
||||||
|
'generateDocs: $generateDocs)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
import 'package:yx_icon_fonts/src/config/generator_config.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/generator/icon_parser.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/string_helper.dart';
|
||||||
|
|
||||||
|
/// Dart 代码构建器
|
||||||
|
///
|
||||||
|
/// 负责生成 Flutter IconData 常量代码
|
||||||
|
class DartCodeBuilder {
|
||||||
|
const DartCodeBuilder({
|
||||||
|
required this.config,
|
||||||
|
required this.meta,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 配置
|
||||||
|
final GeneratorConfig config;
|
||||||
|
|
||||||
|
/// 图标元数据
|
||||||
|
final IconFontMeta meta;
|
||||||
|
|
||||||
|
/// 构建完整的 Dart 文件内容
|
||||||
|
String build() {
|
||||||
|
final buffer = StringBuffer()
|
||||||
|
// 文件头注释
|
||||||
|
.._writeHeader(meta)
|
||||||
|
// 导入语句
|
||||||
|
.._writeImports()
|
||||||
|
// 类定义
|
||||||
|
.._writeClass(config, meta);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension _StringBufferExt on StringBuffer {
|
||||||
|
/// 写入文件头注释
|
||||||
|
void _writeHeader(IconFontMeta meta) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final timestamp = '${now.year}-${_pad(now.month)}-${_pad(now.day)} '
|
||||||
|
'${_pad(now.hour)}:${_pad(now.minute)}';
|
||||||
|
|
||||||
|
this
|
||||||
|
..writeln('// ignore_for_file: constant_identifier_names')
|
||||||
|
..writeln()
|
||||||
|
..writeln('// ============================================')
|
||||||
|
..writeln('// 此文件由 yx_icon_fonts 自动生成,请勿手动修改')
|
||||||
|
..writeln('// 生成时间: $timestamp')
|
||||||
|
..writeln('// 图标数量: ${meta.icons.length}')
|
||||||
|
..writeln('// ============================================')
|
||||||
|
..writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _pad(int n) => n.toString().padLeft(2, '0');
|
||||||
|
|
||||||
|
/// 写入导入语句
|
||||||
|
void _writeImports() {
|
||||||
|
this
|
||||||
|
..writeln("import 'package:flutter/widgets.dart';")
|
||||||
|
..writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入类定义
|
||||||
|
void _writeClass(GeneratorConfig config, IconFontMeta meta) {
|
||||||
|
final className = config.output.className;
|
||||||
|
final fontFamily = config.input.fontFamily;
|
||||||
|
final fontPackage = config.input.fontPackage;
|
||||||
|
final generateDocs = config.output.generateDocs;
|
||||||
|
|
||||||
|
if (generateDocs) {
|
||||||
|
this
|
||||||
|
..writeln('/// ${config.generator.name} 图标常量')
|
||||||
|
..writeln('///')
|
||||||
|
..writeln(
|
||||||
|
'/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用',
|
||||||
|
)
|
||||||
|
..writeln('///')
|
||||||
|
..writeln('/// 示例:')
|
||||||
|
..writeln('/// ```dart')
|
||||||
|
..writeln('/// Icon($className.iconName, size: 24)')
|
||||||
|
..writeln('/// ```');
|
||||||
|
}
|
||||||
|
|
||||||
|
this
|
||||||
|
..writeln('class $className {')
|
||||||
|
..writeln(' $className._();')
|
||||||
|
..writeln();
|
||||||
|
|
||||||
|
if (!config.output.useConstConstructor) {
|
||||||
|
// 添加私有 _icon 工厂方法
|
||||||
|
this
|
||||||
|
..writeln(' // 统一的 IconData 构造方法')
|
||||||
|
..writeln(' static const _icon = _IconDataFactory._();')
|
||||||
|
..writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成图标常量
|
||||||
|
for (final icon in meta.icons) {
|
||||||
|
_writeIconConstant(
|
||||||
|
icon,
|
||||||
|
generateDocs: generateDocs,
|
||||||
|
useConst: config.output.useConstConstructor,
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontPackage: fontPackage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this
|
||||||
|
..writeln('}')
|
||||||
|
..writeln();
|
||||||
|
|
||||||
|
if (!config.output.useConstConstructor) {
|
||||||
|
final hasPackage = fontPackage != null;
|
||||||
|
// 添加私有 IconData 工厂类
|
||||||
|
this
|
||||||
|
..writeln('/// 内部 IconData 工厂类')
|
||||||
|
..writeln('class _IconDataFactory {')
|
||||||
|
..writeln(' const _IconDataFactory._();')
|
||||||
|
..writeln()
|
||||||
|
..writeln(" static const String _fontFamily = '$fontFamily';")
|
||||||
|
..writeln(
|
||||||
|
hasPackage
|
||||||
|
? " static const String _fontPackage = '$fontPackage';"
|
||||||
|
: '',
|
||||||
|
)
|
||||||
|
..writeln()
|
||||||
|
..writeln(
|
||||||
|
' IconData call(int codePoint) => '
|
||||||
|
"IconData(codePoint, fontFamily: _fontFamily${hasPackage ? ', fontPackage: _fontPackage' : ''});",
|
||||||
|
)
|
||||||
|
..writeln('}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入单个图标常量
|
||||||
|
void _writeIconConstant(
|
||||||
|
IconInfo icon, {
|
||||||
|
required bool generateDocs,
|
||||||
|
required bool useConst,
|
||||||
|
required String fontFamily,
|
||||||
|
String? fontPackage,
|
||||||
|
}) {
|
||||||
|
final constantName = StringHelper.toLegalDartName(icon.fontClass);
|
||||||
|
|
||||||
|
if (generateDocs) {
|
||||||
|
writeln(' /// ${icon.name} (U+${icon.unicode.toUpperCase()})');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useConst) {
|
||||||
|
final packageParam =
|
||||||
|
fontPackage != null ? ", fontPackage: '$fontPackage'" : '';
|
||||||
|
writeln(
|
||||||
|
" static const IconData $constantName = IconData(0x${icon.unicode}, fontFamily: '$fontFamily'$packageParam);",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
writeln(
|
||||||
|
' static final IconData $constantName = _icon(0x${icon.unicode});',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
import 'package:yx_icon_fonts/src/config/generator_config.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/generator/dart_code_builder.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/generator/icon_parser.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/file_helper.dart';
|
||||||
|
import 'package:yx_icon_fonts/src/utils/logger.dart';
|
||||||
|
|
||||||
|
/// 图标生成器
|
||||||
|
///
|
||||||
|
/// 协调整个代码生成流程
|
||||||
|
class IconGenerator {
|
||||||
|
IconGenerator({
|
||||||
|
required this.config,
|
||||||
|
this.workingDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 配置
|
||||||
|
final GeneratorConfig config;
|
||||||
|
|
||||||
|
/// 工作目录
|
||||||
|
final String? workingDir;
|
||||||
|
|
||||||
|
/// 生成的图标元数据
|
||||||
|
IconFontMeta? _meta;
|
||||||
|
|
||||||
|
/// 获取图标元数据
|
||||||
|
IconFontMeta? get meta => _meta;
|
||||||
|
|
||||||
|
/// 执行生成
|
||||||
|
Future<GenerationResult> generate() async {
|
||||||
|
final stopwatch = Stopwatch()..start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 解析 JSON 文件
|
||||||
|
appLogger.progress('正在解析图标配置文件...');
|
||||||
|
final jsonPath = FileHelper.resolvePropertyPath(
|
||||||
|
config.input.jsonFile,
|
||||||
|
workingDir: workingDir,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!FileHelper.fileExists(jsonPath)) {
|
||||||
|
return GenerationResult(
|
||||||
|
success: false,
|
||||||
|
error: '图标配置文件不存在: $jsonPath',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_meta = IconParser.parseFile(jsonPath);
|
||||||
|
appLogger
|
||||||
|
..stats('解析完成: 找到 ${_meta!.icons.length} 个图标')
|
||||||
|
// 2. 生成代码
|
||||||
|
..progress('正在生成 Dart 代码...');
|
||||||
|
final builder = DartCodeBuilder(
|
||||||
|
config: config,
|
||||||
|
meta: _meta!,
|
||||||
|
);
|
||||||
|
final code = builder.build();
|
||||||
|
|
||||||
|
// 3. 写入文件
|
||||||
|
final outputPath = FileHelper.resolvePropertyPath(
|
||||||
|
config.output.filePath,
|
||||||
|
workingDir: workingDir,
|
||||||
|
);
|
||||||
|
|
||||||
|
appLogger.progress('正在写入文件: $outputPath');
|
||||||
|
FileHelper.writeFile(outputPath, code);
|
||||||
|
|
||||||
|
stopwatch.stop();
|
||||||
|
|
||||||
|
return GenerationResult(
|
||||||
|
success: true,
|
||||||
|
outputPath: outputPath,
|
||||||
|
iconCount: _meta!.icons.length,
|
||||||
|
duration: stopwatch.elapsed,
|
||||||
|
);
|
||||||
|
} on Exception catch (e) {
|
||||||
|
stopwatch.stop();
|
||||||
|
return GenerationResult(
|
||||||
|
success: false,
|
||||||
|
error: e.toString(),
|
||||||
|
duration: stopwatch.elapsed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 生成结果
|
||||||
|
class GenerationResult {
|
||||||
|
const GenerationResult({
|
||||||
|
required this.success,
|
||||||
|
this.outputPath,
|
||||||
|
this.iconCount = 0,
|
||||||
|
this.error,
|
||||||
|
this.duration,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 是否成功
|
||||||
|
final bool success;
|
||||||
|
|
||||||
|
/// 输出文件路径
|
||||||
|
final String? outputPath;
|
||||||
|
|
||||||
|
/// 生成的图标数量
|
||||||
|
final int iconCount;
|
||||||
|
|
||||||
|
/// 错误信息
|
||||||
|
final String? error;
|
||||||
|
|
||||||
|
/// 执行时间
|
||||||
|
final Duration? duration;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
if (success) {
|
||||||
|
return 'GenerationResult(success: true, icons: $iconCount, '
|
||||||
|
'path: $outputPath)';
|
||||||
|
}
|
||||||
|
return 'GenerationResult(success: false, error: $error)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
import 'package:yx_icon_fonts/src/utils/file_helper.dart';
|
||||||
|
|
||||||
|
/// 图标数据模型
|
||||||
|
class IconInfo {
|
||||||
|
const IconInfo({
|
||||||
|
required this.iconId,
|
||||||
|
required this.name,
|
||||||
|
required this.fontClass,
|
||||||
|
required this.unicode,
|
||||||
|
required this.unicodeDecimal,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 从 JSON Map 创建
|
||||||
|
factory IconInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
return IconInfo(
|
||||||
|
iconId: json['icon_id']?.toString() ?? '',
|
||||||
|
name: json['name'] as String? ?? '',
|
||||||
|
fontClass: json['font_class'] as String? ?? '',
|
||||||
|
unicode: json['unicode'] as String? ?? '',
|
||||||
|
unicodeDecimal: json['unicode_decimal'] as int? ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 图标 ID
|
||||||
|
final String iconId;
|
||||||
|
|
||||||
|
/// 图标名称
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
/// CSS 类名
|
||||||
|
final String fontClass;
|
||||||
|
|
||||||
|
/// Unicode 值(十六进制字符串)
|
||||||
|
final String unicode;
|
||||||
|
|
||||||
|
/// Unicode 值(十进制)
|
||||||
|
final int unicodeDecimal;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'IconInfo(name: $name, unicode: $unicode)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 图标字体元数据
|
||||||
|
class IconFontMeta {
|
||||||
|
const IconFontMeta({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.fontFamily,
|
||||||
|
required this.cssPrefix,
|
||||||
|
required this.description,
|
||||||
|
required this.icons,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 从 JSON Map 创建
|
||||||
|
factory IconFontMeta.fromJson(Map<String, dynamic> json) {
|
||||||
|
final glyphs = json['glyphs'] as List<dynamic>? ?? [];
|
||||||
|
return IconFontMeta(
|
||||||
|
id: json['id']?.toString() ?? '',
|
||||||
|
name: json['name'] as String? ?? '',
|
||||||
|
fontFamily: json['font_family'] as String? ?? 'iconfont',
|
||||||
|
cssPrefix: json['css_prefix_text'] as String? ?? '',
|
||||||
|
description: json['description'] as String? ?? '',
|
||||||
|
icons: glyphs
|
||||||
|
.map((g) => IconInfo.fromJson(g as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 字体 ID
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
/// 字体名称
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
/// 字体家族
|
||||||
|
final String fontFamily;
|
||||||
|
|
||||||
|
/// CSS 前缀
|
||||||
|
final String cssPrefix;
|
||||||
|
|
||||||
|
/// 描述
|
||||||
|
final String description;
|
||||||
|
|
||||||
|
/// 图标列表
|
||||||
|
final List<IconInfo> icons;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'IconFontMeta(name: $name, fontFamily: $fontFamily, '
|
||||||
|
'icons: ${icons.length})';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 图标解析器
|
||||||
|
///
|
||||||
|
/// 负责解析 iconfont.json 文件
|
||||||
|
class IconParser {
|
||||||
|
/// 私有构造函数
|
||||||
|
IconParser._();
|
||||||
|
|
||||||
|
/// 从文件解析
|
||||||
|
static IconFontMeta parseFile(String jsonFilePath) {
|
||||||
|
final jsonData = FileHelper.readJsonFile(jsonFilePath);
|
||||||
|
return IconFontMeta.fromJson(jsonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 从 Map 解析
|
||||||
|
static IconFontMeta parseMap(Map<String, dynamic> jsonData) {
|
||||||
|
return IconFontMeta.fromJson(jsonData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
|
/// 文件操作工具类
|
||||||
|
class FileHelper {
|
||||||
|
/// 私有构造函数,防止实例化
|
||||||
|
FileHelper._();
|
||||||
|
|
||||||
|
/// 读取 JSON 文件并解析
|
||||||
|
static Map<String, dynamic> readJsonFile(String filePath) {
|
||||||
|
final file = File(filePath);
|
||||||
|
|
||||||
|
if (!file.existsSync()) {
|
||||||
|
throw FileNotFoundException('文件不存在: $filePath');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final content = file.readAsStringSync();
|
||||||
|
return json.decode(content) as Map<String, dynamic>;
|
||||||
|
} on FormatException catch (e) {
|
||||||
|
throw FileParseException('JSON 解析错误: ${e.message}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入文件内容
|
||||||
|
///
|
||||||
|
/// 如果目录不存在,会自动创建
|
||||||
|
static void writeFile(String filePath, String content) {
|
||||||
|
final file = File(filePath);
|
||||||
|
final directory = file.parent;
|
||||||
|
|
||||||
|
// 确保目录存在
|
||||||
|
if (!directory.existsSync()) {
|
||||||
|
directory.createSync(recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.writeAsStringSync(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查文件是否存在
|
||||||
|
static bool fileExists(String filePath) {
|
||||||
|
return File(filePath).existsSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取相对于工作目录的绝对路径
|
||||||
|
static String resolvePropertyPath(String relativePath, {String? workingDir}) {
|
||||||
|
final directory = workingDir ?? Directory.current.path;
|
||||||
|
if (path.isAbsolute(relativePath)) {
|
||||||
|
return relativePath;
|
||||||
|
}
|
||||||
|
return path.join(directory, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取文件的目录路径
|
||||||
|
static String getDirectoryPath(String filePath) {
|
||||||
|
return path.dirname(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取文件名(不含扩展名)
|
||||||
|
static String getFileNameWithoutExtension(String filePath) {
|
||||||
|
return path.basenameWithoutExtension(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取文件名(含扩展名)
|
||||||
|
static String getFileName(String filePath) {
|
||||||
|
return path.basename(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 文件未找到异常
|
||||||
|
class FileNotFoundException implements Exception {
|
||||||
|
FileNotFoundException(this.message);
|
||||||
|
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'FileNotFoundException: $message';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 文件解析异常
|
||||||
|
class FileParseException implements Exception {
|
||||||
|
FileParseException(this.message);
|
||||||
|
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'FileParseException: $message';
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
/// 应用程序日志器
|
||||||
|
final Logger appLogger = Logger('YXIconFonts');
|
||||||
|
|
||||||
|
/// 设置日志
|
||||||
|
void setupLogging({Level level = Level.INFO}) {
|
||||||
|
Logger.root.level = level;
|
||||||
|
Logger.root.onRecord.listen((record) {
|
||||||
|
if (record.level >= Level.SEVERE) {
|
||||||
|
stderr.writeln(record.message);
|
||||||
|
} else {
|
||||||
|
stdout.writeln(record.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 日志工具扩展
|
||||||
|
extension LoggerExtension on Logger {
|
||||||
|
/// 成功消息(绿色)
|
||||||
|
void success(String message) {
|
||||||
|
info('✅ $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 进度消息
|
||||||
|
void progress(String message) {
|
||||||
|
info('⏳ $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 完成消息
|
||||||
|
void done(String message) {
|
||||||
|
info('✨ $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 统计消息
|
||||||
|
void stats(String message) {
|
||||||
|
info('📊 $message');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/// 字符串工具类
|
||||||
|
///
|
||||||
|
/// 提供字符串转换和格式化功能
|
||||||
|
class StringHelper {
|
||||||
|
/// 私有构造函数,防止实例化
|
||||||
|
StringHelper._();
|
||||||
|
|
||||||
|
/// 下划线转驼峰命名
|
||||||
|
///
|
||||||
|
/// 例如:icon_32_clean -> icon32Clean
|
||||||
|
static String toCamelCase(String input) {
|
||||||
|
// 预处理:将常见特殊字符转换
|
||||||
|
final processedInput = input
|
||||||
|
.replaceAll('-', '_')
|
||||||
|
.replaceAll('+', 'plus')
|
||||||
|
.replaceAll('(', '')
|
||||||
|
.replaceAll(')', '')
|
||||||
|
.replaceAll(' ', '');
|
||||||
|
|
||||||
|
final parts = processedInput.split('_');
|
||||||
|
if (parts.isEmpty) return input;
|
||||||
|
|
||||||
|
final firstPart = parts[0];
|
||||||
|
final remainingParts = parts.skip(1).map((part) {
|
||||||
|
if (part.isEmpty) return '';
|
||||||
|
return part[0].toUpperCase() + part.substring(1);
|
||||||
|
}).join();
|
||||||
|
|
||||||
|
return firstPart + remainingParts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 转换为合法的 Dart 标识符
|
||||||
|
///
|
||||||
|
/// 确保首字符不是数字,只包含字母、数字和下划线
|
||||||
|
static String toLegalDartName(String input) {
|
||||||
|
var name = toCamelCase(input);
|
||||||
|
|
||||||
|
// 首字符为数字,前面加下划线
|
||||||
|
if (name.isNotEmpty && RegExp('^[0-9]').hasMatch(name[0])) {
|
||||||
|
name = '_$name';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只保留字母、数字和下划线
|
||||||
|
return name.replaceAll(RegExp('[^a-zA-Z0-9_]'), '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 转换为 PascalCase(首字母大写的驼峰命名)
|
||||||
|
///
|
||||||
|
/// 例如:icon_class -> IconClass
|
||||||
|
static String toPascalCase(String input) {
|
||||||
|
final camelCase = toCamelCase(input);
|
||||||
|
if (camelCase.isEmpty) return camelCase;
|
||||||
|
return camelCase[0].toUpperCase() + camelCase.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 格式化时间长度
|
||||||
|
static String formatDuration(Duration duration) {
|
||||||
|
if (duration.inMinutes > 0) {
|
||||||
|
return '${duration.inMinutes}m ${duration.inSeconds % 60}s';
|
||||||
|
} else if (duration.inSeconds > 0) {
|
||||||
|
return '${duration.inSeconds}.${(duration.inMilliseconds % 1000) ~/ 100}s';
|
||||||
|
} else {
|
||||||
|
return '${duration.inMilliseconds}ms';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
|
|
||||||
/// 学习官OA系统图标组件
|
|
||||||
///
|
|
||||||
/// 专门为学习官OA系统图标设计的组件,处理图标渲染和布局
|
|
||||||
/// 可以直接使用 Flutter 的 Icon 组件,也可以使用此专门的 YXIcon 组件
|
|
||||||
class YXIcon extends StatelessWidget {
|
|
||||||
/// 创建图标组件
|
|
||||||
///
|
|
||||||
/// [icon] 图标数据,可以是 YXIconData 或任何 IconData
|
|
||||||
/// [size] 图标大小
|
|
||||||
/// [color] 图标颜色
|
|
||||||
/// [semanticLabel] 语义标签
|
|
||||||
/// [textDirection] 文本方向
|
|
||||||
/// [shadows] 阴影效果
|
|
||||||
const YXIcon(
|
|
||||||
this.icon, {
|
|
||||||
super.key,
|
|
||||||
this.size,
|
|
||||||
this.color,
|
|
||||||
this.semanticLabel,
|
|
||||||
this.textDirection,
|
|
||||||
this.shadows,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// 图标数据
|
|
||||||
///
|
|
||||||
/// 支持 YXIconData 和任何 IconData 类型
|
|
||||||
final IconData? icon;
|
|
||||||
|
|
||||||
/// 图标大小
|
|
||||||
final double? size;
|
|
||||||
|
|
||||||
/// 图标颜色
|
|
||||||
final Color? color;
|
|
||||||
|
|
||||||
/// 图标语义标签
|
|
||||||
final String? semanticLabel;
|
|
||||||
|
|
||||||
/// 文本方向
|
|
||||||
final TextDirection? textDirection;
|
|
||||||
|
|
||||||
/// 阴影效果
|
|
||||||
final List<Shadow>? shadows;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
assert(this.textDirection != null || debugCheckHasDirectionality(context));
|
|
||||||
final TextDirection textDirection = this.textDirection ?? Directionality.of(context);
|
|
||||||
|
|
||||||
final IconThemeData iconTheme = IconTheme.of(context);
|
|
||||||
|
|
||||||
final double? iconSize = size ?? iconTheme.size;
|
|
||||||
final List<Shadow>? iconShadows = shadows ?? iconTheme.shadows;
|
|
||||||
|
|
||||||
if (icon == null) {
|
|
||||||
return Semantics(
|
|
||||||
label: semanticLabel,
|
|
||||||
child: SizedBox(width: iconSize, height: iconSize),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final double iconOpacity = iconTheme.opacity ?? 1.0;
|
|
||||||
Color iconColor = color ?? iconTheme.color!;
|
|
||||||
if (iconOpacity != 1.0) {
|
|
||||||
iconColor = iconColor.withValues(alpha: iconColor.a * iconOpacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget iconWidget = RichText(
|
|
||||||
overflow: TextOverflow.visible,
|
|
||||||
textDirection: textDirection,
|
|
||||||
text: TextSpan(
|
|
||||||
text: String.fromCharCode(icon!.codePoint),
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: false,
|
|
||||||
color: iconColor,
|
|
||||||
fontSize: iconSize,
|
|
||||||
fontFamily: icon!.fontFamily,
|
|
||||||
package: icon!.fontPackage,
|
|
||||||
shadows: iconShadows,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (icon!.matchTextDirection) {
|
|
||||||
switch (textDirection) {
|
|
||||||
case TextDirection.rtl:
|
|
||||||
iconWidget = Transform(
|
|
||||||
transform: Matrix4.identity()..scale(-1.0, 1.0, 1.0),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
transformHitTests: false,
|
|
||||||
child: iconWidget,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case TextDirection.ltr:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Semantics(
|
|
||||||
label: semanticLabel,
|
|
||||||
child: ExcludeSemantics(
|
|
||||||
child: iconWidget,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
|
||||||
super.debugFillProperties(properties);
|
|
||||||
properties.add(IconDataProperty('icon', icon, ifNull: '<empty>', showName: false));
|
|
||||||
properties.add(DoubleProperty('size', size, defaultValue: null));
|
|
||||||
properties.add(ColorProperty('color', color, defaultValue: null));
|
|
||||||
properties.add(IterableProperty<Shadow>('shadows', shadows, defaultValue: null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
|
|
||||||
/// 学习官OA系统图标数据类
|
|
||||||
///
|
|
||||||
/// 继承自 IconData,提供统一的图标数据接口
|
|
||||||
class YXIconData extends IconData {
|
|
||||||
/// 创建图标数据实例
|
|
||||||
///
|
|
||||||
/// [codePoint] Unicode码点
|
|
||||||
const YXIconData(super.codePoint)
|
|
||||||
: super(
|
|
||||||
fontFamily: 'iconfont',
|
|
||||||
fontPackage: 'yx_icon_fonts',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,392 +0,0 @@
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'yx_icon_data.dart';
|
|
||||||
|
|
||||||
/// 学习官OA系统图标字体数据
|
|
||||||
///
|
|
||||||
/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用
|
|
||||||
/// 也可以使用专门的 YXIcon 组件
|
|
||||||
class YXIconFonts {
|
|
||||||
// 私有构造函数,防止实例化
|
|
||||||
YXIconFonts._();
|
|
||||||
|
|
||||||
/// icon_32_clean 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e660
|
|
||||||
static const IconData icon32Clean = YXIconData(0xe660);
|
|
||||||
|
|
||||||
/// icon_36_viewhistory 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e65f
|
|
||||||
static const IconData icon36Viewhistory = YXIconData(0xe65f);
|
|
||||||
|
|
||||||
/// icon_36_revoke 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e65e
|
|
||||||
static const IconData icon36Revoke = YXIconData(0xe65e);
|
|
||||||
|
|
||||||
/// icon_30_edit 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e65b
|
|
||||||
static const IconData icon30Edit = YXIconData(0xe65b);
|
|
||||||
|
|
||||||
/// icon_24_copy2 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e65c
|
|
||||||
static const IconData icon24Copy2 = YXIconData(0xe65c);
|
|
||||||
|
|
||||||
/// icon_30_delete 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e65d
|
|
||||||
static const IconData icon30Delete = YXIconData(0xe65d);
|
|
||||||
|
|
||||||
/// icon_36_add 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e65a
|
|
||||||
static const IconData icon36Add = YXIconData(0xe65a);
|
|
||||||
|
|
||||||
/// icon_32_location 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e659
|
|
||||||
static const IconData icon32Location = YXIconData(0xe659);
|
|
||||||
|
|
||||||
/// icon_24_mypoints 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e657
|
|
||||||
static const IconData icon24Mypoints = YXIconData(0xe657);
|
|
||||||
|
|
||||||
/// icon_44_me_about 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e656
|
|
||||||
static const IconData icon44MeAbout = YXIconData(0xe656);
|
|
||||||
|
|
||||||
/// icon_44_me_pointsmall 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e658
|
|
||||||
static const IconData icon44MePointsmall = YXIconData(0xe658);
|
|
||||||
|
|
||||||
/// icon_44_search 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e655
|
|
||||||
static const IconData icon44Search = YXIconData(0xe655);
|
|
||||||
|
|
||||||
/// icon_36_clear_people 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e654
|
|
||||||
static const IconData icon36ClearPeople = YXIconData(0xe654);
|
|
||||||
|
|
||||||
/// icon_44_me_log_out 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e652
|
|
||||||
static const IconData icon44MeLogOut = YXIconData(0xe652);
|
|
||||||
|
|
||||||
/// icon_44_me_switch 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e653
|
|
||||||
static const IconData icon44MeSwitch = YXIconData(0xe653);
|
|
||||||
|
|
||||||
/// icon_44_wechat_share_white 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e651
|
|
||||||
static const IconData icon44WechatShareWhite = YXIconData(0xe651);
|
|
||||||
|
|
||||||
/// icon_32_publish 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e64e
|
|
||||||
static const IconData icon32Publish = YXIconData(0xe64e);
|
|
||||||
|
|
||||||
/// icon_32_close 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e64f
|
|
||||||
static const IconData icon32Close = YXIconData(0xe64f);
|
|
||||||
|
|
||||||
/// icon_32_output 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e650
|
|
||||||
static const IconData icon32Output = YXIconData(0xe650);
|
|
||||||
|
|
||||||
/// icon_24_download 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e64d
|
|
||||||
static const IconData icon24Download = YXIconData(0xe64d);
|
|
||||||
|
|
||||||
/// icon_voice_pause 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e64b
|
|
||||||
static const IconData iconVoicePause = YXIconData(0xe64b);
|
|
||||||
|
|
||||||
/// icon_voice 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e64c
|
|
||||||
static const IconData iconVoice = YXIconData(0xe64c);
|
|
||||||
|
|
||||||
/// icon_subtract 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e64a
|
|
||||||
static const IconData iconSubtract = YXIconData(0xe64a);
|
|
||||||
|
|
||||||
/// icon_44_edit 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e648
|
|
||||||
static const IconData icon44Edit = YXIconData(0xe648);
|
|
||||||
|
|
||||||
/// icon_44_delete 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e649
|
|
||||||
static const IconData icon44Delete = YXIconData(0xe649);
|
|
||||||
|
|
||||||
/// icon_44_cancel_account 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e647
|
|
||||||
static const IconData icon44CancelAccount = YXIconData(0xe647);
|
|
||||||
|
|
||||||
/// icon_24_search 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e646
|
|
||||||
static const IconData icon24Search = YXIconData(0xe646);
|
|
||||||
|
|
||||||
/// icon_24_up 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e645
|
|
||||||
static const IconData icon24Up = YXIconData(0xe645);
|
|
||||||
|
|
||||||
/// icon_msg_contacts 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e644
|
|
||||||
static const IconData iconMsgContacts = YXIconData(0xe644);
|
|
||||||
|
|
||||||
/// icon_msg_video 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e63e
|
|
||||||
static const IconData iconMsgVideo = YXIconData(0xe63e);
|
|
||||||
|
|
||||||
/// icon_msg_search 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e63f
|
|
||||||
static const IconData iconMsgSearch = YXIconData(0xe63f);
|
|
||||||
|
|
||||||
/// icon_msg_call 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e640
|
|
||||||
static const IconData iconMsgCall = YXIconData(0xe640);
|
|
||||||
|
|
||||||
/// icon_msg_photo 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e641
|
|
||||||
static const IconData iconMsgPhoto = YXIconData(0xe641);
|
|
||||||
|
|
||||||
/// icon_msg_img 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e642
|
|
||||||
static const IconData iconMsgImg = YXIconData(0xe642);
|
|
||||||
|
|
||||||
/// icon_msg_file 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e643
|
|
||||||
static const IconData iconMsgFile = YXIconData(0xe643);
|
|
||||||
|
|
||||||
/// icon_32_arrow_right 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e61d
|
|
||||||
static const IconData icon32ArrowRight = YXIconData(0xe61d);
|
|
||||||
|
|
||||||
/// icon_44_me_password 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e639
|
|
||||||
static const IconData icon44MePassword = YXIconData(0xe639);
|
|
||||||
|
|
||||||
/// icon_44_me_help 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e63a
|
|
||||||
static const IconData icon44MeHelp = YXIconData(0xe63a);
|
|
||||||
|
|
||||||
/// icon_24_minus 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e63b
|
|
||||||
static const IconData icon24Minus = YXIconData(0xe63b);
|
|
||||||
|
|
||||||
/// icon_36_team 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e63c
|
|
||||||
static const IconData icon36Team = YXIconData(0xe63c);
|
|
||||||
|
|
||||||
/// icon_32_filter 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e63d
|
|
||||||
static const IconData icon32Filter = YXIconData(0xe63d);
|
|
||||||
|
|
||||||
/// icon_44_quit_lite 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e631
|
|
||||||
static const IconData icon44QuitLite = YXIconData(0xe631);
|
|
||||||
|
|
||||||
/// icon_44_me_version 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e632
|
|
||||||
static const IconData icon44MeVersion = YXIconData(0xe632);
|
|
||||||
|
|
||||||
/// icon_36_question 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e633
|
|
||||||
static const IconData icon36Question = YXIconData(0xe633);
|
|
||||||
|
|
||||||
/// icon_44_me_privacy 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e634
|
|
||||||
static const IconData icon44MePrivacy = YXIconData(0xe634);
|
|
||||||
|
|
||||||
/// icon_44_more2 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e635
|
|
||||||
static const IconData icon44More2 = YXIconData(0xe635);
|
|
||||||
|
|
||||||
/// icon_36_only_see 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e636
|
|
||||||
static const IconData icon36OnlySee = YXIconData(0xe636);
|
|
||||||
|
|
||||||
/// icon_44_me_user 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e637
|
|
||||||
static const IconData icon44MeUser = YXIconData(0xe637);
|
|
||||||
|
|
||||||
/// icon_44_me_safe 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e62c
|
|
||||||
static const IconData icon44MeSafe = YXIconData(0xe62c);
|
|
||||||
|
|
||||||
/// icon_44_me_phone 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e62d
|
|
||||||
static const IconData icon44MePhone = YXIconData(0xe62d);
|
|
||||||
|
|
||||||
/// icon_24_copy 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e62e
|
|
||||||
static const IconData icon24Copy = YXIconData(0xe62e);
|
|
||||||
|
|
||||||
/// icon_32_quit 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e630
|
|
||||||
static const IconData icon32Quit = YXIconData(0xe630);
|
|
||||||
|
|
||||||
/// icon_44_calendar 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e626
|
|
||||||
static const IconData icon44Calendar = YXIconData(0xe626);
|
|
||||||
|
|
||||||
/// icon_32_student 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e627
|
|
||||||
static const IconData icon32Student = YXIconData(0xe627);
|
|
||||||
|
|
||||||
/// icon_36_delete 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e628
|
|
||||||
static const IconData icon36Delete = YXIconData(0xe628);
|
|
||||||
|
|
||||||
/// icon_44_more 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e629
|
|
||||||
static const IconData icon44More = YXIconData(0xe629);
|
|
||||||
|
|
||||||
/// icon_44_arrow_left 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e62a
|
|
||||||
static const IconData icon44ArrowLeft = YXIconData(0xe62a);
|
|
||||||
|
|
||||||
/// icon_36_edit_line 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e62b
|
|
||||||
static const IconData icon36EditLine = YXIconData(0xe62b);
|
|
||||||
|
|
||||||
/// icon_44_arrow_right 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e622
|
|
||||||
static const IconData icon44ArrowRight = YXIconData(0xe622);
|
|
||||||
|
|
||||||
/// icon_24_delete 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e623
|
|
||||||
static const IconData icon24Delete = YXIconData(0xe623);
|
|
||||||
|
|
||||||
/// icon_56_msg_add 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e624
|
|
||||||
static const IconData icon56MsgAdd = YXIconData(0xe624);
|
|
||||||
|
|
||||||
/// icon_56_msg_face 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e625
|
|
||||||
static const IconData icon56MsgFace = YXIconData(0xe625);
|
|
||||||
|
|
||||||
/// icon_56_msg_voice 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e616
|
|
||||||
static const IconData icon56MsgVoice = YXIconData(0xe616);
|
|
||||||
|
|
||||||
/// icon_44_share 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e615
|
|
||||||
static const IconData icon44Share = YXIconData(0xe615);
|
|
||||||
|
|
||||||
/// icon_36_hint 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e613
|
|
||||||
static const IconData icon36Hint = YXIconData(0xe613);
|
|
||||||
|
|
||||||
/// icon_24_add 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e617
|
|
||||||
static const IconData icon24Add = YXIconData(0xe617);
|
|
||||||
|
|
||||||
/// icon_24_plus 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e618
|
|
||||||
static const IconData icon24Plus = YXIconData(0xe618);
|
|
||||||
|
|
||||||
/// icon_44_keyboard 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e614
|
|
||||||
static const IconData icon44Keyboard = YXIconData(0xe614);
|
|
||||||
|
|
||||||
/// icon_44_quit 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e619
|
|
||||||
static const IconData icon44Quit = YXIconData(0xe619);
|
|
||||||
|
|
||||||
/// icon_44_add 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e61a
|
|
||||||
static const IconData icon44Add = YXIconData(0xe61a);
|
|
||||||
|
|
||||||
/// icon_24_switch 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e61b
|
|
||||||
static const IconData icon24Switch = YXIconData(0xe61b);
|
|
||||||
|
|
||||||
/// icon_44_arrow_down_line 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e61c
|
|
||||||
static const IconData icon44ArrowDownLine = YXIconData(0xe61c);
|
|
||||||
|
|
||||||
/// icon_24_arrow_right 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e61e
|
|
||||||
static const IconData icon24ArrowRight = YXIconData(0xe61e);
|
|
||||||
|
|
||||||
/// icon_32_add 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e61f
|
|
||||||
static const IconData icon32Add = YXIconData(0xe61f);
|
|
||||||
|
|
||||||
/// icon_24_edit 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e620
|
|
||||||
static const IconData icon24Edit = YXIconData(0xe620);
|
|
||||||
|
|
||||||
/// icon_24_arrow_down 图标
|
|
||||||
///
|
|
||||||
/// Unicode: e621
|
|
||||||
static const IconData icon24ArrowDown = YXIconData(0xe621);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +1,48 @@
|
||||||
|
/// YX Icon Fonts - 图标字体代码生成器
|
||||||
|
///
|
||||||
|
/// 从 iconfont.json 生成 Flutter IconData 常量
|
||||||
|
///
|
||||||
|
/// ## 使用方法
|
||||||
|
///
|
||||||
|
/// 1. 添加到 dev_dependencies:
|
||||||
|
/// ```yaml
|
||||||
|
/// dev_dependencies:
|
||||||
|
/// yx_icon_fonts:
|
||||||
|
/// git:
|
||||||
|
/// url: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 2. 初始化配置文件:
|
||||||
|
/// ```bash
|
||||||
|
/// dart run yx_icon_fonts init
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 3. 编辑配置文件 `icon_generator_config.yaml`
|
||||||
|
///
|
||||||
|
/// 4. 生成代码:
|
||||||
|
/// ```bash
|
||||||
|
/// dart run yx_icon_fonts generate
|
||||||
|
/// ```
|
||||||
library yx_icon_fonts;
|
library yx_icon_fonts;
|
||||||
|
|
||||||
// 导出所有公共组件和类
|
// CLI
|
||||||
export 'src/yx_icon.dart';
|
export 'src/cli/icon_fonts_cli.dart';
|
||||||
export 'src/yx_icon_data.dart';
|
|
||||||
export 'src/yx_icon_fonts_data.dart';
|
|
||||||
|
|
||||||
/// 学习官OA系统图标字体库
|
// 命令
|
||||||
///
|
export 'src/commands/base_command.dart';
|
||||||
/// 提供学习官OA系统的图标字体支持,包含所有图标常量和组件
|
export 'src/commands/generate_command.dart';
|
||||||
///
|
export 'src/commands/init_command.dart';
|
||||||
/// ## 使用方法
|
|
||||||
///
|
// 配置
|
||||||
/// ```dart
|
export 'src/config/config_loader.dart';
|
||||||
/// // 使用 YXIcon 组件
|
export 'src/config/generator_config.dart';
|
||||||
/// YXIcon(YXIconFonts.iconMsgContacts, size: 24, color: Colors.blue)
|
|
||||||
///
|
// 生成器
|
||||||
/// // 使用 Flutter 原生 Icon 组件
|
export 'src/generator/dart_code_builder.dart';
|
||||||
/// Icon(YXIconFonts.iconMsgContacts, size: 24, color: Colors.blue)
|
export 'src/generator/icon_generator.dart';
|
||||||
///
|
export 'src/generator/icon_parser.dart';
|
||||||
/// // 在 IconButton 中使用
|
|
||||||
/// IconButton(
|
// 工具
|
||||||
/// icon: YXIcon(YXIconFonts.iconMsgContacts),
|
export 'src/utils/file_helper.dart';
|
||||||
/// onPressed: () {},
|
export 'src/utils/logger.dart';
|
||||||
/// )
|
export 'src/utils/string_helper.dart';
|
||||||
/// ```
|
|
||||||
|
|
|
||||||
350
pubspec.lock
350
pubspec.lock
|
|
@ -1,6 +1,30 @@
|
||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
_fe_analyzer_shared:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _fe_analyzer_shared
|
||||||
|
sha256: "5b7468c326d2f8a4f630056404ca0d291ade42918f4a3c6233618e724f39da8e"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "92.0.0"
|
||||||
|
analyzer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer
|
||||||
|
sha256: "70e4b1ef8003c64793a9e268a551a82869a8a96f39deb73dea28084b0e8bf75e"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "9.0.0"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -17,22 +41,14 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
characters:
|
cli_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: cli_config
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "0.2.0"
|
||||||
clock:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: clock
|
|
||||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.2"
|
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -41,64 +57,86 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.19.1"
|
version: "1.19.1"
|
||||||
fake_async:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: convert
|
||||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.3"
|
version: "3.1.2"
|
||||||
flutter:
|
coverage:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: coverage
|
||||||
|
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.15.0"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.7"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
|
frontend_server_client:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: frontend_server_client
|
||||||
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0"
|
||||||
|
glob:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: glob
|
||||||
|
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.3"
|
||||||
|
http_multi_server:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_multi_server
|
||||||
|
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.2"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.2"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.5"
|
||||||
|
logging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_lints:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: logging
|
||||||
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
|
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "1.3.0"
|
||||||
flutter_test:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
leak_tracker:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker
|
|
||||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "11.0.2"
|
|
||||||
leak_tracker_flutter_testing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker_flutter_testing
|
|
||||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.10"
|
|
||||||
leak_tracker_testing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker_testing
|
|
||||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
lints:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: lints
|
|
||||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.0"
|
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -107,14 +145,6 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.17"
|
||||||
material_color_utilities:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: material_color_utilities
|
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "0.11.1"
|
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -123,19 +153,102 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.16.0"
|
||||||
path:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
node_preamble:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_preamble
|
||||||
|
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
package_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_config
|
||||||
|
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
|
path:
|
||||||
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.9.1"
|
||||||
sky_engine:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description:
|
||||||
source: sdk
|
name: pool
|
||||||
version: "0.0.0"
|
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.2"
|
||||||
|
pub_semver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pub_semver
|
||||||
|
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
|
shelf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf
|
||||||
|
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.2"
|
||||||
|
shelf_packages_handler:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_packages_handler
|
||||||
|
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
shelf_static:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_static
|
||||||
|
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.3"
|
||||||
|
shelf_web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_web_socket
|
||||||
|
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
|
source_map_stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_map_stack_trace
|
||||||
|
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
source_maps:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_maps
|
||||||
|
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.13"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -176,22 +289,46 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.2"
|
version: "1.2.2"
|
||||||
|
test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: test
|
||||||
|
sha256: "77cc98ea27006c84e71a7356cf3daf9ddbde2d91d84f77dbfe64cf0e4d9611ae"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.28.0"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.6"
|
version: "0.7.8"
|
||||||
vector_math:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: test_core
|
||||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
sha256: f1072617a6657e5fc09662e721307f7fb009b4ed89b19f47175d11d5254a62d4
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "0.6.14"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
|
very_good_analysis:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: very_good_analysis
|
||||||
|
sha256: "1fb637c0022034b1f19ea2acb42a3603cbd8314a470646a59a2fb01f5f3a8629"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -200,6 +337,53 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.0.2"
|
version: "15.0.2"
|
||||||
|
watcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: watcher
|
||||||
|
sha256: f52385d4f73589977c80797e60fe51014f7f2b957b5e9a62c3f6ada439889249
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket
|
||||||
|
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
web_socket_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket_channel
|
||||||
|
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.3"
|
||||||
|
webkit_inspection_protocol:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webkit_inspection_protocol
|
||||||
|
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
yaml:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.8.0-0 <4.0.0"
|
dart: ">=3.9.0 <4.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
|
||||||
|
|
|
||||||
30
pubspec.yaml
30
pubspec.yaml
|
|
@ -1,23 +1,25 @@
|
||||||
name: yx_icon_fonts
|
name: yx_icon_fonts
|
||||||
description: 学习官OA系统图标字体库,基于iconfont.ttf和iconfont.json生成
|
description: 图标字体代码生成器 - 从 iconfont.json 生成 Flutter IconData 常量
|
||||||
version: 1.0.7
|
version: 2.1.0
|
||||||
homepage: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
homepage: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
flutter: ">=3.0.0"
|
|
||||||
|
# 可执行命令配置
|
||||||
|
# 使用方式:dart run yx_icon_fonts generate
|
||||||
|
# 或者使用别名:dart run yx_icon_fonts:yx_icon_fonts
|
||||||
|
executables:
|
||||||
|
yx_icon_fonts: main
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
# 日志
|
||||||
sdk: flutter
|
logging: ^1.3.0
|
||||||
|
# 路径处理
|
||||||
|
path: ^1.9.1
|
||||||
|
# YAML 解析
|
||||||
|
yaml: ^3.1.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
test: ^1.24.0
|
||||||
sdk: flutter
|
very_good_analysis: ^6.0.0
|
||||||
flutter_lints: ^3.0.0
|
|
||||||
|
|
||||||
flutter:
|
|
||||||
fonts:
|
|
||||||
- family: iconfont
|
|
||||||
fonts:
|
|
||||||
- asset: fonts/iconfont.ttf
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'utils.dart';
|
|
||||||
|
|
||||||
/// 自动生成示例内容的脚本
|
|
||||||
///
|
|
||||||
/// 使用方法:
|
|
||||||
/// dart scripts/generate_example.dart
|
|
||||||
void main() {
|
|
||||||
final iconData = readIconFontJson();
|
|
||||||
final glyphs = getGlyphs(iconData);
|
|
||||||
// 读取已定义的 YXIconFonts 静态常量
|
|
||||||
final definedIcons = getDefinedIconNames();
|
|
||||||
|
|
||||||
// 生成 icons.dart
|
|
||||||
_generateIconsFile(glyphs, definedIcons);
|
|
||||||
|
|
||||||
print('✅ 成功生成示例应用文件');
|
|
||||||
print('📁 生成的文件:');
|
|
||||||
print(' - example/lib/icons.dart');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 生成 icons.dart 文件
|
|
||||||
void _generateIconsFile(List<dynamic> glyphs, Set<String> definedIcons) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
buffer.writeln("import 'package:yx_icon_fonts/yx_icon_fonts.dart';");
|
|
||||||
buffer.writeln("import 'package:yx_icon_fonts_example/example_icon.dart';");
|
|
||||||
buffer.writeln();
|
|
||||||
buffer.writeln("// 此文件由脚本自动生成!");
|
|
||||||
buffer.writeln();
|
|
||||||
buffer.writeln("final icons = <ExampleIcon>[");
|
|
||||||
|
|
||||||
// 按类别分组图标
|
|
||||||
final categories = <String, List<Map<String, dynamic>>>{};
|
|
||||||
for (final glyph in glyphs) {
|
|
||||||
final name = glyph['font_class'] as String;
|
|
||||||
final unicodeDecimal = glyph['unicode_decimal'] as int;
|
|
||||||
String category = '其他图标';
|
|
||||||
if (name.contains('msg')) {
|
|
||||||
category = '消息相关图标';
|
|
||||||
} else if (name.contains('arrow')) {
|
|
||||||
category = '箭头相关图标';
|
|
||||||
} else if (name.contains('edit')) {
|
|
||||||
category = '编辑相关图标';
|
|
||||||
} else if (name.contains('me_')) {
|
|
||||||
category = '个人中心相关图标';
|
|
||||||
} else if (name.contains('team') || name.contains('student')) {
|
|
||||||
category = '团队和用户相关图标';
|
|
||||||
} else if (name.contains('filter') || name.contains('question') || name.contains('onlysee') || name.contains('hint') || name.contains('switch')) {
|
|
||||||
category = '功能图标';
|
|
||||||
} else if (name.contains('delete')) {
|
|
||||||
category = '删除相关图标';
|
|
||||||
} else if (name.contains('more')) {
|
|
||||||
category = '更多和菜单相关图标';
|
|
||||||
} else if (name.contains('quit')) {
|
|
||||||
category = '退出相关图标';
|
|
||||||
} else if (name.contains('copy')) {
|
|
||||||
category = '复制相关图标';
|
|
||||||
} else if (name.contains('calendar')) {
|
|
||||||
category = '日历相关图标';
|
|
||||||
} else if (name.contains('share')) {
|
|
||||||
category = '分享相关图标';
|
|
||||||
} else if (name.contains('add') || name.contains('+')) {
|
|
||||||
category = '添加相关图标';
|
|
||||||
} else if (name.contains('keyboard')) {
|
|
||||||
category = '键盘相关图标';
|
|
||||||
} else if (name.contains('-')) {
|
|
||||||
category = '特殊字符图标';
|
|
||||||
}
|
|
||||||
categories.putIfAbsent(category, () => []);
|
|
||||||
categories[category]!.add({
|
|
||||||
'name': name,
|
|
||||||
'unicodeDecimal': unicodeDecimal,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成图标列表
|
|
||||||
for (final category in categories.keys) {
|
|
||||||
buffer.writeln(" // $category");
|
|
||||||
for (final icon in categories[category]!) {
|
|
||||||
final name = icon['name'] as String;
|
|
||||||
final camelCaseName = toLegalDartName(name);
|
|
||||||
if (!definedIcons.contains(camelCaseName)) continue; // 跳过未定义的
|
|
||||||
final displayName = _getDisplayName(name);
|
|
||||||
buffer.writeln(" ExampleIcon(YXIconFonts.$camelCaseName, '$displayName'),");
|
|
||||||
}
|
|
||||||
buffer.writeln();
|
|
||||||
}
|
|
||||||
buffer.writeln("];");
|
|
||||||
final file = File('example/lib/icons.dart');
|
|
||||||
file.writeAsStringSync(buffer.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取展示用名称
|
|
||||||
String _getDisplayName(String name) {
|
|
||||||
return name.replaceAll('_', ' ');
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'utils.dart';
|
|
||||||
|
|
||||||
/// 自动生成图标数据文件
|
|
||||||
///
|
|
||||||
/// 从 iconfont.json 文件读取图标信息,生成 Dart 代码
|
|
||||||
void main() {
|
|
||||||
final iconData = readIconFontJson();
|
|
||||||
final icons = getGlyphs(iconData);
|
|
||||||
|
|
||||||
final StringBuffer buffer = StringBuffer();
|
|
||||||
|
|
||||||
// 添加文件头部
|
|
||||||
buffer.writeln("import 'package:flutter/widgets.dart';");
|
|
||||||
buffer.writeln("import 'yx_icon_data.dart';");
|
|
||||||
buffer.writeln();
|
|
||||||
buffer.writeln("/// 学习官OA系统图标字体数据");
|
|
||||||
buffer.writeln("/// ");
|
|
||||||
buffer.writeln("/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用");
|
|
||||||
buffer.writeln("/// 也可以使用专门的 YXIcon 组件");
|
|
||||||
buffer.writeln("class YXIconFonts {");
|
|
||||||
buffer.writeln(" // 私有构造函数,防止实例化");
|
|
||||||
buffer.writeln(" YXIconFonts._();");
|
|
||||||
buffer.writeln();
|
|
||||||
|
|
||||||
// 生成图标常量
|
|
||||||
for (final Map<String, dynamic> icon in icons) {
|
|
||||||
final String name = icon['name'] as String;
|
|
||||||
final String unicode = icon['unicode'] as String;
|
|
||||||
// 转换为驼峰命名并处理特殊字符
|
|
||||||
final String camelCaseName = toCamelCase(name);
|
|
||||||
// 添加注释
|
|
||||||
buffer.writeln(" /// $name 图标");
|
|
||||||
buffer.writeln(" /// ");
|
|
||||||
buffer.writeln(" /// Unicode: $unicode");
|
|
||||||
buffer.writeln(" static const IconData $camelCaseName = YXIconData(0x$unicode);");
|
|
||||||
buffer.writeln();
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.writeln("}");
|
|
||||||
|
|
||||||
// 写入文件
|
|
||||||
final File outputFile = File('lib/src/yx_icon_fonts_data.dart');
|
|
||||||
outputFile.writeAsStringSync(buffer.toString());
|
|
||||||
|
|
||||||
print('✅ 图标数据文件生成成功: [32m${outputFile.path} [0m');
|
|
||||||
print('📊 共生成 ${icons.length} 个图标常量');
|
|
||||||
}
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'utils.dart';
|
|
||||||
|
|
||||||
/// 自动生成外部使用的图标封装文件
|
|
||||||
///
|
|
||||||
/// 从 iconfont.json 文件读取图标信息,生成 FontIcons 封装类
|
|
||||||
/// 生成位置:项目根目录的 icons.dart
|
|
||||||
void main() {
|
|
||||||
final iconData = readIconFontJson();
|
|
||||||
final glyphs = getGlyphs(iconData);
|
|
||||||
final definedIcons = getDefinedIconNames();
|
|
||||||
|
|
||||||
_generateWrapperFile(glyphs, definedIcons);
|
|
||||||
|
|
||||||
print('✅ 外部图标封装文件生成成功: \x1B[32mgenerate/icons.dart\x1B[0m');
|
|
||||||
print('📊 共生成 ${definedIcons.length} 个图标常量');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 生成 icons.dart 文件
|
|
||||||
void _generateWrapperFile(List<dynamic> glyphs, Set<String> definedIcons) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
|
|
||||||
// 文件头部
|
|
||||||
buffer.writeln("// ignore_for_file: constant_identifier_names");
|
|
||||||
buffer.writeln();
|
|
||||||
buffer.writeln("import 'package:flutter/material.dart';");
|
|
||||||
buffer.writeln("import 'package:yx_icon_fonts/yx_icon_fonts.dart';");
|
|
||||||
buffer.writeln();
|
|
||||||
buffer.writeln("class FontIcons {");
|
|
||||||
buffer.writeln(" // 私有构造函数,防止实例化");
|
|
||||||
buffer.writeln(" FontIcons._();");
|
|
||||||
buffer.writeln();
|
|
||||||
|
|
||||||
// 按类别分组图标
|
|
||||||
final categories = _categorizeIcons(glyphs, definedIcons);
|
|
||||||
|
|
||||||
// 定义类别显示顺序
|
|
||||||
final categoryOrder = [
|
|
||||||
'其他图标',
|
|
||||||
'编辑相关图标',
|
|
||||||
'删除相关图标',
|
|
||||||
'个人中心相关图标',
|
|
||||||
'消息相关图标',
|
|
||||||
'箭头相关图标',
|
|
||||||
'特殊字符图标',
|
|
||||||
'团队和用户相关图标',
|
|
||||||
'功能图标',
|
|
||||||
'退出相关图标',
|
|
||||||
'更多和菜单相关图标',
|
|
||||||
'复制相关图标',
|
|
||||||
'日历相关图标',
|
|
||||||
'分享相关图标',
|
|
||||||
'添加相关图标',
|
|
||||||
'键盘相关图标',
|
|
||||||
];
|
|
||||||
|
|
||||||
// 按顺序生成图标
|
|
||||||
for (final category in categoryOrder) {
|
|
||||||
if (categories.containsKey(category) && categories[category]!.isNotEmpty) {
|
|
||||||
buffer.writeln(" // $category");
|
|
||||||
for (final iconName in categories[category]!) {
|
|
||||||
buffer.writeln(" static const IconData $iconName = YXIconFonts.$iconName;");
|
|
||||||
}
|
|
||||||
buffer.writeln();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.writeln("}");
|
|
||||||
|
|
||||||
// 确保 generate 目录存在
|
|
||||||
final dir = Directory('generate');
|
|
||||||
if (!dir.existsSync()) {
|
|
||||||
dir.createSync(recursive: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入文件
|
|
||||||
final file = File('generate/icons.dart');
|
|
||||||
file.writeAsStringSync(buffer.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 将图标按类别分组
|
|
||||||
Map<String, List<String>> _categorizeIcons(List<dynamic> glyphs, Set<String> definedIcons) {
|
|
||||||
final categories = <String, List<String>>{};
|
|
||||||
|
|
||||||
for (final glyph in glyphs) {
|
|
||||||
final name = glyph['font_class'] as String;
|
|
||||||
final camelCaseName = toLegalDartName(name);
|
|
||||||
|
|
||||||
// 跳过未定义的图标
|
|
||||||
if (!definedIcons.contains(camelCaseName)) continue;
|
|
||||||
|
|
||||||
// 确定类别
|
|
||||||
String category = _getCategory(name);
|
|
||||||
|
|
||||||
categories.putIfAbsent(category, () => []);
|
|
||||||
categories[category]!.add(camelCaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 根据图标名称确定类别
|
|
||||||
String _getCategory(String name) {
|
|
||||||
final lowerName = name.toLowerCase();
|
|
||||||
|
|
||||||
if (lowerName.contains('edit')) {
|
|
||||||
return '编辑相关图标';
|
|
||||||
} else if (lowerName.contains('delete')) {
|
|
||||||
return '删除相关图标';
|
|
||||||
} else if (lowerName.contains('me_')) {
|
|
||||||
return '个人中心相关图标';
|
|
||||||
} else if (lowerName.contains('msg')) {
|
|
||||||
return '消息相关图标';
|
|
||||||
} else if (lowerName.contains('arrow')) {
|
|
||||||
return '箭头相关图标';
|
|
||||||
} else if (lowerName == '24_-' || lowerName.contains('subtract')) {
|
|
||||||
return '特殊字符图标';
|
|
||||||
} else if (lowerName.contains('team') || lowerName.contains('student')) {
|
|
||||||
return '团队和用户相关图标';
|
|
||||||
} else if (lowerName.contains('filter') ||
|
|
||||||
lowerName.contains('question') ||
|
|
||||||
lowerName.contains('onlysee') ||
|
|
||||||
lowerName.contains('hint') ||
|
|
||||||
lowerName.contains('switch')) {
|
|
||||||
return '功能图标';
|
|
||||||
} else if (lowerName.contains('quit')) {
|
|
||||||
return '退出相关图标';
|
|
||||||
} else if (lowerName.contains('more')) {
|
|
||||||
return '更多和菜单相关图标';
|
|
||||||
} else if (lowerName.contains('copy')) {
|
|
||||||
return '复制相关图标';
|
|
||||||
} else if (lowerName.contains('calendar')) {
|
|
||||||
return '日历相关图标';
|
|
||||||
} else if (lowerName.contains('share')) {
|
|
||||||
return '分享相关图标';
|
|
||||||
} else if (lowerName.contains('add') || lowerName.contains('+') || lowerName.contains('plus')) {
|
|
||||||
return '添加相关图标';
|
|
||||||
} else if (lowerName.contains('keyboard')) {
|
|
||||||
return '键盘相关图标';
|
|
||||||
} else {
|
|
||||||
return '其他图标';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
/// 读取 iconfont.json 文件,返回解析后的 Map
|
|
||||||
Map<String, dynamic> readIconFontJson([String path = 'iconfont.json']) {
|
|
||||||
final file = File(path);
|
|
||||||
if (!file.existsSync()) {
|
|
||||||
throw Exception('未找到 $path 文件');
|
|
||||||
}
|
|
||||||
final content = file.readAsStringSync();
|
|
||||||
return json.decode(content) as Map<String, dynamic>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取 glyphs 列表
|
|
||||||
List<dynamic> getGlyphs(Map<String, dynamic> iconData) {
|
|
||||||
return iconData['glyphs'] as List<dynamic>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 下划线转驼峰命名,并处理常见特殊字符,保证 Dart 标识符合法
|
|
||||||
String toCamelCase(String input) {
|
|
||||||
String processedInput = input.replaceAll('-', '_').replaceAll('+', 'plus').replaceAll('(', '').replaceAll(')', '').replaceAll(' ', '');
|
|
||||||
final List<String> parts = processedInput.split('_');
|
|
||||||
if (parts.isEmpty) return input;
|
|
||||||
final String firstPart = parts[0];
|
|
||||||
final String remainingParts = parts.skip(1).map((part) => part.isNotEmpty ? part[0].toUpperCase() + part.substring(1) : '').join();
|
|
||||||
return firstPart + remainingParts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dart 标识符合法化(首字符不能为数字,不能有特殊符号)
|
|
||||||
String toLegalDartName(String input) {
|
|
||||||
String name = toCamelCase(input);
|
|
||||||
// 首字符为数字,前面加下划线
|
|
||||||
if (name.isNotEmpty && RegExp(r'^[0-9]').hasMatch(name[0])) {
|
|
||||||
name = '_$name';
|
|
||||||
}
|
|
||||||
// 只保留字母、数字和下划线
|
|
||||||
name = name.replaceAll(RegExp(r'[^a-zA-Z0-9_]'), '');
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 读取 Dart 文件中已定义的静态常量名(如 static const IconData xxx = ...)
|
|
||||||
Set<String> getDefinedIconNames([String path = 'lib/src/yx_icon_fonts_data.dart']) {
|
|
||||||
final file = File(path);
|
|
||||||
if (!file.existsSync()) return {};
|
|
||||||
final content = file.readAsStringSync();
|
|
||||||
final reg = RegExp(r'static const IconData (\w+) =');
|
|
||||||
return reg.allMatches(content).map((m) => m.group(1)!).toSet();
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +1,82 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('YXIconFonts', () {
|
group('StringHelper', () {
|
||||||
test('should have valid icon data', () {
|
test('toCamelCase converts underscore to camelCase', () {
|
||||||
// 测试图标常量是否存在且有效
|
expect(StringHelper.toCamelCase('icon_32_clean'), equals('icon32Clean'));
|
||||||
expect(YXIconFonts.iconMsgContacts, isNotNull);
|
expect(
|
||||||
expect(YXIconFonts.iconMsgContacts.codePoint, isA<int>());
|
StringHelper.toCamelCase('icon_msg_contacts'),
|
||||||
expect(YXIconFonts.iconMsgContacts.fontFamily, equals('iconfont'));
|
equals('iconMsgContacts'),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create YXIcon widget', () {
|
test('toLegalDartName handles numeric prefix', () {
|
||||||
// 测试 YXIcon 组件创建
|
expect(StringHelper.toLegalDartName('32_icon'), equals('_32Icon'));
|
||||||
final icon = YXIcon(YXIconFonts.iconMsgContacts);
|
|
||||||
expect(icon, isNotNull);
|
|
||||||
expect(icon.icon, equals(YXIconFonts.iconMsgContacts));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should have multiple icons defined', () {
|
test('toPascalCase converts to PascalCase', () {
|
||||||
// 测试多个图标常量
|
expect(StringHelper.toPascalCase('icon_class'), equals('IconClass'));
|
||||||
expect(YXIconFonts.iconMsgContacts, isNotNull);
|
});
|
||||||
expect(YXIconFonts.iconMsgSearch, isNotNull);
|
});
|
||||||
expect(YXIconFonts.icon44Edit, isNotNull);
|
|
||||||
expect(YXIconFonts.icon44Delete, isNotNull);
|
group('GeneratorConfig', () {
|
||||||
expect(YXIconFonts.icon44Add, isNotNull);
|
test('fromMap creates config from map', () {
|
||||||
|
final map = {
|
||||||
|
'generator': {'name': 'Test'},
|
||||||
|
'input': {
|
||||||
|
'font_file': 'test.ttf',
|
||||||
|
'json_file': 'test.json',
|
||||||
|
'font_family': 'test',
|
||||||
|
},
|
||||||
|
'output': {
|
||||||
|
'file_path': 'lib/icons.dart',
|
||||||
|
'class_name': 'TestIcons',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
final config = GeneratorConfig.fromMap(map);
|
||||||
|
|
||||||
|
expect(config.generator.name, equals('Test'));
|
||||||
|
expect(config.input.fontFile, equals('test.ttf'));
|
||||||
|
expect(config.input.jsonFile, equals('test.json'));
|
||||||
|
expect(config.output.filePath, equals('lib/icons.dart'));
|
||||||
|
expect(config.output.className, equals('TestIcons'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('defaults creates default config', () {
|
||||||
|
final config = GeneratorConfig.defaults();
|
||||||
|
|
||||||
|
expect(config.input.fontFamily, equals('iconfont'));
|
||||||
|
expect(config.output.className, equals('AppIcons'));
|
||||||
|
expect(config.output.generateDocs, isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('IconParser', () {
|
||||||
|
test('parseMap parses icon font metadata', () {
|
||||||
|
final jsonData = {
|
||||||
|
'id': '123',
|
||||||
|
'name': 'Test Font',
|
||||||
|
'font_family': 'testfont',
|
||||||
|
'glyphs': [
|
||||||
|
{
|
||||||
|
'icon_id': '1',
|
||||||
|
'name': 'icon_test',
|
||||||
|
'font_class': 'icon_test',
|
||||||
|
'unicode': 'e600',
|
||||||
|
'unicode_decimal': 58880,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
final meta = IconParser.parseMap(jsonData);
|
||||||
|
|
||||||
|
expect(meta.name, equals('Test Font'));
|
||||||
|
expect(meta.fontFamily, equals('testfont'));
|
||||||
|
expect(meta.icons.length, equals(1));
|
||||||
|
expect(meta.icons.first.name, equals('icon_test'));
|
||||||
|
expect(meta.icons.first.unicode, equals('e600'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue