generated from timelessco/react-components-template
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tw-merge): ✨ add tw-merge locally to test next build (#167)
- Loading branch information
1 parent
6e793e2
commit 690a400
Showing
14 changed files
with
1,820 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import { ClassGroup, ClassGroupId, ClassValidator, Config } from "./types"; | ||
|
||
export interface ClassPartObject { | ||
nextPart: Record<string, ClassPartObject>; | ||
validators: ClassValidatorObject[]; | ||
classGroupId?: ClassGroupId; | ||
} | ||
|
||
interface ClassValidatorObject { | ||
classGroupId: ClassGroupId; | ||
validator: ClassValidator; | ||
} | ||
|
||
const CLASS_PART_SEPARATOR = "-"; | ||
|
||
export function createClassUtils(config: Config) { | ||
const classMap = createClassMap(config); | ||
|
||
function getClassGroupId(className: string) { | ||
const classParts = className.split(CLASS_PART_SEPARATOR); | ||
|
||
// Classes like `-inset-1` produce an empty string as first classPart. We assume that classes for negative values are used correctly and remove it from classParts. | ||
if (classParts[0] === "" && classParts.length !== 1) { | ||
classParts.shift(); | ||
} | ||
|
||
return getGroupRecursive(classParts, classMap); | ||
} | ||
|
||
function getConflictingClassGroupIds(classGroupId: ClassGroupId) { | ||
return config.conflictingClassGroups[classGroupId] || []; | ||
} | ||
|
||
return { | ||
getClassGroupId, | ||
getConflictingClassGroupIds, | ||
}; | ||
} | ||
|
||
function getGroupRecursive( | ||
classParts: string[], | ||
classPartObject: ClassPartObject, | ||
): ClassGroupId | undefined { | ||
if (classParts.length === 0) { | ||
return classPartObject.classGroupId; | ||
} | ||
|
||
const currentClassPart = classParts[0]!; | ||
const nextClassPartObject = classPartObject.nextPart[currentClassPart]; | ||
const classGroupFromNextClassPart = nextClassPartObject | ||
? getGroupRecursive(classParts.slice(1), nextClassPartObject) | ||
: undefined; | ||
|
||
if (classGroupFromNextClassPart) { | ||
return classGroupFromNextClassPart; | ||
} | ||
|
||
if (classPartObject.validators.length === 0) { | ||
return undefined; | ||
} | ||
|
||
const classRest = classParts.join(CLASS_PART_SEPARATOR); | ||
|
||
return classPartObject.validators.find(({ validator }) => | ||
validator(classRest), | ||
)?.classGroupId; | ||
} | ||
|
||
/** | ||
* Exported for testing only | ||
*/ | ||
export function createClassMap(config: Config) { | ||
const classMap: ClassPartObject = { | ||
nextPart: {}, | ||
validators: [], | ||
}; | ||
|
||
Object.entries(config.classGroups).forEach(([classGroupId, classGroup]) => { | ||
processClassesRecursively(classGroup, classMap, classGroupId); | ||
}); | ||
|
||
return classMap; | ||
} | ||
|
||
function processClassesRecursively( | ||
classGroup: ClassGroup, | ||
classPartObject: ClassPartObject, | ||
classGroupId: ClassGroupId, | ||
) { | ||
classGroup.forEach(classDefinition => { | ||
if (typeof classDefinition === "string") { | ||
const classPartObjectToEdit = | ||
classDefinition === "" | ||
? classPartObject | ||
: getPart(classPartObject, classDefinition); | ||
classPartObjectToEdit.classGroupId = classGroupId; | ||
} else if (typeof classDefinition === "function") { | ||
classPartObject.validators.push({ | ||
validator: classDefinition, | ||
classGroupId, | ||
}); | ||
} else { | ||
Object.entries(classDefinition).forEach(([key, classGroup]) => { | ||
processClassesRecursively( | ||
classGroup, | ||
getPart(classPartObject, key), | ||
classGroupId, | ||
); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
function getPart(classPartObject: ClassPartObject, path: string) { | ||
let currentClassPartObject = classPartObject; | ||
|
||
path.split(CLASS_PART_SEPARATOR).forEach(pathPart => { | ||
if (currentClassPartObject.nextPart[pathPart] === undefined) { | ||
currentClassPartObject.nextPart[pathPart] = { | ||
nextPart: {}, | ||
validators: [], | ||
}; | ||
} | ||
|
||
currentClassPartObject = currentClassPartObject.nextPart[pathPart]!; | ||
}); | ||
|
||
return currentClassPartObject; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { createClassUtils } from "./class-utils"; | ||
import { getLruCache } from "./lru-cache"; | ||
import { createPrefixUtils } from "./prefix-utils"; | ||
import { Config } from "./types"; | ||
|
||
export type ConfigUtils = ReturnType<typeof createConfigUtils>; | ||
|
||
export function createConfigUtils(config: Config) { | ||
return { | ||
cache: getLruCache<string>(config.cacheSize), | ||
...createPrefixUtils(config), | ||
...createClassUtils(config), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
const customValueRegex = /^\[(.+)\]$/; | ||
const fractionRegex = /^\d+\/\d+$/; | ||
const stringLengths = new Set(["px", "full", "screen"]); | ||
const lengthUnitRegex = | ||
/\d+(%|px|em|rem|vh|vw|pt|pc|in|cm|mm|cap|ch|ex|lh|rlh|vi|vb|vmin|vmax)/; | ||
|
||
export function isLength(classPart: string) { | ||
return ( | ||
isCustomLength(classPart) || | ||
!Number.isNaN(Number(classPart)) || | ||
stringLengths.has(classPart) || | ||
fractionRegex.test(classPart) | ||
); | ||
} | ||
|
||
export function isCustomLength(classPart: string) { | ||
const customValue = customValueRegex.exec(classPart)?.[1]; | ||
|
||
if (customValue) { | ||
return ( | ||
customValue.startsWith("length:") || lengthUnitRegex.test(customValue) | ||
); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
export function isInteger(classPart: string) { | ||
const customValue = customValueRegex.exec(classPart)?.[1]; | ||
|
||
if (customValue) { | ||
return Number.isInteger(Number(customValue)); | ||
} | ||
|
||
return Number.isInteger(Number(classPart)); | ||
} | ||
|
||
export function isCustomValue(classPart: string) { | ||
return customValueRegex.test(classPart); | ||
} | ||
|
||
export function isAny() { | ||
return true; | ||
} |
Oops, something went wrong.
690a400
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: