cssinjs / istf-spec

Interoperable Style Transfer Format [DRAFT]
247 stars 8 forks source link

Interpolations inside strings in values #35

Closed kitten closed 6 years ago

kitten commented 6 years ago

While working on parsing CSS values I've come across some edge cases that are not sufficiently covered by the ISTF spec as it is right now.

Considering a value with a string interpolations can be put inside or around the string:

css`
  content: "${'some content'}";
  content: "some ${'content'}";
`

How do we represent an interpolation inside a string? Right now the only way for it to be represented would be:

[COMPOUND_VALUE_START],
  [VALUE, '"'],
  [JS_FUNCTION_VALUE, x], // 'some content'
  [VALUE, '"'],
[COMPOUND_VALUE_END],

and

[COMPOUND_VALUE_START],
  [VALUE, '"some '],
  [JS_FUNCTION_VALUE, x], // 'content'
  [VALUE, '"'],
[COMPOUND_VALUE_END],

The problem here is that since we see whitespaces as non-significant usually inside values, which is quite handy, here it would lead to mistakes. How do we know to join the values without a whitespace in-between them during runtime?

The easiest solution would be to introduce a string value:

// content: "${'some content'}";
[STRING_START, DOUBLE_QUOTES],
[JS_FUNCTION_VALUE],
[STRING_END]

// content: "some ${'content'}";
[STRING_START, DOUBLE_QUOTES],
  [VALUE, 'some '],
  [JS_FUNCTION_VALUE],
[STRING_END],

It's important to keep the type of quote around so we don't have to change any escapes or add more for potential conflicting quotes inside strings: " \" "; For that we could introduce more types e.g. SINGLE_QUOTES = 1 & DOUBLE_QUOTES = 2

cc @kof

kitten commented 6 years ago

So after a quick chat with @kof the proposed solution is adding three new markers:

STRING_START, STRING_END, and STRING.

The first two are encapsulating a string that contains interpolations i.e.:

// `"some${x}string"` =>
[STRING_START],
[VALUE, '"some '],
[VALUE_REF, x],
[VALUE, 'string"'],
[STRING_END]

and the optional (since VALUE could just be used):

// `"some string"` =>
[STRING, '"some string"']

While this one is optional it will make some specialised transformations a little easier.

Both can only occur where normally a VALUE can occur as well