diff --git a/lib/dry/inflector.rb b/lib/dry/inflector.rb index 73398f4..3608fab 100644 --- a/lib/dry/inflector.rb +++ b/lib/dry/inflector.rb @@ -155,7 +155,7 @@ def humanize(input) result = inflections.humans.apply_to(input) result.delete_suffix!("_id") result.tr!("_", " ") - match = /(\W)/.match(result) + match = /([^[:alnum:]])/.match(result) separator = match ? match[0] : DEFAULT_SEPARATOR result.split(separator).map.with_index { |word, index| inflections.acronyms.apply_to(word, capitalize: index.zero?) @@ -283,8 +283,8 @@ def underscore(input) m2 = Regexp.last_match(2) "#{m1 ? "_" : ""}#{m2.downcase}" end - input.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2') - input.gsub!(/([a-z\d])([A-Z])/, '\1_\2') + input.gsub!(/([[:upper:][:digit:]]+)([[:upper:]][[:lower:]])/, '\1_\2') + input.gsub!(/([[:lower:][:digit:]])([[:upper:]])/, '\1_\2') input.tr!("-", "_") input.downcase! input @@ -328,8 +328,10 @@ def to_s # @api private def internal_camelize(input, upper) input = input.to_s.dup - input.sub!(/^[a-z\d]*/) { |match| inflections.acronyms.apply_to(match, capitalize: upper) } - input.gsub!(%r{(?:[_-]|(/))([a-z\d]*)}i) do + input.sub!(/^[[:lower:][:digit:]]*/) do |match| + inflections.acronyms.apply_to(match, capitalize: upper) + end + input.gsub!(%r{(?:[_-]|(/))([[:lower:][:digit:]]*)}i) do m1 = Regexp.last_match(1) m2 = Regexp.last_match(2) "#{m1}#{inflections.acronyms.apply_to(m2)}" diff --git a/spec/unit/dry/inflector/camelize_lower_spec.rb b/spec/unit/dry/inflector/camelize_lower_spec.rb index 0a62108..43f782d 100644 --- a/spec/unit/dry/inflector/camelize_lower_spec.rb +++ b/spec/unit/dry/inflector/camelize_lower_spec.rb @@ -26,7 +26,7 @@ context "custom acronyms" do subject do Dry::Inflector.new do |inflect| - inflect.acronym("IP", "HTML", "XML", "BSD") + inflect.acronym("IP", "HTML", "XML", "BSD", "ÉUA", "4K") end end @@ -38,6 +38,13 @@ expect(subject.camelize_lower(i("force_xml_controller"))).to eql("forceXMLController") expect(subject.camelize_lower(i("free_bsd"))).to eql("freeBSD") end + + it "handles diacritics" do + expect(subject.camelize_lower(i("éclair_fest"))).to eql("éclairFest") + expect(subject.camelize_lower(i("éua-trip"))).to eql("ÉUATrip") + expect(subject.camelize_lower(i("festival_des_éclairs"))).to eql("festivalDesÉclairs") + expect(subject.camelize_lower(i("festival_des_4k"))).to eql("festivalDes4K") + end end end end diff --git a/spec/unit/dry/inflector/camelize_upper_spec.rb b/spec/unit/dry/inflector/camelize_upper_spec.rb index ab6535d..319748c 100644 --- a/spec/unit/dry/inflector/camelize_upper_spec.rb +++ b/spec/unit/dry/inflector/camelize_upper_spec.rb @@ -30,7 +30,7 @@ context "custom acronyms" do subject do Dry::Inflector.new do |inflect| - inflect.acronym("IP", "HTML", "XML", "BSD") + inflect.acronym("IP", "HTML", "XML", "BSD", "ÉUA", "4K") end end @@ -41,6 +41,14 @@ expect(subject.camelize_upper(i("html_tidy_generator"))).to eql("HTMLTidyGenerator") expect(subject.camelize_upper(i("force_xml_controller"))).to eql("ForceXMLController") expect(subject.camelize_upper(i("free_bsd"))).to eql("FreeBSD") + expect(subject.camelize_upper(i("4k-television"))).to eql("4KTelevision") + end + + it "handles diacritics" do + expect(subject.camelize_upper(i("éclair_fest"))).to eql("ÉclairFest") + expect(subject.camelize_upper(i("éua-trip"))).to eql("ÉUATrip") + expect(subject.camelize_upper(i("festival_des_éclairs"))).to eql("FestivalDesÉclairs") + expect(subject.camelize_upper(i("festival_des_4k"))).to eql("FestivalDes4K") end end end diff --git a/spec/unit/dry/inflector/humanize_spec.rb b/spec/unit/dry/inflector/humanize_spec.rb index d31354d..88b8e14 100644 --- a/spec/unit/dry/inflector/humanize_spec.rb +++ b/spec/unit/dry/inflector/humanize_spec.rb @@ -29,5 +29,9 @@ expect(subject.humanize(i("openssl/hmac"))).to eql("OpenSSL/HMAC") expect(subject.humanize(i("openssl/digest"))).to eql("OpenSSL/digest") end + + it "handles diacritics" do + expect(subject.humanize(i("éclair"))).to eql("Éclair") + end end end diff --git a/spec/unit/dry/inflector/underscore_spec.rb b/spec/unit/dry/inflector/underscore_spec.rb index 61a3b38..b78b08d 100644 --- a/spec/unit/dry/inflector/underscore_spec.rb +++ b/spec/unit/dry/inflector/underscore_spec.rb @@ -34,6 +34,10 @@ expect(subject.underscore(i("CLIRunner"))).to eq("cli_runner") end + it "underscores aCli as a_cli" do + expect(subject.underscore(i("aCLI"))).to eq("a_cli") + end + it "accepts symbols" do expect(subject.underscore(:DataMapper)).to eq("data_mapper") end @@ -44,5 +48,41 @@ expect(subject.underscore(i("OpenSSL::HMAC"))).to eql("openssl/hmac") expect(subject.underscore(i("OpenSSL::Digest"))).to eql("openssl/digest") end + + it "handles diacritics" do + expect(subject.underscore(i("éclairFest"))).to eql("éclair_fest") + expect(subject.underscore(i("éuaTrip"))).to eql("éua_trip") + expect(subject.underscore(i("festival-des-éclairs"))).to eql("festival_des_éclairs") + expect(subject.underscore(i("ÉBellisimo"))).to eql("é_bellisimo") + expect(subject.underscore(i("éBellisimo"))).to eql("é_bellisimo") + end + + it "handles number followed by uppercase letter" do + expect(subject.underscore(i("9Lives"))).to eql("9_lives") + end + + pending "handles number followed by lowercase letter" do + pending "this should be `7_ate_9`" + expect(subject.underscore(i("7Ate9"))).to eql("7_ate_9") + end + + it "handles number followed by lowercase letter" do + pending "this should be 9_lives" + expect(subject.underscore(i("9lives"))).to eql("9_lives") + end + + it "handle leading diacritic" do + expect(subject.underscore(i("éBellisimo"))).to eql("é_bellisimo") + end + + it "handles leading number " do + pending "this should be 1_is_one" + expect(subject.underscore(i("1isOne"))).to eql("1_is_one") + end + + it "handles leading number with diacritic" do + pending "this should be 1_é_bellisimo" + expect(subject.underscore(i("1éBellisimo"))).to eql("1_é_bellisimo") + end end end