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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3aa2748d158cbcc46f8db818a6f1dbf5c0f3b210f03b48b96b178ee4e8d4c25c
4
- data.tar.gz: fae3b047cf0136529135c371bae6ecdf4172bdb7f96bed1e16821a41decc9343
3
+ metadata.gz: '09136ec0a7747e58715fc95aae08f3c81599247202a152bc3b21c85217b5dbad'
4
+ data.tar.gz: b4313ed6f949a48149d1e417e88c84bd026dd9791197f68f0137c2217e5798fb
5
5
  SHA512:
6
- metadata.gz: ec9ef9dc0dc7f40e77fbc5ae416abdf1054a959465e5cbd22a86ecefbc6b86454ef4c416833b8c35dbc41749c5fbfa9d8b10a9e1720dba741d1ee51742d68f8d
7
- data.tar.gz: c9210f053328369aa0b25a3e9f14f87a011b84c85f33f65d2a8e5962efccb7a83698cba71b824cc522469f596da2eab7c0701bd931ba0de088620cada7192914
6
+ metadata.gz: 8a797eafd289cc37273f8ebf323241f6245f9a90337dc2c9b9841d279ec7eac957b492ed974b4a4c9bc824485dd057722fc2191ff04d9bddeff6ec3b50b85f43
7
+ data.tar.gz: 7e52a4c5a9b2d763228aab6930895742a2f2dddfbbb2581fb6d8b31dfd719bcb85b75d86a43976f45b65d22dadd6527187a771744a432d808fe24c241c11694a
@@ -1,33 +1,126 @@
1
- use magnus::{define_module, function, prelude::*, Error, RArray, RString, Value};
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(arg: Value) -> Result<RString, Error> {
5
- let mut class_strings = Vec::new();
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
- if let Ok(rstring) = arg.clone().try_convert::<RString>() {
8
- // If it's a string, split on spaces
9
- let s = rstring.to_string()?;
10
- class_strings.extend(s.split_whitespace().map(|s| s.to_string()));
11
- } else if let Ok(rarray) = arg.try_convert::<RArray>() {
12
- // If it's an array, process as before
13
- for arg in rarray.each() {
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
- return Err(Error::new(
19
- magnus::exception::type_error(),
20
- "Expected String or Array of Strings as argument",
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
- let merged = tw_merge(class_strings.join(" "));
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
- module.define_singleton_method("merge", function!(merge_tailwind_classes, 1))?;
123
+ // -1 = variable arity (positional + kw-hash)
124
+ module.define_singleton_method("merge", function!(merge_tailwind_classes, -1))?;
32
125
  Ok(())
33
126
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TailMerge
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tail_merge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Achilleas Buisman