require 'cgi' module Rouge module Formatters class HTMLGitlab < Rouge::Formatter tag 'html_gitlab' # Creates a new Rouge::Formatter::HTMLGitlab instance. # # [+nowrap+] If set to True, don't wrap the output at all, not # even inside a
 tag (default: false).
      # [+cssclass+]        CSS class for the wrapping 
tag # (default: 'highlight'). # [+linenos+] If set to 'table', output line numbers as a table # with two cells, one containing the line numbers, # the other the whole code. This is copy paste friendly, # but may cause alignment problems with some browsers # or fonts. If set to 'inline', the line numbers will # be integrated in the
 tag that contains
      #                     the code (default: nil).
      # [+linenostart+]     The line number for the first line (default: 1).
      # [+lineanchors+]     If set to true the formatter will wrap each output
      #                     line in an anchor tag with a name of L-linenumber.
      #                     This allows easy linking to certain lines
      #                     (default: false).
      # [+lineanchorsid+]   If lineanchors is true the name of the anchors can
      #                     be changed with lineanchorsid to e.g. foo-linenumber
      #                     (default: 'L').
      # [+anchorlinenos+]   If set to true, will wrap line numbers in 
      #                     tags. Used in combination with linenos and lineanchors
      #                     (default: false).
      # [+inline_theme+]    Inline CSS styles for the 
 tag (default: false).
      def initialize(
          nowrap: false,
          cssclass: 'highlight',
          linenos: nil,
          linenostart: 1,
          lineanchors: false,
          lineanchorsid: 'L',
          anchorlinenos: false,
          inline_theme: nil
      )
        @nowrap = nowrap
        @cssclass = cssclass
        @linenos = linenos
        @linenostart = linenostart
        @lineanchors = lineanchors
        @lineanchorsid = lineanchorsid
        @anchorlinenos = anchorlinenos
        @inline_theme = Theme.find(inline_theme).new if inline_theme.is_a?(String)
      end

      def render(tokens)
        case @linenos
        when 'table'
          render_tableized(tokens)
        when 'inline'
          render_untableized(tokens)
        else
          render_untableized(tokens)
        end
      end

      alias_method :format, :render

      private

      def render_untableized(tokens)
        data = process_tokens(tokens)

        html = ''
        html << "
" unless @nowrap
        html << wrap_lines(data[:code])
        html << "
\n" unless @nowrap html end def render_tableized(tokens) data = process_tokens(tokens) html = '' html << "
" unless @nowrap html << '' html << "' html << "' html << '
"
        html << wrap_linenos(data[:numbers])
        html << '
"
        html << wrap_lines(data[:code])
        html << '
' html << '
' unless @nowrap html end def process_tokens(tokens) rendered = [] current_line = '' tokens.each do |tok, val| # In the case of multi-line values (e.g. comments), we need to apply # styling to each line since span elements are inline. val.lines.each do |line| stripped = line.chomp current_line << span(tok, stripped) if line.end_with?("\n") rendered << current_line current_line = '' end end end # Add leftover text rendered << current_line if current_line.present? num_lines = rendered.size numbers = (@linenostart..num_lines + @linenostart - 1).to_a { numbers: numbers, code: rendered } end def wrap_linenos(numbers) if @anchorlinenos numbers.map! do |number| "
#{number}" end end numbers.join("\n") end def wrap_lines(lines) if @lineanchors lines = lines.each_with_index.map do |line, index| number = index + @linenostart if @linenos == 'inline' "" \ "#{number}" \ "#{line}" \ '' else "#{line}" \ '' end end lines.join("\n") else if @linenos == 'inline' lines = lines.each_with_index.map do |line, index| number = index + @linenostart "#{number}#{line}" end lines.join("\n") else lines.join("\n") end end end def span(tok, val) # http://stackoverflow.com/a/1600584/2587286 val = CGI.escapeHTML(val) if tok.shortname.empty? val else if @inline_theme rules = @inline_theme.style_for(tok).rendered_rules "" else "#{val}" end end end end end end