Class: Sass::Tree::Visitors::ToCss

### Home Classes Methods

### In Files

- lib/sass/tree/visitors/to_css.rb

### Parent

Sass::Tree::Visitors::Base

### Methods

- ::new
- #erase!
- #for_node
- #lstrip
- #output
- #prepend!
- #rstrip!
- #visit
- #visit_charset
- #visit_comment
- #visit_cssimport
- #visit_directive
- #visit_keyframerule
- #visit_media
- #visit_prop
- #visit_root
- #visit_rule
- #visit_supports
- #with_tabs

### Class/Module Index

Quicksearch

- Sass
- Sass::BaseEnvironment
- Sass::CSS
- Sass::CacheStores
- Sass::CacheStores::Base
- Sass::CacheStores::Chain
- Sass::CacheStores::Filesystem
- Sass::CacheStores::Memory
- Sass::CacheStores::Null
- Sass::Callbacks
- Sass::Callbacks::InstanceMethods
- Sass::Engine
- Sass::Engine::Line
- Sass::Environment
- Sass::Exec
- Sass::Exec::Base
- Sass::Exec::SassConvert
- Sass::Exec::SassScss
- Sass::Exec::SassScss::Sass::Plugin.compiler
- Sass::Features
- Sass::Importers
- Sass::Importers::Base
- Sass::Importers::Filesystem
- Sass::Logger
- Sass::Logger::Base
- Sass::Logger::LogLevel
- Sass::Logger::LogLevel::ClassMethods
- Sass::Media
- Sass::Media::Query
- Sass::Media::QueryList
- Sass::Plugin
- Sass::Plugin::Compiler
- Sass::Plugin::Configuration
- Sass::Plugin::MerbBootLoader
- Sass::Plugin::Rack
- Sass::Plugin::StalenessChecker
- Sass::ReadOnlyEnvironment
- Sass::Repl
- Sass::SCSS
- Sass::SCSS::CssParser
- Sass::SCSS::Parser
- Sass::SCSS::RX
- Sass::SCSS::ScriptLexer
- Sass::SCSS::ScriptParser
- Sass::SCSS::StaticParser
- Sass::Script
- Sass::Script::CssLexer
- Sass::Script::CssParser
- Sass::Script::Functions
- Sass::Script::Functions::EvaluationContext
- Sass::Script::Lexer
- Sass::Script::Parser
- Sass::Script::Tree
- Sass::Script::Tree::Funcall
- Sass::Script::Tree::Interpolation
- Sass::Script::Tree::ListLiteral
- Sass::Script::Tree::Literal
- Sass::Script::Tree::MapLiteral
- Sass::Script::Tree::Node
- Sass::Script::Tree::Operation
- Sass::Script::Tree::Selector
- Sass::Script::Tree::StringInterpolation
- Sass::Script::Tree::UnaryOperation
- Sass::Script::Tree::Variable
- Sass::Script::Value
- Sass::Script::Value::ArgList
- Sass::Script::Value::Base
- Sass::Script::Value::Bool
- Sass::Script::Value::Color
- Sass::Script::Value::Helpers
- Sass::Script::Value::List
- Sass::Script::Value::Map
- Sass::Script::Value::Null
- Sass::Script::Value::Number
- Sass::Selector
- Sass::Selector::AbstractSequence
- Sass::Selector::Attribute
- Sass::Selector::Class
- Sass::Selector::CommaSequence
- Sass::Selector::Element
- Sass::Selector::Id
- Sass::Selector::Parent
- Sass::Selector::Placeholder
- Sass::Selector::Pseudo
- Sass::Selector::Sequence
- Sass::Selector::Simple
- Sass::Selector::SimpleSequence
- Sass::Selector::Universal
- Sass::SemiGlobalEnvironment
- Sass::Shared
- Sass::Source
- Sass::Source::Map
- Sass::Source::Map::Mapping
- Sass::Source::Position
- Sass::Source::Range
- Sass::Stack
- Sass::Stack::Frame
- Sass::Supports
- Sass::Supports::Condition
- Sass::Supports::Declaration
- Sass::Supports::Interpolation
- Sass::Supports::Negation
- Sass::Supports::Operator
- Sass::SyntaxError
- Sass::Tree
- Sass::Tree::AtRootNode
- Sass::Tree::CharsetNode
- Sass::Tree::CommentNode
- Sass::Tree::ContentNode
- Sass::Tree::CssImportNode
- Sass::Tree::DebugNode
- Sass::Tree::DirectiveNode
- Sass::Tree::EachNode
- Sass::Tree::ErrorNode
- Sass::Tree::ExtendNode
- Sass::Tree::ForNode
- Sass::Tree::FunctionNode
- Sass::Tree::IfNode
- Sass::Tree::ImportNode
- Sass::Tree::KeyframeRuleNode
- Sass::Tree::MediaNode
- Sass::Tree::MixinDefNode
- Sass::Tree::MixinNode
- Sass::Tree::Node
- Sass::Tree::PropNode
- Sass::Tree::ReturnNode
- Sass::Tree::RootNode
- Sass::Tree::RuleNode
- Sass::Tree::SupportsNode
- Sass::Tree::TraceNode
- Sass::Tree::VariableNode
- Sass::Tree::Visitors
- Sass::Tree::Visitors::Base
- Sass::Tree::Visitors::CheckNesting
- Sass::Tree::Visitors::Convert
- Sass::Tree::Visitors::Cssize
- Sass::Tree::Visitors::Cssize::Bubble
- Sass::Tree::Visitors::DeepCopy
- Sass::Tree::Visitors::Extend
- Sass::Tree::Visitors::Perform
- Sass::Tree::Visitors::SetOptions
- Sass::Tree::Visitors::ToCss
- Sass::Tree::WarnNode
- Sass::Tree::WhileNode
- Sass::UnitConversionError
- Sass::Util
- Sass::Util::CrossPlatformRandom
- Sass::Util::MultibyteStringScanner
- Sass::Util::NormalizedMap
- Sass::Util::SubsetMap
- Sass::Util::Test
- Sass::Version
- ActionController
- ActionController::Base
- Object
- OrderedHash

No matching classes.

# Sass::Tree::Visitors::ToCss

A visitor for converting a Sass tree into CSS.

### Constants

NEWLINE

  Avoid allocating lots of new strings for `output`. This is important because `output` is called all the time.

### Attributes

source_mapping[R]

The source mapping for the generated CSS file. This is only set if `build_source_mapping` is passed to the constructor and {Sass::Engine#render} has been run.

### Public Class Methods

new(build_source_mapping = false) click to toggle source

@param build_source_mapping [Boolean] Whether to build a

    \{Sass::Source::Map} while creating the CSS output. The mapping will
    be available from \{#source\_mapping} after the visitor has completed.

    # File lib/sass/tree/visitors/to_css.rb, line 11
    def initialize(build_source_mapping = false)
      @tabs = 0
      @line = 1
      @offset = 1
      @result = ""
      @source_mapping = Sass::Source::Map.new if build_source_mapping
    end

### Public Instance Methods

visit(node) click to toggle source

Runs the visitor on `node`.

@param node [Sass::Tree::Node] The root node of the tree to convert to CSS> @return [String] The CSS output.

    # File lib/sass/tree/visitors/to_css.rb, line 23
    def visit(node)
      super
    rescue Sass::SyntaxError => e
      e.modify_backtrace(:filename => node.filename, :line => node.line)
      raise e
    end

### Protected Instance Methods

erase!(chars) click to toggle source

Move the output cursor back `chars` characters.

    # File lib/sass/tree/visitors/to_css.rb, line 55
    def erase!(chars)
      return if chars == 0
      str = @result.slice!(-chars..-1)
      newlines = str.count("\n")
      if newlines > 0
        @line -= newlines
        @offset = @result[@result.rindex("\n") || 0..-1].size
      else
        @offset -= chars
      end
    end

for_node(node, attr_prefix = nil) click to toggle source

Associate all output produced in a block with a given node. Used for source mapping.

    # File lib/sass/tree/visitors/to_css.rb, line 41
    def for_node(node, attr_prefix = nil)
      return yield unless @source_mapping
      start_pos = Sass::Source::Position.new(@line, @offset)
      yield

      range_attr = attr_prefix ? :"#{attr_prefix}_source_range" : :source_range
      return if node.invisible? || !node.send(range_attr)
      source_range = node.send(range_attr)
      target_end_pos = Sass::Source::Position.new(@line, @offset)
      target_range = Sass::Source::Range.new(start_pos, target_end_pos, nil)
      @source_mapping.add(source_range, target_range)
    end

lstrip() click to toggle source

lstrip the first output in the given block.

    # File lib/sass/tree/visitors/to_css.rb, line 96
    def lstrip
      old_lstrip = @lstrip
      @lstrip = true
      yield
    ensure
      @lstrip = @lstrip && old_lstrip
    end

output(s) click to toggle source

Add `s` to the output string and update the line and offset information accordingly.

    # File lib/sass/tree/visitors/to_css.rb, line 73
    def output(s)
      if @lstrip
        s = s.gsub(/\A\s+/, "")
        @lstrip = false
      end

      newlines = s.count(NEWLINE)
      if newlines > 0
        @line += newlines
        @offset = s[s.rindex(NEWLINE)..-1].size
      else
        @offset += s.size
      end

      @result << s
    end

prepend!(prefix) click to toggle source

Prepend `prefix` to the output string.

    # File lib/sass/tree/visitors/to_css.rb, line 105
    def prepend!(prefix)
      @result.insert 0, prefix
      return unless @source_mapping

      line_delta = prefix.count("\n")
      offset_delta = prefix.gsub(/.*\n/, '').size
      @source_mapping.shift_output_offsets(offset_delta)
      @source_mapping.shift_output_lines(line_delta)
    end

rstrip!() click to toggle source

Strip all trailing whitespace from the output string.

    # File lib/sass/tree/visitors/to_css.rb, line 91
    def rstrip!
      erase! @result.length - 1 - (@result.rindex(/[^\s]/) || -1)
    end

visit_charset(node) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 148
    def visit_charset(node)
      for_node(node) {output("@charset \"#{node.name}\";")}
    end

visit_comment(node) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 152
    def visit_comment(node)
      return if node.invisible?
      spaces = ('  ' * [@tabs - node.resolved_value[/^ */].size, 0].max)

      content = node.resolved_value.gsub(/^/, spaces)
      if node.type == :silent
        content.gsub!(%{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"}
      end
      if (node.style == :compact || node.style == :compressed) && node.type != :loud
        content.gsub!(/\n +(\* *(?!\/))?/, ' ')
      end
      for_node(node) {output(content)}
    end

visit_cssimport(node) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 242
    def visit_cssimport(node)
      visit_directive(node)
    end

visit_directive(node) click to toggle source

@comment

    rubocop:disable MethodLength

    # File lib/sass/tree/visitors/to_css.rb, line 168
    def visit_directive(node)
      was_in_directive = @in_directive
      tab_str = '  ' * @tabs
      if !node.has_children || node.children.empty?
        output(tab_str)
        for_node(node) {output(node.resolved_value)}
        output(!node.has_children ? ";" : " {}")
        return
      end

      @in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
      output(tab_str) if node.style != :compressed
      for_node(node) {output(node.resolved_value)}
      output(node.style == :compressed ? "{" : " {")
      output(node.style == :compact ? ' ' : "\n") if node.style != :compressed

      was_prop = false
      first = true
      node.children.each do |child|
        next if child.invisible?
        if node.style == :compact
          if child.is_a?(Sass::Tree::PropNode)
            with_tabs(first || was_prop ? 0 : @tabs + 1) do
              visit(child)
              output(' ')
            end
          else
            if was_prop
              erase! 1
              output "\n"
            end

            if first
              lstrip {with_tabs(@tabs + 1) {visit(child)}}
            else
              with_tabs(@tabs + 1) {visit(child)}
            end

            rstrip!
            output "\n"
          end
          was_prop = child.is_a?(Sass::Tree::PropNode)
          first = false
        elsif node.style == :compressed
          output(was_prop ? ";" : "")
          with_tabs(0) {visit(child)}
          was_prop = child.is_a?(Sass::Tree::PropNode)
        else
          with_tabs(@tabs + 1) {visit(child)}
          output "\n"
        end
      end
      rstrip!
      if node.style == :expanded
        output("\n#{tab_str}")
      elsif node.style != :compressed
        output(" ")
      end
      output("}")
    ensure
      @in_directive = was_in_directive
    end

visit_keyframerule(node) click to toggle source

@comment

    rubocop:enable MethodLength

    # File lib/sass/tree/visitors/to_css.rb, line 353
    def visit_keyframerule(node)
      visit_directive(node)
    end

visit_media(node) click to toggle source

@comment

    rubocop:enable MethodLength

    # File lib/sass/tree/visitors/to_css.rb, line 233
    def visit_media(node)
      with_tabs(@tabs + node.tabs) {visit_directive(node)}
      output("\n") if node.style != :compressed && node.group_end
    end

visit_prop(node) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 246
    def visit_prop(node)
      return if node.resolved_value.empty?
      tab_str = '  ' * (@tabs + node.tabs)
      output(tab_str)
      for_node(node, :name) {output(node.resolved_name)}
      if node.style == :compressed
        output(":")
        for_node(node, :value) {output(node.resolved_value)}
      else
        output(": ")
        for_node(node, :value) {output(node.resolved_value)}
        output(";")
      end
    end

visit_root(node) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 115
    def visit_root(node)
      node.children.each do |child|
        next if child.invisible?
        visit(child)
        unless node.style == :compressed
          output "\n"
          if child.is_a?(Sass::Tree::DirectiveNode) && child.has_children && !child.bubbles?
            output "\n"
          end
        end
      end
      rstrip!
      return "" if @result.empty?

      output "\n"

      unless Sass::Util.ruby1_8? || @result.ascii_only?
        if node.style == :compressed
          # A byte order mark is sufficient to tell browsers that this
          # file is UTF-8 encoded, and will override any other detection
          # methods as per http://encoding.spec.whatwg.org/#decode-and-encode.
          prepend! "\uFEFF"
        else
          prepend! "@charset \"UTF-8\";\n"
        end
      end

      @result
    rescue Sass::SyntaxError => e
      e.sass_template ||= node.template
      raise e
    end

visit_rule(node) click to toggle source

@comment

    rubocop:disable MethodLength

    # File lib/sass/tree/visitors/to_css.rb, line 263
    def visit_rule(node)
      with_tabs(@tabs + node.tabs) do
        rule_separator = node.style == :compressed ? ',' : ', '
        line_separator =
          case node.style
          when :nested, :expanded; "\n"
          when :compressed; ""
          else; " "
          end
        rule_indent = '  ' * @tabs
        per_rule_indent, total_indent = if [:nested, :expanded].include?(node.style)
                                          [rule_indent, '']
                                        else
                                          ['', rule_indent]
                                        end

        joined_rules = node.resolved_rules.members.map do |seq|
          next if seq.has_placeholder?
          rule_part = seq.to_s
          if node.style == :compressed
            rule_part.gsub!(/([^,])\s*\n\s*/, '\1 ')
            rule_part.gsub!(/\s*([,+>])\s*/, '\1')
            rule_part.strip!
          end
          rule_part
        end.compact.join(rule_separator)

        joined_rules.lstrip!
        joined_rules.gsub!(/\s*\n\s*/, "#{line_separator}#{per_rule_indent}")

        old_spaces = '  ' * @tabs
        if node.style != :compressed
          if node.options[:debug_info] && !@in_directive
            visit(debug_info_rule(node.debug_info, node.options))
            output "\n"
          elsif node.options[:trace_selectors]
            output("#{old_spaces}/* ")
            output(node.stack_trace.gsub("\n", "\n   #{old_spaces}"))
            output(" */\n")
          elsif node.options[:line_comments]
            output("#{old_spaces}/* line #{node.line}")

            if node.filename
              relative_filename =
                if node.options[:css_filename]
                  begin
                    Sass::Util.relative_path_from(
                      node.filename, File.dirname(node.options[:css_filename])).to_s
                  rescue ArgumentError
                    nil
                  end
                end
              relative_filename ||= node.filename
              output(", #{relative_filename}")
            end

            output(" */\n")
          end
        end

        end_props, trailer, tabs  = '', '', 0
        if node.style == :compact
          separator, end_props, bracket = ' ', ' ', ' { '
          trailer = "\n" if node.group_end
        elsif node.style == :compressed
          separator, bracket = ';', '{'
        else
          tabs = @tabs + 1
          separator, bracket = "\n", " {\n"
          trailer = "\n" if node.group_end
          end_props = (node.style == :expanded ? "\n" + old_spaces : ' ')
        end
        output(total_indent + per_rule_indent)
        for_node(node, :selector) {output(joined_rules)}
        output(bracket)

        with_tabs(tabs) do
          node.children.each_with_index do |child, i|
            output(separator) if i > 0
            visit(child)
          end
        end

        output(end_props)
        output("}" + trailer)
      end
    end

visit_supports(node) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 238
    def visit_supports(node)
      visit_media(node)
    end

with_tabs(tabs) click to toggle source

    # File lib/sass/tree/visitors/to_css.rb, line 32
    def with_tabs(tabs)
      old_tabs, @tabs = @tabs, tabs
      yield
    ensure
      @tabs = old_tabs
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.