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

Variant groups broken by uneven amount of quotes #1215

Closed
t2t2 opened this issue Jul 3, 2022 · 1 comment · Fixed by #1231
Closed

Variant groups broken by uneven amount of quotes #1215

t2t2 opened this issue Jul 3, 2022 · 1 comment · Fixed by #1231
Labels
bug Something isn't working core

Comments

@t2t2
Copy link

t2t2 commented Jul 3, 2022

For example caused by English words like "can't":

<div class="before:(content-[✅] mx-2)">
  Checkmark
</div>
Can't use variant groups after this
<div class="before:(content-[✅] mx-2)">
  Missing
</div>

playground

It's not an issue if there's more than one word using the quote, but it breaks again if there's an odd amount until end of file:

<div class="before:(content-[✅] mx-2)">
  Checkmark
</div>
Works b'tween
<div class="before:(content-[✅] mx-2)">
  Checkmark
</div>
And a'ter
<div class="before:(content-[✅] mx-2)">
  Checkmark
</div>
But breaks again on odd'th quote
<div class="before:(content-[✅] mx-2)">
  Missing
</div>

playground

One more test case:

<div class="before:(content-[✅] mx-2)">
  Checkmark
</div>
<div :class="'before:(content-[✅] mx-2)'">
  Transformed
</div>
And for vue'like
<div class="before:(content-[✅] mx-2)">
  Checkmark
</div>
<div :class="'before:(content-[✅] mx-2)'">
  Not transformed
</div>
<div class="before:(content-[✅] mx-2)">
  Missing
</div>

playground

@zyyv
Copy link
Member

zyyv commented Jul 3, 2022

This problem is caused by incomplete quotation marks. During the matching process, the default quotation marks are required to be closed. A single quotation mark skips the following matching rules, resulting in a matching error.

export function extractQuoted(
str: string,
options: ExtractStringOptions<boolean> = {},
): any[] {
const {
deep = false,
templateStaticOnly = false,
details = false,
range: [rstart, rend] = [0, str.length],
} = options
const result: (string | DetailString)[] = []
let quote: DetailString['quote']
const addResult = (start: number, end: number) => result.push(
details
? {
value: str.slice(start, end),
range: [start, end],
quote,
}
: str.slice(start, end),
)
let i = rstart
while (i < rend) {
const char = str[i]
if ((QUOTES.includes as (c: string) => c is typeof quote)(char)) {
quote = char
const start = i + 1
const isTemplate = quote === '`'
let templateStart = start
let end = start
while (end < rend) {
const nextChar = str[end]
if (nextChar === quote) {
if (isTemplate && templateStaticOnly) {
addResult(templateStart, end)
break
}
addResult(start, end)
break
}
if (nextChar === '\\') {
end += 2
}
else if (isTemplate && nextChar === '$' && str[end + 1] === '{') {
const nestStart = end + 2
end = matchingPair(str, '{}', end + 1, true)
if (templateStaticOnly) {
addResult(
templateStart,
nestStart - 2,
)
}
templateStart = end + 1
if (deep) {
result.push(
...extractQuoted(
str,
{
...options,
range: [nestStart, end],
} as ExtractStringOptions<any>,
),
)
}
}
else {
end += 1
}
}
i = end + 1
}
else {
i++
}
}
return result
}

This is a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working core
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants