Skip to content

Commit

Permalink
feat: add initial variant sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
lutaok committed Jun 13, 2024
1 parent 0adbdfe commit b797e78
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
//! - The list of variants, in order of importance (which is used to compute the variants weight).
//! - Other options, such as prefix and separator.

use std::cmp::Ordering;

use bitvec::{order::Lsb0, vec::BitVec};

use super::{
class_lexer::{tokenize_class, ClassSegmentStructure},
sort_config::SortConfig,
Expand Down Expand Up @@ -284,7 +288,7 @@ pub struct ClassInfo {
/// The full text of the class itself.
pub text: String,
/// The total variants weight that results from the combination of all the variants.
pub variant_weight: Option<u64>, // TODO: this will need to be Option<bitvec>
pub variant_weight: Option<BitVec<u8, Lsb0>>,
/// The layer the utility belongs to.
pub layer_index: usize,
/// The index of the utility within the layer.
Expand All @@ -296,14 +300,53 @@ pub struct ClassInfo {
pub fn get_class_info(class_name: &str, sort_config: &SortConfig) -> Option<ClassInfo> {
let utility_data = tokenize_class(class_name)?;
let utility_info = get_utility_info(sort_config.utilities, &utility_data.utility);

if let Some(utility_info) = utility_info {
return Some(ClassInfo {
text: class_name.to_string(),
variant_weight: if utility_data.variants.is_empty() {
None
} else {
// TODO: return None if there is an unknown variant.
Some(0) // TODO: actually compute variant weight
let known_variants = utility_data.variants.iter().any(|variant| {
sort_config
.variants
.iter()
.any(|item| *item.name.to_string() == variant.text)
});
// If there's a custom variant, their weight isn't important
if !known_variants {
return None;
}

// Compute Variants Weight as the BitWise XOR of all the weights
// Variants in SortConfig are already sorted when the file is generated
let variants_weight: BitVec<u8, Lsb0> =
utility_data
.variants
.iter()
.fold(BitVec::<u8, Lsb0>::new(), |acc, curr| {
if let Some(variant) = sort_config
.variants
.iter()
.find(|&item| *item.name.to_string() == curr.text)
{
let mut accumulator = acc.clone();
let mut current_weight = variant.weight.clone();
let acc_len = accumulator.len();
let current_weight_len = current_weight.len();

match acc_len.cmp(&current_weight_len) {
Ordering::Less => accumulator.resize(current_weight_len, false),
Ordering::Greater => current_weight.resize(acc_len, false),
_ => (),
}

return accumulator ^ current_weight;
}
acc
});

Some(variants_weight)
},
layer_index: *sort_config.layer_index_map.get(&utility_info.layer)?,
utility_index: utility_info.index,
Expand All @@ -316,21 +359,24 @@ pub fn get_class_info(class_name: &str, sort_config: &SortConfig) -> Option<Clas
#[cfg(test)]
mod get_class_info_tests {
use super::*;
use crate::lint::nursery::use_sorted_classes::sort_config::UtilityLayer;
use crate::lint::nursery::use_sorted_classes::{
sort_config::UtilityLayer, tailwind_preset::get_variant_classes,
};

#[test]
fn test_get_class_info() {
const UTILITIES_CONFIG: [UtilityLayer; 2] = [
UtilityLayer {
name: "layer0",
classes: &["px-", "py-", "block$"],
classes: &["px-", "py-", "block$", "bg-"],
},
UtilityLayer {
name: "layer1",
classes: &["mx-", "my-", "inline$"],
},
];
let sort_config = SortConfig::new(UTILITIES_CONFIG.as_slice(), vec![]);
let variant_classes = get_variant_classes();
let sort_config = SortConfig::new(UTILITIES_CONFIG.as_slice(), variant_classes);
assert_eq!(
get_class_info("px-2", &sort_config),
Some(ClassInfo {
Expand Down Expand Up @@ -394,6 +440,25 @@ mod get_class_info_tests {
utility_index: 0,
})
);
// TODO: Add Variants tests
// assert_eq!(
// get_class_info("hover:bg-red-500", &sort_config),
// Some(ClassInfo {
// text: "hover:bg-red-500".to_string(),
// variant_weight: None, // TODO: Should we hardcode the bitvector or should we find it from the tailwind config?
// layer_index: 0,
// utility_index: 3
// })
// );
// assert_eq!(
// get_class_info("hover:focus:bg-yellow-600", &sort_config),
// Some(ClassInfo {
// text: "hover:focus:bg-yellow-600".to_string(),
// variant_weight: None, // TODO: Should we hardcode the bitvector or should we find it from the tailwind config?
// layer_index: 0,
// utility_index: 3
// })
// );
assert_eq!(get_class_info("unknown", &sort_config), None);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,21 @@ impl ClassInfo {
None
}

/// Compare based on variants weight. Classes with higher weight go first.
/// Compare based on variants weight. Classes with lower weight go first.
/// First compare variants weight length. Only if their equal compare their actual weight.
/// Returns `None` if they have the same weight.
fn cmp_variants_weight(&self, _other: &ClassInfo) -> Option<Ordering> {
// TODO: implement variant weight comparison.
fn cmp_variants_weight(&self, other: &ClassInfo) -> Option<Ordering> {
let current_weight = self.variant_weight.clone()?;
let other_weight = other.variant_weight.clone()?;

let mut result = current_weight.len().cmp(&other_weight.len());
if result == Ordering::Equal {
result = current_weight.cmp(&other_weight);
}

if result != Ordering::Equal {
return Some(result);
}
None
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
<div class="custom-text foo my-2 font-semibold text-2xl underline" />
<div class="custom-container bar flex-wrap items-start justify-between bg-purple-200 p-5 text-purple-700" />
<div class="custom-border gap-8 border-indigo-500 border-l-4 bg-indigo-100 p-3 text-indigo-900" />
{/* variant sorting */}
<div class="custom-style1 foo p-4 shadow-lg checked:text-center hover:bg-blue-500 focus:text-white hover:focus:rounded-lg" />
<div class="custom-layout bar flex items-center font-bold first-letter:text-lg required:justify-center valid:h-screen valid:required:bg-gray-200" />
<div class="custom-grid m-6 grid grid-cols-3 gap-4 p-6 optional:rounded-md focus-within:border focus-within:border-gray-300 focus-within:hover:shadow-md" />
<div class="lg:custom-alert sm:top-0 sm:rounded-full sm:bg-red-600 sm:text-white md:right-0 md:p-2 lg:absolute lg:m-4 xl:text-sm" />
<div class="bar custom-button rounded border p-2 checked:sm:inline-block sm:checked:border-green-500 hover:md:bg-green-300 hover:lg:text-green-800" />
{/* TODO: arbitrary variant */}
</>;

// functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ expression: sorted.jsx
<div class="custom-text foo my-2 font-semibold text-2xl underline" />
<div class="custom-container bar flex-wrap items-start justify-between bg-purple-200 p-5 text-purple-700" />
<div class="custom-border gap-8 border-indigo-500 border-l-4 bg-indigo-100 p-3 text-indigo-900" />
{/* variant sorting */}
<div class="custom-style1 foo p-4 shadow-lg checked:text-center hover:bg-blue-500 focus:text-white hover:focus:rounded-lg" />
<div class="custom-layout bar flex items-center font-bold first-letter:text-lg required:justify-center valid:h-screen valid:required:bg-gray-200" />
<div class="custom-grid m-6 grid grid-cols-3 gap-4 p-6 optional:rounded-md focus-within:border focus-within:border-gray-300 focus-within:hover:shadow-md" />
<div class="lg:custom-alert sm:top-0 sm:rounded-full sm:bg-red-600 sm:text-white md:right-0 md:p-2 lg:absolute lg:m-4 xl:text-sm" />
<div class="bar custom-button rounded border p-2 checked:sm:inline-block sm:checked:border-green-500 hover:md:bg-green-300 hover:lg:text-green-800" />
{/* TODO: arbitrary variant */}
</>;

// functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
<div class="underline custom-text foo text-2xl font-semibold my-2" />
<div class="flex-wrap custom-container justify-between items-start bar bg-purple-200 p-5 text-purple-700" />
<div class="gap-8 bg-indigo-100 text-indigo-900 p-3 border-l-4 border-indigo-500 custom-border" />
{/* variant sorting */}
{/* SHOULD emit diagnostics (arbitrary variants not supported yet) */}
<div class="checked:text-center custom-style1 p-4 hover:bg-blue-500 focus:text-white foo hover:focus:rounded-lg shadow-lg" />
<div class="flex valid:required:bg-gray-200 custom-layout items-center required:justify-center valid:h-screen bar first-letter:text-lg font-bold" />
<div class="focus-within:hover:shadow-md grid custom-grid grid-cols-3 gap-4 p-6 m-6 focus-within:border focus-within:border-gray-300 optional:rounded-md" />
<div class="lg:absolute sm:top-0 md:right-0 lg:m-4 md:p-2 xl:text-sm sm:bg-red-600 sm:text-white sm:rounded-full lg:custom-alert" />
<div class="checked:sm:inline-block bar hover:md:bg-green-300 hover:lg:text-green-800 p-2 rounded border sm:checked:border-green-500 custom-button" />
{/* TODO: arbitrary variant */}
</>;

// functions
Expand Down
Loading

0 comments on commit b797e78

Please sign in to comment.