Skip to content

Commit f475c58

Browse files
committed
refact: use unicorn rule
1 parent 9d5308f commit f475c58

File tree

24 files changed

+252
-212
lines changed

24 files changed

+252
-212
lines changed

.eslintrc.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
module.exports = {
22
root: true,
3-
extends: ['@icebreakers/eslint-config-ts']
3+
extends: ['@icebreakers/eslint-config-ts', 'plugin:unicorn/recommended'],
4+
rules: {
5+
'unicorn/prefer-module': 0,
6+
'unicorn/prevent-abbreviations': 0,
7+
'unicorn/filename-case': 0,
8+
'unicorn/no-object-as-default-parameter': 0,
9+
'unicorn/no-null': 0
10+
}
411
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"bumpp": "^9.1.1",
3030
"cross-env": "^7.0.3",
3131
"eslint": "^8.42.0",
32+
"eslint-plugin-unicorn": "^47.0.0",
3233
"jest": "^29.5.0",
3334
"only-allow": "^1.1.1",
3435
"prettier": "^2.8.8",

packages/core/src/css/plugins.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ const postcssPlugin = 'postcss-mangle-tailwindcss-plugin'
88

99
export function isVueScoped(s: parser.ClassName): boolean {
1010
if (s.parent) {
11-
const idx = s.parent.nodes.indexOf(s)
12-
if (idx > -1) {
13-
const nextNode = s.parent.nodes[idx + 1]
14-
if (nextNode && nextNode.type === 'attribute' && nextNode.attribute.indexOf('data-v-') > -1) {
11+
const index = s.parent.nodes.indexOf(s)
12+
if (index > -1) {
13+
const nextNode = s.parent.nodes[index + 1]
14+
if (nextNode && nextNode.type === 'attribute' && nextNode.attribute.includes('data-v-')) {
1515
return true
1616
}
1717
}
@@ -27,10 +27,8 @@ const postcssMangleTailwindcssPlugin: PostcssMangleTailwindcssPlugin = (options)
2727
// must set newClassMap options
2828
let set: Set<string> = new Set()
2929

30-
if (options) {
31-
if (options.runtimeSet) {
32-
set = options.runtimeSet
33-
}
30+
if (options && options.runtimeSet) {
31+
set = options.runtimeSet
3432
}
3533
return {
3634
postcssPlugin,
@@ -54,10 +52,8 @@ const postcssMangleTailwindcssPlugin: PostcssMangleTailwindcssPlugin = (options)
5452
} else {
5553
let newClassMap: Record<string, IClassGeneratorContextItem> = {}
5654

57-
if (options) {
58-
if (options.classGenerator) {
59-
newClassMap = options.classGenerator.newClassMap
60-
}
55+
if (options && options.classGenerator) {
56+
newClassMap = options.classGenerator.newClassMap
6157
}
6258

6359
return {

packages/core/src/html/index.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ export function htmlHandler(rawSource: string, options: IHtmlHandlerOptions) {
88
const fragment = parse(rawSource)
99
traverse(fragment, {
1010
element(node, parent) {
11-
const attr = node.attrs.find((x) => x.name === 'class')
12-
if (attr) {
13-
const arr = splitCode(attr.value, {
11+
const attribute = node.attrs.find((x) => x.name === 'class')
12+
if (attribute) {
13+
const array = splitCode(attribute.value, {
1414
splitQuote: false
1515
})
16-
for (let i = 0; i < arr.length; i++) {
17-
const v = arr[i]
16+
for (const v of array) {
1817
if (runtimeSet.has(v)) {
19-
attr.value = attr.value.replace(makeRegex(v), classGenerator.generateClassName(v).name)
18+
attribute.value = attribute.value.replace(makeRegex(v), classGenerator.generateClassName(v).name)
2019
}
2120
}
2221
}

packages/core/src/js/index.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,28 @@ import * as t from '@babel/types'
33
import { transformSync, type BabelFileResult, type NodePath } from '@babel/core'
44
import type { IJsHandlerOptions } from '../types'
55
import { makeRegex, splitCode } from '../shared'
6-
import { isProd } from '../env'
6+
import { isProd as isProduction } from '../env'
77

8-
export function handleValue(str: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions) {
8+
export function handleValue(string_: string, node: StringLiteral | TemplateElement, options: IJsHandlerOptions) {
99
const { runtimeSet: set, classGenerator: clsGen, splitQuote = true } = options
1010

11-
const arr = splitCode(str, {
11+
const array = splitCode(string_, {
1212
splitQuote
1313
})
14-
let rawStr = str
15-
for (let i = 0; i < arr.length; i++) {
16-
const v = arr[i]
14+
let rawString = string_
15+
for (const v of array) {
1716
if (set.has(v)) {
1817
let ignoreFlag = false
1918
if (Array.isArray(node.leadingComments)) {
2019
ignoreFlag = node.leadingComments.findIndex((x) => x.value.includes('tw-mangle') && x.value.includes('ignore')) > -1
2120
}
2221

2322
if (!ignoreFlag) {
24-
rawStr = rawStr.replace(makeRegex(v), clsGen.generateClassName(v).name)
23+
rawString = rawString.replace(makeRegex(v), clsGen.generateClassName(v).name)
2524
}
2625
}
2726
}
28-
return rawStr
27+
return rawString
2928
}
3029

3130
export function jsHandler(rawSource: string, options: IJsHandlerOptions) {
@@ -52,12 +51,10 @@ export function jsHandler(rawSource: string, options: IJsHandlerOptions) {
5251
enter(p: NodePath<CallExpression>) {
5352
const n = p.node
5453
// eval()
55-
if (t.isIdentifier(n.callee) && n.callee.name === 'eval') {
56-
if (t.isStringLiteral(n.arguments[0])) {
57-
const res = jsHandler(n.arguments[0].value, options)
58-
if (res.code) {
59-
n.arguments[0].value = res.code
60-
}
54+
if (t.isIdentifier(n.callee) && n.callee.name === 'eval' && t.isStringLiteral(n.arguments[0])) {
55+
const res = jsHandler(n.arguments[0].value, options)
56+
if (res.code) {
57+
n.arguments[0].value = res.code
6158
}
6259
}
6360
}
@@ -67,7 +64,7 @@ export function jsHandler(rawSource: string, options: IJsHandlerOptions) {
6764
}
6865
}
6966
],
70-
minified: options.minified ?? isProd(),
67+
minified: options.minified ?? isProduction(),
7168
sourceMaps: false,
7269
configFile: false
7370
})

packages/core/test/html.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ describe('html handler', () => {
1010
it('common usage', () => {
1111
const runtimeSet = new Set<string>()
1212

13-
splitCode('text-3xl font-bold underline').forEach((x) => {
13+
for (const x of splitCode('text-3xl font-bold underline')) {
1414
runtimeSet.add(x)
15-
})
15+
}
1616
const res = htmlHandler(getTestCase('hello-world.html'), {
1717
classGenerator,
1818
runtimeSet
@@ -23,9 +23,9 @@ describe('html handler', () => {
2323
it('trailing slash case', () => {
2424
const runtimeSet = new Set<string>()
2525

26-
splitCode('bg-red-500 bg-red-500/50').forEach((x) => {
26+
for (const x of splitCode('bg-red-500 bg-red-500/50')) {
2727
runtimeSet.add(x)
28-
})
28+
}
2929
const res = htmlHandler(getTestCase('trailing-slash.html'), {
3030
classGenerator,
3131
runtimeSet

packages/core/test/js.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ describe('js handler', () => {
6565

6666
it('z-10 not transform', () => {
6767
const runtimeSet = new Set<string>()
68-
'z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex'.split(' ').forEach((cls) => {
68+
for (const cls of 'z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex'.split(' ')) {
6969
runtimeSet.add(cls)
70-
})
70+
}
7171

7272
const testCase = `{ className: "z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex" }`
7373
const code = jsHandler(testCase, {
@@ -79,9 +79,9 @@ describe('js handler', () => {
7979

8080
it('z-10 not transform with splitQuote false', () => {
8181
const runtimeSet = new Set<string>()
82-
'z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex'.split(' ').forEach((cls) => {
82+
for (const cls of 'z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex'.split(' ')) {
8383
runtimeSet.add(cls)
84-
})
84+
}
8585

8686
const testCase = `{ className: "z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex" }`
8787
const code = jsHandler(testCase, {

packages/shared/src/classGenerator.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,12 @@ class ClassGenerator implements IClassGenerator {
4444

4545
includeFilePath(filePath: string): boolean {
4646
const { include } = this.opts
47-
if (Array.isArray(include)) {
48-
return regExpTest(include, filePath)
49-
} else {
50-
return true
51-
}
47+
return Array.isArray(include) ? regExpTest(include, filePath) : true
5248
}
5349

5450
excludeFilePath(filePath: string): boolean {
5551
const { exclude } = this.opts
56-
if (Array.isArray(exclude)) {
57-
return regExpTest(exclude, filePath)
58-
} else {
59-
return false
60-
}
52+
return Array.isArray(exclude) ? regExpTest(exclude, filePath) : false
6153
}
6254

6355
isFileIncluded(filePath: string) {

packages/shared/src/regex.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export function escapeStringRegexp(str: string) {
22
if (typeof str !== 'string') {
33
throw new TypeError('Expected a string')
44
}
5-
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')
5+
return str.replaceAll(/[$()*+.?[\\\]^{|}]/g, '\\$&').replaceAll('-', '\\x2d')
66
}
77

88
export function makeRegex(

packages/shared/src/split.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const validateFilterRE = /[\w\u00A0-\uFFFF-_:%-?]/
1+
export const validateFilterRE = /[\w%-?\u00A0-\uFFFF-]/
22

33
export function isValidSelector(selector = ''): selector is string {
44
return validateFilterRE.test(selector)
@@ -10,6 +10,6 @@ export const splitCode = (
1010
splitQuote?: boolean
1111
} = { splitQuote: true }
1212
) => {
13-
const regex = options.splitQuote ? /[\s"]+/ : /[\s]+/
14-
return code.split(regex).filter(isValidSelector)
13+
const regex = options.splitQuote ? /[\s"]+/ : /\s+/
14+
return code.split(regex).filter((x) => isValidSelector(x))
1515
}

packages/shared/src/utils.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,47 @@ export const defaultMangleClassFilter = (className: string) => {
44
// ignore className like 'filter','container'
55
// it may be dangerous to mangle/rename all StringLiteral , so use /-/ test for only those with /-/ like:
66
// bg-[#123456] w-1 etc...
7-
return /[-:]/.test(className)
7+
return /[:-]/.test(className)
88
}
99

1010
export function groupBy<T>(arr: T[], cb: (arg: T) => string): Record<string, T[]> {
1111
if (!Array.isArray(arr)) {
12-
throw new Error('expected an array for first argument')
12+
throw new TypeError('expected an array for first argument')
1313
}
1414

1515
if (typeof cb !== 'function') {
16-
throw new Error('expected a function for second argument')
16+
throw new TypeError('expected a function for second argument')
1717
}
1818

1919
const result: Record<string, T[]> = {}
20-
for (let i = 0; i < arr.length; i++) {
21-
const item = arr[i]
20+
for (const item of arr) {
2221
const bucketCategory = cb(item)
2322
const bucket = result[bucketCategory]
2423

25-
if (!Array.isArray(bucket)) {
26-
result[bucketCategory] = [item]
27-
} else {
24+
if (Array.isArray(bucket)) {
2825
result[bucketCategory].push(item)
26+
} else {
27+
result[bucketCategory] = [item]
2928
}
3029
}
3130

3231
return result
3332
}
3433

35-
export const acceptChars = 'abcdefghijklmnopqrstuvwxyz'.split('')
34+
export const acceptChars = [...'abcdefghijklmnopqrstuvwxyz']
3635

3736
export function stripEscapeSequence(words: string) {
38-
return words.replace(/\\/g, '')
37+
return words.replaceAll('\\', '')
3938
}
4039

4140
export const validate = (opts: IClassGeneratorOptions, classGenerator: IClassGenerator) => {
4241
if (!opts.log) return
4342
for (const className in classGenerator.newClassMap) {
4443
const c = classGenerator.newClassMap[className]
45-
if (c.usedBy.length >= 1) {
44+
if (c.usedBy.length > 0) {
4645
continue
4746
}
48-
if (c.usedBy[0].match(/.+\.css:*$/)) {
47+
if (/.+\.css:*$/.test(c.usedBy[0])) {
4948
console.log(`The class name '${className}' is not used: defined at ${c.usedBy[0]}.`)
5049
} else {
5150
console.log(`The class name '${className}' is not defined: used at ${c.usedBy[0]}.`)
@@ -63,8 +62,7 @@ export function isMap(value: unknown) {
6362

6463
export function regExpTest(arr: (string | RegExp)[] = [], str: string) {
6564
if (Array.isArray(arr)) {
66-
for (let i = 0; i < arr.length; i++) {
67-
const item = arr[i]
65+
for (const item of arr) {
6866
if (typeof item === 'string') {
6967
if (item === str) {
7068
return true

packages/shared/test/reg.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ describe('regex', () => {
44
it('z-10 regex', () => {
55
const testCase = 'z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex'
66
const regex = makeRegex('z-10')
7-
const arr = Array.from(testCase.matchAll(regex))
7+
const arr = [...testCase.matchAll(regex)]
88
expect(arr.length).toBe(1)
99
expect(arr).toMatchSnapshot()
1010
})
@@ -14,15 +14,15 @@ describe('regex', () => {
1414
const regex = makeRegex('bg-red-500', {
1515
exact: false
1616
})
17-
const arr = Array.from(testCase.matchAll(regex))
17+
const arr = [...testCase.matchAll(regex)]
1818
expect(arr.length).toBe(2)
1919
expect(arr).toMatchSnapshot()
2020
})
2121

2222
it('trailing slash should exact match case 1', () => {
2323
const testCase = 'bg-red-500 bg-red-500/50'
2424
const regex = makeRegex('bg-red-500')
25-
const arr = Array.from(testCase.matchAll(regex))
25+
const arr = [...testCase.matchAll(regex)]
2626
expect(arr.length).toBe(1)
2727
expect(arr).toMatchSnapshot()
2828
})

0 commit comments

Comments
 (0)