Skip to content

Commit

Permalink
simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
romainmenke committed Dec 9, 2023
1 parent a5830d1 commit eddfcd1
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 72 deletions.
49 changes: 11 additions & 38 deletions lib/apply-conditions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict"

const formatImportPrelude = require("./format-import-prelude")
const base64EncodedConditionalImport = require("./base64-encoded-import")

module.exports = function applyConditions(bundle, atRule) {
bundle.forEach(stmt => {
Expand All @@ -13,34 +13,10 @@ module.exports = function applyConditions(bundle, atRule) {
}

if (stmt.type === "import") {
if (stmt.conditions.length === 1) {
stmt.node.params = `${stmt.fullUri} ${formatImportPrelude(
stmt.conditions[0].layer,
stmt.conditions[0].media,
stmt.conditions[0].supports
)}`
} else {
const reverseConditions = stmt.conditions.slice().reverse()
const first = reverseConditions.pop()
let params = `${stmt.fullUri} ${formatImportPrelude(
first.layer,
first.media,
first.supports
)}`

for (const condition of reverseConditions) {
params = `'data:text/css;base64,${Buffer.from(
`@import ${params}`
).toString("base64")}' ${formatImportPrelude(
condition.layer,
condition.media,
condition.supports
)}`
}

stmt.node.params = params
}

stmt.node.params = base64EncodedConditionalImport(
stmt.fullUri,
stmt.conditions
)
return
}

Expand All @@ -58,33 +34,30 @@ module.exports = function applyConditions(bundle, atRule) {

// Convert conditions to at-rules
for (const condition of stmt.conditions) {
if (condition.media.length > 0) {
if (typeof condition.media !== "undefined") {
const mediaNode = atRule({
name: "media",
params: condition.media.join(", "),
params: condition.media,
source: parent.source,
})

atRules.push(mediaNode)
}

if (condition.supports.length > 0) {
if (typeof condition.supports !== "undefined") {
const supportsNode = atRule({
name: "supports",
params:
condition.supports.length === 1
? `(${condition.supports[0]})`
: condition.supports.map(x => `(${x})`).join(" and "),
params: `(${condition.supports})`,
source: parent.source,
})

atRules.push(supportsNode)
}

if (condition.layer.length > 0) {
if (typeof condition.layer !== "undefined") {
const layerNode = atRule({
name: "layer",
params: condition.layer.join("."),
params: condition.layer,
source: parent.source,
})

Expand Down
30 changes: 30 additions & 0 deletions lib/base64-encoded-import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use strict"

const formatImportPrelude = require("./format-import-prelude")

// Base64 encode an import with conditions
// The order of conditions is important and is interleaved with cascade layer declarations
// Each group of conditions and cascade layers needs to be interpreted in order
// To achieve this we create a list of base64 encoded imports, where each import contains a stylesheet with another import.
// Each import can define a single group of conditions and a single cascade layer.
module.exports = function base64EncodedConditionalImport(prelude, conditions) {
conditions.reverse()
const first = conditions.pop()
let params = `${prelude} ${formatImportPrelude(
first.layer,
first.media,
first.supports
)}`

for (const condition of conditions) {
params = `'data:text/css;base64,${Buffer.from(`@import ${params}`).toString(
"base64"
)}' ${formatImportPrelude(
condition.layer,
condition.media,
condition.supports
)}`
}

return params
}
18 changes: 7 additions & 11 deletions lib/format-import-prelude.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,21 @@
module.exports = function formatImportPrelude(layer, media, supports) {
const parts = []

if (layer.length) {
const layerName = layer.join(".")

if (typeof layer !== "undefined") {
let layerParams = "layer"
if (layerName) {
layerParams = `layer(${layerName})`
if (layer) {
layerParams = `layer(${layer})`
}

parts.push(layerParams)
}

if (supports.length === 1) {
parts.push(`supports(${supports[0]})`)
} else if (supports.length > 0) {
parts.push(`supports(${supports.map(x => `(${x})`).join(" and ")})`)
if (typeof supports !== "undefined") {
parts.push(`supports(${supports})`)
}

if (media.length) {
parts.push(media.join(", "))
if (typeof media !== "undefined") {
parts.push(media)
}

return parts.join(" ")
Expand Down
24 changes: 14 additions & 10 deletions lib/parse-statements.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ function parseImport(result, atRule, conditions, from) {
from,
}

let layer = []
let media = []
let supports = []
let layer
let media
let supports

for (let i = 0; i < params.length; i++) {
const node = params[i]
Expand Down Expand Up @@ -184,13 +184,13 @@ function parseImport(result, atRule, conditions, from) {
(node.type === "word" || node.type === "function") &&
/^layer$/i.test(node.value)
) {
if (layer.length > 0) {
if (typeof layer !== "undefined") {
return result.warn(`Multiple layers in '${atRule.toString()}'`, {
node: atRule,
})
}

if (supports.length > 0) {
if (typeof supports !== "undefined") {
return result.warn(
`layers must be defined before support conditions in '${atRule.toString()}'`,
{
Expand All @@ -200,16 +200,16 @@ function parseImport(result, atRule, conditions, from) {
}

if (node.nodes) {
layer = [stringify(node.nodes)]
layer = stringify(node.nodes)
} else {
layer = [""]
layer = ""
}

continue
}

if (node.type === "function" && /^supports$/i.test(node.value)) {
if (supports.length > 0) {
if (typeof supports !== "undefined") {
return result.warn(
`Multiple support conditions in '${atRule.toString()}'`,
{
Expand All @@ -218,7 +218,7 @@ function parseImport(result, atRule, conditions, from) {
)
}

supports = [stringify(node.nodes)]
supports = stringify(node.nodes)

continue
}
Expand All @@ -233,7 +233,11 @@ function parseImport(result, atRule, conditions, from) {
})
}

if (media.length > 0 || layer.length > 0 || supports.length > 0) {
if (
typeof media !== "undefined" ||
typeof layer !== "undefined" ||
typeof supports !== "undefined"
) {
stmt.conditions.push({
layer,
media,
Expand Down
18 changes: 11 additions & 7 deletions lib/parse-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,21 @@ function isProcessableURL(uri) {
}

function serializeConditions(conditions) {
let layer = []
let media = []
let supports = []
const layer = []
const media = new Set()
const supports = new Set()

for (const condition of conditions) {
layer = layer.concat(condition.layer)
media = Array.from(new Set(media.concat(condition.media)))
supports = Array.from(new Set(supports.concat(condition.supports)))
layer.push(condition.layer)
media.add(condition.media)
supports.add(condition.supports)
}

return JSON.stringify({ layer, media, supports })
return JSON.stringify({
layer,
media: Array.from(media),
supports: Array.from(supports),
})
}

module.exports = parseStyles
2 changes: 1 addition & 1 deletion test/fixtures/filter-all.expected.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
@import url("foobar.css");
@import url("foobar.css") screen and (min-width: 25em);
@import url('foobarbaz.css');
@import url('foobarbaz.css') print, screen and (min-width: 25em);
@import url('foobarbaz.css') print,screen and (min-width: 25em);
content{}
2 changes: 1 addition & 1 deletion test/fixtures/filter-some.expected.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ baz{}
baz{}
}
foobarbaz{}
@media print, screen and (min-width: 25em){
@media print,screen and (min-width: 25em){
foobarbaz{}
}
content{}
4 changes: 2 additions & 2 deletions test/fixtures/ignore.expected.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
@import url(//css);
@import "http://css" layer;
@import "http://css" layer(bar);
@import "http://css" layer screen and (min-width: 25em), print;
@import "http://css" layer(bar) screen and (min-width: 25em), print;
@import "http://css" layer screen and (min-width: 25em),print;
@import "http://css" layer(bar) screen and (min-width: 25em),print;
@media (min-width: 25em){
ignore{}
}
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/media-join.expected.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@media and-left-2 and and-right-2 {}
}

@media or-left-1, or-right-1 {
@media or-left-1,or-right-1 {

@media one-2 {}

Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/simple.expected.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ foobar{}
foobar{}
}
foobarbaz{}
@media print, screen and (min-width: 25em){
@media print,screen and (min-width: 25em){
foobarbaz{}
}
content{}

0 comments on commit eddfcd1

Please sign in to comment.