Class: Kwartz::Handler

Inherits:
Object
  • Object
show all
Includes:
Assertion, ConvertErrorHelper, Expander, HandlerHelper
Defined in:
lib/kwartz/converter.rb

Overview

(abstract) handle directives

Constant Summary collapse

@@class_table =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Expander

#expand_element_info, #expand_statement, #expand_statements

Methods included from Assertion

assert

Methods included from HandlerHelper

#_last_stmt_kind, #add_foreach_stmts, #add_native_code, #add_native_expr_with_default, #build_print_args, #build_print_expr_stmt, #build_print_stmt, #create_text_print_stmt, #error_if_empty_tag, #error_when_last_stmt_is_not_if, #etag_stmt, #expand_attr_vars, #expand_attr_vars_in_native_expr, #expand_attr_vars_in_native_stmt, #stag_stmt, #wrap_content_with_native_stmt, #wrap_element_with_native_stmt

Methods included from ConvertErrorHelper

#convert_error

Constructor Details

#initialize(rulesets = [], properties = {}) ⇒ Handler

Returns a new instance of Handler.



629
630
631
632
633
634
635
636
# File 'lib/kwartz/converter.rb', line 629

def initialize(rulesets=[], properties={})
  @ruleset_table = {}
  rulesets.each { |ruleset| _register_ruleset(ruleset) }
  @elem_info_table = {}
  @delspan = properties.fetch(:delspan, Config::PROPERTY_DELSPAN)  # delete dummy <span> tag or not
  @odd     = properties.fetch(:odd,     Config::PROPERTY_ODD)      # "'odd'"
  @even    = properties.fetch(:even,    Config::PROPERTY_EVEN)     # "'even'"
end

Instance Attribute Details

#evenObject (readonly)

Returns the value of attribute even.



637
638
639
# File 'lib/kwartz/converter.rb', line 637

def even
  @even
end

#filenameObject

Returns the value of attribute filename.



638
639
640
# File 'lib/kwartz/converter.rb', line 638

def filename
  @filename
end

#oddObject (readonly)

Returns the value of attribute odd.



637
638
639
# File 'lib/kwartz/converter.rb', line 637

def odd
  @odd
end

Class Method Details

.get_class(lang) ⇒ Object



931
932
933
# File 'lib/kwartz/converter.rb', line 931

def self.get_class(lang)
  return @@class_table[lang]
end

.register_class(lang, klass) ⇒ Object



926
927
928
# File 'lib/kwartz/converter.rb', line 926

def self.register_class(lang, klass)
  @@class_table[lang] = klass
end

Instance Method Details

#_elem_info_tableObject

:nodoc:



665
666
667
# File 'lib/kwartz/converter.rb', line 665

def _elem_info_table    # :nodoc:
  return @elem_info_table
end

#_import_element_info_from_handler(handler, names = nil) ⇒ Object

:nodoc:



670
671
672
673
674
675
676
677
678
679
680
681
# File 'lib/kwartz/converter.rb', line 670

def _import_element_info_from_handler(handler, names=nil) # :nodoc:
  if names
    regexp_list = names.collect { |name| Kwartz::Util.pattern_to_regexp(name) }
    handler._elem_info_table.each do |name, elem_info|
      if regexp_list.any? { |regexp| regexp =~ name }
        @elem_info_table[name] = elem_info
      end
    end
  else
    @elem_info_table.update(handler._elem_info_table)
  end
end

#apply_rulesets(elem_info) ⇒ Object



900
901
902
903
904
905
906
907
908
909
910
# File 'lib/kwartz/converter.rb', line 900

def apply_rulesets(elem_info)
  assert unless !elem_info.applied
  elem_info.applied = true
  tagname = elem_info.stag_info.tagname
  classname = elem_info.attr_info['class']
  #idname = elem_info.name || elem_info.attr_info['id']
  ruleset = nil
  elem_info.apply(ruleset) if ruleset = get_ruleset(tagname)
  elem_info.apply(ruleset) if classname && (ruleset = get_ruleset('.'+classname))
  #elem_info.apply(ruleset) if idname && (ruleset = get_ruleset('#'+idname))
end

#extract(elem_name, content_only = false) ⇒ Object



913
914
915
916
917
918
919
920
# File 'lib/kwartz/converter.rb', line 913

def extract(elem_name, content_only=false)
  elem_info = @elem_info_table[elem_name]
  elem_info or raise convert_error("element '#{elem_name}' not found.", nil)
  stmt_list = []
  expand_element_info(elem_info, stmt_list, content_only)
  #stmt_list << build_print_stmt(etag_info, nil, nil)
  return stmt_list
end

#get_element_info(name) ⇒ Object

for Expander module



655
656
657
# File 'lib/kwartz/converter.rb', line 655

def get_element_info(name)  # for Expander module
  return @elem_info_table[name]
end

#get_ruleset(selector) ⇒ Object

for Expander module and Converter class



650
651
652
# File 'lib/kwartz/converter.rb', line 650

def get_ruleset(selector)  # for Expander module and Converter class
  return @ruleset_table[selector]
end

#handle(directive, elem_info, stmt_list) ⇒ Object

handle directives (‘stag’, ‘etag’, ‘elem’, ‘cont’(=‘value’))

return true if directive name is one of ‘stag’, ‘etag’, ‘elem’, ‘cont’, and ‘value’, else return false.



772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
# File 'lib/kwartz/converter.rb', line 772

def handle(directive, elem_info, stmt_list)
  d_name = directive.name
  d_arg  = directive.arg
  d_str  = directive.str
  d_attr = directive.dattr
  e = elem_info
  linenum = e.stag_info.linenum

  case d_name

  when nil
    assert false

  when :dummy
    # nothing

  when :id, :mark
    unless d_arg =~ /\A([-\w]+)\z/ || d_arg =~ /\A'([-\w]+)'\z/
      raise convert_error("'#{d_str}': invalid marking name.", linenum)
    end
    name = $1
    if get_element_info(name)
      unless Config::ALLOW_DUPLICATE_ID
        previous_linenum = get_element_info(name).stag_info.linenum
        msg = "'#{d_str}': id '#{name}' is already used at line #{previous_linenum}."
        raise convert_error(msg, linenum)
      end
    end
    ruleset = get_ruleset('#' + name)
    elem_info.apply(ruleset) if ruleset
    register_element_info(name, elem_info)
    #stmt_list << ExpandStatement.new(:element, name)     # lazy expantion
    expand_element_info(elem_info, stmt_list)

  when :stag, :Stag, :STAG
    error_if_empty_tag(elem_info, d_str)
    flag_escape = d_name == :stag ? nil : (d_name == :Stag)
    expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
    expr = NativeExpression.new(expr_str, flag_escape)
    stmt_list << build_print_expr_stmt(expr, e.stag_info, nil)
    stmt_list.concat(e.cont_stmts)
    stmt_list << etag_stmt(elem_info)

  when :etag, :Etag, :ETAG
    error_if_empty_tag(elem_info, d_str)
    flag_escape = d_name == :etag ? nil : (d_name == :Etag)
    expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
    expr = NativeExpression.new(expr_str, flag_escape)
    stmt_list << stag_stmt(elem_info)
    stmt_list.concat(e.cont_stmts)
    stmt_list << build_print_expr_stmt(expr, nil, e.etag_info)

  when :elem, :Elem, :ELEM
    flag_escape = d_name == :elem ? nil : (d_name == :Elem)
    expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
    expr = NativeExpression.new(expr_str, flag_escape)
    stmt_list << build_print_expr_stmt(expr, e.stag_info, e.etag_info)

  when :cont, :Cont, :CONT, :value, :Value, :VALUE
    error_if_empty_tag(elem_info, directive.str)
    e.stag_info.tail_space = e.etag_info.head_space = nil    # delete spaces
    pargs = build_print_args(e.stag_info, e.attr_info, e.append_exprs)
    flag_escape = (d_name == :cont || d_name == :value) ? nil : (d_name == :Cont || d_name == :Value)
    expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
    pargs << NativeExpression.new(expr_str, flag_escape)
    pargs << e.etag_info.tag_text if e.etag_info.tagname
    stmt_list << PrintStatement.new(pargs)

  when :attr, :Attr, :ATTR
    unless d_arg =~ self.mapping_pattern()     # ex. /\A'([-:\w]+)'\s+(.*)\z/
      raise convert_error("'#{d_str}': invalid attr pattern.", linenum)
    end
    aname = $1;  avalue = $2
    flag_escape = d_name == :attr ? nil : (d_name == :Attr)
    expr_str = d_attr == 'id' ? parse_expr_str(avalue, linenum) : avalue
    e.attr_info[aname] = NativeExpression.new(expr_str, flag_escape)

  when :append, :Append, :APPEND
    flag_escape = d_name == :append ? nil : (d_name == :Append)
    expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
    e.append_exprs << NativeExpression.new(expr_str, flag_escape)

  when :replace_element_with_element, :replace_element_with_content,
       :replace_content_with_element, :replace_content_with_content
    arr = d_name.to_s.split(/_/)
    replace_cont = arr[1] == 'content'
    with_content = arr[3] == 'content'
    name = d_arg
    #
    error_if_empty_tag(elem_info, d_str)   if replace_cont
    stmt_list << stag_stmt(elem_info) if replace_cont
    #stmt_list << ExpandStatement.new(:element, name)
    elem_info2 = @elem_info_table[name]
    unless elem_info
      raise convert_error("'#{d_str}': element '#{name}' not found.", linenum)
    end
    expand_element_info(elem_info2, stmt_list, with_content)
    stmt_list << etag_stmt(elem_info) if replace_cont

  when :replace_element_with, :replace_content_with, :replace, :placeholder
    unless d_arg =~ /\A_?(element|content)\(["']?(\w+)["']?\)\z/
      raise convert_error("'#{d_str}': invalid #{d_name} format.", linenum)
    end
    kind = $1
    name = $2
    replace_cont = d_name == :replace_content_with || d_name == :placeholder
    with_content = kind == 'content'
    #
    error_if_empty_tag(elem_info, d_str) if replace_cont
    stmt_list << stag_stmt(elem_info) if replace_cont
    #stmt_list << ExpandStatement.new(:element, name)
    elem_info2 = @elem_info_table[name]
    unless elem_info2
      msg = "'#{d_str}': element '#{name}' not found."
      raise convert_error(msg, linenum)
    end
    expand_element_info(elem_info2, stmt_list, with_content)
    stmt_list << etag_stmt(elem_info) if replace_cont

  else
    return false
  end #case

  return true

end

#handle_directives(directive, elem_info, stmt_list) ⇒ Object



710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
# File 'lib/kwartz/converter.rb', line 710

def handle_directives(directive, elem_info, stmt_list)
  e = elem_info
  linenum = elem_info.stag_info.linenum
  append_exprs = nil

  if directive.dattr == 'id'
    ## nothing
  else
    ## handle 'attr:' and 'append:' directives
    d_str = nil
    directive.str.split(/;/).each do |d_str|
      d_str.strip!
      unless d_str =~ self.directive_pattern     # ex. /\A(\w+):\s*(.*)\z/
        raise convert_error("'#{d_str}': invalid directive pattern", linenum)
      end
      d_name = $1.intern   # directive name
      d_arg  = $2 || ''    # directive arg
      case d_name
      when :attr, :Attr, :ATTR
        directive2 = Directive.new(:name=>d_name, :arg=>d_arg, :sr=>d_str)
        handle(directive2, elem_info, stmt_list)
      when :append, :Append, :APPEND
        append_exprs ||= []
        elem_info.append_exprs = append_exprs
        directive2 = Directive.new(:name=>d_name, :arg=>d_arg, :sr=>d_str)
        handle(directive2, elem_info, stmt_list)
      else
        if directive.name
          raise convert_error("'#{d_str}': not available with '#{directive.name}' directive.", linenum)
        end
        directive.name = d_name
        directive.arg  = d_arg
        directive.str  = d_str
      end #case
    end
  end

  ## remove dummy <span> tag
  if @delspan && elem_info.dummy_span_tag?('span')
    #e.stag_info.tagname = e.etag_info.tagname = nil
    e.stag_info.clear_as_dummy_tag()
    e.etag_info.clear_as_dummy_tag()
  end

  ## handle other directives
  if directive.name
    handled = handle(directive, elem_info, stmt_list)
    handled or raise convert_error("'#{directive.str}': unknown directive.", linenum)
  else   # for 'attr' and 'append' directive
    assert unless !elem_info.attr_info.empty? || !elem_info.append_exprs.empty?
    stmt_list << stag_stmt(elem_info)
    stmt_list.concat(elem_info.cont_stmts)
    stmt_list << etag_stmt(elem_info) if elem_info.etag_info   # when empty-tag
  end

end

#register_element_info(name, elem_info) ⇒ Object



660
661
662
# File 'lib/kwartz/converter.rb', line 660

def register_element_info(name, elem_info)
  @elem_info_table[name] = elem_info
end