scssphp icon indicating copy to clipboard operation
scssphp copied to clipboard

Error "Array to String conversion" when handling pseudo + attribute selector

Open ikkez opened this issue 2 years ago • 11 comments

I tried to compile the latest uikit version but it fails hard with an error.

Problem is this type of selector:

:where([class*='foo']) p {
 // ...
}

To be more precise it's this at transition.scss:

:where(.uk-transition-fade),
:where([class*='uk-transition-scale']),
:where([class*='uk-transition-slide']) {
    --uk-position-translate-x: 0;
    --uk-position-translate-y: 0;
}

https://github.com/uikit/uikit/blob/87801983205aa9bb81a122c4e0f1b96b5117c169/src/scss/components/transition.scss#L51-L56

The error happens at array_diff which compares two incompatible nested array structures I guess: https://github.com/scssphp/scssphp/blob/c54b0a33d296807bc44ca1305882b2d9f49a3632/src/Compiler.php#L773-L780

Debug:

Bildschirmfoto 2022-08-15 um 22 30 33

ikkez avatar Aug 15 '22 20:08 ikkez

Please provide an actual reproducing case. The code snippet you gave does not trigger any error when I run it.

stof avatar Aug 16 '22 09:08 stof

Reproducing case:

:where(.uk-transition-fade),
:where([class*='uk-transition-scale']),
:where([class*='uk-transition-slide']) {
    --uk-position-translate-x: 0;
    --uk-position-translate-y: 0;
}

.a {
    color: blue;
}

.b {
    @extend .a;
}

stof avatar Sep 02 '22 20:09 stof

I tried to debug it, but our handling of selectors in 1.x is a huge mess and I did not manage to fix the issue.

stof avatar Sep 02 '22 21:09 stof

Hi, I got now the same error. But i have no idea which scss result in this error. I got this error after I update scssphp.

How can I get the SCSS which is resulting this error? Or how can I solve this?

janstieler avatar Oct 25 '22 21:10 janstieler

I got this error after I update scssphp.

Updating from which version to which one ?

stof avatar Oct 26 '22 08:10 stof

@stof I upgrade it from 1.10.2 to 1.11.0. I use scssphp inside of the Kirby CMS but this should not affect scssphp.

janstieler avatar Oct 26 '22 08:10 janstieler

The problem may be are the child arrays and maybe this is the solution:

add this function to scssphp/src/Compiler.php

protected function diff_recursive($array1, $array2) {
    $difference=array();
    foreach($array1 as $key => $value) {
       if(is_array($value) && isset($array2[$key])){ // it's an array and both have the key
          $new_diff = diff_recursive($value, $array2[$key]);
          if( !empty($new_diff) )
             $difference[$key] = $new_diff;
          } else if(is_string($value) && !in_array($value, $array2)) { // the value is a string and it's not in array B
             $difference[$key] = $value . " is missing from the second array";
          } else if(!is_numeric($key) && !array_key_exists($key, $array2)) { // the key is not numberic and is missing from array B
             $difference[$key] = "Missing from the second array";
          }
    }
    return $difference;
}

and in function matchExtends use this new function instead of array_diff

// check that we are not building an infinite loop of extensions
// if the new part is just including a previous part don't try to extend anymore
if (\count($part) > 1) {
   foreach ($partsPile as $previousPart) {
      // old
      // if (! \count(array_diff($previousPart, $part))) {
      // 	continue 2;
      // }
      // new
      if (! \count($this->diff_recursive($previousPart, $part))) {
         continue 2;
      }
   }
}

baggyownz avatar Sep 28 '23 12:09 baggyownz

I can confirm the error with scssphp v1.11.1 when trying to combine picoCss. The problematic line of code is the highlighted one:

a:is([aria-current], :hover, :active, :focus),

a:is([aria-current], :hover, :active, :focus),
[role=link]:is([aria-current], :hover, :active, :focus) {
  --color: var(--primary-hover);
  --text-decoration: underline;
}

The solution from @baggyownz works!

MDevster avatar Nov 03 '23 17:11 MDevster

@MDevster Please provide a reproducer of the issue.

Taking only the code snippet you gave in your comment compiles without triggering the bug, so it is not a reproducer.

stof avatar Nov 03 '23 17:11 stof

Hi, I'm facing the same problem.

Here is a reproducer:

%heading {
  margin-top: 0;
}

h1 {
  @extend %heading;
}

abbr:where([title]) {
  -webkit-text-decoration: underline dotted;
          text-decoration: underline dotted;
}

When I execute pcss from the command line with the given snippet, l get the warning:

bin/pscss -s expanded problem.scss out.css
PHP Warning:  Array to string conversion in /home/claus/Workspace/codebarista/scssphp/src/Compiler.php on line 927

Here are the values of $previousPart and $part that cause the warning in array_diff:

$previousPart =
array(2) {
  [0]=>
  string(4) "abbr"
  [1]=>
  string(15) ":where([title])"
}
$part =
array(3) {
  [0]=>
  string(1) "["
  [1]=>
  array(3) {
    [0]=>
    string(6) "string"
    [1]=>
    string(0) ""
    [2]=>
    array(1) {
      [0]=>
      string(5) "title"
    }
  }
  [2]=>
  string(1) "]"
}

csteuer avatar Jan 24 '24 20:01 csteuer

Had the same problem while using SASS placeholder selectors in my Typo3 v11.5.36 installation.

Using the solution of @baggyownz worked: https://github.com/scssphp/scssphp/issues/606#issuecomment-1739092199

Would be nice to get an official bugfix down the line.

Nefiji avatar Mar 12 '24 16:03 Nefiji