| import { AnyConfig, ParsedClassName } from './types' |
|
|
| export const IMPORTANT_MODIFIER = '!' |
|
|
| const MODIFIER_SEPARATOR = ':' |
| const EMPTY_MODIFIERS: string[] = [] |
|
|
| |
| const createResultObject = ( |
| modifiers: string[], |
| hasImportantModifier: boolean, |
| baseClassName: string, |
| maybePostfixModifierPosition?: number, |
| isExternal?: boolean, |
| ): ParsedClassName => ({ |
| modifiers, |
| hasImportantModifier, |
| baseClassName, |
| maybePostfixModifierPosition, |
| isExternal, |
| }) |
|
|
| export const createParseClassName = (config: AnyConfig) => { |
| const { prefix, experimentalParseClassName } = config |
|
|
| |
| |
| |
| |
| |
| |
| let parseClassName = (className: string): ParsedClassName => { |
| |
| const modifiers: string[] = [] |
|
|
| let bracketDepth = 0 |
| let parenDepth = 0 |
| let modifierStart = 0 |
| let postfixModifierPosition: number | undefined |
|
|
| const len = className.length |
| for (let index = 0; index < len; index++) { |
| const currentCharacter = className[index]! |
|
|
| if (bracketDepth === 0 && parenDepth === 0) { |
| if (currentCharacter === MODIFIER_SEPARATOR) { |
| modifiers.push(className.slice(modifierStart, index)) |
| modifierStart = index + 1 |
| continue |
| } |
|
|
| if (currentCharacter === '/') { |
| postfixModifierPosition = index |
| continue |
| } |
| } |
|
|
| if (currentCharacter === '[') bracketDepth++ |
| else if (currentCharacter === ']') bracketDepth-- |
| else if (currentCharacter === '(') parenDepth++ |
| else if (currentCharacter === ')') parenDepth-- |
| } |
|
|
| const baseClassNameWithImportantModifier = |
| modifiers.length === 0 ? className : className.slice(modifierStart) |
|
|
| |
| let baseClassName = baseClassNameWithImportantModifier |
| let hasImportantModifier = false |
|
|
| if (baseClassNameWithImportantModifier.endsWith(IMPORTANT_MODIFIER)) { |
| baseClassName = baseClassNameWithImportantModifier.slice(0, -1) |
| hasImportantModifier = true |
| } else if ( |
| |
| |
| |
| |
| baseClassNameWithImportantModifier.startsWith(IMPORTANT_MODIFIER) |
| ) { |
| baseClassName = baseClassNameWithImportantModifier.slice(1) |
| hasImportantModifier = true |
| } |
|
|
| const maybePostfixModifierPosition = |
| postfixModifierPosition && postfixModifierPosition > modifierStart |
| ? postfixModifierPosition - modifierStart |
| : undefined |
|
|
| return createResultObject( |
| modifiers, |
| hasImportantModifier, |
| baseClassName, |
| maybePostfixModifierPosition, |
| ) |
| } |
|
|
| if (prefix) { |
| const fullPrefix = prefix + MODIFIER_SEPARATOR |
| const parseClassNameOriginal = parseClassName |
| parseClassName = (className: string) => |
| className.startsWith(fullPrefix) |
| ? parseClassNameOriginal(className.slice(fullPrefix.length)) |
| : createResultObject(EMPTY_MODIFIERS, false, className, undefined, true) |
| } |
|
|
| if (experimentalParseClassName) { |
| const parseClassNameOriginal = parseClassName |
| parseClassName = (className: string) => |
| experimentalParseClassName({ className, parseClassName: parseClassNameOriginal }) |
| } |
|
|
| return parseClassName |
| } |
|
|