css_knife/
short_classes.rs1use std::{
2 cmp::Ordering,
3 collections::{btree_map::Entry, BTreeMap},
4 fs,
5};
6
7use lightningcss::stylesheet::{PrinterOptions, StyleSheet};
8
9type OneClass = [u8; 5];
10
11pub enum CSSToken {
12 Class,
13 CustomProperty,
14}
15
16#[derive(Default, Clone, PartialEq, Eq)]
17pub struct ClassContainer {
18 class_name: [ClassIter; 2],
19 container: [BTreeMap<String, String>; 2],
20}
21
22impl Default for ClassIter {
23 fn default() -> Self {
24 ClassIter {
25 array: [1, 0, 0, 0, 0],
26 current_index: 0,
27 }
28 }
29}
30
31impl ClassContainer {
32 pub fn add(&mut self, key: String, token: CSSToken) -> Option<String> {
33 let index = token as usize;
34 if let Some(map) = self.container.get_mut(index) {
35 let oldclass = css_to_html(&key);
36 match map.entry(oldclass) {
37 Entry::Vacant(entry) => {
38 if let Some(new) = self.class_name[index].next() {
39 return Some(entry.insert(new_class(&new)).to_string());
40 }
41 }
42 Entry::Occupied(entry) => {
43 return Some(entry.get().clone());
44 }
45 }
46 }
47 None
48 }
49
50 pub fn get(&self, key: String, container: CSSToken) -> Option<String> {
51 let index = container as usize;
52 if let Some(map) = self.container.get(index) {
53 if let Some(v) = map.get(&key) {
54 return Some(v.to_string());
55 }
56 }
57 None
58 }
59
60 pub fn into_file(&self, stylesheet: StyleSheet) {
61 let opt = PrinterOptions {
62 minify: true,
63 ..Default::default()
64 };
65 if let Ok(f) = stylesheet.to_css(opt) {
66 let _ = fs::write("src/output.css", f.code);
67 }
68 }
69}
70
71#[derive(Clone, PartialEq, Eq)]
72pub struct ClassIter {
73 array: OneClass,
74 current_index: usize,
75}
76
77impl ClassIter {}
78
79impl Iterator for ClassIter {
80 type Item = OneClass;
81
82 fn next(&mut self) -> Option<Self::Item> {
83 let current = self.array;
84 self.array[self.current_index] += 1;
85 if self.array[self.current_index] == 27 {
86 self.array[self.current_index] = 1;
87 let mut add_new = true;
88 for i in (0..self.current_index).rev() {
89 let v = self.array[i];
90 match v.cmp(&26) {
91 Ordering::Less => {
92 add_new = false;
93 self.array[i] += 1;
94 self.array[self.current_index] = 1;
95 break;
96 }
97 Ordering::Equal => {
98 self.array[i] = 1;
99 }
100 Ordering::Greater => (),
101 }
102 }
103 if add_new {
104 if self.current_index == 4 {
105 return None;
106 }
107
108 for i in (0..self.current_index).rev() {
109 self.array[i] = 1;
110 }
111
112 self.current_index += 1;
113 self.array[self.current_index] = 1;
114 }
115 }
116 Some(current)
117 }
118}
119
120fn css_to_html(old: &str) -> String {
121 if old.starts_with('.') {
122 let mut chars = old.chars();
123 chars.next();
124 chars.as_str().replace('\\', "")
125 } else {
126 String::from(old)
127 }
128}
129
130fn new_class(new_class: &OneClass) -> String {
131 let mut s = String::new();
132 for i in new_class {
133 if i == &0 {
134 break;
135 }
136 let c = 96_u8 + i;
137 s.push(c as char);
138 }
139 s
140}