lib/xass.rb in xass-0.1.7 vs lib/xass.rb in xass-0.1.8

- old
+ new

@@ -1,67 +1,107 @@ require_relative 'initialize' -module Sass - module Tree - class RootNode - alias :old_render :render +module Sass::Tree + class Visitors::Perform + def visit_mixin(node) + include_loop = true + handle_include_loop!(node) if @stack.any? {|e| e[:name] == node.name} + include_loop = false - def render - old_render.split('/*').map { |x| - next x unless x.match(/^ line [0-9]+, /) - a, b = x.split("\n", 2) - m = a.match(/\/app\/assets\/stylesheets\/([^. ]+)\./) - next "#{a}\n#{b}" unless m - selector = class_replaced_selector(b.split("\n")[0].strip[0...-1].strip, class_prefix(m[1])) - "#{a}\n#{selector} {\n#{b.split("\n", 2)[1]}" - }.join('/*') + @stack.push(:filename => node.filename, :line => node.line, :name => node.name) + raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin = @environment.mixin(node.name) + + if node.children.any? && !mixin.has_content + raise Sass::SyntaxError.new(%Q{Mixin "#{node.name}" does not accept a content block.}) end - private + args = node.args.map {|a| a.perform(@environment)} + keywords = Sass::Util.map_hash(node.keywords) {|k, v| [k, v.perform(@environment)]} + splat = node.splat.perform(@environment) if node.splat - def class_replaced_selector(selector, class_prefix) - doc = CSSPool.CSS("#{selector} {}") - replace_class(doc, class_prefix) - doc_to_selector(doc) - end + self.class.perform_arguments(mixin, args, keywords, splat) do |env| + env.caller = Sass::Environment.new(@environment) + env.content = node.children if node.has_children - def class_prefix(name) - names = name.split('/') - names = names[1..(names.index { |x| x.start_with?('!') } || -1)] - names.join('__') + trace_node = Sass::Tree::TraceNode.from_node(node.name, node) + with_environment(env) { + trace_node.children = mixin.tree.map {|c| + d = c.dup + d.filename = node.filename + visit(d) + }.flatten + } + trace_node end + rescue Sass::SyntaxError => e + unless include_loop + e.modify_backtrace(:mixin => node.name, :line => node.line) + e.add_backtrace(:line => node.line) + end + raise e + ensure + @stack.pop unless include_loop + end + end - def replace_class(doc, class_prefix) - doc.rule_sets[0].selectors.map do |selector| - selector.simple_selectors.each do |simple_selector| - simple_selector.additional_selectors.each do |additional_selector| - case additional_selector - when CSSPool::Selectors::Class - additional_selector.name = extended_selector(class_prefix, additional_selector.name) - when CSSPool::Selectors::PseudoClass - next unless additional_selector.extra - extra = class_replaced_selector(additional_selector.extra, class_prefix) rescue nil - additional_selector.extra = extra if extra - end + class RootNode + alias :old_render :render + + def render + old_render.split('/*').map { |x| + next x unless x.match(/^ line [0-9]+, /) + a, b = x.split("\n", 2) + m = a.match(/\/app\/assets\/stylesheets\/([^. ]+)\./) + next "#{a}\n#{b}" unless m + selector = class_replaced_selector(b.split("\n")[0].strip[0...-1].strip, class_prefix(m[1])) + "#{a}\n#{selector} {\n#{b.split("\n", 2)[1]}" + }.join('/*') + end + + private + + def class_replaced_selector(selector, class_prefix) + doc = CSSPool.CSS("#{selector} {}") + replace_class(doc, class_prefix) + doc_to_selector(doc) + end + + def class_prefix(name) + names = name.split('/') + names = names[1..(names.index { |x| x.start_with?('!') } || -1)] + names.join('__') + end + + def replace_class(doc, class_prefix) + doc.rule_sets[0].selectors.map do |selector| + selector.simple_selectors.each do |simple_selector| + simple_selector.additional_selectors.each do |additional_selector| + case additional_selector + when CSSPool::Selectors::Class + additional_selector.name = extended_selector(class_prefix, additional_selector.name) + when CSSPool::Selectors::PseudoClass + next unless additional_selector.extra + extra = class_replaced_selector(additional_selector.extra, class_prefix) rescue nil + additional_selector.extra = extra if extra end end end end + end - def doc_to_selector(doc) - doc.to_css.split("\n")[0][0...-1].strip.gsub(/\\[0-9a-f]{6}/) do |c| - [c[1..-1].tr('0', '').to_i(16)].pack('U') - end + def doc_to_selector(doc) + doc.to_css.split("\n")[0][0...-1].strip.gsub(/\\[0-9a-f]{6}/) do |c| + [c[1..-1].tr('0', '').to_i(16)].pack('U') end + end - def extended_selector(class_prefix, klass) - if klass == 'root' - class_prefix - elsif klass.start_with?('_') - klass[1..-1] - else - "#{class_prefix}___#{klass}" - end + def extended_selector(class_prefix, klass) + if klass == 'root' + class_prefix + elsif klass.start_with?('_') + klass[1..-1] + else + "#{class_prefix}___#{klass}" end end end end