postcss-sort-media-queries 6.1.0 → 6.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/build/index.cjs +57 -41
- package/build/wrapper.cjs +9 -9
- package/package.json +10 -4
- package/src/index.js +137 -122
package/README.md
CHANGED
|
@@ -261,8 +261,10 @@ See [Releases history]
|
|
|
261
261
|
## Thanks
|
|
262
262
|
|
|
263
263
|
- Andrey Sitnik [@ai](https://github.com/ai)
|
|
264
|
-
- Oleh Dutchenko [@
|
|
264
|
+
- Oleh Dutchenko [@OlehDutchenko](https://github.com/OlehDutchenko)
|
|
265
265
|
- Jakub Caban [@Lustmored](https://github.com/Lustmored)
|
|
266
266
|
- Dmytro Symonov [@Kassaila](https://github.com/Kassaila)
|
|
267
267
|
- Kai Falkowski [@SassNinja](https://github.com/SassNinja)
|
|
268
268
|
- Khayot Razzakov [@Khayotbek1](https://github.com/Khayotbek1)
|
|
269
|
+
- ReindDooyeweerd [@ReindDooyeweerd](https://github.com/ReindDooyeweerd)
|
|
270
|
+
- msev [@msev](https://github.com/msev)
|
package/build/index.cjs
CHANGED
|
@@ -235,12 +235,20 @@ function createSort(configuration) {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
// src/index.js
|
|
238
|
+
var import_crypto = require("crypto");
|
|
238
239
|
function sortAtRules(queries, options, sortCSSmq) {
|
|
239
240
|
if (typeof options.sort !== "function") {
|
|
240
241
|
options.sort = options.sort === "desktop-first" ? sortCSSmq.desktopFirst : sortCSSmq;
|
|
241
242
|
}
|
|
242
243
|
return queries.sort(options.sort);
|
|
243
244
|
}
|
|
245
|
+
function getDepth(node) {
|
|
246
|
+
let depth = 0;
|
|
247
|
+
for (let p = node.parent; p; p = p.parent) {
|
|
248
|
+
depth++;
|
|
249
|
+
}
|
|
250
|
+
return depth;
|
|
251
|
+
}
|
|
244
252
|
function plugin(options = {}) {
|
|
245
253
|
options = Object.assign(
|
|
246
254
|
{
|
|
@@ -254,55 +262,63 @@ function plugin(options = {}) {
|
|
|
254
262
|
postcssPlugin: "postcss-sort-media-queries",
|
|
255
263
|
// Execute once after the entire tree has been parsed
|
|
256
264
|
OnceExit(root, { AtRule }) {
|
|
257
|
-
let parents =
|
|
258
|
-
root: [],
|
|
259
|
-
nested: []
|
|
260
|
-
};
|
|
261
|
-
let processed = /* @__PURE__ */ Symbol("processed");
|
|
265
|
+
let parents = [];
|
|
262
266
|
root.walkAtRules("media", (atRule) => {
|
|
263
|
-
if (atRule.parent
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
parents.nested.push(atRule.parent);
|
|
267
|
+
if (!atRule.parent.groupId) {
|
|
268
|
+
let groupId = (0, import_crypto.randomUUID)();
|
|
269
|
+
atRule.parent.groupId = groupId;
|
|
270
|
+
parents[groupId] = {
|
|
271
|
+
parent: atRule.parent,
|
|
272
|
+
depth: getDepth(atRule.parent)
|
|
273
|
+
};
|
|
271
274
|
}
|
|
272
|
-
atRule.parent[processed] = true;
|
|
273
275
|
return;
|
|
274
276
|
});
|
|
275
|
-
|
|
276
|
-
|
|
277
|
+
if (!parents) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
parents = Object.fromEntries(
|
|
281
|
+
Object.entries(parents).sort(([, a], [, b]) => {
|
|
282
|
+
return b.depth - a.depth;
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
Object.keys(parents).forEach((groupId) => {
|
|
286
|
+
let { parent } = parents[groupId];
|
|
287
|
+
let medias = parent.nodes.filter(
|
|
288
|
+
(node) => node.type === "atrule" && node.name === "media"
|
|
289
|
+
);
|
|
290
|
+
if (!medias) {
|
|
277
291
|
return;
|
|
278
292
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
let atRules = [];
|
|
287
|
-
media.forEach((atRule) => {
|
|
288
|
-
let query = atRule.params;
|
|
289
|
-
if (!atRules[query]) {
|
|
290
|
-
atRules[query] = new AtRule({
|
|
291
|
-
name: atRule.name,
|
|
292
|
-
params: atRule.params,
|
|
293
|
-
source: atRule.source
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
atRule.nodes.forEach((node) => {
|
|
297
|
-
atRules[query].append(node);
|
|
298
|
-
});
|
|
299
|
-
atRule.remove();
|
|
300
|
-
});
|
|
301
|
-
if (atRules) {
|
|
302
|
-
sortAtRules(Object.keys(atRules), options, sortCSSmq).forEach((query) => {
|
|
303
|
-
parent.append(atRules[query]);
|
|
293
|
+
let atRules = [];
|
|
294
|
+
medias.forEach((atRule) => {
|
|
295
|
+
if (!atRules[atRule.params]) {
|
|
296
|
+
atRules[atRule.params] = new AtRule({
|
|
297
|
+
name: atRule.name,
|
|
298
|
+
params: atRule.params,
|
|
299
|
+
source: atRule.source
|
|
304
300
|
});
|
|
305
301
|
}
|
|
302
|
+
[...atRule.nodes].forEach((node) => {
|
|
303
|
+
atRules[atRule.params].append(node);
|
|
304
|
+
});
|
|
305
|
+
atRule.remove();
|
|
306
|
+
});
|
|
307
|
+
if (atRules) {
|
|
308
|
+
sortAtRules(Object.keys(atRules), options, sortCSSmq).forEach((query) => {
|
|
309
|
+
parent.append(atRules[query]);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
root.walkAtRules("media", (parent) => {
|
|
314
|
+
let medias = parent.nodes.filter(
|
|
315
|
+
(node) => node.type === "atrule" && node.name === "media"
|
|
316
|
+
);
|
|
317
|
+
if (!medias) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
medias.forEach((atRule) => {
|
|
321
|
+
parent.append(atRule);
|
|
306
322
|
});
|
|
307
323
|
});
|
|
308
324
|
}
|
package/build/wrapper.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const mod = require('./index.cjs');
|
|
4
|
-
|
|
5
|
-
const plugin = mod.default;
|
|
6
|
-
|
|
7
|
-
plugin.postcss = mod.postcss;
|
|
8
|
-
|
|
9
|
-
module.exports = plugin;
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const mod = require('./index.cjs');
|
|
4
|
+
|
|
5
|
+
const plugin = mod.default;
|
|
6
|
+
|
|
7
|
+
plugin.postcss = mod.postcss;
|
|
8
|
+
|
|
9
|
+
module.exports = plugin;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postcss-sort-media-queries",
|
|
3
3
|
"description": "PostCSS plugin for sorting and combining CSS media queries with mobile first / **desktop first methodologies",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.2.2",
|
|
5
5
|
"engines": {
|
|
6
|
-
"node": ">=
|
|
6
|
+
"node": ">=20.0.0"
|
|
7
7
|
},
|
|
8
8
|
"keywords": [
|
|
9
9
|
"postcss",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"bugs": {
|
|
32
32
|
"url": "https://github.com/yunusga/postcss-sort-media-queries/issues"
|
|
33
33
|
},
|
|
34
|
-
"homepage": "https://
|
|
34
|
+
"homepage": "https://yunusga.uz/postcss-sort-media-queries",
|
|
35
35
|
"type": "module",
|
|
36
36
|
"main": "src/index.js",
|
|
37
37
|
"module": "src/index.js",
|
|
@@ -46,15 +46,21 @@
|
|
|
46
46
|
"build"
|
|
47
47
|
],
|
|
48
48
|
"scripts": {
|
|
49
|
-
"test": "vitest run",
|
|
49
|
+
"test": "npm run build && vitest run",
|
|
50
50
|
"test:watch": "vitest --watch",
|
|
51
51
|
"coverage": "vitest --coverage",
|
|
52
|
+
"lint": "eslint",
|
|
53
|
+
"prepare": "husky",
|
|
52
54
|
"build": "npm run build:cjs",
|
|
53
55
|
"build:cjs": "esbuild src/index.js --outfile=build/index.cjs --format=cjs --bundle --platform=node --external:postcss"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
|
58
|
+
"@eslint/js": "^10.0.1",
|
|
56
59
|
"@vitest/coverage-v8": "^4.0.18",
|
|
57
60
|
"esbuild": "^0.27.3",
|
|
61
|
+
"eslint": "^10.0.3",
|
|
62
|
+
"globals": "^17.4.0",
|
|
63
|
+
"husky": "^9.1.7",
|
|
58
64
|
"postcss": "^8.5.6",
|
|
59
65
|
"prettier": "3.8.1",
|
|
60
66
|
"vitest": "^4.0.18"
|
package/src/index.js
CHANGED
|
@@ -1,122 +1,137 @@
|
|
|
1
|
-
import createSort from 'sort-css-media-queries/create-sort';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (atRule.parent.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
1
|
+
import createSort from 'sort-css-media-queries/create-sort';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
|
|
4
|
+
// PostCSS plugin to sort CSS @media rules according to a configurable order.
|
|
5
|
+
// The plugin groups top-level and nested media at-rules, merges rules
|
|
6
|
+
// with identical queries, and re-inserts them in the desired order.
|
|
7
|
+
|
|
8
|
+
// Helper that ensures `options.sort` is a function and sorts queries.
|
|
9
|
+
function sortAtRules(queries, options, sortCSSmq) {
|
|
10
|
+
if (typeof options.sort !== 'function') {
|
|
11
|
+
options.sort = options.sort === 'desktop-first' ? sortCSSmq.desktopFirst : sortCSSmq;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return queries.sort(options.sort);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getDepth(node) {
|
|
18
|
+
let depth = 0;
|
|
19
|
+
|
|
20
|
+
for (let p = node.parent; p; p = p.parent) {
|
|
21
|
+
depth++;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return depth;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function plugin(options = {}) {
|
|
28
|
+
|
|
29
|
+
// Set default options and allow user overrides
|
|
30
|
+
options = Object.assign(
|
|
31
|
+
{
|
|
32
|
+
sort: 'mobile-first',
|
|
33
|
+
configuration: false,
|
|
34
|
+
},
|
|
35
|
+
options
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Create a sorter based on configuration (from sort-css-media-queries)
|
|
39
|
+
const sortCSSmq = createSort(options.configuration);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
postcssPlugin: 'postcss-sort-media-queries',
|
|
43
|
+
|
|
44
|
+
// Execute once after the entire tree has been parsed
|
|
45
|
+
OnceExit(root, { AtRule }) {
|
|
46
|
+
// Collect parent nodes that contain media at-rules. We separate
|
|
47
|
+
// top-level (`root`) parents from nested parents so ordering
|
|
48
|
+
// semantics can be preserved independently.
|
|
49
|
+
let parents = [];
|
|
50
|
+
|
|
51
|
+
// Walk all @media at-rules and group their parents
|
|
52
|
+
root.walkAtRules('media', (atRule) => {
|
|
53
|
+
if (!atRule.parent.groupId) {
|
|
54
|
+
let groupId = randomUUID();
|
|
55
|
+
|
|
56
|
+
atRule.parent.groupId = groupId;
|
|
57
|
+
|
|
58
|
+
parents[groupId] = {
|
|
59
|
+
parent: atRule.parent,
|
|
60
|
+
depth: getDepth(atRule.parent),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (!parents) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
parents = Object.fromEntries(
|
|
72
|
+
Object.entries(parents).sort(([, a], [, b]) => {
|
|
73
|
+
return b.depth - a.depth;
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
Object.keys(parents).forEach((groupId) => {
|
|
78
|
+
let { parent } = parents[groupId];
|
|
79
|
+
|
|
80
|
+
// Filter only @media nodes from the parent's children
|
|
81
|
+
let medias = parent.nodes.filter(
|
|
82
|
+
(node) => node.type === 'atrule' && node.name === 'media'
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
if (!medias) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let atRules = [];
|
|
90
|
+
|
|
91
|
+
medias.forEach((atRule) => {
|
|
92
|
+
if (!atRules[atRule.params]) {
|
|
93
|
+
atRules[atRule.params] = new AtRule({
|
|
94
|
+
name: atRule.name,
|
|
95
|
+
params: atRule.params,
|
|
96
|
+
source: atRule.source,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[...atRule.nodes].forEach((node) => {
|
|
101
|
+
atRules[atRule.params].append(node);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Remove the original at-rule since its contents have been
|
|
105
|
+
// merged into `atRules[atRule.params]`.
|
|
106
|
+
atRule.remove();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Sort query keys and append merged at-rules back to the parent
|
|
110
|
+
if (atRules) {
|
|
111
|
+
sortAtRules(Object.keys(atRules), options, sortCSSmq).forEach((query) => {
|
|
112
|
+
parent.append(atRules[query]);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
root.walkAtRules('media', (parent) => {
|
|
118
|
+
// Filter only @media nodes from the parent's children
|
|
119
|
+
let medias = parent.nodes.filter(
|
|
120
|
+
(node) => node.type === 'atrule' && node.name === 'media'
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
if (!medias) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
medias.forEach((atRule) => {
|
|
128
|
+
parent.append(atRule);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
plugin.postcss = true;
|
|
136
|
+
|
|
137
|
+
export default plugin;
|