Skip to content

Commit 85684b5

Browse files
authored
fix: avoid "Invalid regular expression: invalid group specifier name"… (#122)
… error
1 parent 47614da commit 85684b5

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

index.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,15 @@ export function format(css, { minify = false } = {}) {
395395

396396
return buffer
397397
.replace(/\s*([:,])/g, buffer.toLowerCase().includes('selector(') ? '$1' : '$1 ') // force whitespace after colon or comma, except inside `selector()`
398-
.replace(/\s*(=>|<=)\s*/g, ' $1 ') // force whitespace around => and <=
399398
.replace(/\)([a-zA-Z])/g, ') $1') // force whitespace between closing parenthesis and following text (usually and|or)
400-
.replace(/(?<!<=)(?<!=>)(?<!<= )([<>])(?![<= ])(?![=> ])(?![ =>])/g, ' $1 ')
401-
.replace(/calc\(([^*]*)\*([^*])/g, 'calc($1 * $2') // force correct whitespace around * in calc()
402-
.replace(/\s+/g, SPACE) // collapse multiple whitespaces into one
399+
.replace(/\s*(=>|<=)\s*/g, ' $1 ') // force whitespace around => and <=
400+
.replace(/([^<>=\s])([<>])([^<>=\s])/g, `$1${OPTIONAL_SPACE}$2${OPTIONAL_SPACE}$3`) // add spacing around < or > except when it's part of <=, >=, =>
401+
.replace(/\s+/g, OPTIONAL_SPACE) // collapse multiple whitespaces into one
402+
.replace(/calc\(\s*([^()+\-*/]+)\s*([*/+-])\s*([^()+\-*/]+)\s*\)/g, (_, left, operator, right) => {
403+
// force required or optional whitespace around * and / in calc()
404+
let space = operator === '+' || operator === '-' ? SPACE : OPTIONAL_SPACE
405+
return `calc(${left.trim()}${space}${operator}${space}${right.trim()})`
406+
})
403407
.replace(/selector|url|supports|layer\(/ig, (match) => lowercase(match)) // lowercase function names
404408
}
405409

test/atrules.test.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { suite } from 'uvu'
22
import * as assert from 'uvu/assert'
3-
import { format } from '../index.js'
3+
import { format, minify } from '../index.js'
44

55
let test = suite('Atrules')
66

@@ -166,6 +166,24 @@ test('calc() inside @media', () => {
166166
assert.equal(actual, expected)
167167
})
168168

169+
test('minify: calc(*) inside @media', () => {
170+
let actual = minify(`@media (min-width: calc(1px*1)) {}`)
171+
let expected = `@media (min-width:calc(1px*1)){}`
172+
assert.equal(actual, expected)
173+
})
174+
175+
test('minify: calc(+) inside @media', () => {
176+
let actual = minify(`@media (min-width: calc(1px + 1em)) {}`)
177+
let expected = `@media (min-width:calc(1px + 1em)){}`
178+
assert.equal(actual, expected)
179+
})
180+
181+
test('minify: calc(-) inside @media', () => {
182+
let actual = minify(`@media (min-width: calc(1em - 1px)) {}`)
183+
let expected = `@media (min-width:calc(1em - 1px)){}`
184+
assert.equal(actual, expected)
185+
})
186+
169187
test('@import prelude formatting', () => {
170188
let fixtures = [
171189
['@import url("fineprint.css") print;', '@import url("fineprint.css") print;'],
@@ -204,6 +222,18 @@ test('@layer prelude formatting', () => {
204222
}
205223
})
206224

225+
test('minify: @layer prelude formatting', () => {
226+
let fixtures = [
227+
[`@layer test;`, `@layer test;`],
228+
[`@layer tbody,thead;`, `@layer tbody,thead;`],
229+
]
230+
231+
for (let [css, expected] of fixtures) {
232+
let actual = minify(css)
233+
assert.equal(actual, expected)
234+
}
235+
})
236+
207237
test('single empty line after a rule, before atrule', () => {
208238
let actual = format(`
209239
rule1 { property: value }
@@ -314,6 +344,12 @@ test('new-fangled comparators (width > 1000px)', () => {
314344
assert.is(actual, expected)
315345
})
316346

347+
test('minify: new-fangled comparators (width > 1000px)', () => {
348+
let actual = minify(`@container (width>1000px) {}`)
349+
let expected = `@container (width>1000px){}`
350+
assert.is(actual, expected)
351+
})
352+
317353
test.skip('preserves comments', () => {
318354
let actual = format(`
319355
@media /* comment */ all {}

test/comments.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ test('strips comments in minification mode', () => {
558558
}
559559
/* comment 5 */
560560
`, { minify: true })
561-
let expected = `selector{}@media (min-width: 1000px){selector{}}`
561+
let expected = `selector{}@media (min-width:1000px){selector{}}`
562562
assert.is(actual, expected)
563563
})
564564

0 commit comments

Comments
 (0)