mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
[Sass] Handle newlines in selectors differently.
Allow newlines to appear anywhere in selectors and produce output appropriately. The indented syntax still only allows newlines following a comma; this change is for SCSS.
This commit is contained in:
parent
e4ac61fa11
commit
a887d2a0e8
3 changed files with 50 additions and 44 deletions
|
@ -25,7 +25,7 @@ module Sass
|
|||
class RuleNode
|
||||
# @see Node#to_sass
|
||||
def to_sass(tabs, opts = {})
|
||||
name = rules.first
|
||||
name = rule
|
||||
name = "\\" + name if name[0] == ?:
|
||||
str = "\n#{' ' * tabs}#{name}#{children.any? { |c| c.is_a? PropNode } ? "\n" : ''}"
|
||||
|
||||
|
@ -126,8 +126,8 @@ module Sass
|
|||
# @param root [Tree::Node] The parent node
|
||||
def expand_commas(root)
|
||||
root.children.map! do |child|
|
||||
next child unless Tree::RuleNode === child && child.rules.first.include?(',')
|
||||
child.rules.first.split(',').map do |rule|
|
||||
next child unless Tree::RuleNode === child && child.rule.include?(',')
|
||||
child.rule.split(',').map do |rule|
|
||||
node = Tree::RuleNode.new(rule.strip)
|
||||
node.children = child.children
|
||||
node
|
||||
|
@ -174,15 +174,15 @@ module Sass
|
|||
current_rule = nil
|
||||
root.children.select { |c| Tree::RuleNode === c }.each do |child|
|
||||
root.children.delete child
|
||||
first, rest = child.rules.first.scan(/^(&?(?: .|[^ ])[^.#: \[]*)([.#: \[].*)?$/).first
|
||||
first, rest = child.rule.scan(/^(&?(?: .|[^ ])[^.#: \[]*)([.#: \[].*)?$/).first
|
||||
|
||||
if current_rule.nil? || current_rule.rules.first != first
|
||||
if current_rule.nil? || current_rule.rule != first
|
||||
current_rule = Tree::RuleNode.new(first)
|
||||
root << current_rule
|
||||
end
|
||||
|
||||
if rest
|
||||
child.rules = ["&" + rest]
|
||||
child.rule = "&" + rest
|
||||
current_rule << child
|
||||
else
|
||||
current_rule.children += child.children
|
||||
|
@ -208,7 +208,7 @@ module Sass
|
|||
def remove_parent_refs(root)
|
||||
root.children.each do |child|
|
||||
if child.is_a?(Tree::RuleNode)
|
||||
child.rules.first.gsub! /^& +/, ''
|
||||
child.rule.gsub! /^& +/, ''
|
||||
remove_parent_refs child
|
||||
end
|
||||
end
|
||||
|
@ -249,10 +249,10 @@ module Sass
|
|||
while rule.children.size == 1 && rule.children.first.is_a?(Tree::RuleNode)
|
||||
child = rule.children.first
|
||||
|
||||
if child.rules.first[0] == ?&
|
||||
rule.rules = [child.rules.first.gsub(/^&/, rule.rules.first)]
|
||||
if child.rule[0] == ?&
|
||||
rule.rule = child.rule.gsub(/^&/, rule.rule)
|
||||
else
|
||||
rule.rules = ["#{rule.rules.first} #{child.rules.first}"]
|
||||
rule.rule = "#{rule.rule} #{child.rule}"
|
||||
end
|
||||
|
||||
rule.children = child.children
|
||||
|
@ -282,7 +282,7 @@ module Sass
|
|||
next child unless child.is_a?(Tree::RuleNode)
|
||||
|
||||
if prev_rule && prev_rule.children == child.children
|
||||
prev_rule.rules.first << ", #{child.rules.first}"
|
||||
prev_rule.rule << ", #{child.rule}"
|
||||
next nil
|
||||
end
|
||||
|
||||
|
|
|
@ -312,17 +312,18 @@ END
|
|||
|
||||
def check_for_no_children(node)
|
||||
return unless node.is_a?(Tree::RuleNode) && node.children.empty?
|
||||
warning = (node.rules.size == 1) ? <<SHORT : <<LONG
|
||||
WARNING on line #{node.line}:
|
||||
Selector #{node.rules.first.inspect} doesn't have any properties and will not be rendered.
|
||||
SHORT
|
||||
warning = (node.rule.include?("\n")) ? <<LONG : <<SHORT
|
||||
|
||||
WARNING on line #{node.line}:
|
||||
Selector
|
||||
#{node.rules.join("\n ")}
|
||||
#{node.rule.gsub("\n", "\n ")}
|
||||
doesn't have any properties and will not be rendered.
|
||||
LONG
|
||||
|
||||
WARNING on line #{node.line}:
|
||||
Selector #{node.rule.inspect} doesn't have any properties and will not be rendered.
|
||||
SHORT
|
||||
|
||||
warn(warning.strip)
|
||||
end
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ module Sass::Tree
|
|||
# "bip, bop, bup"]
|
||||
#
|
||||
# @return [Array<String>]
|
||||
attr_accessor :rules
|
||||
attr_accessor :rule
|
||||
|
||||
# The CSS selectors for this rule,
|
||||
# parsed for commas and parent-references.
|
||||
|
@ -84,7 +84,7 @@ module Sass::Tree
|
|||
|
||||
# @param rule [String] The first CSS rule. See \{#rules}
|
||||
def initialize(rule)
|
||||
@rules = [rule]
|
||||
@rule = rule
|
||||
@tabs = 0
|
||||
super()
|
||||
end
|
||||
|
@ -95,19 +95,19 @@ module Sass::Tree
|
|||
# @return [Boolean] Whether or not this node and the other object
|
||||
# are the same
|
||||
def ==(other)
|
||||
self.class == other.class && rules == other.rules && super
|
||||
self.class == other.class && rule == other.rule && super
|
||||
end
|
||||
|
||||
# Adds another {RuleNode}'s rules to this one's.
|
||||
#
|
||||
# @param node [RuleNode] The other node
|
||||
def add_rules(node)
|
||||
@rules += node.rules
|
||||
@rule << "\n" << node.rule
|
||||
end
|
||||
|
||||
# @return [Boolean] Whether or not this rule is continued on the next line
|
||||
def continued?
|
||||
@rules.last[-1] == ?,
|
||||
@rule[-1] == ?,
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -120,12 +120,17 @@ module Sass::Tree
|
|||
tabs = tabs + self.tabs
|
||||
|
||||
rule_separator = style == :compressed ? ',' : ', '
|
||||
line_separator = [:nested, :expanded].include?(style) ? ",\n" : rule_separator
|
||||
line_separator =
|
||||
case style
|
||||
when :nested, :expanded; "\n"
|
||||
when :compressed; ""
|
||||
else; " "
|
||||
end
|
||||
rule_indent = ' ' * (tabs - 1)
|
||||
per_rule_indent, total_indent = [:nested, :expanded].include?(style) ? [rule_indent, ''] : ['', rule_indent]
|
||||
|
||||
total_rule = total_indent + resolved_rules.map do |line|
|
||||
per_rule_indent + line.join(rule_separator)
|
||||
total_rule = total_indent + resolved_rules.join(rule_separator).split("\n").map do |line|
|
||||
per_rule_indent + line.strip
|
||||
end.join(line_separator)
|
||||
|
||||
to_return = ''
|
||||
|
@ -171,7 +176,7 @@ module Sass::Tree
|
|||
# @param environment [Sass::Environment] The lexical environment containing
|
||||
# variable and mixin values
|
||||
def perform!(environment)
|
||||
@parsed_rules = @rules.map {|r| parse_selector(interpolate(r, environment))}
|
||||
@parsed_rules = parse_selector(interpolate(@rule, environment))
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -210,32 +215,29 @@ module Sass::Tree
|
|||
|
||||
def resolve_parent_refs(super_rules)
|
||||
if super_rules.nil?
|
||||
return @parsed_rules.map do |line|
|
||||
line.map do |rule|
|
||||
if rule.include?(:parent)
|
||||
raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'.")
|
||||
end
|
||||
return @parsed_rules.map do |rule|
|
||||
if rule.include?(:parent)
|
||||
raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'.")
|
||||
end
|
||||
|
||||
rule.join
|
||||
end.compact
|
||||
rule.join
|
||||
end
|
||||
end
|
||||
|
||||
new_rules = []
|
||||
super_rules.each do |super_line|
|
||||
@parsed_rules.each do |line|
|
||||
super_rules.each do |super_rule|
|
||||
@parsed_rules.each do |rule|
|
||||
new_rules << []
|
||||
|
||||
super_line.each do |super_rule|
|
||||
line.each do |rule|
|
||||
rule = [:parent, " ", *rule] unless rule.include?(:parent)
|
||||
# An initial newline of the child rule
|
||||
# should be moved to the beginning of the entire rule
|
||||
rule.first.slice!(0) if nl = (rule.first.is_a?(String) && rule.first[0] == ?\n)
|
||||
rule = [nl ? "\n" : "", :parent, " ", *rule] unless rule.include?(:parent)
|
||||
|
||||
new_rules.last << rule.map do |segment|
|
||||
next segment unless segment == :parent
|
||||
super_rule
|
||||
end.join
|
||||
end
|
||||
end
|
||||
new_rules.last << rule.map do |segment|
|
||||
next segment unless segment == :parent
|
||||
super_rule
|
||||
end.join
|
||||
end
|
||||
end
|
||||
new_rules
|
||||
|
@ -251,7 +253,10 @@ module Sass::Tree
|
|||
when '&'; rules.last << :parent
|
||||
when ','
|
||||
scanner.scan(/\s*/)
|
||||
rules << [] if scanner.rest?
|
||||
if scanner.rest?
|
||||
rules << []
|
||||
rules.last << "\n" if scanner.matched.include?("\n")
|
||||
end
|
||||
when '"'
|
||||
rules.last << '"' << scanner.scan(/([^"\\]|\\.)*/)
|
||||
# We don't want to enforce that strings are closed,
|
||||
|
|
Loading…
Add table
Reference in a new issue