Skip to content

Commit

Permalink
check cycles
Browse files Browse the repository at this point in the history
  • Loading branch information
romainmenke committed Jul 20, 2023
1 parent 4dbc931 commit c5a8870
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 16 deletions.
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function AtImport(options) {
state,
[],
[],
[],
postcss
)

Expand Down
19 changes: 12 additions & 7 deletions lib/parse-statements.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ function split(params, start) {
return list
}

module.exports = function parseStatements(result, styles) {
module.exports = function parseStatements(result, styles, from) {
const statements = []
let nodes = []

styles.each(node => {
let stmt
if (node.type === "atrule") {
if (node.name === "import") stmt = parseImport(result, node)
else if (node.name === "media") stmt = parseMedia(result, node)
else if (node.name === "charset") stmt = parseCharset(result, node)
if (node.name === "import") stmt = parseImport(result, node, from)
else if (node.name === "media") stmt = parseMedia(result, node, from)
else if (node.name === "charset") stmt = parseCharset(result, node, from)
}

if (stmt) {
Expand All @@ -39,6 +39,7 @@ module.exports = function parseStatements(result, styles) {
nodes,
media: [],
layer: [],
from,
})
nodes = []
}
Expand All @@ -52,23 +53,25 @@ module.exports = function parseStatements(result, styles) {
nodes,
media: [],
layer: [],
from,
})
}

return statements
}

function parseMedia(result, atRule) {
function parseMedia(result, atRule, from) {
const params = valueParser(atRule.params).nodes
return {
type: "media",
node: atRule,
media: split(params, 0),
layer: [],
from,
}
}

function parseCharset(result, atRule) {
function parseCharset(result, atRule, from) {
if (atRule.prev()) {
return result.warn("@charset must precede all other statements", {
node: atRule,
Expand All @@ -79,10 +82,11 @@ function parseCharset(result, atRule) {
node: atRule,
media: [],
layer: [],
from,
}
}

function parseImport(result, atRule) {
function parseImport(result, atRule, from) {
let prev = atRule.prev()
if (prev) {
do {
Expand Down Expand Up @@ -119,6 +123,7 @@ function parseImport(result, atRule) {
media: [],
layer: [],
supports: [],
from,
}

for (let i = 0; i < params.length; i++) {
Expand Down
18 changes: 15 additions & 3 deletions lib/parse-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ async function parseStyles(
state,
media,
layer,
from,
postcss
) {
const statements = parseStatements(result, styles)
const statements = parseStatements(result, styles, from)

for (const stmt of statements) {
stmt.media = joinMedia(media, stmt.media || [])
Expand Down Expand Up @@ -141,7 +142,7 @@ async function loadImportContent(
postcss
) {
const atRule = stmt.node
const { media, layer } = stmt
const { media, layer, from } = stmt

assignLayerNames(layer, atRule, state, options)

Expand All @@ -159,6 +160,8 @@ async function loadImportContent(
state.importedFiles[filename][media] = {}
}
state.importedFiles[filename][media][layer] = true
} else if (from.includes(filename)) {
return
}

const content = await options.load(filename, options)
Expand Down Expand Up @@ -201,7 +204,16 @@ async function loadImportContent(
}

// recursion: import @import from imported file
return parseStyles(result, styles, options, state, media, layer, postcss)
return parseStyles(
result,
styles,
options,
state,
media,
layer,
[...from, filename],
postcss
)
}

module.exports = parseStyles
2 changes: 2 additions & 0 deletions test/fixtures/cyclical.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "cyclical-a.css";
@import "cyclical-b.css";
17 changes: 17 additions & 0 deletions test/fixtures/cyclical.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@


.b {
color: red;
}

.a {
color: blue;
}

.a {
color: blue;
}

.b {
color: red;
}
5 changes: 5 additions & 0 deletions test/fixtures/imports/cyclical-a.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import url(cyclical-b.css);

.a {
color: blue;
}
5 changes: 5 additions & 0 deletions test/fixtures/imports/cyclical-b.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import url(cyclical-a.css);

.b {
color: red;
}
26 changes: 20 additions & 6 deletions test/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,29 @@ const atImport = require("..")
// internal tooling
const checkFixture = require("./helpers/check-fixture")

test("should import stylsheets", checkFixture, "simple")
test("should import stylesheets", checkFixture, "simple")

test("should not import a stylsheet twice", checkFixture, "no-duplicate")
test("should not import a stylesheet twice", checkFixture, "no-duplicate")

test("should be able to import a stylsheet twice", checkFixture, "duplicates", {
skipDuplicates: false,
})
test(
"should be able to import a stylesheet twice",
checkFixture,
"duplicates",
{
skipDuplicates: false,
}
)

test(
"should be able to import a stylesheet with cyclical dependencies",
checkFixture,
"cyclical",
{
skipDuplicates: false,
}
)

test("should import stylsheets with same content", checkFixture, "same")
test("should import stylesheets with same content", checkFixture, "same")

test("should ignore & adjust external import", checkFixture, "ignore")

Expand Down

0 comments on commit c5a8870

Please sign in to comment.