Skip to content

Commit 4c03bd9

Browse files
committed
feat: update CLI to use clack-prompts for user interaction, add new dependency, and improve file handling
1 parent aac0c01 commit 4c03bd9

File tree

8 files changed

+152
-70
lines changed

8 files changed

+152
-70
lines changed

cli.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/usr/bin/env node --no-warnings
2-
import('./dist/cli.js')
2+
import('./dist/cli.cjs')

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
},
6060
"dependencies": {
6161
"@babel/core": "^7.26.10",
62+
"@simon_he/clack-prompts": "^0.8.11",
6263
"fast-glob": "^3.3.3"
6364
},
6465
"devDependencies": {

pnpm-lock.yaml

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli.ts

Lines changed: 114 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,94 +2,144 @@ import type { SuffixType } from './type'
22
import fs from 'node:fs'
33
import path from 'node:path'
44
import process from 'node:process'
5+
import { setTimeout } from 'node:timers/promises'
6+
import * as p from '@simon_he/clack-prompts'
57
import colorize from '@simon_he/colorize'
68
import fg from 'fast-glob'
79
import { transfromCode } from './transformCode'
8-
import { flag } from './utils'
9-
10-
const log = console.log
10+
import { TRANSFER_FLAG } from './utils'
1111

1212
export async function cli() {
13+
console.clear()
14+
await setTimeout(100)
15+
const s = p.spinner()
16+
p.intro(
17+
`${colorize({
18+
text: colorize({
19+
text: ' 🚀 Transform Code To Unocss ',
20+
color: 'black',
21+
}),
22+
bgColor: 'cyan',
23+
})}`,
24+
)
1325
const asset = process.argv[2]
1426

1527
if (!asset) {
16-
log(
17-
colorize({
18-
text: '需要指定一个目录',
19-
color: 'red',
20-
}),
21-
)
28+
p.cancel('❌ Please specify a directory or file path to convert.')
2229
return
2330
}
2431
const fileDir = path.resolve(process.cwd(), asset)
32+
// 如果传入的是一个文件路径,则直接转换这个文件
33+
if (fs.existsSync(fileDir) && fs.statSync(fileDir).isFile()) {
34+
p.note(`${fileDir}`, 'Converting file...')
35+
s.start('Converting...')
36+
const suffix = fileDir.slice(fileDir.lastIndexOf('.') + 1) as SuffixType
37+
const code = await fs.promises.readFile(fileDir, 'utf-8')
38+
const codeTransfer = await transfromCode(code, {
39+
filepath: fileDir,
40+
type: suffix,
41+
})
42+
// 创建新文件
43+
try {
44+
await fs.promises.writeFile(
45+
fileDir.replace(`.${suffix}`, `${TRANSFER_FLAG}.${suffix}`),
46+
codeTransfer,
47+
)
48+
s.stop('Conversion completed.')
49+
}
50+
catch (error) {
51+
p.cancel(`❌ Conversion failed: ${error}`)
52+
}
53+
return
54+
}
55+
// 判断这个目录是否存在
56+
if (!fs.existsSync(fileDir)) {
57+
p.cancel(`Directory not found: ${fileDir}`)
58+
return
59+
}
2560
const isRevert = process.argv[3] === '-r' || process.argv[3] === '--revert'
61+
const isForce = process.argv.includes('--force')
2662
const entries = await fg(
2763
['**.vue', '**.tsx', '**.html', '**.svelte', '**.astro'],
2864
{ cwd: fileDir },
2965
)
30-
entries
31-
.filter(entry => !entry.endsWith(flag))
32-
.forEach(async (entry) => {
33-
const filepath = `${fileDir}/${entry}`
34-
const suffix = entry.slice(entry.lastIndexOf('.') + 1) as SuffixType
66+
if (!entries.length) {
67+
p.cancel('No convertible files found in the specified directory.')
68+
return
69+
}
3570

36-
const newfilepath = filepath.endsWith(flag)
37-
? filepath
38-
: filepath.replace(`.${suffix}`, `${flag}.${suffix}`)
39-
if (fs.existsSync(newfilepath)) {
40-
if (isRevert) {
41-
// 删除
42-
try {
43-
await fs.promises.unlink(newfilepath)
44-
log(
45-
colorize({
46-
text: `${newfilepath} already revert`,
47-
color: 'green',
48-
}),
49-
)
71+
p.note(`${fileDir}`, 'Converting directory...')
72+
73+
s.start('Converting...')
74+
await Promise.all(
75+
entries
76+
.filter(entry => !entry.includes(TRANSFER_FLAG))
77+
.map(async (entry) => {
78+
const filepath = path.join(fileDir, entry)
79+
const suffix = entry.slice(entry.lastIndexOf('.') + 1) as SuffixType
80+
81+
const newfilepath = filepath.endsWith(TRANSFER_FLAG)
82+
? filepath
83+
: filepath.replace(`.${suffix}`, `${TRANSFER_FLAG}.${suffix}`)
84+
if (fs.existsSync(newfilepath)) {
85+
if (isRevert) {
86+
try {
87+
await fs.promises.unlink(newfilepath)
88+
p.note(
89+
colorize({ text: newfilepath, color: 'cyan' }),
90+
colorize({ text: 'Revert succeeded', color: 'green' }),
91+
)
92+
}
93+
catch (error) {
94+
p.note(
95+
colorize({ text: newfilepath, color: 'cyan' }),
96+
colorize({ text: `Revert failed: ${error}`, color: 'red' }),
97+
)
98+
}
99+
return
100+
}
101+
if (isForce) {
102+
// Overwrite
50103
}
51-
catch (error) {
52-
log(
104+
else {
105+
p.note(
106+
colorize({ text: newfilepath, color: 'cyan' }),
53107
colorize({
54-
text: `revert failed: ${error}`,
55-
color: 'red',
108+
text: 'Skipped (use --force to overwrite)',
109+
color: 'yellow',
56110
}),
57111
)
112+
return
58113
}
114+
}
115+
else if (isRevert) {
59116
return
60117
}
61-
log(
62-
colorize({
63-
text: `${newfilepath} has transferred`,
64-
color: 'yellow',
65-
}),
66-
)
67-
return
68-
}
69-
else if (isRevert) {
70-
return
71-
}
72-
const code = await fs.promises.readFile(filepath, 'utf-8')
73-
const codeTransfer = await transfromCode(code, { filepath, type: suffix })
74-
// 创建新文件
75-
try {
76-
await fs.promises.writeFile(newfilepath, codeTransfer)
77-
log(
78-
colorize({
79-
text: `${newfilepath} transfer succeed`,
80-
color: 'green',
81-
}),
82-
)
83-
}
84-
catch (error) {
85-
log(
86-
colorize({
87-
text: `${newfilepath} transfer failed: ${error}`,
88-
color: 'red',
89-
}),
90-
)
91-
}
92-
})
118+
const code = await fs.promises.readFile(filepath, 'utf-8')
119+
const codeTransfer = await transfromCode(code, {
120+
filepath,
121+
type: suffix,
122+
})
123+
try {
124+
await fs.promises.writeFile(newfilepath, codeTransfer)
125+
p.note(
126+
colorize({ text: newfilepath, color: 'cyan' }),
127+
colorize({
128+
text: `Transfer succeeded${isForce ? ' (overwritten)' : ''}`,
129+
color: 'green',
130+
}),
131+
)
132+
}
133+
catch (error) {
134+
p.note(
135+
colorize({ text: newfilepath, color: 'cyan' }),
136+
colorize({ text: `Transfer failed: ${error}`, color: 'red' }),
137+
)
138+
}
139+
}),
140+
)
141+
s.stop('Conversion completed.')
142+
p.outro('✅ All files have been processed.')
93143
}
94144

95145
cli()

src/transformCss.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import { tail } from './tail'
99
import { transformVue } from './transformVue'
1010
import {
1111
diffTemplateStyle,
12-
flag,
1312
getCssType,
1413
getStyleScoped,
1514
getVueCompilerSfc, // 从utils引入公共函数
1615
isEmptyStyle,
1716
isNot,
1817
joinWithUnderLine,
18+
TRANSFER_FLAG,
1919
transformUnocssBack,
2020
trim,
2121
} from './utils'
@@ -255,7 +255,7 @@ async function importCss(
255255
const restStyle = getStyleScoped(transfer)
256256

257257
fsp.writeFile(
258-
url.replace(`.${type}`, `${flag}.${type}`),
258+
url.replace(`.${type}`, `${TRANSFER_FLAG}.${type}`),
259259
restStyle,
260260
'utf-8',
261261
)

src/transformJsx.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export async function transformJsx(
1414
const ast = babelParse(code, {
1515
babelrc: false,
1616
comments: true,
17-
plugins: [[vueJsxPlugin, {}]],
17+
plugins: [[vueJsxPlugin]],
1818
})
1919

2020
let container: any = null

src/utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createGenerator } from '@unocss/core'
22
import presetUno from '@unocss/preset-uno'
33

44
export type CssType = 'less' | 'scss' | 'css' | 'styl'
5-
export const flag = '.__unocss_transfer__'
5+
export const TRANSFER_FLAG = '.__unocss_transfer__'
66

77
export function isNot(s: string) {
88
return /\[&:not\(/.test(s)
@@ -92,7 +92,8 @@ export function transformUnocssBack(code: string[]) {
9292
export function diffTemplateStyle(before: string, after: string) {
9393
const s1 = before.match(/<style scoped>.*<\/style>/s)!
9494
const s2 = after.match(/<style scoped>.*<\/style>/s)!
95-
95+
if (!s1 || !s2)
96+
return false
9697
return s1[0] === s2[0]
9798
}
9899

tsup.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default defineConfig({
1414
'fast-glob',
1515
'unocss',
1616
'@vue/compiler-sfc',
17+
'@babel/core',
1718
],
1819
dts: {
1920
resolve: true,

0 commit comments

Comments
 (0)