Skip to content

Commit

Permalink
add parsing support for supports conditions (#530)
Browse files Browse the repository at this point in the history
* add parsing support for supports conditions

* add a changelog entry

* feedback from code review
  • Loading branch information
romainmenke committed Jul 20, 2023
1 parent 82d7c98 commit 0aaed50
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 38 deletions.
112 changes: 75 additions & 37 deletions lib/parse-statements.js
Expand Up @@ -113,59 +113,97 @@ function parseImport(result, atRule) {
const params = valueParser(atRule.params).nodes
const stmt = {
type: "import",
uri: "",
fullUri: "",
node: atRule,
media: [],
layer: [],
supports: [],
}

// prettier-ignore
if (
!params.length ||
(
params[0].type !== "string" ||
!params[0].value
) &&
(
params[0].type !== "function" ||
params[0].value !== "url" ||
!params[0].nodes.length ||
!params[0].nodes[0].value
)
) {
return result.warn(`Unable to find uri in '${ atRule.toString() }'`, {
node: atRule,
})
}
for (let i = 0; i < params.length; i++) {
const node = params[i]

if (params[0].type === "string") stmt.uri = params[0].value
else stmt.uri = params[0].nodes[0].value
stmt.fullUri = stringify(params[0])
if (node.type === "space" || node.type === "comment") continue

let remainder = params
if (remainder.length > 2) {
if (
(remainder[2].type === "word" || remainder[2].type === "function") &&
remainder[2].value === "layer"
) {
if (remainder[1].type !== "space") {
return result.warn("Invalid import layer statement", { node: atRule })
if (node.type === "string") {
if (stmt.uri) {
return result.warn(`Multiple url's in '${atRule.toString()}'`, {
node: atRule,
})
}

if (!node.value) {
return result.warn(`Unable to find uri in '${atRule.toString()}'`, {
node: atRule,
})
}

stmt.uri = node.value
stmt.fullUri = stringify(node)
continue
}

if (node.type === "function" && /^url$/i.test(node.value)) {
if (stmt.uri) {
return result.warn(`Multiple url's in '${atRule.toString()}'`, {
node: atRule,
})
}

if (!node.nodes?.[0]?.value) {
return result.warn(`Unable to find uri in '${atRule.toString()}'`, {
node: atRule,
})
}

if (remainder[2].nodes) {
stmt.layer = [stringify(remainder[2].nodes)]
stmt.uri = node.nodes[0].value
stmt.fullUri = stringify(node)
continue
}

if (!stmt.uri) {
return result.warn(`Unable to find uri in '${atRule.toString()}'`, {
node: atRule,
})
}

if (
(node.type === "word" || node.type === "function") &&
/^layer$/i.test(node.value)
) {
if (node.nodes) {
stmt.layer = [stringify(node.nodes)]
} else {
stmt.layer = [""]
}
remainder = remainder.slice(2)

continue
}
}

if (remainder.length > 2) {
if (remainder[1].type !== "space") {
return result.warn("Invalid import media statement", { node: atRule })
if (node.type === "function" && /^supports$/i.test(node.value)) {
stmt.supports = [stringify(node.nodes)]

continue
}

stmt.media = split(remainder, 2)
stmt.media = split(params, i)
break
}

if (!stmt.uri) {
return result.warn(`Unable to find uri in '${atRule.toString()}'`, {
node: atRule,
})
}

if (stmt.supports.length) {
return result.warn(
`Supports conditions are not implemented at this time.`,
{
node: atRule,
}
)
}

return stmt
Expand Down
63 changes: 62 additions & 1 deletion test/lint.js
Expand Up @@ -144,19 +144,80 @@ test("should warn on invalid url", t => {
@import url();
@import url('');
@import url("");
@import layer url("");
@import supports(foo: bar) url("");
`,
{ from: undefined }
)
.then(result => {
const warnings = result.warnings()
t.is(warnings.length, 7)
t.is(warnings.length, 9)
t.is(warnings[0].text, `Unable to find uri in '@import foo-bar'`)
t.is(warnings[1].text, `Unable to find uri in '@import '`)
t.is(warnings[2].text, `Unable to find uri in '@import '''`)
t.is(warnings[3].text, `Unable to find uri in '@import ""'`)
t.is(warnings[4].text, `Unable to find uri in '@import url()'`)
t.is(warnings[5].text, `Unable to find uri in '@import url('')'`)
t.is(warnings[6].text, `Unable to find uri in '@import url("")'`)
t.is(warnings[7].text, `Unable to find uri in '@import layer url("")'`)
t.is(
warnings[8].text,
`Unable to find uri in '@import supports(foo: bar) url("")'`
)
})
})

test("should warn on duplicate url's", t => {
return processor
.process(
`
@import 'foo' "bar";
@import "foo" url(bar);
@import url(foo) "bar";
@import url('foo') url(bar);
@import url('foo') layer url(bar);
@import url('foo') layer(foo) "bar";
@import url('foo') supports(foo: bar) url(bar);
`,
{ from: undefined }
)
.then(result => {
const warnings = result.warnings()
t.is(warnings.length, 7)
t.is(warnings[0].text, `Multiple url's in '@import 'foo' "bar"'`)
t.is(warnings[1].text, `Multiple url's in '@import "foo" url(bar)'`)
t.is(warnings[2].text, `Multiple url's in '@import url(foo) "bar"'`)
t.is(warnings[3].text, `Multiple url's in '@import url('foo') url(bar)'`)
t.is(
warnings[4].text,
`Multiple url's in '@import url('foo') layer url(bar)'`
)
t.is(
warnings[5].text,
`Multiple url's in '@import url('foo') layer(foo) "bar"'`
)
t.is(
warnings[6].text,
`Multiple url's in '@import url('foo') supports(foo: bar) url(bar)'`
)
})
})

test("should warn on unimplemented features", t => {
return processor
.process(
`
@import url('foo') supports(foo: bar);
`,
{ from: undefined }
)
.then(result => {
const warnings = result.warnings()
t.is(warnings.length, 1)
t.is(
warnings[0].text,
`Supports conditions are not implemented at this time.`
)
})
})

Expand Down

0 comments on commit 0aaed50

Please sign in to comment.