Sass mixin recursion; @include loop

妖精的绣舞 提交于 2019-12-24 16:23:05

问题


Does anyone know if it's possible to revert Sass's functionality, to prevent the "bug-fix"1 that was implemented to prevent @include recursion?

The message is:

Syntax error: An @include loop has been found: <mixin-name> includes itself

This was "fixed"1 in 3.0.5, and I'd prefer not to (read: I can't) downgrade that far. I unfortunately don't know enough Ruby to go sifting through the source, and while I'm making time to change that, it doesn't help me now.

So, is it possible2 to revert this functionality to that of pre-3.0.5 without having to downgrade; is there a re-patch floating around somewhere? I haven't been able to find one.

Edit: While I've answered this myself now, I'm still open to better answers; specifically, more portable solutions since now the Sass files will break anywhere else (anywhere that isn't pre-3.0.5)

1 Quotes used to indicate I don't think this is a fix. I think it is a break; I'll take that up with those responsible though.
2I know its possible, but I mean specifically for someone with no practical experience with Ruby. I'm learning Ruby!


回答1:


Okay, there's a cleaner way apply your hack: monkey-patching with Compass.

It will let you share your project safely and everybody else will be able to compile it without modifying their own SASS compilers.

1)

Create sass-visit-mixin-monkey-patch.rb next to compass.rb and apply your hack from there:

class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
  # Runs a mixin.
  def visit_mixin(node)
    #include_loop = true
    #handle_include_loop!(node) if @stack.any? {|e| e[:name] == node.name}
    include_loop = false

    @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

    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

    self.class.perform_arguments(mixin, args, keywords, splat) do |env|
      env.caller = Sass::Environment.new(@environment)
      env.content = node.children if node.has_children

      trace_node = Sass::Tree::TraceNode.from_node(node.name, node)
      with_environment(env) {trace_node.children = mixin.tree.map {|c| visit(c)}.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

2)

Require the monkey patch from the config.rb:

# Enabling mixin recursion by applying a monkey patch to SASS compiler
require "./sass-visit-mixin-monkey-patch"

3)

Compile your project with compass compile.




回答2:


You know, I know enough Ruby to comment out a line or two ;)

At .\lib\sass\tree\visitors\perform.rb : 249 just comment:

# Runs a mixin.
def visit_mixin(node)
  include_loop = true
  handle_include_loop!(node) if @stack.any? {|e| e[:name] == node.name}
  include_loop = false

Into:

# Runs a mixin.
def visit_mixin(node)
  # include_loop = true
  # handle_include_loop!(node) if @stack.any? {|e| e[:name] == node.name}
  include_loop = false

Suddenly, rainbows of glorious recursion.



来源:https://stackoverflow.com/questions/15531004/sass-mixin-recursion-include-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!