Skip to content

Commit 48118d5

Browse files
committed
fixes #30; url in loose mode shouldn't combine contents into single node
1 parent 1d1c8e7 commit 48118d5

File tree

3 files changed

+34
-20
lines changed

3 files changed

+34
-20
lines changed

README.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,30 @@ let color = ast // the Root node
6767
.first; // a Word node, containing the color value.
6868
```
6969

70-
## CSS-Like Languages
70+
## Loose Mode
7171

72-
If your intent is to use this parser with a CSS-like language (eg. SASS, LESS)
73-
then you can instruct the parser **_not to adhere to strict CSS_** parsing rules as
74-
per [the spec](https://drafts.csswg.org/css-values-3/). For example, the parser
75-
will throw an error by default if `calc` parameters [don't adhere to the spec](https://drafts.csswg.org/css-values-3/#calc-syntax).
72+
Loose mode was introduced to support adherence to the W3C CSS Specification as
73+
well as the ability to parse noncompliant CSS for variants like LESS, SCSS, and
74+
CSSNext. If you're working with a noncompliant or CSS-like variant, then loose
75+
mode is for you.
7676

77-
We call this `loose` mode. To enable `loose` mode, pass an options object to the
78-
`parser` method:
77+
For example, the parser
78+
will throw an error by default if `calc` parameters [don't adhere to the spec](https://www.w3.org/TR/css-values/#calc-syntax).
79+
However, with loose mode enabled, the parse will ignore spec rules and succeed.
80+
81+
In-draft features, or CSS features in modules not yet finalized, often cause parser
82+
errors. eg. `url(var(--somevar))`. Loose mode supports parsing of these features.
83+
84+
Loose Mode is enabled by passing an option of `loose: true` to the `parser` method.
7985

8086
```js
87+
const less = 'calc(2+2)'; // not valid per spec, but valid in LESS
88+
const cssnext = 'url(var(--somevar))'; // not valid per spec, but in spec draft
89+
8190
const parser = require('postcss-values-parser');
82-
const ast = parser('#fff', { loose: true }).parse();
91+
const ast = parser(less, { loose: true }).parse();
92+
93+
// parse will succeed
8394
```
8495

8596
## Acknowledgements

lib/parser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ module.exports = class Parser {
297297
// parens get treated as one word, if the contents aren't not a string.
298298
if (this.current.type === 'func' && this.current.unbalanced &&
299299
this.current.value === 'url' && this.currToken[0] !== 'string' &&
300-
this.currToken[0] !== ')') {
300+
this.currToken[0] !== ')' && !this.options.loose) {
301301

302302
let nextToken = this.nextToken,
303303
value = this.currToken[1],

test/function.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,20 @@ describe('Parser → Function', () => {
3535
{ type: 'word', value: 'baz' }
3636
]
3737
},
38-
// not ready yet - #30
39-
// {
40-
// it: 'should loosely parse url function with sub func',
41-
// test: 'url(var(foo))',
42-
// loose: true,
43-
// expected: [
44-
// { type: 'func', value: 'url' },
45-
// { type: 'paren', value: '(' },
46-
// { type: 'paren', value: ')' }
47-
// ]
48-
// },
38+
{
39+
it: 'should loosely parse url function with sub func #30',
40+
test: 'url(var(foo))',
41+
loose: true,
42+
expected: [
43+
{ type: 'func', value: 'url' },
44+
{ type: 'paren', value: '(' },
45+
{ type: 'func', value: 'var' },
46+
{ type: 'paren', value: '(' },
47+
{ type: 'word', value: 'foo' },
48+
{ type: 'paren', value: ')' },
49+
{ type: 'paren', value: ')' }
50+
]
51+
},
4952
{
5053
it: 'should parse url function',
5154
test: 'url( /gfx/img/bg.jpg )',

0 commit comments

Comments
 (0)