postcss-sort-media-queries 6.1.0 → 6.3.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 +375 -2
- package/build/index.cjs +86 -41
- package/build/wrapper.cjs +9 -9
- package/package.json +11 -5
- package/src/index.js +70 -55
package/README.md
CHANGED
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
- [Examples](#examples)
|
|
25
25
|
- [Mobile first sorting](#mobile-first-sorting)
|
|
26
26
|
- [Desktop first sorting](#desktop-first-sorting)
|
|
27
|
+
- [Nested media queries sorting](#nested-media-queries-sorting)
|
|
27
28
|
- [Install](#install)
|
|
28
29
|
- [Usage](#usage)
|
|
29
30
|
- [Options](#options)
|
|
30
31
|
- [sort](#sort)
|
|
31
32
|
- [Custom sort function](#custom-sort-function)
|
|
32
33
|
- [Sort configuration](#sort-configuration)
|
|
33
|
-
- [Only Top Level](#only-top-level)
|
|
34
34
|
- [Changelog](#changelog)
|
|
35
35
|
- [License](#license)
|
|
36
36
|
- [Other PostCSS plugins](#other-postcss-plugins)
|
|
@@ -128,6 +128,377 @@ And here is the [Online Demo]
|
|
|
128
128
|
}
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
### Nested media queries sorting
|
|
132
|
+
|
|
133
|
+
**Before**
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
@media (min-width: 710px) {
|
|
137
|
+
.print-only-global-2 {
|
|
138
|
+
display: block;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@media (min-width: 1210px) {
|
|
143
|
+
.print-only-global-4 {
|
|
144
|
+
display: block;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.print-only-global-5 {
|
|
148
|
+
display: block;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.print-only-global-6 {
|
|
152
|
+
display: block;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@media (min-width: 310px) {
|
|
157
|
+
.print-only-global-1 {
|
|
158
|
+
display: block;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@media (min-width: 710px) {
|
|
163
|
+
.print-only-global-3 {
|
|
164
|
+
display: block;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@media (min-width: 1210px) {
|
|
169
|
+
.print-only-global-7 {
|
|
170
|
+
display: block;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@media print {
|
|
175
|
+
.print-only {
|
|
176
|
+
display: block;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.print-only-parent-1 {
|
|
180
|
+
display: block;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@media (orientation: landscape) {
|
|
184
|
+
.print-only {
|
|
185
|
+
color: black;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@media (min-width: 910px) {
|
|
189
|
+
.nested-landscape-3 {
|
|
190
|
+
color: black;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.nested-landscape-4 {
|
|
194
|
+
color: black;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.nested-landscape-5 {
|
|
198
|
+
color: black;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@media (min-width: 810px) {
|
|
203
|
+
.nested-landscape-2 {
|
|
204
|
+
color: black;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@media (min-width: 710px) {
|
|
209
|
+
.nested-landscape-1 {
|
|
210
|
+
color: black;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.nested-landscape-0 {
|
|
215
|
+
color: black;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@media (min-width: 710px) {
|
|
219
|
+
.nested-landscape-4 {
|
|
220
|
+
color: black;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.nested-landscape-5 {
|
|
224
|
+
color: black;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.nested-landscape-6 {
|
|
228
|
+
color: black;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@media (min-width: 710px) {
|
|
233
|
+
.nested-landscape-8 {
|
|
234
|
+
color: black;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.nested-landscape-9 {
|
|
238
|
+
color: black;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@media (min-width: 500px) {
|
|
244
|
+
.print-only {
|
|
245
|
+
color: black;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.print-only-parent-2 {
|
|
250
|
+
display: block;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@media (min-width: 500px) {
|
|
254
|
+
.print-only {
|
|
255
|
+
color: black;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@media (orientation: portrait) {
|
|
260
|
+
.print-only {
|
|
261
|
+
color: gray;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.print-only-parent-3 {
|
|
266
|
+
display: block;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@media (min-width: 320px) {
|
|
270
|
+
.print-only {
|
|
271
|
+
color: black;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@media (orientation: landscape) {
|
|
276
|
+
.print-only-landscape-1-1 {
|
|
277
|
+
color: gray;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.print-only-landscape-1-2 {
|
|
281
|
+
color: gray;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.print-only-landscape-1-3 {
|
|
285
|
+
color: gray;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@layer base {
|
|
291
|
+
|
|
292
|
+
@media (min-width: 1220px) {
|
|
293
|
+
.print-only-1200-1 {
|
|
294
|
+
color: black;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@media (min-width: 320px) {
|
|
299
|
+
.print-only-320-1 {
|
|
300
|
+
color: black;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
@media (min-width: 1220px) {
|
|
305
|
+
.print-only-1200-2 {
|
|
306
|
+
color: black;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
@media (min-width: 620px) {
|
|
311
|
+
.print-only-640-1 {
|
|
312
|
+
color: black;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@media (min-width: 320px) {
|
|
317
|
+
.print-only-320-2 {
|
|
318
|
+
color: black;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
@media (min-width: 320px) {
|
|
323
|
+
.print-only-320-3 {
|
|
324
|
+
color: black;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
@media (min-width: 620px) {
|
|
329
|
+
.print-only-640-2 {
|
|
330
|
+
color: black;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**After**
|
|
337
|
+
|
|
338
|
+
```css
|
|
339
|
+
@layer base {
|
|
340
|
+
@media (min-width: 320px) {
|
|
341
|
+
.print-only-320-1 {
|
|
342
|
+
color: black;
|
|
343
|
+
}
|
|
344
|
+
.print-only-320-2 {
|
|
345
|
+
color: black;
|
|
346
|
+
}
|
|
347
|
+
.print-only-320-3 {
|
|
348
|
+
color: black;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
@media (min-width: 620px) {
|
|
352
|
+
.print-only-640-1 {
|
|
353
|
+
color: black;
|
|
354
|
+
}
|
|
355
|
+
.print-only-640-2 {
|
|
356
|
+
color: black;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
@media (min-width: 1220px) {
|
|
360
|
+
.print-only-1200-1 {
|
|
361
|
+
color: black;
|
|
362
|
+
}
|
|
363
|
+
.print-only-1200-2 {
|
|
364
|
+
color: black;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
@media (min-width: 310px) {
|
|
369
|
+
.print-only-global-1 {
|
|
370
|
+
display: block;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
@media (min-width: 710px) {
|
|
374
|
+
.print-only-global-2 {
|
|
375
|
+
display: block;
|
|
376
|
+
}
|
|
377
|
+
.print-only-global-3 {
|
|
378
|
+
display: block;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
@media (min-width: 1210px) {
|
|
382
|
+
.print-only-global-4 {
|
|
383
|
+
display: block;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.print-only-global-5 {
|
|
387
|
+
display: block;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.print-only-global-6 {
|
|
391
|
+
display: block;
|
|
392
|
+
}
|
|
393
|
+
.print-only-global-7 {
|
|
394
|
+
display: block;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
@media print {
|
|
398
|
+
.print-only {
|
|
399
|
+
display: block;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.print-only-parent-1 {
|
|
403
|
+
display: block;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.print-only-parent-2 {
|
|
407
|
+
display: block;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.print-only-parent-3 {
|
|
411
|
+
display: block;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@media (min-width: 320px) {
|
|
415
|
+
.print-only {
|
|
416
|
+
color: black;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
@media (min-width: 500px) {
|
|
421
|
+
.print-only {
|
|
422
|
+
color: black;
|
|
423
|
+
}
|
|
424
|
+
.print-only {
|
|
425
|
+
color: black;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
@media (orientation: landscape) {
|
|
430
|
+
.print-only {
|
|
431
|
+
color: black;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.nested-landscape-0 {
|
|
435
|
+
color: black;
|
|
436
|
+
}
|
|
437
|
+
.print-only-landscape-1-1 {
|
|
438
|
+
color: gray;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.print-only-landscape-1-2 {
|
|
442
|
+
color: gray;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.print-only-landscape-1-3 {
|
|
446
|
+
color: gray;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
@media (min-width: 710px) {
|
|
450
|
+
.nested-landscape-1 {
|
|
451
|
+
color: black;
|
|
452
|
+
}
|
|
453
|
+
.nested-landscape-4 {
|
|
454
|
+
color: black;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.nested-landscape-5 {
|
|
458
|
+
color: black;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.nested-landscape-6 {
|
|
462
|
+
color: black;
|
|
463
|
+
}
|
|
464
|
+
.nested-landscape-8 {
|
|
465
|
+
color: black;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.nested-landscape-9 {
|
|
469
|
+
color: black;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
@media (min-width: 810px) {
|
|
474
|
+
.nested-landscape-2 {
|
|
475
|
+
color: black;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
@media (min-width: 910px) {
|
|
480
|
+
.nested-landscape-3 {
|
|
481
|
+
color: black;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.nested-landscape-4 {
|
|
485
|
+
color: black;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.nested-landscape-5 {
|
|
489
|
+
color: black;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
@media (orientation: portrait) {
|
|
495
|
+
.print-only {
|
|
496
|
+
color: gray;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
131
502
|
## Install
|
|
132
503
|
|
|
133
504
|
First thing's, install the module:
|
|
@@ -261,8 +632,10 @@ See [Releases history]
|
|
|
261
632
|
## Thanks
|
|
262
633
|
|
|
263
634
|
- Andrey Sitnik [@ai](https://github.com/ai)
|
|
264
|
-
- Oleh Dutchenko [@
|
|
635
|
+
- Oleh Dutchenko [@OlehDutchenko](https://github.com/OlehDutchenko)
|
|
265
636
|
- Jakub Caban [@Lustmored](https://github.com/Lustmored)
|
|
266
637
|
- Dmytro Symonov [@Kassaila](https://github.com/Kassaila)
|
|
267
638
|
- Kai Falkowski [@SassNinja](https://github.com/SassNinja)
|
|
268
639
|
- Khayot Razzakov [@Khayotbek1](https://github.com/Khayotbek1)
|
|
640
|
+
- ReindDooyeweerd [@ReindDooyeweerd](https://github.com/ReindDooyeweerd)
|
|
641
|
+
- msev [@msev](https://github.com/msev)
|
package/build/index.cjs
CHANGED
|
@@ -234,6 +234,36 @@ function createSort(configuration) {
|
|
|
234
234
|
return sortCSSmq;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
// node_modules/nanoid/index.js
|
|
238
|
+
var import_node_crypto = require("node:crypto");
|
|
239
|
+
|
|
240
|
+
// node_modules/nanoid/url-alphabet/index.js
|
|
241
|
+
var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
242
|
+
|
|
243
|
+
// node_modules/nanoid/index.js
|
|
244
|
+
var POOL_SIZE_MULTIPLIER = 128;
|
|
245
|
+
var pool;
|
|
246
|
+
var poolOffset;
|
|
247
|
+
function fillPool(bytes) {
|
|
248
|
+
if (!pool || pool.length < bytes) {
|
|
249
|
+
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
|
250
|
+
import_node_crypto.webcrypto.getRandomValues(pool);
|
|
251
|
+
poolOffset = 0;
|
|
252
|
+
} else if (poolOffset + bytes > pool.length) {
|
|
253
|
+
import_node_crypto.webcrypto.getRandomValues(pool);
|
|
254
|
+
poolOffset = 0;
|
|
255
|
+
}
|
|
256
|
+
poolOffset += bytes;
|
|
257
|
+
}
|
|
258
|
+
function nanoid(size = 21) {
|
|
259
|
+
fillPool(size |= 0);
|
|
260
|
+
let id = "";
|
|
261
|
+
for (let i = poolOffset - size; i < poolOffset; i++) {
|
|
262
|
+
id += urlAlphabet[pool[i] & 63];
|
|
263
|
+
}
|
|
264
|
+
return id;
|
|
265
|
+
}
|
|
266
|
+
|
|
237
267
|
// src/index.js
|
|
238
268
|
function sortAtRules(queries, options, sortCSSmq) {
|
|
239
269
|
if (typeof options.sort !== "function") {
|
|
@@ -241,6 +271,13 @@ function sortAtRules(queries, options, sortCSSmq) {
|
|
|
241
271
|
}
|
|
242
272
|
return queries.sort(options.sort);
|
|
243
273
|
}
|
|
274
|
+
function getDepth(node) {
|
|
275
|
+
let depth = 0;
|
|
276
|
+
for (let p = node.parent; p; p = p.parent) {
|
|
277
|
+
depth++;
|
|
278
|
+
}
|
|
279
|
+
return depth;
|
|
280
|
+
}
|
|
244
281
|
function plugin(options = {}) {
|
|
245
282
|
options = Object.assign(
|
|
246
283
|
{
|
|
@@ -254,55 +291,63 @@ function plugin(options = {}) {
|
|
|
254
291
|
postcssPlugin: "postcss-sort-media-queries",
|
|
255
292
|
// Execute once after the entire tree has been parsed
|
|
256
293
|
OnceExit(root, { AtRule }) {
|
|
257
|
-
let parents =
|
|
258
|
-
root: [],
|
|
259
|
-
nested: []
|
|
260
|
-
};
|
|
261
|
-
let processed = /* @__PURE__ */ Symbol("processed");
|
|
294
|
+
let parents = [];
|
|
262
295
|
root.walkAtRules("media", (atRule) => {
|
|
263
|
-
if (atRule.parent
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
parents.nested.push(atRule.parent);
|
|
296
|
+
if (!atRule.parent.groupId) {
|
|
297
|
+
let groupId = nanoid();
|
|
298
|
+
atRule.parent.groupId = groupId;
|
|
299
|
+
parents[groupId] = {
|
|
300
|
+
parent: atRule.parent,
|
|
301
|
+
depth: getDepth(atRule.parent)
|
|
302
|
+
};
|
|
271
303
|
}
|
|
272
|
-
atRule.parent[processed] = true;
|
|
273
304
|
return;
|
|
274
305
|
});
|
|
275
|
-
|
|
276
|
-
|
|
306
|
+
if (!parents) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
parents = Object.fromEntries(
|
|
310
|
+
Object.entries(parents).sort(([, a], [, b]) => {
|
|
311
|
+
return b.depth - a.depth;
|
|
312
|
+
})
|
|
313
|
+
);
|
|
314
|
+
Object.keys(parents).forEach((groupId) => {
|
|
315
|
+
let { parent } = parents[groupId];
|
|
316
|
+
let medias = parent.nodes.filter(
|
|
317
|
+
(node) => node.type === "atrule" && node.name === "media"
|
|
318
|
+
);
|
|
319
|
+
if (!medias) {
|
|
277
320
|
return;
|
|
278
321
|
}
|
|
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]);
|
|
322
|
+
let atRules = [];
|
|
323
|
+
medias.forEach((atRule) => {
|
|
324
|
+
if (!atRules[atRule.params]) {
|
|
325
|
+
atRules[atRule.params] = new AtRule({
|
|
326
|
+
name: atRule.name,
|
|
327
|
+
params: atRule.params,
|
|
328
|
+
source: atRule.source
|
|
304
329
|
});
|
|
305
330
|
}
|
|
331
|
+
[...atRule.nodes].forEach((node) => {
|
|
332
|
+
atRules[atRule.params].append(node);
|
|
333
|
+
});
|
|
334
|
+
atRule.remove();
|
|
335
|
+
});
|
|
336
|
+
if (atRules) {
|
|
337
|
+
sortAtRules(Object.keys(atRules), options, sortCSSmq).forEach((query) => {
|
|
338
|
+
parent.append(atRules[query]);
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
root.walkAtRules("media", (parent) => {
|
|
343
|
+
let medias = parent.nodes.filter(
|
|
344
|
+
(node) => node.type === "atrule" && node.name === "media"
|
|
345
|
+
);
|
|
346
|
+
if (!medias) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
medias.forEach((atRule) => {
|
|
350
|
+
parent.append(atRule);
|
|
306
351
|
});
|
|
307
352
|
});
|
|
308
353
|
}
|
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.3.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,20 +46,26 @@
|
|
|
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",
|
|
58
|
-
"
|
|
61
|
+
"eslint": "^10.0.3",
|
|
62
|
+
"globals": "^17.4.0",
|
|
63
|
+
"husky": "^9.1.7",
|
|
59
64
|
"prettier": "3.8.1",
|
|
60
65
|
"vitest": "^4.0.18"
|
|
61
66
|
},
|
|
62
67
|
"peerDependencies": {
|
|
68
|
+
"nanoid": "^5.1.6",
|
|
63
69
|
"postcss": "^8.5.6"
|
|
64
70
|
},
|
|
65
71
|
"dependencies": {
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import createSort from 'sort-css-media-queries/create-sort';
|
|
2
|
+
import { nanoid } from 'nanoid';
|
|
2
3
|
|
|
3
4
|
// PostCSS plugin to sort CSS @media rules according to a configurable order.
|
|
4
5
|
// The plugin groups top-level and nested media at-rules, merges rules
|
|
@@ -13,6 +14,16 @@ function sortAtRules(queries, options, sortCSSmq) {
|
|
|
13
14
|
return queries.sort(options.sort);
|
|
14
15
|
}
|
|
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
|
+
|
|
16
27
|
function plugin(options = {}) {
|
|
17
28
|
|
|
18
29
|
// Set default options and allow user overrides
|
|
@@ -35,82 +46,86 @@ function plugin(options = {}) {
|
|
|
35
46
|
// Collect parent nodes that contain media at-rules. We separate
|
|
36
47
|
// top-level (`root`) parents from nested parents so ordering
|
|
37
48
|
// semantics can be preserved independently.
|
|
38
|
-
let parents =
|
|
39
|
-
root: [],
|
|
40
|
-
nested: [],
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// Symbol used to mark parents that we've already collected
|
|
44
|
-
let processed = Symbol('processed');
|
|
49
|
+
let parents = [];
|
|
45
50
|
|
|
46
51
|
// Walk all @media at-rules and group their parents
|
|
47
52
|
root.walkAtRules('media', (atRule) => {
|
|
48
|
-
if (atRule.parent
|
|
49
|
-
|
|
50
|
-
}
|
|
53
|
+
if (!atRule.parent.groupId) {
|
|
54
|
+
let groupId = nanoid();
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
if (atRule.parent.type === 'root') {
|
|
54
|
-
parents.root.push(atRule.parent);
|
|
55
|
-
}
|
|
56
|
+
atRule.parent.groupId = groupId;
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
parents[groupId] = {
|
|
59
|
+
parent: atRule.parent,
|
|
60
|
+
depth: getDepth(atRule.parent),
|
|
61
|
+
}
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
// Mark this parent so we don't collect it twice
|
|
63
|
-
atRule.parent[processed] = true;
|
|
64
|
-
|
|
65
64
|
return;
|
|
66
65
|
});
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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) {
|
|
71
86
|
return;
|
|
72
87
|
}
|
|
73
88
|
|
|
74
|
-
|
|
75
|
-
// Filter only @media nodes from the parent's children
|
|
76
|
-
let media = parent.nodes.filter(
|
|
77
|
-
n => n.type === 'atrule' && n.name === 'media'
|
|
78
|
-
);
|
|
89
|
+
let atRules = [];
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
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
|
+
});
|
|
82
98
|
}
|
|
83
99
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
[...atRule.nodes].forEach((node) => {
|
|
101
|
+
atRules[atRule.params].append(node);
|
|
102
|
+
});
|
|
87
103
|
|
|
88
|
-
|
|
89
|
-
|
|
104
|
+
// Remove the original at-rule since its contents have been
|
|
105
|
+
// merged into `atRules[atRule.params]`.
|
|
106
|
+
atRule.remove();
|
|
107
|
+
});
|
|
90
108
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
+
});
|
|
98
116
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
+
);
|
|
102
122
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
123
|
+
if (!medias) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
107
126
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
sortAtRules(Object.keys(atRules), options, sortCSSmq).forEach((query) => {
|
|
111
|
-
parent.append(atRules[query]);
|
|
112
|
-
});
|
|
113
|
-
}
|
|
127
|
+
medias.forEach((atRule) => {
|
|
128
|
+
parent.append(atRule);
|
|
114
129
|
});
|
|
115
130
|
});
|
|
116
131
|
}
|