-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract Sortable module, add StringSorter
- Loading branch information
Showing
8 changed files
with
215 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
module TailwindSorter | ||
module Config | ||
class Config | ||
DEFAULT_CONFIG_FILE = "config/tailwind_sorter.yml" | ||
|
||
def initialize(config_file = DEFAULT_CONFIG_FILE) | ||
unless config_file && File.exist?(config_file) | ||
raise ArgumentError, "Configuration file '#{config_file}' does not exist" | ||
end | ||
|
||
@config_file = config_file | ||
end | ||
|
||
def load | ||
@config = YAML.load_file(@config_file) | ||
convert_class_order_regexps! | ||
@config | ||
end | ||
|
||
private | ||
|
||
def convert_class_order_regexps! | ||
@config["classes_order"].each_value do |class_patterns| | ||
class_patterns.map! do |class_or_pattern| | ||
if (patterns = class_or_pattern.match(%r{\A/(.*)/\z}).to_a).empty? | ||
class_or_pattern | ||
else | ||
/\A#{patterns.last}\z/ | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# frozen_string_literal: true | ||
|
||
module TailwindSorter | ||
module Sortable | ||
private | ||
|
||
# Returns the Tailwind classes array sorted according to the config file. | ||
def sort_classes_array(classes) | ||
classes = classes.map do |css_class_with_variants| | ||
sort_variants(css_class_with_variants) | ||
end | ||
|
||
classes.sort_by { |css_class| sorting_key_lambda.call(css_class) } | ||
end | ||
|
||
# Lambda for sorting the Tailwind CSS classes. It is memoized to avoid repeated class groups lookups. | ||
def sorting_key_lambda(default_index: 0) | ||
@sorting_key_lambda ||= begin | ||
class_groups = @config["classes_order"].keys | ||
->(tw_class) { sorting_key(tw_class, class_groups:, default_index:) } | ||
end | ||
end | ||
|
||
# Reorders multiple variants, e.g.: "focus:sm:block" -> "sm:focus:block". | ||
def sort_variants(css_class_with_variants) | ||
*variants, css_class = css_class_with_variants.split(":") | ||
return css_class_with_variants if variants.length <= 1 | ||
|
||
variants.sort_by! { |variant| @config["variants_order"].index(variant) } | ||
"#{variants.join(':')}:#{css_class}" | ||
end | ||
|
||
# Constructs the sorting key for sorting CSS classes in the following way: | ||
# | ||
# group_index, variant1_index, variant2_index, class_index | ||
# "sm:focus:flex" -> "01,01,11,0010" | ||
# "flex" -> "01,00,00,0010" | ||
# "custom-class" -> "00,00,00,0000" | ||
def sorting_key(css_class_with_variants, class_groups:, default_index: 0) | ||
return @sorting_keys_cache[css_class_with_variants] if @sorting_keys_cache[css_class_with_variants] | ||
|
||
*variants, css_class = css_class_with_variants.split(":") | ||
|
||
matching_index_in_group = nil | ||
matching_group = class_groups.find do |group| | ||
matching_index_in_group ||= @config["classes_order"][group].index { _1 === css_class } | ||
end | ||
|
||
key = [ | ||
format("%02d", (matching_group && class_groups.index(matching_group)) || default_index), | ||
format("%02d", @config["variants_order"].index(variants[0]) || default_index), | ||
format("%02d", @config["variants_order"].index(variants[1]) || default_index), | ||
format("%04d", matching_index_in_group || default_index) | ||
].join(",") | ||
|
||
@sorting_keys_cache[css_class_with_variants] = key | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
require "yaml" | ||
|
||
require "tailwind_sorter/config" | ||
require "tailwind_sorter/sortable" | ||
|
||
module TailwindSorter | ||
class StringSorter | ||
include Sortable | ||
|
||
def initialize(config_file: Config::DEFAULT_CONFIG_FILE) | ||
@config = Config.new(config_file).load | ||
@sorting_keys_cache = {} | ||
end | ||
|
||
def sort(classes_string) | ||
sort_classes_array(classes_string.split.map(&:strip).reject(&:empty?).uniq).join(" ") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# frozen_string_literal: true | ||
|
||
require "spec_helper" | ||
require "fileutils" | ||
require "bundler" | ||
|
||
require "tailwind_sorter" | ||
|
||
RSpec.describe TailwindSorter::StringSorter do | ||
let(:config_file) { "spec/support/basic_config.yml" } | ||
|
||
def run_tailwind_sorter(content) | ||
TailwindSorter::StringSorter.new(config_file:).sort(content) | ||
end | ||
|
||
describe "class reordering with pure strings in the config" do | ||
it "does basic class reordering" do | ||
expect(run_tailwind_sorter("rounded my-4 block")).to eq("block my-4 rounded") | ||
end | ||
|
||
it "orders unknown classes first" do | ||
expect(run_tailwind_sorter("rounded my-4 block nr-class")).to eq("nr-class block my-4 rounded") | ||
end | ||
|
||
it "orders variants to the end of the same group" do | ||
expect(run_tailwind_sorter("sm:block block lg:my-4 my-8")).to eq("block sm:block my-8 lg:my-4") | ||
end | ||
|
||
it "orders multiple variants" do | ||
expect(run_tailwind_sorter("focus:hover:sm:block my-4")).to eq("sm:hover:focus:block my-4") | ||
end | ||
end | ||
|
||
describe "class reordering with regexps in classes_order config" do | ||
let(:config_file) { "spec/support/regexp_config.yml" } | ||
|
||
it "does basic class reordering" do | ||
expect(run_tailwind_sorter("rounded my-4 block")).to eq("block my-4 rounded") | ||
end | ||
|
||
it "orders unknown classes first" do | ||
expect(run_tailwind_sorter("rounded my-4 block nr-class")).to eq("nr-class block my-4 rounded") | ||
end | ||
|
||
it "orders variants to the end of the same group" do | ||
expect(run_tailwind_sorter("sm:block block lg:my-4 my-8")).to eq("block sm:block my-8 lg:my-4") | ||
end | ||
|
||
it "orders multiple variants" do | ||
expect(run_tailwind_sorter("focus:hover:sm:block my-4")).to eq("sm:hover:focus:block my-4") | ||
end | ||
end | ||
|
||
it "removes duplicate classes" do | ||
expect(run_tailwind_sorter("block my-4 block")).to eq("block my-4") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters