代码之家  ›  专栏  ›  技术社区  ›  Ramon Tayag

Ruby/Rails:通过表单确定要更新的纯文本变量

  •  0
  • Ramon Tayag  · 技术社区  · 15 年前

    SCSS syntax ). 这很好,但是,我最终希望这些CSS文件是“可编程的”,这样不知道CSS的用户仍然可以用一种基本的方式编辑它们。怎么用?

    如果我可以将某些内容标记为可编辑的,就不必创建不可能的数据库模式。例如,我有一个名为style.scss的scss文件:

    // @type color
    $header_bg_color: #555;
    
    // @type image
    $header_image: "http://someurl.com/image.jpg";
    

    然后我可以这样做:

    SomeParser.parse(contents of style.scss here)

    这将返回散列或类似的变量:

    {:header_bg_color => {:type => "color", :value => "#555"}, :header_image => {:type => "image", :value => "http://someurl.com/image.jpg"} }
    

    创建/配置自己的解析器以便读取注释并从中提取“变量”的最佳方法是什么?然后,再次轻松地更新文本文件?

    另一种可能的方式是这样的:

    o = SomeParser.new(contents of style.scss here)
    o.header_bg_color #returns "#555"
    o.header_image = "http://anotherurl.com/image2.jpg" # "updates" or replaces the old header image variable with the new one
    o.render # returns the text with the new values
    

    提前谢谢!

    1 回复  |  直到 15 年前
        1
  •  0
  •   Ramon Tayag    15 年前

    我用得不彻底,但我的测试通过了。我想这已经足够让我产生这样的想法了:)我花了几个小时的学习,然后又花了几个小时来实现它。

    顺便说一下,我没有在这里做任何优化。对我来说,不需要很快

    查看我的规范文件:

    require 'spec_helper'
    
    describe StyleParser do
      describe "given properly formatted input" do
        it "should set and return variables properly" do
          text = %{# @name Masthead Background Image
    # @kind file
    # @description Background image.
    $mbc2: "http://someurl.com/image.jpg";
    
    # @name Masthead BG Color
    # @kind color
    # @description Background color.
    $mbc: #555;}
          @s = StyleParser.new(text)
    
          @s.mbc.name.should == "Masthead BG Color"
          @s.mbc.kind.should == "color"
          @s.mbc.description.should == "Background color."
          @s.mbc.value.should == "#555"
    
          @s.mbc2.name.should == "Masthead Background Image"
          @s.mbc2.kind.should == "file"
          @s.mbc2.description.should == "Background image."
          @s.mbc2.value.should == %Q("http://someurl.com/image.jpg")
        end
      end
    
      describe "when assigning values" do
        it "should update its values" do
          text = %{# @name Masthead Background Image
    # @kind file
    # @description Background image.
    $mbc2: "http://someurl.com/image.jpg";}
          @s = StyleParser.new(text)
          @s.mbc2.value = %Q("Another URL")
          @s.mbc2.value.should == %Q("Another URL")
    
          rendered_text = @s.render
          rendered_text.should_not match(/http:\/\/someurl\.com\/image\.jpg/)
          rendered_text.should match(/\$mbc2: "Another URL";/)
    
          @s.mbc2.value = %Q("Some third URL")
          @s.mbc2.value.should == %Q("Some third URL")
          rendered_text = @s.render
          rendered_text.should_not match(/\$mbc2: "Another URL";/)
          rendered_text.should match(/\$mbc2: "Some third URL";/)
        end
    
        it "should render the correct values" do
          text_old = %{# @name Masthead Background Image
    # @kind file
    # @description Background image.
    $mbc2: "http://someurl.com/image.jpg";}
          text_new = %{# @name Masthead Background Image
    # @kind file
    # @description Background image.
    $mbc2: "Another URL";}
          @s = StyleParser.new(text_old)
          @s.mbc2.value = %Q("Another URL")
          @s.render.should == text_new
        end
      end
    end
    

    然后是以下两个文件:

    # Used to parse through an scss stylesheet to make editing of that stylesheet simpler
    # Ex. Given a file called style.scss
    #
    # // @name Masthead Background Color
    # // @type color
    # // @description Background color of the masthead.
    # $masthead_bg_color: #444;
    #
    # sp = StyleParser.new(contents of style.scss)
    #
    # # Reading
    # sp.masthead_bg_color.value # returns "#444"
    # sp.masthead_bg_color.name # returns "Masthead Background Color"
    # sp.masthead_bg_color.type # returns "color"
    # sp.masthead_bg_color.description # returns "Background color of the masthead."
    #
    # # Writing
    # sp.masthead_bg_color.value = "#555"
    # sp.render # returns all the text above except masthead_bg_color is now #555;
    
    class StyleParser
      def initialize(text)
        @text = text
        @variables = {}
    
        @eol = '\n'
        @context_lines = 3
        @context = "((?:.*#{@eol}){#{@context_lines}})"
      end
    
      # Works this way: http://rubular.com/r/jWSYvfVrjj
      # Derived from http://stackoverflow.com/questions/2760759/ruby-equivalent-to-grep-c-5-to-get-context-of-lines-around-the-match
      def get_context(s)
        regexp = /.*\${1}#{s}:.*;[#{@eol}]*/
        @text =~ /^#{@context}(#{regexp})/
        before, match = $1, $2
        "#{before}#{match}"
      end
    
      def render
        @variables.each do |key, var|
          @text.gsub!(/^\$#{key}: .+;/, %Q($#{key}: #{var.value};))
        end
        @text
      end
    
      def method_missing(method_name)
        if method_name.to_s =~ /[\w]+/
          context = get_context(method_name)
    
          @variables[method_name] ||= StyleVariable.new(method_name, context)
        end
      end
    end
    
    class StyleVariable
      METADATA = %w(name kind description)
    
      def initialize(var, text)
        @var = var
        @text = text
      end
    
      def method_missing(method_name)
        if METADATA.include? method_name.to_s
          content_of(method_name.to_s)
        end
      end
    
      def value
        @text.each do |string|
          string =~ /^\${1}#{@var}: (.+);/
          return $1 if $1
        end
      end
    
      def value=(val)
        @text.gsub!(/^\$#{@var}: .+;/, "$#{@var}: #{val};")
      end
    
      private
    
      def content_of(variable)
        @text.each do |string|
          string =~ /^# @([\w]+[^\s]) (.+)/
          return $2 if $1 == variable
        end
      end
    end