def parse
      ## pass 1) check for (css style) classes and data attributes
      ## check for css style classes
      from = 0
      while( pos = @content.index( /<!-- _S9(SLIDE|STYLE)_(.*?)-->/m, from ))
        logger.debug "  adding css classes from pi >#{$1.downcase}<: >#{$2.strip}<"

        from = Regexp.last_match.end(0)  # continue search later from here
        
        values = $2.strip.dup
        
        # remove data values (eg. x=-20 scale=4) and store in data hash
        values.gsub!( /([-\w]+)[ \t]*=[ \t]*([-\w\.]+)/ ) do |_|
          logger.debug "    adding data pair: key=>#{$1.downcase}< value=>#{$2}<"
          @data[ $1.downcase.dup ] = $2.dup
          " "  # replace w/ space
        end
        
        values.strip!  # remove spaces  # todo: use squish or similar and check for empty string
                
        if @classes.nil?
          @classes = values
        else
          @classes << " #{values}"
        end
      end

      ## pass 2) split slide source into header (optional) and content/body

      ## todo: add option split on h1/h2 etc.

      # try to extract first header using non-greedy .+? pattern;
      # tip test regex online at rubular.com
      #  note/fix: needs to get improved to also handle case for h1 wrapped into div

      if @header_level == 1
        pattern = /^(.*?)(<h1.*?>.*?<\/h1>)(.*)/m
      else # assume header level 2
        ## note: header_level 2 also incl. header_level 1 slides
        pattern = /^(.*?)(<(?:h1|h2).*?>.*?<\/(?:h1|h2)>)(.*)/m
      end

      if @content =~ pattern
        @header  = $2
        @content_without_header = ($1 ? $1 : '') + ($3 ? $3 : '')
        logger.debug "  adding slide with header:\n#{@header}"
      else
        @header = nil    # todo: set to '' empty string? why not?
        @content_without_header = @content
        logger.debug "  adding slide with *no* header:\n#{@content}"
      end
    end
def parse
      ## pass 1) check for (css style) classes and data attributes
      ## check for css style classes
      from = 0
      while( pos = @content.index( /<!-- _S9(SLIDE|STYLE)_(.*?)-->/m, from ))
        logger.debug "  adding css classes from pi >#{$1.downcase}<: >#{$2.strip}<"

        from = Regexp.last_match.end(0)  # continue search later from here
        
        values = $2.strip.dup
        
        # remove data values (eg. x=-20 scale=4) and store in data hash
        values.gsub!( /([-\w]+)[ \t]*=[ \t]*([-\w\.]+)/ ) do |_|
          logger.debug "    adding data pair: key=>#{$1.downcase}< value=>#{$2}<"
          @data[ $1.downcase.dup ] = $2.dup
          " "  # replace w/ space
        end
        
        values.strip!  # remove spaces  # todo: use squish or similar and check for empty string
                
        if @classes.nil?
          @classes = values
        else
          @classes << " #{values}"
        end
      end

      ## pass 2) split slide source into header (optional) and content/body

      ## todo: add option split on h1/h2 etc.

      # try to extract first header using non-greedy .+? pattern;
      # tip test regex online at rubular.com
      #  note/fix: needs to get improved to also handle case for h1 wrapped into div

      if @header_level == 1
        pattern = /^(.*?)(<h1.*?>.*?<\/h1>)(.*)/m
      else # assume header level 2
        ## note: header_level 2 also incl. header_level 1 slides
        pattern = /^(.*?)(<(?:h1|h2).*?>.*?<\/(?:h1|h2)>)(.*)/m
      end

      if @content =~ pattern
        @header  = $2
        @content_without_header = ($1 ? $1 : '') + ($3 ? $3 : '')
        logger.debug "  adding slide with header:\n#{@header}"
      else
        @header = nil    # todo: set to '' empty string? why not?
        @content_without_header = @content
        logger.debug "  adding slide with *no* header:\n#{@content}"
      end
    end
def to_drop() SlideDrop.new( self ); end  -- add - why? why not??