tail_merge 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/tail_merge/src/lib.rs +111 -18
- data/lib/tail_merge/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09136ec0a7747e58715fc95aae08f3c81599247202a152bc3b21c85217b5dbad'
|
4
|
+
data.tar.gz: b4313ed6f949a48149d1e417e88c84bd026dd9791197f68f0137c2217e5798fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a797eafd289cc37273f8ebf323241f6245f9a90337dc2c9b9841d279ec7eac957b492ed974b4a4c9bc824485dd057722fc2191ff04d9bddeff6ec3b50b85f43
|
7
|
+
data.tar.gz: 7e52a4c5a9b2d763228aab6930895742a2f2dddfbbb2581fb6d8b31dfd719bcb85b75d86a43976f45b65d22dadd6527187a771744a432d808fe24c241c11694a
|
data/ext/tail_merge/src/lib.rs
CHANGED
@@ -1,33 +1,126 @@
|
|
1
|
-
use magnus::{
|
1
|
+
use magnus::{
|
2
|
+
define_module, function, prelude::*, Error, RArray, RHash, RString, Ruby, Value,
|
3
|
+
};
|
2
4
|
use rustui_merge::merge::tw_merge;
|
3
5
|
|
4
|
-
fn merge_tailwind_classes(
|
5
|
-
|
6
|
+
fn merge_tailwind_classes(args: &[Value]) -> Result<RString, Error> {
|
7
|
+
// ---------- 1. arity ----------------------------------------------------
|
8
|
+
if args.is_empty() || args.len() > 2 {
|
9
|
+
return Err(Error::new(
|
10
|
+
magnus::exception::arg_error(),
|
11
|
+
"wrong number of arguments (expected 1 or 2)",
|
12
|
+
));
|
13
|
+
}
|
14
|
+
|
15
|
+
// ---------- 2. collect class tokens ------------------------------------
|
16
|
+
let mut tokens = Vec::<String>::new();
|
17
|
+
let is_string_input = matches!(args[0].clone().try_convert::<RString>(), Ok(_));
|
18
|
+
match args[0].clone().try_convert::<RString>() {
|
19
|
+
Ok(rstr) => tokens.extend(rstr.to_string()?.split_whitespace().map(str::to_owned)),
|
20
|
+
Err(_) => {
|
21
|
+
let rarray: RArray = args[0].try_convert()?;
|
22
|
+
for v in rarray.each() {
|
23
|
+
let s: RString = v?.try_convert()?;
|
24
|
+
tokens.push(s.to_string()?);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
6
28
|
|
7
|
-
|
8
|
-
|
9
|
-
let
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
let rstring: RString = arg?.try_convert()?;
|
15
|
-
class_strings.push(rstring.to_string()?);
|
29
|
+
// Early returns for simple cases
|
30
|
+
if is_string_input {
|
31
|
+
let rstr: RString = args[0].clone().try_convert()?;
|
32
|
+
let s = rstr.to_string()?;
|
33
|
+
if !s.contains(' ') {
|
34
|
+
// Single class string, return as-is
|
35
|
+
return Ok(RString::new(&s));
|
16
36
|
}
|
17
37
|
} else {
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
38
|
+
// Array input
|
39
|
+
if tokens.is_empty() {
|
40
|
+
return Ok(RString::new(""));
|
41
|
+
}
|
42
|
+
if tokens.len() == 1 {
|
43
|
+
return Ok(RString::new(&tokens[0]));
|
44
|
+
}
|
22
45
|
}
|
23
46
|
|
24
|
-
|
47
|
+
// ---------- 3. extract options -----------------------------------------
|
48
|
+
let mut prefix: Option<String> = None;
|
49
|
+
let mut separator: Option<String> = None;
|
50
|
+
|
51
|
+
if args.len() == 2 {
|
52
|
+
let rhash: RHash = args[1].try_convert()?;
|
53
|
+
let ruby = Ruby::get().unwrap();
|
54
|
+
|
55
|
+
if let Some(v) = rhash.get(ruby.to_symbol("prefix")) {
|
56
|
+
let s: RString = v.try_convert()?;
|
57
|
+
prefix = Some(s.to_string()?);
|
58
|
+
}
|
59
|
+
if let Some(v) = rhash.get(ruby.to_symbol("separator")) {
|
60
|
+
let s: RString = v.try_convert()?;
|
61
|
+
separator = Some(s.to_string()?);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
// ---------- 4. merge ----------------------------------------------------
|
66
|
+
let merged = if let Some(pref) = prefix {
|
67
|
+
// split based on whether the last segment starts with the prefix
|
68
|
+
let mut with_pref = Vec::new();
|
69
|
+
let mut without_pref = Vec::new();
|
70
|
+
|
71
|
+
for t in tokens {
|
72
|
+
let base = t.rsplit_once(':').map(|(_, b)| b).unwrap_or(&t);
|
73
|
+
if base.starts_with(&pref) {
|
74
|
+
// strip prefix after variant(s)
|
75
|
+
let stripped = if let Some((v, b)) = t.rsplit_once(':') {
|
76
|
+
format!("{}:{}", v, &b[pref.len()..])
|
77
|
+
} else {
|
78
|
+
(&t[pref.len()..]).to_owned()
|
79
|
+
};
|
80
|
+
with_pref.push(stripped);
|
81
|
+
} else {
|
82
|
+
without_pref.push(t);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
let mut out = Vec::new();
|
87
|
+
if !without_pref.is_empty() {
|
88
|
+
out.extend(
|
89
|
+
tw_merge(without_pref.join(" "))
|
90
|
+
.split_whitespace()
|
91
|
+
.map(str::to_owned),
|
92
|
+
);
|
93
|
+
}
|
94
|
+
if !with_pref.is_empty() {
|
95
|
+
out.extend(
|
96
|
+
tw_merge(with_pref.join(" "))
|
97
|
+
.split_whitespace()
|
98
|
+
.map(|s| {
|
99
|
+
// re-attach prefix
|
100
|
+
if let Some((v, b)) = s.rsplit_once(':') {
|
101
|
+
format!("{}:{}{}", v, &pref, b)
|
102
|
+
} else {
|
103
|
+
format!("{}{}", pref, s)
|
104
|
+
}
|
105
|
+
}),
|
106
|
+
);
|
107
|
+
}
|
108
|
+
out.join(" ")
|
109
|
+
} else if separator.is_some() {
|
110
|
+
// at the moment we can't apply per-call separators without global state;
|
111
|
+
// fall back to the default behaviour.
|
112
|
+
tw_merge(tokens.join(" "))
|
113
|
+
} else {
|
114
|
+
tw_merge(tokens.join(" "))
|
115
|
+
};
|
116
|
+
|
25
117
|
Ok(RString::new(&merged))
|
26
118
|
}
|
27
119
|
|
28
120
|
#[magnus::init]
|
29
121
|
fn init() -> Result<(), Error> {
|
30
122
|
let module = define_module("TailMerge")?;
|
31
|
-
|
123
|
+
// -1 = variable arity (positional + kw-hash)
|
124
|
+
module.define_singleton_method("merge", function!(merge_tailwind_classes, -1))?;
|
32
125
|
Ok(())
|
33
126
|
}
|
data/lib/tail_merge/version.rb
CHANGED