evolutionxbox evolutionxbox - 6 months ago 27
Ruby Question

CamelCase Jekyll Filter

I am trying to make a CamelCase Jekyll filter.

=begin
# Custom to camelcase function
# Usage:
# 'string'.camelize
# 'string'.camelize(:lower)
=end
class String
def camelize(*separators)
case separators.first
when Symbol, TrueClass, FalseClass, NilClass
first_letter = separators.shift
end

separators = ['_', '\s'] if separators.empty?

str = self.dup

separators.each do |s|
str = str.gsub(/(?:#{s}+)([a-z])/){ $1.upcase }
end

case first_letter
when :upper, true
str = str.gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
when :lower, false
str = str.gsub(/(\A|\s)([A-Z])/){ $1 + $2.downcase }
end

str
end
end

=begin
Jekyll filter to convert string to camelcase
Usage:
{% 'string' | camelcase %}
=end
module Jekyll
module CamelCase
def camelcase(input)
input.camelize(:lower)
end
end
end
Liquid::Template.register_filter(Jekyll::CamelCase)


It is successful when filtering a string:

{{ 'Page Title' | camelcase }} # pageTitle


...but not when used on a page variable:

{{ page.title | camelcase }} # Page Title


Could there be something I am missing?
Could someone try this on there own Jekyll installation?

It's not super important, but it has been bugging me for hours.

Thanks everyone. =)

Answer

The problem was with these three lines:

# mainly this one
str = str.gsub(/(?:#{s}+)([a-z])/){ $1.upcase }

# but also these two as well
str = str.gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
str = str.gsub(/(\A|\s)([A-Z])/){ $1 + $2.downcase }

When I supplied the string Hello World, the regex didn't match the space as it is followed by a capital letter. E.g. \s[a-z] doesn't match ' W'. So "shorthand Word character" (\w) was used instead.

The code below works:

=begin
 # Custom to camelcase function
 # Usage:
 #   'string'.camelize
 #   'string'.camelize(:lower)
=end
class String
  def camelize(*separators)
    case separators.first
    when Symbol, TrueClass, FalseClass, NilClass
      first_letter = separators.shift
    end

    separators = ['_', '\s'] if separators.empty?

    str = self.dup

    separators.each do |s|
      str = str.gsub(/(?:#{s}+)([\w])/){ $1.upcase }
    end

    case first_letter
    when :upper, true
      str = str.gsub(/(\A|\s)([\w])/){ $1 + $2.upcase }
    when :lower, false
      str = str.gsub(/(\A|\s)([\w])/){ $1 + $2.downcase }
    end

    str
  end
end

puts('Hello World'.camelize())        # HelloWorld
puts('Hello World'.camelize(:lower))  # helloWorld
puts('Hello World'.camelize(:upper))  # HelloWorld
puts('hello world'.camelize())        # HelloWorld
puts('hello world'.camelize(:lower))  # helloWorld
puts('hello world'.camelize(:upper))  # HelloWorld