Descendants not working in mixins

Mark's Avatar

Mark

02 May, 2012 06:34 PM

The problem I'm having is that if I put some descendant selectors inside a mixin, Sassee parses them as though they were global. For example:

@mixin menuStyle($color){
  border-color:$color;
  color:$color;
  div.close{background-color:$color;}       
}

The first two lines work as expected. What the last line should do (unless I'm mistaken about SASS syntax) is apply the background color rule to any div.close located inside whatever element has the mixin applied. So if I use the mixin on .menu like so:

.menu{@include menuStyle($purple);}

I would expect the last rule of the mixin to compile to something like this:

.menu div.close{background-color:$color;}

Instead, it ignores the rule's placement inside the mixin, and the rule that actually gets put into the CSS is just:

div.close{background-color:$color;}

Am I misunderstanding how Sass is supposed to handle these rules, or is this a bug?

  1. Support Staff 1 Posted by Wouter Vervloet on 02 May, 2012 06:46 PM

    Wouter Vervloet's Avatar

    Hi Mark,

    Is it possible that this particular syntax is a new addition to SASS? The parsing engine I'm using now hasn't been maintained or updated for a while, so it is missing some of the newer functionality.

    I am looking into migrating to a different (more up-to-date) parser, but at the moment the available parser are very limited or dodge at best.

    – Wouter

  2. 2 Posted by Mark on 02 May, 2012 07:00 PM

    Mark's Avatar

    Is it possible that this particular syntax is a new addition to SASS?

    Could be. I'm pretty new to SASS myself, so I don't know much about the development history. There's an example of something like this on the front page of the official SASS website, which is why I think it must be a pretty established piece of syntax:

    @mixin table-base {
      th {
        text-align: center;
        font-weight: bold;
      }
      td, th {padding: 2px}
    }
    
  3. Support Staff 3 Posted by Wouter Vervloet on 06 May, 2012 08:14 PM

    Wouter Vervloet's Avatar

    Hi Mark,

    How is the example from the website similar to yours? I don't see any nested selectors in there... Are you sure it is a valid syntax?

    – Wouter

  4. 4 Posted by Mark on 07 May, 2012 12:21 PM

    Mark's Avatar

    Perhaps I'm misreading it, but I take it to imply that table-base would be applied to

    or some other higher-level element, and that the rules for "th" and "th,td" would be applied to all of those elements below the one with table-base applied. This is analogous to me expecting all div.close below my element with menuStyle to be effected.
  5. Support Staff 5 Posted by Wouter Vervloet on 07 May, 2012 05:33 PM

    Wouter Vervloet's Avatar

    Hi Mark,

    Sorry... I formatted the example snippet in your original post so it shows up correctly here and now I see what you mean.

    I'll look into it and get back to you on that.

    – Wouter

  6. Support Staff 6 Posted by Wouter Vervloet on 07 May, 2012 05:45 PM

    Wouter Vervloet's Avatar

    Hi Mark,

    I just pasted your example into my Sassee test environment and it works as expected...

    @mixin menuStyle($color){
      border-color:$color;
      color:$color;
      div.close{background-color:$color;}       
    }
    
    .menu{@include menuStyle(green);}
    

    Gets parsed as:

    .menu{border-color:green;color:green;}.menu div.close{background-color:green;}
    

    Is there something special about your server?

  7. 7 Posted by Mark on 07 May, 2012 06:26 PM

    Mark's Avatar

    Wouter, I really appreciate your continued help on this.

    At this point I am pretty stumped though. Your test seems to completely capture all the relevant aspects of my problem, yet it turns out differently for you than for me. I stripped my .scss file down to the bear minimum to recreate the bug, but it still parses incorrectly. I've attached both the .scss file and the CSS output below, with debugging enabled (both to prove that I'm not crazy and in hopes that you'll be able to spot some issue).

    I can't think of anything special about my server environment that would cause this. Are there any plausible possibilities? It seems like the stack trace would be pretty self-contained, I can't imagine what could cause Sassee to parse something incorrectly without breaking it entirely. I don't think it could be a cache problem, the stylesheet always updates itself right away upon a page refresh.

    I mentioned in a previous thread that I do have one line of SassNode.php commented out, but it's simply an exception thrower. I tried uncommenting it, but as expected it broke Sassee entirely, so I couldn't really perform that test. AFAIK this is the only way in which my installation would differ from a clean install.

    The config file says I'm using Sassee 1.01, if that helps at all.

  8. Support Staff 8 Posted by Wouter Vervloet on 07 May, 2012 06:35 PM

    Wouter Vervloet's Avatar

    There must be something else going on with your Sassee install, because your exact sass file render like this for me:

    .sectionmenu.involve {
      border-color: green;
      color: green;
    }
    .sectionmenu.involve div.close {
      background-color: green;
    }
    .sectionmenu.discuss {
      border-color: blue;
      color: blue;
    }
    .sectionmenu.discuss div.close {
      background-color: blue;
    }
    .sectionmenu.about {
      border-color: red;
      color: red;
    }
    .sectionmenu.about div.close {
      background-color: red;
    }
    div.close {
      height: 30px;
      width: 30px;
    }
    

    Could you perhaps zip up your Sassee install and attach it here so I can compare it to my copy?

    – Wouter

  9. 9 Posted by Mark on 07 May, 2012 06:40 PM

    Mark's Avatar

    Attached.

  10. Support Staff 10 Posted by Wouter Vervloet on 07 May, 2012 07:42 PM

    Wouter Vervloet's Avatar

    Hi Mark,

    There must be something wrong with either your server or how you're including the sass file, because when I drop in your copy of Sassee everything still works.

    How are you calling Sassee in your template? I'm doing it like this:

    <link rel="stylesheet" type="text/css" href="{exp:sassee:file file='mark.scss'}" />
    

    And I have all the config variables set to default.

    – Wouter

  11. 11 Posted by Mark on 07 May, 2012 07:57 PM

    Mark's Avatar

    Pretty much the same:

    <link type="text/css" href="{exp:sassee:file file='style.scss' debug='yes'}" rel="Stylesheet" />

    I'm calling from a snippet, though I doubt that matters.

    I've also tried playing around with the various output options (which works, but doesn't effect the bug), and passing parameters explicitly instead of using my defaults (which are "compressed" and "scss"). Template debugging reveals nothing except that the expected class and method are called.

    Do you have any idea what sorts of environment differences might cause the problem? I'm running PHP 5.1.6. Unfortunately I can't upgrade to a newer PHP, though I can edit the php.ini file.

  12. 12 Posted by Mark on 07 May, 2012 08:08 PM

    Mark's Avatar

    I'm beginning to think that the block of code for which I had to comment out the exception is the culprit. Whenever I uncomment the exception throwing line, the errors I get are mixin related: it dies on the first mention of @mixin. If I comment this out, it dies at the next mixin. Only when I comment out all my mixin code does it find something unrelated to die on (specifically, it dies on the first selector in my .scss file).

    This makes me think that the problem is that it fails to parse the mixin code correctly on it's first pass, and so ends up parsing it incorrectly on subsequent passes. Normally it would just die on the first failure, but instead since I've commented out that line, it retries later without realizing there's been an error.

    So is there some other way to make this segment of code work, that might also work in my environment?

    public function __set($name, $value) {
        $setter = 'set' . ucfirst($name);
        if (method_exists($this, $setter)) {
            $this->$setter($value);
            return $this;
        }
        throw new SassNodeException('No setter function for {what}', array('{what}'=>$name), $this);
    }
    
  13. Support Staff 13 Posted by Wouter Vervloet on 07 May, 2012 09:14 PM

    Wouter Vervloet's Avatar

    Weird thing is... when I add the following code, everything still works.

        public function __set($name, $value) {
          die($name);
          $setter = 'set' . ucfirst($name);
    

    So it almost seems like this code isn't even being run. The oldest PHP version I have is 5.2.17, but it all works fine there as well...

    Perhaps if I could get access to your server I could figure out what is going on, but I can't reproduce the error on my side so there's not much I can do.

    – Wouter

  14. 14 Posted by Mark on 08 May, 2012 12:55 PM

    Mark's Avatar

    That is strange...

    Unfortunately I don't think I'll be allowed to grant you access to the server I'm on, though I appreciate the offer to do so. As a last attempt, here's the output in the PHP error logs from a single page load (with the aforementioned commented-out line put back in). Perhaps this might help determine why the code is apparently being run on my installation but not on yours?

    [08-May-2012 08:48:00] PHP Fatal error: Uncaught exception 'SassNodeException' with message 'No setter function for parent: style.scss::18 Source: box-sizing:$type' in /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/SassNode.php:88 Stack trace: <a href="/discussions/sassee/0" title="Discussion #0">#0</a> /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/SassMixinNode.php(75): SassNode->__set('parent', Object(SassMixinNode)) <a href="/discussions/sassee/1" title="Discussion #1">#1</a> /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/SassNode.php(329): SassMixinNode->parse(Object(SassContext)) <a href="/discussions/sassee/2" title="Discussion #2">#2</a> /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/SassRuleNode.php(87): SassNode->parseChildren(Object(SassContext)) <a href="/discussions/sassee/3" title="Discussion #3">#3</a> /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/SassNode.php(329): SassRuleNode->parse(Object(SassContext)) <a href="/discussions/sassee/4" title="Discussion #4">#4</a> /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/Sass in /usr/www/diversity/public_html/sys_config/expressionengine/third_party/sassee/libraries/sass/tree/SassNode.php on line 88

  15. 15 Posted by Mark on 08 May, 2012 07:30 PM

    Mark's Avatar

    Sorry, that didn't carry the formatting over very well at all. Attached as file.

  16. 16 Posted by Mark on 08 May, 2012 08:55 PM

    Mark's Avatar

    So... having completely run out of ideas for how to hack around the issue, I tried dropping in this updated Sass parser, and miraculously it looks like it's working fine. There are no exceptions being thrown, the mixin selector bug has gone away, and only one element on the page is rendering any differently than it did before (quite possibly more correct now, I haven't looked into it).

    Anyway, at a very cursory first glance, that library seems to work as drop-in replacement, so if anyone has similar issues I'd recommend at least trying it out.

    Wouter, thanks again for working with me on this.

  17. Support Staff 17 Posted by Wouter Vervloet on 08 May, 2012 09:32 PM

    Wouter Vervloet's Avatar

    That phpsass library looks promising... at the very least it is still actively maintained. I'll do some more digging and poking around to see if this will be a viable option. But it is good to know that it seems to work for you.

    –  Wouter

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:

»

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac