diff --git a/lib/parse-statements.js b/lib/parse-statements.js index f7f09fcd..59bb4274 100644 --- a/lib/parse-statements.js +++ b/lib/parse-statements.js @@ -66,6 +66,11 @@ function parseMedia(result, atRule) { } function parseCharset(result, atRule) { + if (atRule.prev()) { + return result.warn("@charset must precede all other statements", { + node: atRule, + }) + } return { type: "charset", node: atRule, @@ -74,19 +79,20 @@ function parseCharset(result, atRule) { } function parseImport(result, atRule) { - let prev = getPrev(atRule) + let prev = atRule.prev() if (prev) { do { if ( - prev.type !== "atrule" || - (prev.name !== "import" && prev.name !== "charset") + prev.type !== "comment" && + (prev.type !== "atrule" || + (prev.name !== "import" && prev.name !== "charset")) ) { return result.warn( "@import must precede all other statements (besides @charset)", { node: atRule } ) } - prev = getPrev(prev) + prev = prev.prev() } while (prev) } @@ -137,11 +143,3 @@ function parseImport(result, atRule) { return stmt } - -function getPrev(item) { - let prev = item.prev() - while (prev && prev.type === "comment") { - prev = prev.prev() - } - return prev -} diff --git a/test/lint.js b/test/lint.js index 6361ae71..7e65c098 100644 --- a/test/lint.js +++ b/test/lint.js @@ -78,6 +78,23 @@ test("should not warn when @charset or @import statement before", t => { }) }) +test("should warn when @charset is not first", t => { + return Promise.all([ + processor.process(`a {} @charset "utf-8";`, { from: undefined }), + processor.process(`@media {} @charset "utf-8";`, { from: undefined }), + processor.process(`/* foo */ @charset "utf-8";`, { from: undefined }), + processor.process(`@import "bar.css"; @charset "utf-8";`, { + from: "test/fixtures/imports/foo.css", + }), + ]).then(results => { + results.forEach(result => { + const warnings = result.warnings() + t.is(warnings.length, 1) + t.is(warnings[0].text, "@charset must precede all other statements") + }) + }) +}) + test("should warn when a user didn't close an import with ;", t => { return processor .process(`@import url('http://') :root{}`, { from: undefined })