tailwind-sorter 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef76f37afeb8183be5169a62f202a8082ed9eef254165dd5deafe69938c98a8c
4
- data.tar.gz: fd691f852943aa5a25e0f610b4bdd09c2292521bf17abb2c88d2fe05e97b9179
3
+ metadata.gz: 82b25d2e48c760db25e242cafa14a986831e6ccaff1498ea7fbf638dc22392d9
4
+ data.tar.gz: dc94b034b7e7922bafc9f618a7db6f839d102eb2c38f916689f538fcfab07d2c
5
5
  SHA512:
6
- metadata.gz: 39bf625392ad648e2d7d6ca313d7c76b80ee5d930eff7cdc5582d0d65d4da7ac2932f4b94010077b19c0f1d93cdc7ce5e06e1830b19fe935ecd6a98b88dd8a76
7
- data.tar.gz: 1c60d0526b8afe14a14abf6de9a57948e350cc742cc1fda88b2c82068014f65860e9c98a046655d14f333b28d181feeeff9275858354c02484a2df2b3a9755ea
6
+ metadata.gz: 95a45a46c6a5911db7bd2e48fde99b7a752f2de25bc5832b009c0fe5d840912474be6047caf2f7ecb3d2325e894c466bab4ff9f32f71fe88506448ff204bb74c
7
+ data.tar.gz: 98a11cdfd1bebff6fd7a8a24069326dc26776dffdcb4b37f8271374793c04133823ebd2c3375c5a6192cec5f5f68ac0b61e9322be9757658b102d32898f02358
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ ### 0.4.0
2
+
3
+ - Add support for regular expressions in configuration for class ordering (#3)
4
+
5
+ So instead of having to specify all variants of a certain Tailwind class, now you can cover all of them with a
6
+ regular expression.
7
+ - Cache sorting keys during processing (speeds up sorting a file with repeating CSS classes).
8
+ - Fix LOAD_PATH issues when running tests (#2).
9
+ - Add Github Action for tests, enhance tests.
10
+ - Require ruby 3.1+.
11
+
12
+ ### 0.3.1
13
+
14
+ Return warnings when called from ruby code in warn_only mode.
15
+
16
+ ### 0.3.0
17
+
18
+ First public release of the gemified version of Tailwind sorter.
19
+
20
+ ### 0.0.0 - the original script
21
+
22
+ The repository with the bare-bones sorter script can be found here: https://github.com/NejRemeslnici/tailwind-sorter/tree/original-script
data/README.md CHANGED
@@ -12,8 +12,11 @@ The gem contains a standalone executable script that can work in two ways:
12
12
  Out of the box the script supports sorting classes in [Slim templates](http://slim-lang.com/) but can be configured for
13
13
  anything else. The script also removes duplicate classes.
14
14
 
15
- _This is what it looks like when Tailwind sorter is auto-run upon saving a changed template file in the RubyMine IDE:_
16
- <img src="img/tailwind_sorter_intro.gif" alt="Automatically ordering CSS classes upon file saving"></img>
15
+ _This is what it looks like when Tailwind sorter is auto-run upon saving a changed template file in VS Code:_
16
+ <img src="img/tailwind_sorter_vscode.gif" alt="Automatically ordering CSS classes upon file saving in VS Code"></img>
17
+
18
+ _And similarly in RubyMine IDE:_
19
+ <img src="img/tailwind_sorter_rubymine.gif" alt="Automatically ordering CSS classes upon file saving in RubyMine"></img>
17
20
 
18
21
  Please read the [accompanying post on dev.to](https://dev.to/nejremeslnici/tailwind-css-class-sorter-the-custom-way-35g5) for more details, if interested.
19
22
 
@@ -37,12 +40,11 @@ solution. This problem is even larger if you’ve added
37
40
  [custom utility classes](https://tailwindcss.com/docs/adding-new-utilities) to your project.
38
41
 
39
42
  Above all, it is **surprisingly easy** to create a custom sorting script – the one we use and present here is only
40
- ~110 lines. So, take this script and config as a **template for you to revise and adapt**.
43
+ ~150 lines. So, take this script and especially its config as a **template for you to revise and adapt**.
41
44
 
42
45
  ## Installation
43
46
 
44
- Since version 0.3, the script has been packed into a gem so that it can be used directly from ruby as well as a standalone script (now a binstub). If you just want to grab the original ruby script, have a look at the [`original-script` tag](https://github.com/NejRemeslnici/tailwind-sorter/tree/original-script).
45
-
47
+ Since version 0.3, the script has been packed into a gem so that it can be used directly from ruby as well as a standalone script (now a binstub).
46
48
 
47
49
  ### Installing the gem
48
50
 
@@ -69,7 +71,7 @@ $ bundle binstubs tailwind-sorter
69
71
 
70
72
  This will create a `bin/tailwind_sorter` binstub file.
71
73
 
72
- The gem has **no dependencies**, apart from ruby (tested on ruby 3.0+) and its stdlib.
74
+ The gem has **no dependencies**, apart from ruby (tested on ruby 3.1+) and its stdlib.
73
75
 
74
76
  ## Configuration
75
77
 
@@ -78,28 +80,61 @@ configured.
78
80
 
79
81
  There are two important places to configure in the YAML file:
80
82
 
81
- - **regular expressions** to match the classes in your files: out of the box, the script matches classes in the Slim
82
- format (such as `section#flash-messages.hidden.mt-4`) and classes in the context of the `class` attribute in ruby /
83
- Rails helpers (`link_to "E-shop", eshop_path, class: "no-underline font-bold red-100")`,
83
+ - **regular expressions** that tell the Tailwind sorter where to find CSS classes to sort: out of the box, the script
84
+ matches classes in the Slim format (such as `section#flash-messages.hidden.mt-4`) and classes in the context of the
85
+ `class` attribute in ruby / Rails helpers (`link_to "E-shop", eshop_path, class: "no-underline font-bold red-100")`,
84
86
 
85
87
  - **CSS classes order and grouping**: the `classes_order` section in the YAML file determines the order in which the
86
88
  classes will be sorted. If you want the classes with Tailwind variants (such as `sm:`, `hover:` etc.) to always be
87
89
  ordered towards the end of line, put the classes in one big group, otherwise split them into any groups you want and
88
90
  they will be ordered last in the particular group.
89
91
 
90
- Unknown (i.e. custom) classes will be **ordered first by default**. If you want them ordered last, you'll have to resort to using the original script and replacing the [`default_index`](https://github.com/NejRemeslnici/tailwind-sorter/blob/original-script/bin/tailwind_sorter.rb#L20) parameter in it with a big-enough number. We recommend ordering custom classes first though as in our opinion such classes usually bear more important meanings than the Tailwind ones and this setup also makes it easier to spot typos in class names.
92
+ You have two options when specifying classes in this config section: pure strings and regular expressions:
93
+
94
+ - You can always just **list the CSS class names** in the config. This style gives you a full control over the ordering and it is the fastest option as well. The downside of it is that you'll find yourself having to update the config more often as new Tailwind classes variants emerge in your project and / or Tailwind itself:
95
+
96
+ ```yaml
97
+ classes_order:
98
+ spacing:
99
+ ...
100
+ - py-2
101
+ - py-4
102
+ - py-8
103
+ ...
104
+ ```
105
+
106
+ - Or, you can use **regular expressions** to cover all variants of a Tailwind class at once. A regular expression in
107
+ this part of the config is specified as a string delimited by slashes. Note that the
108
+ [`\A` and `\z` boundaries](https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label-Boundary+Anchors) are
109
+ automatically added to the expression so that it always matches the whole class name, not just part of it. Using regular expressions to sort classes shortens your configuration greatly but makes it a bit harder to understand.
110
+
111
+ ```yaml
112
+ classes_order:
113
+ spacing:
114
+ ...
115
+ - /py-\d+/
116
+ ...
117
+ ```
118
+
119
+ - And, of course, you can also freely mix these two approaches.
120
+
121
+ Unknown (e.g. your custom) classes will be **ordered first**. If you want to sort them differently, you will have to add them
122
+ to the config file to their proper place under `classes_order`. We recommend ordering custom classes first though as in
123
+ our opinion such classes usually bear more important meanings than the Tailwind ones and this setup also makes it easier
124
+ to spot typos in class names.
91
125
 
92
- The default sort order of the classes resembles the one of Headwind which, in turn, seems to be inspired by the order of
93
- the sections in the [official Tailwind documentation](https://tailwindcss.com/docs).
126
+ The default sort order of the classes in the bundled config file resembles the one of Headwind which, in turn, seems to
127
+ be inspired by the order of the sections in the [official Tailwind documentation](https://tailwindcss.com/docs).
94
128
 
95
- More details about the configuration file can be found in [the wiki](https://github.com/NejRemeslnici/tailwind-sorter/wiki/The-config-file-explanation).
129
+ More details about the configuration file can be found in
130
+ [the wiki](https://github.com/NejRemeslnici/tailwind-sorter/wiki/The-config-file-explanation).
96
131
 
97
132
  ### Adding your unique set of Tailwind classes
98
133
 
99
134
  The script works best if you only include the classes that you really use in your project. Once you grab all the classes
100
- e.g. from your [purged](https://tailwindcss.com/docs/optimizing-for-production) / [JIT-ed](https://tailwindcss.com/docs/just-in-time-mode) production CSS bundle, you can initially reorder them using the following ruby snippet. Suppose you
135
+ e.g. from your [JIT-ed](https://tailwindcss.com/docs/just-in-time-mode) production CSS bundle, you can initially reorder them using the following ruby snippet. Suppose you
101
136
  have the ”default“ Tailwind classes sorted (taken e.g. from
102
- [here](https://github.com/avencera/rustywind/blob/master/src/defaults.rs)), one per line, in
137
+ [here](https://github.com/avencera/rustywind/blob/master/rustywind-core/src/defaults.rs), one per line, in
103
138
  the `default_classes.txt` file and your own (unordered) classes in `our_classes.txt`. Then the sorting could go along these lines:
104
139
 
105
140
  ```ruby
@@ -114,7 +149,7 @@ the `sorted_classes.txt` file) and move all of them to the appropriate sections
114
149
 
115
150
  ## Running the script
116
151
 
117
- Of course, you can run the script manually, like so:
152
+ You can run the script manually like so:
118
153
 
119
154
  ```sh
120
155
  bin/tailwind_sorter app/views/my_template.html.slim
@@ -122,7 +157,7 @@ bin/tailwind_sorter app/views/my_template.html.slim
122
157
 
123
158
  The script finds all css classes and reorders them in-place in the file.
124
159
 
125
- You can tweak the configuration file path instead of the default `config/tailwind_sorter.yml` with the `-c` parameter:
160
+ The script requires the configuration file to be present in `config/tailwind_sorter.yml` by default. You can tweak the configuration file path with the `-c` parameter:
126
161
 
127
162
  ```sh
128
163
  bin/tailwind_sorter -c path/to/my/config_file.yml app/views/my_template.html.slim
@@ -161,10 +196,10 @@ You can also optionally pass in ome arguments such as `warn_only: true` to only
161
196
  ```sh
162
197
  bundle install # to install the rspec gem
163
198
  bundle exec rspec
164
- .............
199
+ .................
165
200
 
166
- Finished in 0.34583 seconds (files took 0.07635 seconds to load)
167
- 13 examples, 0 failures
201
+ Finished in 1.08 seconds (files took 0.03424 seconds to load)
202
+ 17 examples, 0 failures
168
203
  ```
169
204
 
170
205
  ## Answers for the curious
data/exe/tailwind_sorter CHANGED
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "tailwind_sorter/sorter"
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require "tailwind_sorter"
4
7
 
5
8
  warn_only = false
6
9
  config_file = "config/tailwind_sorter.yml"
@@ -3,6 +3,10 @@ require "yaml"
3
3
 
4
4
  module TailwindSorter
5
5
  class Sorter
6
+ def initialize
7
+ @sorting_keys_cache = {}
8
+ end
9
+
6
10
  # reorders multiple variants, e.g.: "focus:sm:block" -> "sm:focus:block"
7
11
  def sort_variants(css_class_with_variants, variants_order:)
8
12
  *variants, css_class = css_class_with_variants.split(":")
@@ -15,32 +19,54 @@ module TailwindSorter
15
19
  # Constructs the sorting key for sorting CSS classes in the following way:
16
20
  #
17
21
  # group_index, variant1_index, variant2_index, class_index
18
- # "sm:focus:flex" "01,01,11,0010"
19
- # "flex" "01,00,00,0010"
20
- # "nr-custom-class" "00,00,00,0000"
21
- def sorting_key(css_class_with_variants, variants_order:, classes_order:, class_groups:, sort_order:, default_index: 0)
22
+ # "sm:focus:flex" -> "01,01,11,0010"
23
+ # "flex" -> "01,00,00,0010"
24
+ # "custom-class" -> "00,00,00,0000"
25
+ def sorting_key(css_class_with_variants, variants_order:, classes_order:, class_groups:, default_index: 0)
26
+ return @sorting_keys_cache[css_class_with_variants] if @sorting_keys_cache[css_class_with_variants]
27
+
22
28
  *variants, css_class = css_class_with_variants.split(":")
29
+
30
+ matching_index_in_group = nil
31
+ matching_group = class_groups.find do |group|
32
+ matching_index_in_group ||= classes_order[group].index { _1 === css_class }
33
+ end
34
+
23
35
  key = [
24
- format("%02d", class_groups.index { |group| classes_order[group].include?(css_class) } || default_index),
36
+ format("%02d", matching_group && class_groups.index(matching_group) || default_index),
25
37
  format("%02d", variants_order.index(variants[0]) || default_index),
26
38
  format("%02d", variants_order.index(variants[1]) || default_index),
27
- format("%04d", sort_order.index(css_class) || default_index)
39
+ format("%04d", matching_index_in_group || default_index)
28
40
  ].join(",")
29
41
 
30
42
  # puts "#{css_class_with_variants} #{key}"
31
- key
43
+ @sorting_keys_cache[css_class_with_variants] = key
44
+ end
45
+
46
+ def convert_regexps!(classes_order)
47
+ classes_order.each do |group, class_patterns|
48
+ class_patterns.map! do |class_or_pattern|
49
+ if !(patterns = class_or_pattern.match(%r{\A/(.*)/\z}).to_a).empty?
50
+ Regexp.new(/\A#{patterns.last}\z/)
51
+ else
52
+ class_or_pattern
53
+ end
54
+ end
55
+ end
56
+
57
+ classes_order
32
58
  end
33
59
 
34
60
  def sort_classes(file, regexps:, variants_order:, classes_order:, default_index: 0, warn_only: false)
61
+ convert_regexps!(classes_order)
35
62
  class_groups = classes_order.keys
36
- sort_order = classes_order.values.flatten
37
63
  warnings = []
38
64
 
39
65
  infile = File.open(file)
40
66
  outfile = Tempfile.create("#{File.basename(file)}.sorted")
41
67
 
42
68
  calculate_sorting_key = lambda do |css_class_with_variants|
43
- sorting_key(css_class_with_variants, variants_order:, classes_order:, class_groups:, sort_order:, default_index:)
69
+ sorting_key(css_class_with_variants, variants_order:, classes_order:, class_groups:, default_index:)
44
70
  end
45
71
 
46
72
  changed = false
@@ -88,7 +114,8 @@ module TailwindSorter
88
114
 
89
115
  warnings
90
116
 
91
- rescue StandardError
117
+ rescue StandardError => e
118
+ warn "An error occurred: #{e}"
92
119
  success = false
93
120
 
94
121
  ensure
@@ -118,4 +145,4 @@ module TailwindSorter
118
145
  new.run(...)
119
146
  end
120
147
  end
121
- end
148
+ end
@@ -1,3 +1,3 @@
1
1
  module TailwindSorter
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -2,4 +2,4 @@ require "tailwind_sorter/sorter"
2
2
  require "tailwind_sorter/version"
3
3
 
4
4
  module TailwindSorter
5
- end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tailwind-sorter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - NejŘemeslníci.cz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-19 00:00:00.000000000 Z
11
+ date: 2024-08-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Simple but customizable sorter for TailwindCSS classes
14
14
  email:
@@ -18,6 +18,7 @@ executables:
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - CHANGELOG.md
21
22
  - README.md
22
23
  - Rakefile
23
24
  - exe/tailwind_sorter
@@ -39,14 +40,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
39
40
  requirements:
40
41
  - - ">="
41
42
  - !ruby/object:Gem::Version
42
- version: '3.0'
43
+ version: '3.1'
43
44
  required_rubygems_version: !ruby/object:Gem::Requirement
44
45
  requirements:
45
46
  - - ">="
46
47
  - !ruby/object:Gem::Version
47
48
  version: '0'
48
49
  requirements: []
49
- rubygems_version: 3.4.19
50
+ rubygems_version: 3.5.3
50
51
  signing_key:
51
52
  specification_version: 4
52
53
  summary: Customizable TailwindCSS classes sorter