Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 统一操作系统路径格式 #34

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"eslint.useFlatConfig": true,
"iconify.customCollectionJsonPaths": [
"playground/node_modules/.unplugin-iconify/icon.json",
"playground/node_modules/.unplugin-iconify/suffix.json",
"playground/node_modules/.unplugin-iconify/svg.json"
],
"[svg]": {
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ pnpm i -D @waset/unplugin-iconify

```ts
Iconify({
/**
* 工作区路径
* @description 项目根目录
* @default process.cwd()
*/
workspace: cwd(),
/**
* 图标转换配置
*/
convert: {
// 直接导出目录
icon: 'assets/icons',
svg: 'assets/icons',
// 不导出颜色
svg: {
icon: {
path: 'assets/icons',
noColor: true,
},
Expand All @@ -33,13 +39,14 @@ Iconify({

/**
* 输出目录
* @default 'node_modules/.unplugin-iconify'
* @type string
* @default `path.join(process.cwd(), 'node_modules/.unplugin-iconify')`
*/
output: 'dist/icons',

/**
* 是否适配 VSCode 插件 Iconify IntelliSense
*
* @type boolean | string
* @default false
*/
iconifyIntelliSense: true,
Expand Down
12 changes: 10 additions & 2 deletions playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ export default defineConfig({
Iconify({
workspace: join(cwd(), '..'),
convert: {
// 直接导出目录
svg: './icons',
// 不导出颜色
icon: {
path: './icons',
noColor: true,
},
svg: './icons',
// 不导出颜色且添加后缀
suffix: {
path: './icons',
noColor: true,
suffix: 'color',
},
},
output: './playground/node_modules/.unplugin-iconify',
output: join(cwd(), '../playground/node_modules/.unplugin-iconify'),
iconifyIntelliSense: true,
}),
],
Expand Down
2 changes: 1 addition & 1 deletion src/core/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function Generateds(options: Required<Options>): Promise<void> {
}

for (const key in options.convert) {
await Generated(key, options.convert[key], join(options.workspace, options.output))
await Generated(key, options.convert[key], options.output)
}

// eslint-disable-next-line no-console
Expand Down
291 changes: 149 additions & 142 deletions src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,142 +1,149 @@
import type { Convert, Loaders, Optional, Options } from './types'
import { join } from 'node:path'
import { cwd } from 'node:process'
import { OUTPUT } from '../env'
import { getOutputFiles, UnocssLoader } from '../loader'
import { Generateds } from './convert'
import { IconifyIntelliSenseSettings } from './vscode'

export class Iconify {
/**
* 配置
*/
options: Required<Options>

/**
* 默认配置
*
* @description 统一管理默认值,避免使用 `if` 判断
*/
defaultOptions: Optional<Options> = {
workspace: cwd(),
output: OUTPUT,
iconifyIntelliSense: false,
convert: {},
}

/**
* 默认转换配置
*
* @description 统一管理默认值,避免使用 `if` 判断
*/
defaultConvert: Optional<Convert> = {
suffix: '',
noColor: false,
}

/**
* 构造器
* @param options Options
*/
constructor(options: Options) {
this.options = { ...this.defaultOptions, ...options }
this.setOptions(this.options)
}

/**
* 设置配置
* @param options Options
*/
private setOptions(options: Required<Options>): void {
if (!Object.keys(options.convert).length) {
return
}

/**
* 处理 convert 配置并设置默认值
*/
for (const key in options.convert) {
const value = options.convert[key]
if (typeof value === 'string') {
options.convert[key] = {
path: value,
...this.defaultConvert,
}
}
else if (typeof value === 'object') {
options.convert[key] = {
...this.defaultConvert,
...value,
}
}
}

// 更新配置
this.options = options
}

/**
* 转换
*/
async toConvert(): Promise<void> {
try {
await Generateds(this.options)
}
catch (error) {
console.error('toConvert 出错了:', error)
}
}

/**
* 生成的 JSON 文件
*/
outputs: string[] = []

/**
* 获取输出文件
*/
async toLoad(): Promise<void> {
try {
this.outputs = getOutputFiles(this.options.output)
}
catch (error) {
console.error('toLoad 出错了:', error)
}
}

/**
* 获取加载器
*
* @param dir 目录
*/
getLoaders(dir: string = this.options.output): Record<Loaders, any> {
return {
unocss: UnocssLoader(dir),
}
}

/**
* 生成 Iconify IntelliSense 配置
*/
async toIntelliSense(): Promise<void> {
// 如果未开启 IntelliSense,则直接返回
if (!this.options.iconifyIntelliSense) {
return
}
// 生成文件的文件路径
const paths = []
for (const dir of this.outputs) {
paths.push(dir.replace(`${this.options.workspace}/`, ''))
}
// 如果没有生成文件,则直接返回
if (!paths.length) {
return
}
// 生成 IntelliSense 配置文件
const dir = typeof this.options.iconifyIntelliSense === 'string' ? this.options.iconifyIntelliSense : '.vscode'
await IconifyIntelliSenseSettings(
join(this.options.workspace, dir),
paths,
)
}
}
import type { Convert, Loaders, Optional, Options } from './types'
import { existsSync } from 'node:fs'
import { join } from 'node:path'
import { cwd } from 'node:process'
import { OUTPUT } from '../env'
import { getOutputFiles, UnocssLoader } from '../loader'
import { Generateds } from './convert'
import { normalizePath } from './utils'
import { IconifyIntelliSenseSettings } from './vscode'

export class Iconify {
/**
* 配置
*/
options: Required<Options>

/**
* 默认配置
*
* @description 统一管理默认值,避免使用 `if` 判断
*/
defaultOptions: Optional<Options> = {
workspace: cwd(),
output: join(cwd(), OUTPUT),
iconifyIntelliSense: false,
convert: {},
}

/**
* 默认转换配置
*
* @description 统一管理默认值,避免使用 `if` 判断
*/
defaultConvert: Optional<Convert> = {
suffix: '',
noColor: false,
}

/**
* 构造器
* @param options Options
*/
constructor(options: Options) {
this.options = { ...this.defaultOptions, ...options }
this.setOptions(this.options)
}

/**
* 设置配置
* @param options Options
*/
private setOptions(options: Required<Options>): void {
if (!Object.keys(options.convert).length) {
return
}

/**
* 处理 convert 配置并设置默认值
*/
for (const key in options.convert) {
const value = options.convert[key]
if (typeof value === 'string') {
options.convert[key] = {
path: value,
...this.defaultConvert,
}
}
else if (typeof value === 'object') {
options.convert[key] = {
...this.defaultConvert,
...value,
}
}
}

// 更新配置
this.options = options
}

/**
* 转换
*/
async toConvert(): Promise<void> {
try {
await Generateds(this.options)
}
catch (error) {
console.error('toConvert 出错了:', error)
}
}

/**
* 生成的 JSON 文件
*/
outputs: string[] = []

/**
* 获取输出文件
*/
async toLoad(): Promise<void> {
try {
this.outputs = getOutputFiles(this.options.output)
}
catch (error) {
console.error('toLoad 出错了:', error)
}
}

/**
* 获取加载器
*
* @param dir 目录
*/
getLoaders(dir: string = this.options.output): Record<Loaders, any> {
return {
unocss: UnocssLoader(dir),
}
}

/**
* 生成 Iconify IntelliSense 配置
*/
async toIntelliSense(): Promise<void> {
// 如果未开启 IntelliSense,则直接返回
if (!this.options.iconifyIntelliSense) {
return
}
// 生成文件的文件路径
const paths = []
for (const dir of this.outputs) {
if (!existsSync(dir)) {
continue
}
paths.push(normalizePath(dir, this.options.workspace))
}

// 如果没有生成文件,则直接返回
if (!paths.length) {
return
}

// 生成 IntelliSense 配置文件
const dir = typeof this.options.iconifyIntelliSense === 'string' ? this.options.iconifyIntelliSense : '.vscode'
await IconifyIntelliSenseSettings(
join(this.options.workspace, dir),
paths,
)
}
}
2 changes: 1 addition & 1 deletion src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export interface Options {
/**
* 生成的类型文件的输出目录。
*
* @default 'node_modules/.unplugin-iconify'
* @default path.join(process.cwd(), 'node_modules/.unplugin-iconify')
*/
output?: string

Expand Down
Loading
Loading