From 4dbc9317cc2d1887b380fb1a89c14fb350548f9c Mon Sep 17 00:00:00 2001 From: Romain Menke <11521496+romainmenke@users.noreply.github.com> Date: Thu, 20 Jul 2023 15:29:09 +0200 Subject: [PATCH 1/2] add c8 test coverage (#533) --- lib/process-content.js | 1 + package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/process-content.js b/lib/process-content.js index ec413e06..e0c2ac89 100644 --- a/lib/process-content.js +++ b/lib/process-content.js @@ -21,6 +21,7 @@ module.exports = function processContent( // SugarSS support: if (ext === ".sss") { if (!sugarss) { + /* c8 ignore next 3 */ try { sugarss = require("sugarss") } catch {} // Ignore diff --git a/package.json b/package.json index a81ea5f0..11d8e96c 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "devDependencies": { "ava": "^5.0.0", + "c8": "^8.0.0", "eslint": "^8.2.0", "eslint-config-problems": "^7.0.0", "eslint-plugin-prettier": "^4.0.0", @@ -42,7 +43,7 @@ "ci": "eslint . && ava", "lint": "eslint . --fix", "pretest": "npm run lint", - "test": "ava" + "test": "c8 ava" }, "eslintConfig": { "extends": "eslint-config-problems", From 81a7701dee0cd8ee9c26642d6fdfb23323a1d100 Mon Sep 17 00:00:00 2001 From: Romain Menke <11521496+romainmenke@users.noreply.github.com> Date: Sat, 22 Jul 2023 23:36:21 +0200 Subject: [PATCH 2/2] extend and fix data url imports (#534) * extend and fix data url imports * explain the purpose of the code and couple bits that belong together --- index.js | 1 + lib/data-url.js | 20 ++++++++++++++++---- lib/parse-statements.js | 19 ++++++++++++------- lib/parse-styles.js | 19 +++++++++++++++++-- test/fixtures/data-url.css | 4 ++++ test/fixtures/data-url.expected.css | 26 ++++---------------------- 6 files changed, 54 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index cc1237da..1871a639 100755 --- a/index.js +++ b/index.js @@ -62,6 +62,7 @@ function AtImport(options) { state, [], [], + "", postcss ) diff --git a/lib/data-url.js b/lib/data-url.js index a59c5fb5..69c4ce94 100644 --- a/lib/data-url.js +++ b/lib/data-url.js @@ -1,14 +1,26 @@ "use strict" -const dataURLRegexp = /^data:text\/css;base64,/i +const anyDataURLRegexp = /^data:text\/css(?:;(base64|plain))?,/i +const base64DataURLRegexp = /^data:text\/css;base64,/i +const plainDataURLRegexp = /^data:text\/css;plain,/i function isValid(url) { - return dataURLRegexp.test(url) + return anyDataURLRegexp.test(url) } function contents(url) { - // "data:text/css;base64,".length === 21 - return Buffer.from(url.slice(21), "base64").toString() + if (base64DataURLRegexp.test(url)) { + // "data:text/css;base64,".length === 21 + return Buffer.from(url.slice(21), "base64").toString() + } + + if (plainDataURLRegexp.test(url)) { + // "data:text/css;plain,".length === 20 + return decodeURIComponent(url.slice(20)) + } + + // "data:text/css,".length === 14 + return decodeURIComponent(url.slice(14)) } module.exports = { diff --git a/lib/parse-statements.js b/lib/parse-statements.js index aa66e5bd..88a90ebc 100644 --- a/lib/parse-statements.js +++ b/lib/parse-statements.js @@ -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) { @@ -39,6 +39,7 @@ module.exports = function parseStatements(result, styles) { nodes, media: [], layer: [], + from, }) nodes = [] } @@ -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, @@ -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 { @@ -119,6 +123,7 @@ function parseImport(result, atRule) { media: [], layer: [], supports: [], + from, } for (let i = 0; i < params.length; i++) { diff --git a/lib/parse-styles.js b/lib/parse-styles.js index 50b74eba..d021dd4d 100644 --- a/lib/parse-styles.js +++ b/lib/parse-styles.js @@ -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 || []) @@ -90,6 +91,11 @@ async function resolveImportId(result, stmt, options, state, postcss) { postcss ) + return + } else if (dataURL.isValid(stmt.from)) { + // Data urls can't be used a base url to resolve imports. + // When the parent statement has a data url + // and the current statement doesn't have a data url we ignore the statement. return } @@ -201,7 +207,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, + filename, + postcss + ) } module.exports = parseStyles diff --git a/test/fixtures/data-url.css b/test/fixtures/data-url.css index 6f1276ef..4b2b4b37 100644 --- a/test/fixtures/data-url.css +++ b/test/fixtures/data-url.css @@ -4,3 +4,7 @@ /* Mixed imports: */ @import url(data:text/css;base64,QGltcG9ydCB1cmwoZm9vLmNzcyk7CgpwIHsKICBjb2xvcjogYmx1ZTsKfQo=); @import url(data-url.css); + +/* url encoded: */ +@import url(data:text/css;plain,bar%20%7B%20color%3A%20green%20%7D); +@import url(data:text/css,bar%20%7B%20color%3A%20pink%20%7D); diff --git a/test/fixtures/data-url.expected.css b/test/fixtures/data-url.expected.css index 207253e4..af160fc5 100644 --- a/test/fixtures/data-url.expected.css +++ b/test/fixtures/data-url.expected.css @@ -1,24 +1,6 @@ -p { color: green; } +@import url(foo.css);p { color: green; }p { color: blue; }@media (min-width: 320px){@layer foo{ +p { color: green; } } }@media (min-width: 320px){@layer foo{ -p { color: blue; } - -@media (min-width: 320px) { - - @layer foo { -p { color: green; } } } - -@media (min-width: 320px) { - - @layer foo { - -p { color: blue; } } } - -/* Mixed imports: */ - -foo{} - -p { +p { color: blue; } } }/* Mixed imports: */p { color: blue; -} - -p { color: pink; } +}p { color: pink; }/* url encoded: */bar { color: green }bar { color: pink }