\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef/embedded/lib/ruby/gems/2.7.0/gems/coderay-1.1.3/lib/coderay/scanners/

Viewing File: sass.rb

module CodeRay
module Scanners
  
  # A scanner for Sass.
  class Sass < CSS
    
    register_for :sass
    file_extension 'sass'
    
  protected
    
    def setup
      @state = :initial
    end
    
    def scan_tokens encoder, options
      states = Array(options[:state] || @state).dup
      
      encoder.begin_group :string if states.last == :sqstring || states.last == :dqstring
      
      until eos?
        
        if bol? && (match = scan(/(?>( +)?(\/[\*\/])(.+)?)(?=\n)/))
          encoder.text_token self[1], :space if self[1]
          encoder.begin_group :comment
          encoder.text_token self[2], :delimiter
          encoder.text_token self[3], :content if self[3]
          if match = scan(/(?:\n+#{self[1]} .*)+/)
            encoder.text_token match, :content
          end
          encoder.end_group :comment
        elsif match = scan(/\n|[^\n\S]+\n?/)
          encoder.text_token match, :space
          if match.index(/\n/)
            value_expected = false
            states.pop if states.last == :include
          end
        
        elsif states.last == :sass_inline && (match = scan(/\}/))
          encoder.text_token match, :inline_delimiter
          encoder.end_group :inline
          states.pop
        
        elsif case states.last
          when :initial, :media, :sass_inline
            if match = scan(/(?>#{RE::Ident})(?!\()/ox)
              encoder.text_token match, value_expected ? :value : (check(/.*:(?![a-z])/) ? :key : :tag)
              next
            elsif !value_expected && (match = scan(/\*/))
              encoder.text_token match, :tag
              next
            elsif match = scan(RE::Class)
              encoder.text_token match, :class
              next
            elsif match = scan(RE::Id)
              encoder.text_token match, :id
              next
            elsif match = scan(RE::PseudoClass)
              encoder.text_token match, :pseudo_class
              next
            elsif match = scan(RE::AttributeSelector)
              # TODO: Improve highlighting inside of attribute selectors.
              encoder.text_token match[0,1], :operator
              encoder.text_token match[1..-2], :attribute_name if match.size > 2
              encoder.text_token match[-1,1], :operator if match[-1] == ?]
              next
            elsif match = scan(/(\=|@mixin +)#{RE::Ident}/o)
              encoder.text_token match, :function
              next
            elsif match = scan(/@import\b/)
              encoder.text_token match, :directive
              states << :include
              next
            elsif match = scan(/@media\b/)
              encoder.text_token match, :directive
              # states.push :media_before_name
              next
            end
          
          when :block
            if match = scan(/(?>#{RE::Ident})(?!\()/ox)
              if value_expected
                encoder.text_token match, :value
              else
                encoder.text_token match, :key
              end
              next
            end
            
          when :sqstring, :dqstring
            if match = scan(states.last == :sqstring ? /(?:[^\n\'\#]+|\\\n|#{RE::Escape}|#(?!\{))+/o : /(?:[^\n\"\#]+|\\\n|#{RE::Escape}|#(?!\{))+/o)
              encoder.text_token match, :content
            elsif match = scan(/['"]/)
              encoder.text_token match, :delimiter
              encoder.end_group :string
              states.pop
            elsif match = scan(/#\{/)
              encoder.begin_group :inline
              encoder.text_token match, :inline_delimiter
              states.push :sass_inline
            elsif match = scan(/ \\ | $ /x)
              encoder.end_group states.last
              encoder.text_token match, :error unless match.empty?
              states.pop
            else
              raise_inspect "else case #{states.last} reached; %p not handled." % peek(1), encoder
            end
          
          when :include
            if match = scan(/[^\s'",]+/)
              encoder.text_token match, :include
              next
            end
          
          else
            #:nocov:
            raise_inspect 'Unknown state: %p' % [states.last], encoder
            #:nocov:
            
          end
          
        elsif match = scan(/\$#{RE::Ident}/o)
          encoder.text_token match, :variable
          next
        
        elsif match = scan(/&/)
          encoder.text_token match, :local_variable
          
        elsif match = scan(/\+#{RE::Ident}/o)
          encoder.text_token match, :include
          value_expected = true
          
        elsif match = scan(/\/\*(?:.*?\*\/|.*)|\/\/.*/)
          encoder.text_token match, :comment
          
        elsif match = scan(/#\{/)
          encoder.begin_group :inline
          encoder.text_token match, :inline_delimiter
          states.push :sass_inline
          
        elsif match = scan(/\{/)
          value_expected = false
          encoder.text_token match, :operator
          states.push :block
          
        elsif match = scan(/\}/)
          value_expected = false
          encoder.text_token match, :operator
          if states.last == :block || states.last == :media
            states.pop
          end
          
        elsif match = scan(/['"]/)
          encoder.begin_group :string
          encoder.text_token match, :delimiter
          if states.include? :sass_inline
            # no nesting, just scan the string until delimiter
            content = scan_until(/(?=#{match}|\}|\z)/)
            encoder.text_token content, :content unless content.empty?
            encoder.text_token match, :delimiter if scan(/#{match}/)
            encoder.end_group :string
          else
            states.push match == "'" ? :sqstring : :dqstring
          end
          
        elsif match = scan(/#{RE::Function}/o)
          encoder.begin_group :function
          start = match[/^[-\w]+\(/]
          encoder.text_token start, :delimiter
          if match[-1] == ?)
            encoder.text_token match[start.size..-2], :content
            encoder.text_token ')', :delimiter
          else
            encoder.text_token match[start.size..-1], :content if start.size < match.size
          end
          encoder.end_group :function
          
        elsif match = scan(/[a-z][-a-z_]*(?=\()/o)
          encoder.text_token match, :predefined
          
        elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox)
          encoder.text_token match, :float
          
        elsif match = scan(/#{RE::HexColor}/o)
          encoder.text_token match, :color
          
        elsif match = scan(/! *(?:important|optional)/)
          encoder.text_token match, :important
          
        elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/)
          encoder.text_token match, :color
          
        elsif match = scan(/@else if\b|#{RE::AtKeyword}/o)
          encoder.text_token match, :directive
          value_expected = true
          
        elsif match = scan(/ == | != | [-+*\/>~:;,.=()] /x)
          if match == ':'
            value_expected = true
          elsif match == ';'
            value_expected = false
          end
          encoder.text_token match, :operator
          
        else
          encoder.text_token getch, :error
          
        end
        
      end
      
      states.pop if states.last == :include
      
      if options[:keep_state]
        @state = states.dup
      end
      
      while state = states.pop
        if state == :sass_inline
          encoder.end_group :inline
        elsif state == :sqstring || state == :dqstring
          encoder.end_group :string
        end
      end
      
      encoder
    end
    
  end
  
end
end