class SimpleLayerTag

Author

liveralmask

Copyright

Copyright © 2013 liveralmask

License

MIT

Constants

COPY_END
COPY_UNLIMITED
KEYWORD_COMMENT
KEYWORD_COPY
KEYWORD_MULTI_COPY_BEGIN
KEYWORD_MULTI_COPY_END
KEYWORD_SINGLE_COPY
RGX_ALL
RGX_BLANK_SPACE
RGX_INDENT
RGX_KEYWORD
RGX_VALUE
STR_INDENT

Public Class Methods

new() click to toggle source
# File lib/slt/simple_layer_tag.rb, line 6
def initialize
        @singleTagList = []
        
        @singleHtmlTagList = [
                "br",
                "img",
                "hr",
                "meta",
                "input",
                "embed",
                "area",
                "base",
                "col",
                "keygen",
                "link",
                "param",
                "source"
        ]
end

Public Instance Methods

html( str ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 78
def html( str )
        self.tag( str, @singleHtmlTagList )
end
tag( str, singleTagList = [] ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 31
def tag( str, singleTagList = [] )
        @singleTagList = singleTagList
        
        # 処理しやすい形式に変換しておく
        list = parse( str )
        
        tagList = []
        unfinishedTagList = []
        list.each{|hash|
                # 処理している階層より前の終了タグを出力
                tagList.concat( extract_end_tag_list( unfinishedTagList, hash[ "level" ] ) )
                
                case hash[ "keyword" ]
                when KEYWORD_COPY            # コピー
                        tagList.push( hash[ "value" ] )
                        
                        # 階層の順序を維持するために必要
                        hash[ "keyword" ]   = ""
                        unfinishedTagList.push( hash )
                when KEYWORD_COMMENT # コメント
                        tagList.push( comment_tag( hash[ "value" ] ) )
                        
                        # 階層の順序を維持するために必要
                        hash[ "keyword" ]   = ""
                        unfinishedTagList.push( hash )
                else                                 # タグ
                        tag = start_tag( hash )
                        if tag.empty?
                                next if hash[ "value" ].strip.empty?       # 空白行は無視
                                
                                tagList.push( comment_tag( "Error => #{hash[ 'number' ]}:#{hash[ 'value' ]}" ) )
                                next
                        end
                        
                        tagList.push( tag )
                        unfinishedTagList.push( hash )
                end
        }
        
        # 残りの終了タグ
        tagList.concat( extract_end_tag_list( unfinishedTagList ) )
        
        tagText = "#{tagList.join.strip}"
        
        return tagText
end

Private Instance Methods

add_single_tag( name ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 252
def add_single_tag( name )
        name = name.downcase
        
        return if @singleTagList.include?( name )
        
        @singleTagList.push( name )
end
comment_tag( str ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 222
def comment_tag( str )
        "\n<!-- #{str} -->"
end
end_tag( hash ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 243
def end_tag( hash )
        return "" if @singleTagList.include?( hash[ "keyword" ].downcase )
        
        # 終了タグが存在しない場合もある
        return "" if hash[ "keyword" ].empty?
        
        "</#{hash[ 'keyword' ]}>"
end
extract_end_tag_list( unfinishedTagList, base_level = 0 ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 198
def extract_end_tag_list( unfinishedTagList, base_level = 0 )
        endTagList = []
        while ! unfinishedTagList.empty?
                hash = unfinishedTagList.pop
                
                if hash[ "level" ] < base_level
                        # 元に戻す
                        unfinishedTagList.push( hash )
                        break
                end
                
                # 基準レベルより深い階層の終了タグ
                endTagList.push( end_tag( hash ) )
        end
        
        endTagList
end
indent( level ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 218
def indent( level )
        STR_INDENT * level
end
parse( str ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 90
def parse( str )
        list = []
        copyHash = {
                "copyableCount"      => 0,        # 0:コピーしない/-1:無制限/1以上:残りコピー可能回数
                "level"                      => -1,
                "number"             => 0,
                "list"                       => []
        }
        str.split( "\n" ).each_with_index{|line, i|
                indent, keyword, value = parse_line( line )
                
                hash = {
                        "level"             => indent.length,
                        "keyword"   => keyword,
                        "value"             => value,
                        "number"    => i + 1
                }
                
                # コピー情報
                case hash[ "keyword" ]
                when KEYWORD_SINGLE_COPY             # 前後の空白なしの単一行コピー
                        if 0 == copyHash[ "copyableCount" ]
                                copyHash[ "copyableCount" ]        = 1
                                copyHash[ "level" ]                        = hash[ "level" ]
                                copyHash[ "number" ]               = hash[ "number" ]
                        end
                when KEYWORD_MULTI_COPY_BEGIN        # 前後の空白ありの複数行コピー開始
                        if 0 == copyHash[ "copyableCount" ]
                                copyHash[ "copyableCount" ]        = COPY_UNLIMITED
                                copyHash[ "level" ]                        = hash[ "level" ]
                                copyHash[ "number" ]               = hash[ "number" ]
                                next
                        end
                when KEYWORD_MULTI_COPY_END          # 前後の空白ありの複数行コピー終了
                        if hash[ "level" ] == copyHash[ "level" ]
                                copyHash[ "copyableCount" ]        = COPY_END
                                copyHash[ "number" ]               = "#{copyHash[ 'number' ]}-#{hash[ 'number' ]}"
                        end
                when ""
                        next if 0 == copyHash[ "copyableCount" ] && hash[ "value" ].empty?
                end
                
                if 0 != copyHash[ "copyableCount" ]
                # コピー中
                        hash[ "value" ] = line if copyHash[ "copyableCount" ] < 0
                        
                        copyHash[ "list" ].push( hash[ "value" ] )
                        
                        copyHash[ "copyableCount" ] -= 1 if 0 < copyHash[ "copyableCount" ]
                end
                
                if 0 == copyHash[ "copyableCount" ]
                        if 0 <= copyHash[ "level" ]
                        # コピー終了
                                hash = {
                                        "level"           => copyHash[ "level" ],
                                        "keyword" => KEYWORD_COPY,
                                        "value"           => copyHash[ "list" ].join( "\n" ),
                                        "number"  => copyHash[ "number" ]
                                }
                                
                                copyHash[ "level" ]        = -1
                                copyHash[ "list" ] = []
                        end
                else
                        next
                end
                
                list.push( hash )
        }
        
        list
end
parse_line( line ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 170
def parse_line( line )
        indent        = ""
        keyword       = ""
        value = ""
        
        begin
                # インデントの取得
                str = line
                break if /^(#{RGX_INDENT})(#{RGX_ALL})/ !~ str
                
                indent       = $~[1]
                str          = $~[2]
                
                # シンプルレイヤータグでは、
                # キーワードと値を空白で区切ったほうが美しい
                if /^(#{RGX_KEYWORD})#{RGX_BLANK_SPACE}(#{RGX_VALUE})$/ =~ str
                        keyword     = $~[1]
                        value       = $~[2]
                elsif /^(#{RGX_KEYWORD})$/ =~ str
                        keyword     = $~[1]
                else
                        value = line
                end
        end while false
        
        return indent, keyword, value
end
start_tag( hash ) click to toggle source
# File lib/slt/simple_layer_tag.rb, line 226
def start_tag( hash )
        # 開始タグ名が存在しないのはマズイので、スルー
        return "" if hash[ "keyword" ].empty?
        
        if /^!/ =~ hash[ "keyword" ]
                add_single_tag( hash[ "keyword" ] )
        elsif /^\?/ =~ hash[ "keyword" ]
                add_single_tag( hash[ "keyword" ] )
                hash[ "value" ] += "?"
        end
        
        tag = "<#{hash[ 'keyword' ]}>"
        tag = "<#{hash[ 'keyword' ]} #{hash[ 'value' ]}>" if ! hash[ "value" ].empty?
        
        "\n#{tag}"
end