feat: robust metric extraction with confidence score and proof snippets
- fixed Year-Prefix Bug in MetricParser - added metric_confidence and metric_proof_text to database - added Entity-Check and Annual-Priority to LLM prompt - improved UI: added confidence traffic light and mouse-over proof tooltip - restored missing API endpoints (create, bulk, wiki-override)
This commit is contained in:
214
company-explorer/frontend/node_modules/tailwind-merge/src/lib/class-group-utils.ts
generated
vendored
Normal file
214
company-explorer/frontend/node_modules/tailwind-merge/src/lib/class-group-utils.ts
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
import {
|
||||
AnyClassGroupIds,
|
||||
AnyConfig,
|
||||
AnyThemeGroupIds,
|
||||
ClassGroup,
|
||||
ClassValidator,
|
||||
Config,
|
||||
ThemeGetter,
|
||||
ThemeObject,
|
||||
} from './types'
|
||||
|
||||
export interface ClassPartObject {
|
||||
nextPart: Map<string, ClassPartObject>
|
||||
validators: ClassValidatorObject[]
|
||||
classGroupId?: AnyClassGroupIds
|
||||
}
|
||||
|
||||
interface ClassValidatorObject {
|
||||
classGroupId: AnyClassGroupIds
|
||||
validator: ClassValidator
|
||||
}
|
||||
|
||||
const CLASS_PART_SEPARATOR = '-'
|
||||
|
||||
export const createClassGroupUtils = (config: AnyConfig) => {
|
||||
const classMap = createClassMap(config)
|
||||
const { conflictingClassGroups, conflictingClassGroupModifiers } = config
|
||||
|
||||
const 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) || getGroupIdForArbitraryProperty(className)
|
||||
}
|
||||
|
||||
const getConflictingClassGroupIds = (
|
||||
classGroupId: AnyClassGroupIds,
|
||||
hasPostfixModifier: boolean,
|
||||
) => {
|
||||
const conflicts = conflictingClassGroups[classGroupId] || []
|
||||
|
||||
if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) {
|
||||
return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]!]
|
||||
}
|
||||
|
||||
return conflicts
|
||||
}
|
||||
|
||||
return {
|
||||
getClassGroupId,
|
||||
getConflictingClassGroupIds,
|
||||
}
|
||||
}
|
||||
|
||||
const getGroupRecursive = (
|
||||
classParts: string[],
|
||||
classPartObject: ClassPartObject,
|
||||
): AnyClassGroupIds | undefined => {
|
||||
if (classParts.length === 0) {
|
||||
return classPartObject.classGroupId
|
||||
}
|
||||
|
||||
const currentClassPart = classParts[0]!
|
||||
const nextClassPartObject = classPartObject.nextPart.get(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
|
||||
}
|
||||
|
||||
const arbitraryPropertyRegex = /^\[(.+)\]$/
|
||||
|
||||
const getGroupIdForArbitraryProperty = (className: string) => {
|
||||
if (arbitraryPropertyRegex.test(className)) {
|
||||
const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)![1]
|
||||
const property = arbitraryPropertyClassName?.substring(
|
||||
0,
|
||||
arbitraryPropertyClassName.indexOf(':'),
|
||||
)
|
||||
|
||||
if (property) {
|
||||
// I use two dots here because one dot is used as prefix for class groups in plugins
|
||||
return 'arbitrary..' + property
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exported for testing only
|
||||
*/
|
||||
export const createClassMap = (config: Config<AnyClassGroupIds, AnyThemeGroupIds>) => {
|
||||
const { theme, prefix } = config
|
||||
const classMap: ClassPartObject = {
|
||||
nextPart: new Map<string, ClassPartObject>(),
|
||||
validators: [],
|
||||
}
|
||||
|
||||
const prefixedClassGroupEntries = getPrefixedClassGroupEntries(
|
||||
Object.entries(config.classGroups),
|
||||
prefix,
|
||||
)
|
||||
|
||||
prefixedClassGroupEntries.forEach(([classGroupId, classGroup]) => {
|
||||
processClassesRecursively(classGroup, classMap, classGroupId, theme)
|
||||
})
|
||||
|
||||
return classMap
|
||||
}
|
||||
|
||||
const processClassesRecursively = (
|
||||
classGroup: ClassGroup<AnyThemeGroupIds>,
|
||||
classPartObject: ClassPartObject,
|
||||
classGroupId: AnyClassGroupIds,
|
||||
theme: ThemeObject<AnyThemeGroupIds>,
|
||||
) => {
|
||||
classGroup.forEach((classDefinition) => {
|
||||
if (typeof classDefinition === 'string') {
|
||||
const classPartObjectToEdit =
|
||||
classDefinition === '' ? classPartObject : getPart(classPartObject, classDefinition)
|
||||
classPartObjectToEdit.classGroupId = classGroupId
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof classDefinition === 'function') {
|
||||
if (isThemeGetter(classDefinition)) {
|
||||
processClassesRecursively(
|
||||
classDefinition(theme),
|
||||
classPartObject,
|
||||
classGroupId,
|
||||
theme,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
classPartObject.validators.push({
|
||||
validator: classDefinition,
|
||||
classGroupId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Object.entries(classDefinition).forEach(([key, classGroup]) => {
|
||||
processClassesRecursively(
|
||||
classGroup,
|
||||
getPart(classPartObject, key),
|
||||
classGroupId,
|
||||
theme,
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const getPart = (classPartObject: ClassPartObject, path: string) => {
|
||||
let currentClassPartObject = classPartObject
|
||||
|
||||
path.split(CLASS_PART_SEPARATOR).forEach((pathPart) => {
|
||||
if (!currentClassPartObject.nextPart.has(pathPart)) {
|
||||
currentClassPartObject.nextPart.set(pathPart, {
|
||||
nextPart: new Map(),
|
||||
validators: [],
|
||||
})
|
||||
}
|
||||
|
||||
currentClassPartObject = currentClassPartObject.nextPart.get(pathPart)!
|
||||
})
|
||||
|
||||
return currentClassPartObject
|
||||
}
|
||||
|
||||
const isThemeGetter = (func: ClassValidator | ThemeGetter): func is ThemeGetter =>
|
||||
(func as ThemeGetter).isThemeGetter
|
||||
|
||||
const getPrefixedClassGroupEntries = (
|
||||
classGroupEntries: Array<[classGroupId: string, classGroup: ClassGroup<AnyThemeGroupIds>]>,
|
||||
prefix: string | undefined,
|
||||
): Array<[classGroupId: string, classGroup: ClassGroup<AnyThemeGroupIds>]> => {
|
||||
if (!prefix) {
|
||||
return classGroupEntries
|
||||
}
|
||||
|
||||
return classGroupEntries.map(([classGroupId, classGroup]) => {
|
||||
const prefixedClassGroup = classGroup.map((classDefinition) => {
|
||||
if (typeof classDefinition === 'string') {
|
||||
return prefix + classDefinition
|
||||
}
|
||||
|
||||
if (typeof classDefinition === 'object') {
|
||||
return Object.fromEntries(
|
||||
Object.entries(classDefinition).map(([key, value]) => [prefix + key, value]),
|
||||
)
|
||||
}
|
||||
|
||||
return classDefinition
|
||||
})
|
||||
|
||||
return [classGroupId, prefixedClassGroup]
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user