Skip to content
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 Interpolation in strings #37

Closed
1 of 4 tasks
lydell opened this issue Sep 3, 2017 · 5 comments
Closed
1 of 4 tasks

SCSS Interpolation in strings #37

lydell opened this issue Sep 3, 2017 · 5 comments

Comments

@lydell
Copy link
Contributor

lydell commented Sep 3, 2017

  • Node Version: 8.3.0
  • NPM Version: 5.3.0
  • postcss-values-parser Version: 1.3.0

This issue is regarding a problem with:

  • Standard CSS
  • LESS
  • SCSS
  • SASS
"a #{"1"} b #{2} c"

Actual Behavior

Parsed as:

StringNode {
  value: 'a #{'
}
NumberNode {
  value: '1'
}
StringNode {
  value: '} b #{2} c'
}

Expected Behavior

Proposal:

Similar to how Babylon parses template literals in JavaScript: astexplorer

Something like this:

InterpolationStringNode {
  expressions: [
    StringNode {
      value: '1'
    },
    NumberNode {
      value: '2'
    }
  ],
  quasis: [
    InterpolationStringElementNode {
      value: 'a '
    },
    InterpolationStringElementNode {
      value: ' b '
    },
    InterpolationStringElementNode {
      value: ' c'
    }
  ]
}

(The "expressions" and "quasis" names comes from Babylon’s AST. I made up "InterpolationStringNode". I don’t care about what they’re called.)

When you encounter #{ in a string

  1. Push the string so far to quasis
  2. Recursively parse with postcss-values-parser until the next unbalanced }. (Error handling, if no ending } is found throw TokenizeError: Unclosed interpolation or something.)
  3. Start to parse as a string again (until the end quote or the next #{).

Notes:

  • Interpolations can contain any expression, even another string with
    interpolations (recursively).
  • It is possible to escape interpolations: "\#{1}" is a single StringNode.

How can we reproduce the behavior?

const parse = require("postcss-values-parser")

const test = '"a #{"1"} b #{2} c"'
const ast = parse(test, {loose: true}).parse()

console.dir(ast, {colors: true, depth: null})

Related

@shellscape
Copy link
Owner

I'd go with InterpolationNode and put InterpolationElementNode under its child nodes. A property for tracking the type of interpolation, or format (#{..} etc) would be desirable. A proper implementation would support interpolation in LESS and SCSS.

@lydell
Copy link
Contributor Author

lydell commented Sep 4, 2017

Sounds good! Just a quick note: As far as I know, Less only supports simple variable interpolations of the form @{variable-name} (interpolating expressions is not supported).

@shellscape
Copy link
Owner

@lydell are you interested in submitting a PR for this?

@lydell
Copy link
Contributor Author

lydell commented Oct 9, 2017

No, I'm not. I wish I was, though.

@shellscape
Copy link
Owner

Happy to report that the offending css value passes in the next branch. This is accomplished for SCSS by using the options for the parser:

const options = {
  interpolation: { prefix: '#' }
};
const root = parse('a #{"1"} b #{2} c', options);

I'll be releasing a beta of 3.0.0 later today. Thanks for reporting the issue. Cheers 🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants