-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SCSS] Fixes issues with URIs when handling interp and unary #217
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please explain to me what's the proposed difference between "raw" and "non-raw" types, and what "raw" is supposed to mean now? Comments for checkUri1
and checkUri2
functions seem to be the same :)
|
||
// Store the opening parenthesis token as we will reference it's `right` | ||
// property to determine when the parentheses close | ||
token = tokens[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't reassign token
anywhere later so you can move let
from line 4032 here and rename variable to something like leftParenthesis
@tonyganch From a quick look |
@tonyganch Updated the code. Any further thoughts? |
@bgriffith, I'm researching grammar and use cases, will get back to you shortly |
case TokenType.LeftSquareBracket: | ||
case TokenType.RightSquareBracket: | ||
case TokenType.LowLine: | ||
case TokenType.Tilde: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe there should be a different set of valid tokens.
According to css spec, any of the characters from this regexp are valid: [!#$%&*-\[\]-~]
. Note that there are two groups, so the full list of valid characters is: !
, #
, $
, %
, &
, *
, +
, ,
, -
, .
, /
, :
, ;
, <
, =
, >
, ?
, @
, [
, ]
, ^
, _
, {
, |
, }
, plus backtick, digits and letters. Both "
and '
are invalid.
raw = newNode(NodeType.RawType, joinValues(pos, pos + l), token.ln, | ||
token.col); | ||
if (l = checkIdent(i)) i += l; | ||
else if (l = checkNumber(i)) i += l; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both ident and number checks should be moved to checkUriRawCharacters
, since all those characters are just part of raw
and I see not much sense in trying to parse them differently from other 26 token types.
else if (l = checkNumber(i)) i += l; | ||
else if (l = _checkUriRawCharacters(i)) i += l; | ||
// As comments are not allowed within the uri token, include as part of node | ||
else if (l = checkCommentML(i)) i += l; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check for comment should be removed and more tokens should be added to checkUriRawCharacters
instead: not every comment is valid inside uri, for example, this is invalid code according to css spec: url(a/*(*/)
(note (
inside the comment).
|
||
uri.push(raw); | ||
return i - start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can store position of final token as uri_end
, for example, in which case getUriRaw
will not need to loop through characters again to find it.
* Check for a raw URI | ||
* (1) `url(http://foo/bar.png)` | ||
* (2) `url(http://foo/#{bar}.png)` | ||
* (3) `url(#{foo}/bar.png)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please either update examples or clarify description, that "raw" in that case means "without quotes" and that we only check inner part, without url
and parentheses?
if (l = checkSC(i)) i += l; | ||
|
||
while (i < tokensLength) { | ||
if (checkVariable(i) || checkFunction(i)) return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this line can be removed. We don't need to check for function because parentheses are invalid raw tokens. Plus we should not break on variables because url($a)
is a perfectly valid piece of css code where $a
is just part of uri and not a variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tonyganch - So are you ok with parsing the $a
in url($a)
always as raw
and not variable
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For css syntax = definitely :) What will compiler assume? That this is variable in any case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking out loud - #{$a}
would always parse as raw
too right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah guess it HAS to be, incase we end up breaking up a totally legit url into many incorrect nodes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked with both css validator and sassmeister. CSS validator treats url(#{$a})
as a valid url thus parsing it as "raw", and sassmeister interprets it strongly as interpolation.
So I guess the logic for css and scss/sass should be different here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have to check but I think the current implementation for the CSS parser is problem free.
So on the SCSS/Sass front, where would you stop? Would you parse url($a)
as variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for SCSS/Sass those should be variables and interpolations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I've removed checkFunction
but left checkVariable
due to the above.
// Determine the type of URI | ||
if (checkUri1(i)) tokens[start].uriType = 1; // Raw based URI | ||
else if (checkUri2(i)) tokens[start].uriType = 2; // Non-raw based URI | ||
else return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current implementation doesn't guarantee that those checkUri
checks will go through all characters between parentheses because we don't compare token position with a matching right parenthesis anywhere. In checkUri1
for example we check for i < tokensLength
in while loop. I suppose that will parse the following example as valid even though it is not: url(abc(()
if (l = checkSC(i)) i += l; | ||
|
||
// Check if URI contains a raw node | ||
if (!isRaw) return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually need that? Consider url(#{abc})
, even though there is no raw node besides a lonely interpolation, it still can be parsed inside this check without need to call checkUri2
if (l = checkSC(i)) i += l; | ||
else if (l = checkString(i)) i += l; | ||
else if (l = checkFunction(i)) i += l; | ||
else if (l = checkUnary(i)) i += l; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unary operator is the one that gives sign to a number, for example, -3
or +8
. I think it can't be applied to uris but I guess there isn't anything more suitable in the code now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha yeah I know, just wasn't one for just a plus sign 😛
Related issue which should be fixed with this PR: #210 |
Awesome feedback @tonyganch - thanks a lot! I'll go through it and implement the changes. |
@tonyganch Updated the PR! Let me know what you think - if it's all good I'll port the changes to |
Few issues have cropped up and I noticed some bugs in my code! Hold yer horses 🐴 |
@tonyganch Ok! So I've cleaned up the loops, and fixed a few issues. Give me a shout if there's anything not quite right. |
I'm okay with this PR, can you please port the changes to Sass and merge it? |
410d1a8
to
157ae64
Compare
157ae64
to
ca34795
Compare
@tonyganch Ported and merged! Glad to get that one in! 😁 |
Cool, thanks, will publish it tonight or tomorrow.
|
This PR rewrites the way we handle URI nodes by allowing either a raw uri or non-raw uri that can be made up of multiple nodes (interps, numbers, idents, unary etc)
It solves issues highlighted in #85
Only implement in SCSS but if approved I'll add it into Sass too.