Skip to content

Commit 8e80730

Browse files
committed
Refactor
1 parent a37b5e3 commit 8e80730

File tree

3 files changed

+74
-69
lines changed

3 files changed

+74
-69
lines changed

src/index.ts

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as prettierParserBabel from 'prettier/plugins/babel'
1111
// @ts-ignore
1212
import * as recast from 'recast'
1313
import { getTailwindConfig } from './config.js'
14-
import { getCustomizations } from './options.js'
14+
import { createMatcher, type Matcher } from './options.js'
1515
import { loadPlugins } from './plugins.js'
1616
import { sortClasses, sortClassList } from './sorting.js'
1717
import type { Customizations, StringChange, TransformerContext, TransformerEnv, TransformerMetadata } from './types'
@@ -55,12 +55,12 @@ function createParser(
5555
// @ts-ignore: We pass three options in the case of plugins that support Prettier 2 _and_ 3.
5656
let ast = await original.parse(text, options, options)
5757

58-
let customizations = getCustomizations(options, parserFormat, customizationDefaults)
58+
let matcher = createMatcher(options, parserFormat, customizationDefaults)
5959

6060
let changes: any[] = []
6161

6262
transform(ast, {
63-
env: { context, customizations, parsers: {}, options },
63+
env: { context, matcher, parsers: {}, options },
6464
changes,
6565
})
6666

@@ -160,7 +160,7 @@ function transformDynamicAngularAttribute(attr: any, env: TransformerEnv) {
160160
}
161161

162162
function transformDynamicJsAttribute(attr: any, env: TransformerEnv) {
163-
let { functions } = env.customizations
163+
let { matcher } = env
164164

165165
let ast = recast.parse(`let __prettier_temp__ = ${attr.value}`, {
166166
parser: prettierParserBabel.parsers['babel-ts'],
@@ -251,7 +251,7 @@ function transformDynamicJsAttribute(attr: any, env: TransformerEnv) {
251251
)
252252
})
253253

254-
if (isSortableTemplateExpression(path.node, functions)) {
254+
if (isSortableTemplateExpression(path.node, matcher)) {
255255
let sorted = sortTemplateLiteral(path.node.quasi, {
256256
env,
257257
collapseWhitespace: {
@@ -275,13 +275,13 @@ function transformDynamicJsAttribute(attr: any, env: TransformerEnv) {
275275
}
276276

277277
function transformHtml(ast: any, { env, changes }: TransformerContext) {
278-
let { staticAttrs, dynamicAttrs, staticAttrsRegex, dynamicAttrsRegex } = env.customizations
278+
let { matcher } = env
279279
let { parser } = env.options
280280

281281
for (let attr of ast.attrs ?? []) {
282-
if (hasMatch(attr.name, staticAttrs, staticAttrsRegex)) {
282+
if (matcher.hasStaticAttr(attr.name)) {
283283
attr.value = sortClasses(attr.value, { env })
284-
} else if (hasMatch(attr.name, dynamicAttrs, dynamicAttrsRegex)) {
284+
} else if (matcher.hasDynamicAttr(attr.name)) {
285285
if (!/[`'"]/.test(attr.value)) {
286286
continue
287287
}
@@ -300,11 +300,11 @@ function transformHtml(ast: any, { env, changes }: TransformerContext) {
300300
}
301301

302302
function transformGlimmer(ast: any, { env }: TransformerContext) {
303-
let { staticAttrs, staticAttrsRegex } = env.customizations
303+
let { matcher } = env
304304

305305
visit(ast, {
306306
AttrNode(attr, _path, meta) {
307-
if (hasMatch(attr.name, staticAttrs, staticAttrsRegex) && attr.value) {
307+
if (matcher.hasStaticAttr(attr.name) && attr.value) {
308308
meta.sortTextNodes = true
309309
}
310310
},
@@ -356,12 +356,12 @@ function transformGlimmer(ast: any, { env }: TransformerContext) {
356356
}
357357

358358
function transformLiquid(ast: any, { env }: TransformerContext) {
359-
let { staticAttrs, staticAttrsRegex } = env.customizations
359+
let { matcher } = env
360360

361361
function isClassAttr(node: { name: string | { type: string; value: string }[] }) {
362362
return Array.isArray(node.name)
363-
? node.name.every((n) => n.type === 'TextNode' && hasMatch(n.value, staticAttrs, staticAttrsRegex))
364-
: hasMatch(node.name, staticAttrs, staticAttrsRegex)
363+
? node.name.every((n) => n.type === 'TextNode' && matcher.hasStaticAttr(n.value))
364+
: matcher.hasStaticAttr(node.name)
365365
}
366366

367367
function hasSurroundingQuotes(str: string) {
@@ -570,26 +570,26 @@ function sortTemplateLiteral(
570570

571571
function isSortableTemplateExpression(
572572
node: import('@babel/types').TaggedTemplateExpression | import('ast-types').namedTypes.TaggedTemplateExpression,
573-
functions: Set<string>,
573+
matcher: Matcher,
574574
): boolean {
575-
return isSortableExpression(node.tag, functions)
575+
return isSortableExpression(node.tag, matcher)
576576
}
577577

578578
function isSortableCallExpression(
579579
node: import('@babel/types').CallExpression | import('ast-types').namedTypes.CallExpression,
580-
functions: Set<string>,
580+
matcher: Matcher,
581581
): boolean {
582582
if (!node.arguments?.length) return false
583583

584-
return isSortableExpression(node.callee, functions)
584+
return isSortableExpression(node.callee, matcher)
585585
}
586586

587587
function isSortableExpression(
588588
node:
589589
| import('@babel/types').Expression
590590
| import('@babel/types').V8IntrinsicIdentifier
591591
| import('ast-types').namedTypes.ASTNode,
592-
functions: Set<string>,
592+
matcher: Matcher,
593593
): boolean {
594594
// Traverse property accesses and function calls to find the leading ident
595595
while (node.type === 'CallExpression' || node.type === 'MemberExpression') {
@@ -601,7 +601,7 @@ function isSortableExpression(
601601
}
602602

603603
if (node.type === 'Identifier') {
604-
return hasMatch(node.name, functions, [])
604+
return matcher.hasFunction(node.name)
605605
}
606606

607607
return false
@@ -655,7 +655,7 @@ function canCollapseWhitespaceIn(path: Path<import('@babel/types').Node, any>) {
655655
// We cross several parsers that share roughly the same shape so things are
656656
// good enough. The actual AST we should be using is probably estree + ts.
657657
function transformJavaScript(ast: import('@babel/types').Node, { env }: TransformerContext) {
658-
let { staticAttrs, functions, staticAttrsRegex } = env.customizations
658+
let { matcher } = env
659659

660660
function sortInside(ast: import('@babel/types').Node) {
661661
visit(ast, (node, path) => {
@@ -666,7 +666,7 @@ function transformJavaScript(ast: import('@babel/types').Node, { env }: Transfor
666666
} else if (node.type === 'TemplateLiteral') {
667667
sortTemplateLiteral(node, { env, collapseWhitespace })
668668
} else if (node.type === 'TaggedTemplateExpression') {
669-
if (isSortableTemplateExpression(node, functions)) {
669+
if (isSortableTemplateExpression(node, matcher)) {
670670
sortTemplateLiteral(node.quasi, { env, collapseWhitespace })
671671
}
672672
}
@@ -687,7 +687,7 @@ function transformJavaScript(ast: import('@babel/types').Node, { env }: Transfor
687687
return
688688
}
689689

690-
if (!hasMatch(node.name.name, staticAttrs, staticAttrsRegex)) {
690+
if (!matcher.hasStaticAttr(node.name.name)) {
691691
return
692692
}
693693

@@ -701,7 +701,7 @@ function transformJavaScript(ast: import('@babel/types').Node, { env }: Transfor
701701
CallExpression(node) {
702702
node = node as import('@babel/types').CallExpression
703703

704-
if (!isSortableCallExpression(node, functions)) {
704+
if (!isSortableCallExpression(node, matcher)) {
705705
return
706706
}
707707

@@ -711,7 +711,7 @@ function transformJavaScript(ast: import('@babel/types').Node, { env }: Transfor
711711
TaggedTemplateExpression(node, path) {
712712
node = node as import('@babel/types').TaggedTemplateExpression
713713

714-
if (!isSortableTemplateExpression(node, functions)) {
714+
if (!isSortableTemplateExpression(node, matcher)) {
715715
return
716716
}
717717

@@ -794,16 +794,16 @@ function transformCss(ast: any, { env }: TransformerContext) {
794794
}
795795

796796
function transformAstro(ast: any, { env, changes }: TransformerContext) {
797-
let { staticAttrs, dynamicAttrs, staticAttrsRegex, dynamicAttrsRegex } = env.customizations
797+
let { matcher } = env
798798

799799
if (ast.type === 'element' || ast.type === 'custom-element' || ast.type === 'component') {
800800
for (let attr of ast.attributes ?? []) {
801-
if (hasMatch(attr.name, staticAttrs, staticAttrsRegex) && attr.type === 'attribute' && attr.kind === 'quoted') {
801+
if (matcher.hasStaticAttr(attr.name) && attr.type === 'attribute' && attr.kind === 'quoted') {
802802
attr.value = sortClasses(attr.value, {
803803
env,
804804
})
805805
} else if (
806-
hasMatch(attr.name, dynamicAttrs, dynamicAttrsRegex) &&
806+
matcher.hasDynamicAttr(attr.name) &&
807807
attr.type === 'attribute' &&
808808
attr.kind === 'expression' &&
809809
typeof attr.value === 'string'
@@ -819,7 +819,7 @@ function transformAstro(ast: any, { env, changes }: TransformerContext) {
819819
}
820820

821821
function transformMarko(ast: any, { env }: TransformerContext) {
822-
let { staticAttrs } = env.customizations
822+
let { matcher } = env
823823

824824
const nodesToVisit = [ast]
825825
while (nodesToVisit.length > 0) {
@@ -839,7 +839,7 @@ function transformMarko(ast: any, { env }: TransformerContext) {
839839
nodesToVisit.push(...currentNode.body)
840840
break
841841
case 'MarkoAttribute':
842-
if (!staticAttrs.has(currentNode.name)) break
842+
if (!matcher.hasStaticAttr(currentNode.name)) break
843843
switch (currentNode.value.type) {
844844
case 'ArrayExpression':
845845
const classList = currentNode.value.elements
@@ -861,15 +861,15 @@ function transformMarko(ast: any, { env }: TransformerContext) {
861861
}
862862

863863
function transformTwig(ast: any, { env, changes }: TransformerContext) {
864-
let { staticAttrs, functions } = env.customizations
864+
let { matcher } = env
865865

866866
for (let child of ast.expressions ?? []) {
867867
transformTwig(child, { env, changes })
868868
}
869869

870870
visit(ast, {
871871
Attribute(node, _path, meta) {
872-
if (!staticAttrs.has(node.name.name)) return
872+
if (!matcher.hasStaticAttr(node.name.name)) return
873873

874874
meta.sortTextNodes = true
875875
},
@@ -890,7 +890,7 @@ function transformTwig(ast: any, { env, changes }: TransformerContext) {
890890
}
891891

892892
if (node.type === 'Identifier') {
893-
if (!hasMatch(node.name, functions, [])) return
893+
if (!matcher.hasFunction(node.name)) return
894894
}
895895

896896
meta.sortTextNodes = true
@@ -922,7 +922,7 @@ function transformTwig(ast: any, { env, changes }: TransformerContext) {
922922
}
923923

924924
function transformPug(ast: any, { env }: TransformerContext) {
925-
let { staticAttrs } = env.customizations
925+
let { matcher } = env
926926

927927
// This isn't optimal
928928
// We should merge the classes together across class attributes and class tokens
@@ -931,7 +931,7 @@ function transformPug(ast: any, { env }: TransformerContext) {
931931

932932
// First sort the classes in attributes
933933
for (const token of ast.tokens) {
934-
if (token.type === 'attribute' && staticAttrs.has(token.name)) {
934+
if (token.type === 'attribute' && matcher.hasStaticAttr(token.name)) {
935935
token.val = [token.val.slice(0, 1), sortClasses(token.val.slice(1, -1), { env }), token.val.slice(-1)].join('')
936936
}
937937
}
@@ -976,10 +976,10 @@ function transformPug(ast: any, { env }: TransformerContext) {
976976
}
977977

978978
function transformSvelte(ast: any, { env, changes }: TransformerContext) {
979-
let { staticAttrs } = env.customizations
979+
let { matcher } = env
980980

981981
for (let attr of ast.attributes ?? []) {
982-
if (!staticAttrs.has(attr.name) || attr.type !== 'Attribute') {
982+
if (!matcher.hasStaticAttr(attr.name) || attr.type !== 'Attribute') {
983983
continue
984984
}
985985

@@ -1071,19 +1071,6 @@ function transformSvelte(ast: any, { env, changes }: TransformerContext) {
10711071
}
10721072
}
10731073

1074-
/**
1075-
* Check for matches against a static list or possible regex patterns
1076-
*/
1077-
function hasMatch(name: string, list: Set<string>, patterns: RegExp[]): boolean {
1078-
if (list.has(name)) return true
1079-
1080-
for (let regex of patterns) {
1081-
if (regex.test(name)) return true
1082-
}
1083-
1084-
return false
1085-
}
1086-
10871074
export { options } from './options.js'
10881075

10891076
export const printers: Record<string, Printer> = (function () {

src/options.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,13 @@ export const options: Record<string, SupportOption> = {
6161
},
6262
}
6363

64-
function parseRegex(str: string): RegExp | null {
65-
if (!str.startsWith('/')) return null
66-
67-
let lastSlash = str.lastIndexOf('/')
68-
if (str.lastIndexOf('/') <= 0) return null
69-
70-
try {
71-
let pattern = str.slice(1, lastSlash)
72-
let flags = str.slice(lastSlash + 1)
73-
return new RegExp(pattern, flags)
74-
} catch {
75-
return null
76-
}
64+
export interface Matcher {
65+
hasStaticAttr(name: string): boolean
66+
hasDynamicAttr(name: string): boolean
67+
hasFunction(name: string): boolean
7768
}
7869

79-
export function getCustomizations(options: RequiredOptions, parser: string, defaults: Customizations): Customizations {
70+
export function createMatcher(options: RequiredOptions, parser: string, defaults: Customizations): Matcher {
8071
let staticAttrs = new Set<string>(defaults.staticAttrs)
8172
let dynamicAttrs = new Set<string>(defaults.dynamicAttrs)
8273
let functions = new Set<string>(defaults.functions)
@@ -127,10 +118,36 @@ export function getCustomizations(options: RequiredOptions, parser: string, defa
127118
}
128119

129120
return {
130-
functions,
131-
staticAttrs,
132-
dynamicAttrs,
133-
staticAttrsRegex,
134-
dynamicAttrsRegex,
121+
hasStaticAttr: (name: string) => hasMatch(name, staticAttrs, staticAttrsRegex),
122+
hasDynamicAttr: (name: string) => hasMatch(name, dynamicAttrs, dynamicAttrsRegex),
123+
hasFunction: (name: string) => hasMatch(name, functions, []),
124+
}
125+
}
126+
127+
/**
128+
* Check for matches against a static list or possible regex patterns
129+
*/
130+
function hasMatch(name: string, list: Set<string>, patterns: RegExp[]): boolean {
131+
if (list.has(name)) return true
132+
133+
for (let regex of patterns) {
134+
if (regex.test(name)) return true
135+
}
136+
137+
return false
138+
}
139+
140+
function parseRegex(str: string): RegExp | null {
141+
if (!str.startsWith('/')) return null
142+
143+
let lastSlash = str.lastIndexOf('/')
144+
if (str.lastIndexOf('/') <= 0) return null
145+
146+
try {
147+
let pattern = str.slice(1, lastSlash)
148+
let flags = str.slice(lastSlash + 1)
149+
return new RegExp(pattern, flags)
150+
} catch {
151+
return null
135152
}
136153
}

src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { ParserOptions } from 'prettier'
2+
import type { Matcher } from './options'
23

34
export interface TransformerMetadata {
45
// Default customizations for a given transformer
@@ -26,7 +27,7 @@ export interface UnifiedApi {
2627

2728
export interface TransformerEnv {
2829
context: UnifiedApi
29-
customizations: Customizations
30+
matcher: Matcher
3031
parsers: any
3132
options: ParserOptions
3233
}

0 commit comments

Comments
 (0)