From f41ea030f9b88254466521d1551f6cec26297aec Mon Sep 17 00:00:00 2001 From: Javier Aranda Date: Wed, 16 Oct 2024 10:55:13 +0200 Subject: [PATCH] Prepare code for development --- .envrc | 1 + .github/workflows/testing.yml | 33 +++++++-- .gitignore | 55 --------------- .rubocop.yml | 20 ++++++ Gemfile | 13 ++++ Gemfile.lock | 86 +++++++++++++++++++++++ Rakefile | 5 +- bench.rb | 10 +-- bin/console | 7 ++ bin/rake | 27 +++++++ bin/rubocop | 27 +++++++ class_variants.gemspec | 38 +++++----- lib/class_variants.rb | 2 +- lib/class_variants/action_view/helpers.rb | 2 +- lib/class_variants/instance.rb | 84 +++++++++++----------- lib/class_variants/railtie.rb | 6 +- lib/class_variants/version.rb | 2 +- test/class_variants_test.rb | 4 +- 18 files changed, 287 insertions(+), 135 deletions(-) create mode 100644 .envrc create mode 100644 .rubocop.yml create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100755 bin/console create mode 100755 bin/rake create mode 100755 bin/rubocop diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..234188d --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +PATH_add bin diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e86286c..c1b2da2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -1,6 +1,26 @@ name: Testing on: push jobs: + rubocop: + name: Rubocop + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + ruby: + - "3.0" + - "3.1" + - "3.2" + - "3.3" + steps: + - uses: actions/checkout@v4 + - name: Setup Ruby ${{ matrix.ruby }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run Rubocop + run: bin/rubocop tests: name: Tests runs-on: ubuntu-latest @@ -8,15 +28,16 @@ jobs: fail-fast: false matrix: ruby: - - '3.0' - - '3.1' - - '3.2' - - '3.3' + - "3.0" + - "3.1" + - "3.2" + - "3.3" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Ruby ${{ matrix.ruby }} uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} + bundler-cache: true - name: Run tests - run: rake test + run: bin/rake test diff --git a/.gitignore b/.gitignore index 33c0f8a..c111b33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,56 +1 @@ *.gem -*.rbc -/.config -/coverage/ -/InstalledFiles -/pkg/ -/spec/reports/ -/spec/examples.txt -/test/tmp/ -/test/version_tmp/ -/tmp/ - -# Used by dotenv library to load environment variables. -# .env - -# Ignore Byebug command history file. -.byebug_history - -## Specific to RubyMotion: -.dat* -.repl_history -build/ -*.bridgesupport -build-iPhoneOS/ -build-iPhoneSimulator/ - -## Specific to RubyMotion (use of CocoaPods): -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control -# -# vendor/Pods/ - -## Documentation cache and generated files: -/.yardoc/ -/_yardoc/ -/doc/ -/rdoc/ - -## Environment normalization: -/.bundle/ -/vendor/bundle -/lib/bundler/man/ - -# for a library or gem, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# Gemfile.lock -# .ruby-version -# .ruby-gemset - -# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: -.rvmrc - -# Used by RuboCop. Remote config files pulled in from inherit_from directive. -# .rubocop-https?--* \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..f2a09c0 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,20 @@ +inherit_mode: + merge: + - Exclude + +require: + - standard + - standard-performance + - rubocop-performance + - rubocop-minitest + - rubocop-rake + +inherit_gem: + standard: config/base.yml + standard-performance: config/base.yml + +AllCops: + DisplayCopNames: true + Exclude: + - "**/bin/**/*" + NewCops: enable diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..c5687eb --- /dev/null +++ b/Gemfile @@ -0,0 +1,13 @@ +source "https://rubygems.org" + +gemspec + +gem "benchmark-ips" +gem "irb" +gem "minitest" +gem "rake" +gem "rubocop", require: false +gem "rubocop-minitest", require: false +gem "rubocop-rake", require: false +gem "standard", ">= 1.35.1", require: false +gem "standard-performance", require: false diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..2194e32 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,86 @@ +PATH + remote: . + specs: + class_variants (0.0.7) + +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.2) + benchmark-ips (2.14.0) + io-console (0.7.2) + irb (1.14.1) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.7.2) + language_server-protocol (3.17.0.3) + lint_roller (1.1.0) + minitest (5.25.1) + parallel (1.26.3) + parser (3.3.5.0) + ast (~> 2.4.1) + racc + psych (5.1.2) + stringio + racc (1.8.1) + rainbow (3.1.1) + rake (13.2.1) + rdoc (6.7.0) + psych (>= 4.0.0) + regexp_parser (2.9.2) + reline (0.5.10) + io-console (~> 0.5) + rubocop (1.66.1) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.4, < 3.0) + rubocop-ast (>= 1.32.2, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.32.3) + parser (>= 3.3.1.0) + rubocop-minitest (0.36.0) + rubocop (>= 1.61, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-performance (1.22.1) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + ruby-progressbar (1.13.0) + standard (1.41.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.66.0) + standard-custom (~> 1.0.0) + standard-performance (~> 1.5) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.5.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.22.0) + stringio (3.1.1) + unicode-display_width (2.6.0) + +PLATFORMS + arm64-darwin-24 + ruby + +DEPENDENCIES + benchmark-ips + class_variants! + irb + minitest + rake + rubocop + rubocop-minitest + rubocop-rake + standard (>= 1.35.1) + standard-performance + +BUNDLED WITH + 2.5.20 diff --git a/Rakefile b/Rakefile index ad13ced..c927afa 100644 --- a/Rakefile +++ b/Rakefile @@ -1,4 +1,5 @@ require "rake/testtask" +require "rubocop/rake_task" Rake::TestTask.new(:test) do |t| t.libs << "test" @@ -6,4 +7,6 @@ Rake::TestTask.new(:test) do |t| t.test_files = FileList["test/**/*_test.rb"] end -task default: :test +RuboCop::RakeTask.new + +task default: %i[rubocop test] diff --git a/bench.rb b/bench.rb index 35333c8..d7db4a2 100644 --- a/bench.rb +++ b/bench.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "benchmark/ips" module ClassVariants @@ -6,7 +7,6 @@ module ClassVariants require_relative "lib/class_variants/instance" - Benchmark.ips do |x| button_classes = ClassVariants::Instance.new( "rounded border-2 focus:ring-blue-500", @@ -14,20 +14,20 @@ module ClassVariants size: { sm: "text-xs px-1.5 py-1", base: "text-sm px-2 py-1.5", - lg: "text-base px-3 py-2", + lg: "text-base px-3 py-2" }, color: { white: "text-white bg-transparent border-white", blue: "text-white bg-blue-500 border-blue-700 hover:bg-blue-600", - red: "text-white bg-red-500 border-red-700 hover:bg-red-600", + red: "text-white bg-red-500 border-red-700 hover:bg-red-600" }, block: "justify-center w-full", - "!block": "justify-between", + "!block": "justify-between" }, defaults: { size: :base, color: :white, - block: false, + block: false } ) diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..7e0779f --- /dev/null +++ b/bin/console @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby + +require "bundler/setup" +require "class_variants" +require "irb" + +IRB.start diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..4eb7d7b --- /dev/null +++ b/bin/rake @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rake", "rake") diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 0000000..369a05b --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rubocop' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rubocop", "rubocop") diff --git a/class_variants.gemspec b/class_variants.gemspec index 47de431..b83c725 100644 --- a/class_variants.gemspec +++ b/class_variants.gemspec @@ -1,27 +1,25 @@ require_relative "lib/class_variants/version" Gem::Specification.new do |s| - s.name = "class_variants" - s.version = ClassVariants::VERSION - s.summary = "Easily configure styles and apply them as classes." + # information + s.name = "class_variants" + s.version = ClassVariants::VERSION + s.summary = "Easily configure styles and apply them as classes." s.description = "Easily configure styles and apply them as classes." - s.authors = ["Adrian Marin"] - s.email = "adrian@adrianthedev.com" - s.files = Dir["{lib}/**/*"] - s.homepage = "https://github.com/avo-hq/class_variants" - s.license = "MIT" + s.authors = ["Adrian Marin"] + s.email = "adrian@adrianthedev.com" + s.homepage = "https://github.com/avo-hq/class_variants" + s.license = "MIT" - # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' - # to allow pushing to a single host or delete this section to allow pushing to any host. - if s.respond_to?(:metadata) - s.metadata["bug_tracker_uri"] = "https://github.com/avo-hq/class_variants/issues" - s.metadata["homepage_uri"] = "https://github.com/avo-hq/class_variants" - s.metadata["source_code_uri"] = "https://github.com/avo-hq/class_variants" - else - raise "RubyGems 2.0 or newer is required to protect against " \ - "public gem pushes." - end + # metadata + s.metadata["homepage_uri"] = s.homepage + s.metadata["source_code_uri"] = s.homepage + s.metadata["bug_tracker_uri"] = "#{s.homepage}/issues" + s.metadata["changelog_uri"] = "#{s.homepage}/releases" - s.add_development_dependency "benchmark-ips" -end + # gem files + s.files = Dir["lib/**/*", "LICENSE", "README.md"] + # ruby minimal version + s.required_ruby_version = Gem::Requirement.new(">= 3.0") +end diff --git a/lib/class_variants.rb b/lib/class_variants.rb index 684dc1c..6b0a21d 100644 --- a/lib/class_variants.rb +++ b/lib/class_variants.rb @@ -9,4 +9,4 @@ def build(classes, **args) Instance.new classes, **args end end -end \ No newline at end of file +end diff --git a/lib/class_variants/action_view/helpers.rb b/lib/class_variants/action_view/helpers.rb index 689dba0..1e21c0a 100644 --- a/lib/class_variants/action_view/helpers.rb +++ b/lib/class_variants/action_view/helpers.rb @@ -6,4 +6,4 @@ def class_variants(classes, **args) end end end -end \ No newline at end of file +end diff --git a/lib/class_variants/instance.rb b/lib/class_variants/instance.rb index bca5f97..2ee5cdc 100644 --- a/lib/class_variants/instance.rb +++ b/lib/class_variants/instance.rb @@ -1,53 +1,57 @@ -class ClassVariants::Instance - attr_reader :classes - attr_reader :variants - attr_reader :defaults - - def initialize(classes = "", variants: {}, compoundVariants: [], defaults: {}) - @classes = classes - @variants = expand_boolean_variants(variants) - @compoundVariants = compoundVariants - @defaults = defaults - end +module ClassVariants + class Instance + attr_reader :classes, :variants, :compoundVariants, :defaults + + # rubocop:disable Naming/VariableName + def initialize(classes = "", variants: {}, compoundVariants: [], defaults: {}) + @classes = classes + @variants = expand_boolean_variants(variants) + @compoundVariants = compoundVariants + @defaults = defaults + end + # rubocop:enable Naming/VariableName - def render(**overrides) - # Start with our default classes - result = [@classes] + def render(**overrides) + # Start with our default classes + result = [@classes] - # Then merge the passed in overrides on top of the defaults - selected = @defaults.merge(overrides) + # Then merge the passed in overrides on top of the defaults + selected = @defaults.merge(overrides) - selected.each do |variant_type, variant| - # dig the classes out and add them to the result - result << @variants.dig(variant_type, variant) - end + selected.each do |variant_type, variant| + # dig the classes out and add them to the result + result << @variants.dig(variant_type, variant) + end - @compoundVariants.each do |compound_variant| - if (compound_variant.keys - [:class]).all? { |key| selected[key] == compound_variant[key] } - result << compound_variant[:class] + @compoundVariants.each do |compound_variant| + if (compound_variant.keys - [:class]).all? { |key| selected[key] == compound_variant[key] } + result << compound_variant[:class] + end end - end - # Compact out any nil values we may have dug up - result.compact! + # Compact out any nil values we may have dug up + result.compact! - # Return the final token list - result.join " " - end + # Return the final token list + result.join " " + end - private + private + + def expand_boolean_variants(variants) + expanded = variants.map do |key, value| + case value + when String + s_key = key.to_s + {s_key.delete_prefix("!").to_sym => {!s_key.start_with?("!") => value}} + else + {key => value} + end + end - def expand_boolean_variants(variants) - variants.each.map { |key, value| - case value - when String - s_key = key.to_s - { s_key.delete_prefix("!").to_sym => { !s_key.start_with?("!") => value } } - else - { key => value } + expanded.reduce do |output, next_variant| + output.merge!(next_variant) { |_key, v1, v2| v1.merge!(v2) } end - }.reduce do |variants, more_variants| - variants.merge!(more_variants) { |_key, v1, v2| v1.merge!(v2) } end end end diff --git a/lib/class_variants/railtie.rb b/lib/class_variants/railtie.rb index 8d3ca26..3ff3ba3 100644 --- a/lib/class_variants/railtie.rb +++ b/lib/class_variants/railtie.rb @@ -1,12 +1,12 @@ -require 'rails/railtie' +require "rails/railtie" module ClassVariants class Railtie < ::Rails::Railtie - initializer "class_variants.action_view" do |app| + initializer "class_variants.action_view" do ActiveSupport.on_load :action_view do require "class_variants/action_view/helpers" include ClassVariants::ActionView::Helpers end end end -end \ No newline at end of file +end diff --git a/lib/class_variants/version.rb b/lib/class_variants/version.rb index 5b6af58..31d688b 100644 --- a/lib/class_variants/version.rb +++ b/lib/class_variants/version.rb @@ -1,3 +1,3 @@ module ClassVariants - VERSION = "0.0.7" unless const_defined?(:VERSION) + VERSION = "0.0.7".freeze end diff --git a/test/class_variants_test.rb b/test/class_variants_test.rb index c801df8..cae1123 100644 --- a/test/class_variants_test.rb +++ b/test/class_variants_test.rb @@ -18,8 +18,8 @@ def setup "!visible": "hidden" }, compoundVariants: [ - { ring: true, color: :red, class: "focus:ring-red-600" }, - { ring: true, color: :green, class: "focus:ring-green-600" } + {ring: true, color: :red, class: "focus:ring-red-600"}, + {ring: true, color: :green, class: "focus:ring-green-600"} ], defaults: { size: :md