読者です 読者をやめる 読者になる 読者になる

ウェブサービスを作っています。

TinyCss クラス

Ruby CSS

CSS::Tiny を参考にして、RubyCSS を処理する TinyCss クラスを作りました。

css = TinyCss.new.read('style.css')
css.style['a']['background'] = 'black'
css.write 'new_style.css'

みたいに使えます。詳しくはソースを見てください。

class TinyCss
  attr_accessor :style

  def initialize
    @style = Hash.new { |h, k| h[k] = {} }
  end

  def read(file)
    read_string open(file).read
  end

  def read_string(str)
    str.tr!("\n\t", '  ').gsub!(%r!/\*.*?\*/!, '')

    ary = str.split(/\}/)
    if ary.last =~ /\S/
      raise StandardError, 'Invalid or unexpected style data'
    end

    ary.reject { |v| v !~ /\S/ }.each do |v|
      unless match = v.match(/^\s*([^{]+?)\s*\{(.*)\s*$/)
        raise StandardError, "Invalid or unexpected style data '#{ v }'"
      end

      styles = match.captures.first.gsub(/\s+/, ' ').split(/\s*,\s*/).
        reject { |v| v !~ /\S/ }

      match.captures.last.split(/\;/).reject { |v| v !~ /\S/ }.each do |v|
        unless match = v.match(/^\s*([\w._-]+)\s*:\s*(.*?)\s*$/)
          raise StandardError,
          "unexpected property '#{ v }' in style '#{ style }'"
        end
        styles.each do |v|
          @style[v][match.captures.first.downcase] = match.captures.last
        end
      end
    end

    self
  end

  def write(file)
    open(file, 'w').write write_string
  end

  def write_string
    contents = ''
    @style.keys.sort.reverse.each do |style|
      contents += "#{ style } {\n"
      @style[style].keys.sort.each do |v|
        contents += "\t#{ v }: #{ @style[style][v] };\n"
      end
      contents += "}\n"
    end

    contents
  end
end