Skip to content

Commit

Permalink
feat: 统一操作系统路径格式
Browse files Browse the repository at this point in the history
  • Loading branch information
waset committed Oct 30, 2024
1 parent e3497ce commit 36e0c7d
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 150 deletions.
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 `process.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
301 changes: 159 additions & 142 deletions src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,142 +1,159 @@
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 { 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)) {
return
}
const workspace = this.options.workspace.replace(/\\/g, '/')
let path = dir.replace(/\\/g, '/')
if (path.startsWith(workspace)) {
path = path.replace(workspace, '')
}
if (path.startsWith('/')) {
path = path.slice(1)
}
if (path.endsWith('/')) {
path = path.slice(0, -1)
}
paths.push(path)
}

// 如果没有生成文件,则直接返回
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 process.join(process.cwd(), 'node_modules/.unplugin-iconify')
*/
output?: string

Expand Down

0 comments on commit 36e0c7d

Please sign in to comment.