@esportsplus/ui 0.53.0 → 0.55.0
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 +51 -6
- package/build/components/accordion/index.d.ts +714 -23
- package/build/components/accordion/index.js +22 -11
- package/build/components/accordion/scss/index.scss +1 -1
- package/build/components/anchor/scss/index.scss +1 -1
- package/build/components/button/scss/index.scss +1 -1
- package/build/components/card/scss/index.scss +1 -1
- package/build/components/checkbox/constants.d.ts +2 -0
- package/build/components/checkbox/constants.js +2 -0
- package/build/components/checkbox/index.d.ts +16 -10
- package/build/components/checkbox/index.js +53 -39
- package/build/components/checkbox/scss/index.scss +1 -1
- package/build/components/checkbox/svg/check.svg +1 -0
- package/build/components/clipboard/copy.d.ts +11 -0
- package/build/components/clipboard/copy.js +54 -0
- package/build/components/clipboard/index.d.ts +1435 -1229
- package/build/components/clipboard/index.js +3 -2
- package/build/components/clipboard/onclick.d.ts +4 -38
- package/build/components/clipboard/onclick.js +10 -12
- package/build/components/counter/index.d.ts +1 -1
- package/build/components/counter/index.js +59 -71
- package/build/components/counter/scss/index.scss +1 -1
- package/build/components/form/action.d.ts +1 -1
- package/build/components/form/action.js +9 -12
- package/build/components/form/index.d.ts +5 -5
- package/build/components/form/input.d.ts +4 -4
- package/build/components/grid/scss/index.scss +1 -1
- package/build/components/icon/index.d.ts +2 -19
- package/build/components/icon/index.js +6 -6
- package/build/components/icon/scss/index.scss +1 -1
- package/build/components/index.d.ts +0 -7
- package/build/components/index.js +0 -7
- package/build/components/input/index.d.ts +1 -1
- package/build/components/input/index.js +12 -13
- package/build/components/input/scss/index.scss +1 -1
- package/build/components/link/scss/index.scss +1 -1
- package/build/components/loading/index.js +5 -5
- package/build/components/modal/scss/index.scss +1 -1
- package/build/components/normalize/scss/index.scss +1 -1
- package/build/components/overlay/index.d.ts +2 -19
- package/build/components/overlay/index.js +7 -7
- package/build/components/page/scss/index.scss +1 -1
- package/build/components/radio/index.d.ts +3 -10
- package/build/components/radio/index.js +2 -2
- package/build/components/range/index.d.ts +1 -1
- package/build/components/range/index.js +13 -13
- package/build/components/range/scss/index.scss +1 -1
- package/build/components/root/scss/index.scss +1 -1
- package/build/components/select/constants.d.ts +4 -0
- package/build/components/select/constants.js +4 -0
- package/build/components/select/index.d.ts +15 -52
- package/build/components/select/index.js +65 -94
- package/build/components/select/scss/index.scss +1 -1
- package/build/components/sidebar/index.d.ts +2 -19
- package/build/components/sidebar/index.js +7 -7
- package/build/components/sidebar/scss/index.scss +1 -1
- package/build/components/switch/index.d.ts +3 -10
- package/build/components/switch/index.js +2 -2
- package/build/components/tabs/scss/index.scss +2 -0
- package/build/components/text/scss/index.scss +1 -1
- package/build/components/textarea/index.d.ts +719 -6
- package/build/components/textarea/index.js +36 -17
- package/build/components/textarea/scss/index.scss +1 -1
- package/build/components/toast/index.js +43 -43
- package/build/components/toast/scss/index.scss +1 -1
- package/build/components/tooltip/constants.d.ts +3 -0
- package/build/components/tooltip/constants.js +3 -0
- package/build/components/tooltip/index.d.ts +8 -2546
- package/build/components/tooltip/index.js +2 -1
- package/build/components/tooltip/menu.d.ts +9 -21
- package/build/components/tooltip/menu.js +26 -29
- package/build/components/tooltip/onclick.d.ts +717 -1229
- package/build/components/tooltip/onclick.js +18 -60
- package/build/components/tooltip/onhover.d.ts +716 -20
- package/build/components/tooltip/onhover.js +14 -19
- package/build/components/tooltip/scss/index.scss +1 -1
- package/build/components/typewriter/index.d.ts +2 -19
- package/build/components/typewriter/index.js +8 -8
- package/build/css-utilities/background/scss/index.scss +1 -1
- package/build/css-utilities/border/scss/index.scss +1 -1
- package/build/css-utilities/color/scss/index.scss +1 -1
- package/build/css-utilities/font/geist/scss/Geist-Italic-Variable.woff2 +0 -0
- package/build/css-utilities/font/geist/scss/Geist-Variable.woff2 +0 -0
- package/build/css-utilities/font/geist/scss/GeistMono-Italic-Variable.woff2 +0 -0
- package/build/css-utilities/font/geist/scss/GeistMono-Variable.woff2 +0 -0
- package/build/css-utilities/font/geist/scss/index.scss +2 -0
- package/build/css-utilities/font/montserrat/index.d.ts +1 -0
- package/build/css-utilities/font/montserrat/index.js +1 -0
- package/build/css-utilities/font/montserrat/scss/index.scss +2 -0
- package/build/css-utilities/index.scss +1 -1
- package/build/css-utilities/inline/scss/index.scss +1 -1
- package/build/css-utilities/scrollbar/scss/index.scss +1 -1
- package/build/css-utilities/tabular/scss/index.scss +2 -0
- package/build/css-utilities/text/scss/index.scss +1 -1
- package/build/themes/dark/index.d.ts +0 -1
- package/build/themes/dark/index.js +0 -1
- package/build/themes/dark/input.d.ts +709 -115
- package/build/themes/dark/select.d.ts +3 -1409
- package/build/themes/dark/select.js +12 -9
- package/build/themes/dark/textarea.d.ts +716 -119
- package/package.json +12 -12
- package/pnpm-workspace.yaml +4 -3
- package/scripts/css-variables.test.mjs +50 -0
- package/scripts/sort-scss.md +57 -0
- package/scripts/sort-scss.mjs +233 -0
- package/scripts/sort-scss.test.mjs +217 -0
- package/src/components/accordion/index.ts +7 -14
- package/src/components/accordion/scss/index.scss +3 -1
- package/src/components/anchor/scss/index.scss +2 -2
- package/src/components/button/scss/index.scss +23 -57
- package/src/components/button/scss/variables.scss +1 -19
- package/src/components/card/scss/index.scss +11 -46
- package/src/components/card/scss/variables.scss +1 -2
- package/src/components/checkbox/constants.ts +4 -0
- package/src/components/checkbox/index.ts +20 -35
- package/src/components/checkbox/scss/index.scss +86 -28
- package/src/components/checkbox/scss/variables.scss +71 -30
- package/src/components/checkbox/svg/check.svg +1 -0
- package/src/components/clipboard/copy.ts +55 -0
- package/src/components/clipboard/index.ts +3 -2
- package/src/components/clipboard/onclick.ts +4 -9
- package/src/components/counter/index.ts +57 -66
- package/src/components/counter/scss/index.scss +4 -5
- package/src/components/counter/scss/variables.scss +0 -1
- package/src/components/form/action.ts +2 -8
- package/src/components/form/input.ts +4 -3
- package/src/components/grid/scss/index.scss +1 -1
- package/src/components/icon/scss/variables.scss +0 -1
- package/src/components/index.ts +1 -8
- package/src/components/input/index.ts +8 -6
- package/src/components/input/scss/index.scss +8 -7
- package/src/components/input/scss/variables.scss +0 -1
- package/src/components/link/scss/index.scss +9 -34
- package/src/components/link/scss/variables.scss +0 -12
- package/src/components/modal/scss/index.scss +4 -4
- package/src/components/normalize/scss/index.scss +0 -1
- package/src/components/page/scss/index.scss +0 -6
- package/src/components/page/scss/variables.scss +0 -2
- package/src/components/radio/index.ts +5 -3
- package/src/components/range/index.ts +1 -1
- package/src/components/range/scss/index.scss +5 -5
- package/src/components/root/scss/index.scss +37 -63
- package/src/components/root/scss/variables.scss +37 -67
- package/src/components/select/constants.ts +8 -0
- package/src/components/select/index.ts +49 -70
- package/src/components/select/scss/index.scss +10 -7
- package/src/components/select/scss/variables.scss +0 -1
- package/src/components/sidebar/scss/index.scss +3 -3
- package/src/components/switch/index.ts +5 -3
- package/src/components/tabs/scss/index.scss +62 -0
- package/src/components/tabs/scss/variables.scss +4 -0
- package/src/components/text/scss/index.scss +8 -1
- package/src/components/text/scss/variables.scss +5 -3
- package/src/components/textarea/index.ts +45 -13
- package/src/components/textarea/scss/index.scss +24 -13
- package/src/components/textarea/scss/variables.scss +0 -1
- package/src/components/toast/scss/index.scss +1 -1
- package/src/components/tooltip/constants.ts +6 -0
- package/src/components/tooltip/index.ts +4 -1
- package/src/components/tooltip/menu.ts +18 -29
- package/src/components/tooltip/onclick.ts +21 -88
- package/src/components/tooltip/onhover.ts +18 -29
- package/src/components/tooltip/scss/index.scss +2 -3
- package/src/css-utilities/background/scss/variables.scss +2 -2
- package/src/css-utilities/border/scss/index.scss +1 -27
- package/src/css-utilities/border/scss/variables.scss +3 -34
- package/src/css-utilities/color/scss/variables.scss +2 -6
- package/src/css-utilities/font/geist/scss/Geist-Italic-Variable.woff2 +0 -0
- package/src/css-utilities/font/geist/scss/Geist-Variable.woff2 +0 -0
- package/src/css-utilities/font/geist/scss/GeistMono-Italic-Variable.woff2 +0 -0
- package/src/css-utilities/font/geist/scss/GeistMono-Variable.woff2 +0 -0
- package/src/css-utilities/font/geist/scss/index.scss +55 -0
- package/src/css-utilities/font/montserrat/index.ts +1 -0
- package/src/{fonts → css-utilities/font}/montserrat/scss/index.scss +15 -0
- package/src/css-utilities/index.scss +6 -12
- package/src/css-utilities/inline/scss/index.scss +0 -1
- package/src/css-utilities/scrollbar/scss/index.scss +42 -0
- package/src/css-utilities/tabular/scss/index.scss +3 -0
- package/src/css-utilities/text/scss/index.scss +30 -71
- package/src/lib/scss/css-variables.scss +29 -5
- package/src/themes/dark/index.ts +0 -1
- package/src/themes/dark/select.ts +14 -9
- package/src/tokens/index.scss +1 -3
- package/src/tokens/scss/border-radius.scss +1 -6
- package/src/tokens/scss/color.scss +3 -3
- package/src/tokens/scss/scale.scss +1 -1
- package/src/tokens/scss/size.scss +7 -0
- package/src/tokens/scss/transition.scss +4 -0
- package/storage/svg/arrow-left.svg +1 -0
- package/storage/svg/arrow-right.svg +1 -0
- package/storage/svg/book.svg +1 -0
- package/storage/svg/cube.svg +1 -0
- package/storage/svg/github.svg +1 -0
- package/storage/svg/info.svg +1 -0
- package/storage/svg/palette.svg +1 -0
- package/storage/svg/search.svg +2 -0
- package/storage/svg/type.svg +1 -0
- package/vite.config.ts +8 -3
- package/build/components/back/index.d.ts +0 -21
- package/build/components/back/index.js +0 -16
- package/build/components/back/scss/index.scss +0 -2
- package/build/components/back/svg/arrow.svg +0 -15
- package/build/components/bubble/scss/index.scss +0 -2
- package/build/components/button/index.d.ts +0 -103
- package/build/components/button/index.js +0 -60
- package/build/components/ellipsis/index.d.ts +0 -4
- package/build/components/ellipsis/index.js +0 -8
- package/build/components/ellipsis/scss/index.scss +0 -2
- package/build/components/frame/index.d.ts +0 -21
- package/build/components/frame/index.js +0 -13
- package/build/components/frame/scss/index.scss +0 -2
- package/build/components/highlight/index.d.ts +0 -22
- package/build/components/highlight/index.js +0 -56
- package/build/components/highlight/scss/index.scss +0 -2
- package/build/components/loader/index.d.ts +0 -22
- package/build/components/loader/index.js +0 -78
- package/build/components/loader/scss/index.scss +0 -2
- package/build/components/radio/scss/index.scss +0 -2
- package/build/components/root/index.d.ts +0 -7
- package/build/components/root/index.js +0 -4
- package/build/components/root/onclick.d.ts +0 -5
- package/build/components/root/onclick.js +0 -12
- package/build/components/switch/scss/index.scss +0 -2
- package/build/css-utilities/[margin,padding]/scss/index.scss +0 -2
- package/build/css-utilities/error/scss/index.scss +0 -2
- package/build/css-utilities/flicker/scss/index.scss +0 -2
- package/build/css-utilities/focus/scss/index.scss +0 -2
- package/build/css-utilities/gap/scss/index.scss +0 -2
- package/build/css-utilities/line-height/scss/index.scss +0 -2
- package/build/css-utilities/pointer/scss/index.scss +0 -2
- package/build/css-utilities/scroll-fade/scss/index.scss +0 -2
- package/build/css-utilities/size/scss/index.scss +0 -2
- package/build/css-utilities/viewport/scss/index.scss +0 -2
- package/build/css-utilities/width/scss/index.scss +0 -2
- package/build/fonts/index.d.ts +0 -1
- package/build/fonts/index.js +0 -1
- package/build/fonts/montserrat/scss/index.scss +0 -2
- package/build/themes/dark/back.d.ts +0 -19
- package/build/themes/dark/back.js +0 -7
- package/build/themes/dark/button/scss/index.scss +0 -2
- package/build/themes/dark/link/scss/index.scss +0 -2
- package/src/components/back/index.ts +0 -20
- package/src/components/back/scss/index.scss +0 -17
- package/src/components/back/svg/arrow.svg +0 -15
- package/src/components/bubble/scss/index.scss +0 -32
- package/src/components/bubble/scss/variables.scss +0 -20
- package/src/components/button/index.ts +0 -53
- package/src/components/ellipsis/index.ts +0 -11
- package/src/components/ellipsis/scss/index.scss +0 -30
- package/src/components/ellipsis/scss/variables.scss +0 -5
- package/src/components/frame/index.ts +0 -13
- package/src/components/frame/scss/index.scss +0 -39
- package/src/components/frame/scss/variables.scss +0 -4
- package/src/components/highlight/index.ts +0 -66
- package/src/components/highlight/scss/index.scss +0 -7
- package/src/components/highlight/scss/variables.scss +0 -4
- package/src/components/loader/index.ts +0 -80
- package/src/components/loader/scss/index.scss +0 -71
- package/src/components/loader/scss/variables.scss +0 -6
- package/src/components/radio/scss/index.scss +0 -50
- package/src/components/radio/scss/variables.scss +0 -67
- package/src/components/root/index.ts +0 -6
- package/src/components/root/onclick.ts +0 -20
- package/src/components/switch/scss/index.scss +0 -48
- package/src/components/switch/scss/variables.scss +0 -74
- package/src/css-utilities/[margin,padding]/scss/index.scss +0 -43
- package/src/css-utilities/[margin,padding]/scss/variables.scss +0 -54
- package/src/css-utilities/error/scss/index.scss +0 -24
- package/src/css-utilities/error/scss/variables.scss +0 -3
- package/src/css-utilities/flicker/scss/index.scss +0 -15
- package/src/css-utilities/flicker/scss/variables.scss +0 -5
- package/src/css-utilities/focus/scss/index.scss +0 -7
- package/src/css-utilities/focus/scss/variables.scss +0 -5
- package/src/css-utilities/gap/scss/index.scss +0 -13
- package/src/css-utilities/gap/scss/variables.scss +0 -39
- package/src/css-utilities/line-height/scss/index.scss +0 -1
- package/src/css-utilities/line-height/scss/variables.scss +0 -10
- package/src/css-utilities/pointer/scss/index.scss +0 -5
- package/src/css-utilities/scroll-fade/scss/index.scss +0 -47
- package/src/css-utilities/scroll-fade/scss/variables.scss +0 -3
- package/src/css-utilities/size/scss/index.scss +0 -1
- package/src/css-utilities/size/scss/variables.scss +0 -12
- package/src/css-utilities/text/scss/variables.scss +0 -31
- package/src/css-utilities/viewport/scss/index.scss +0 -5
- package/src/css-utilities/width/scss/index.scss +0 -5
- package/src/css-utilities/width/scss/variables.scss +0 -9
- package/src/fonts/index.ts +0 -1
- package/src/themes/dark/back.ts +0 -9
- package/src/themes/dark/button/scss/index.scss +0 -46
- package/src/themes/dark/link/scss/index.scss +0 -26
- package/src/tokens/scss/font-weight.scss +0 -6
- package/src/tokens/scss/line-height.scss +0 -9
- package/src/tokens/scss/transition-duration.scss +0 -1
- /package/build/{fonts/montserrat → css-utilities/font/geist}/index.d.ts +0 -0
- /package/build/{fonts/montserrat → css-utilities/font/geist}/index.js +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Bold.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Bold.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-BoldItalic.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-BoldItalic.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Italic.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Italic.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Medium.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Medium.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-MediumItalic.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-MediumItalic.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Regular.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Regular.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBold.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBold.woff2 +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBoldItalic.woff +0 -0
- /package/build/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBoldItalic.woff2 +0 -0
- /package/src/{fonts/montserrat → css-utilities/font/geist}/index.ts +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Bold.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Bold.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-BoldItalic.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-BoldItalic.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Italic.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Italic.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Medium.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Medium.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-MediumItalic.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-MediumItalic.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Regular.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-Regular.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBold.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBold.woff2 +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBoldItalic.woff +0 -0
- /package/src/{fonts → css-utilities/font}/montserrat/scss/Montserrat-SemiBoldItalic.woff2 +0 -0
package/package.json
CHANGED
|
@@ -2,31 +2,29 @@
|
|
|
2
2
|
"author": "ICJR",
|
|
3
3
|
"dependencies": {
|
|
4
4
|
"@esportsplus/action": "^0.1.8",
|
|
5
|
-
"@esportsplus/queue": "^0.4.6",
|
|
6
5
|
"@esportsplus/reactivity": "^0.36.7",
|
|
7
|
-
"@esportsplus/template": "^0.
|
|
8
|
-
"@esportsplus/utilities": "^0.28.
|
|
6
|
+
"@esportsplus/template": "^0.50.0",
|
|
7
|
+
"@esportsplus/utilities": "^0.28.5",
|
|
9
8
|
"modern-normalize": "^3.0.1"
|
|
10
9
|
},
|
|
11
10
|
"devDependencies": {
|
|
12
|
-
"@esportsplus/typescript": "^0.
|
|
13
|
-
"@types/node": "^26.6.
|
|
11
|
+
"@esportsplus/typescript": "^0.35.1",
|
|
12
|
+
"@types/node": "^26.6.2",
|
|
14
13
|
"@types/shelljs": "^0.10.0",
|
|
15
14
|
"autoprefixer": "^10.6.1",
|
|
16
15
|
"glob": "^13.0.6",
|
|
17
16
|
"lightningcss": "^1.33.0",
|
|
18
17
|
"npm-run-all": "^4.1.5",
|
|
19
|
-
"
|
|
18
|
+
"postcss": "8.5.28",
|
|
19
|
+
"postcss-scss": "4.0.9",
|
|
20
|
+
"sass": "^1.105.0",
|
|
20
21
|
"shelljs": "^0.10.0",
|
|
21
22
|
"vite": "^8.3.0"
|
|
22
23
|
},
|
|
23
24
|
"exports": {
|
|
24
25
|
"./css-utilities.scss": "./build/css-utilities/index.scss",
|
|
25
26
|
"./css-utilities/*.scss": "./build/css-utilities/*/scss/index.scss",
|
|
26
|
-
"./
|
|
27
|
-
"types": "./build/fonts/index.d.ts",
|
|
28
|
-
"default": "./build/fonts/index.js"
|
|
29
|
-
},
|
|
27
|
+
"./css-utilities/font/*.scss": "./build/css-utilities/font/*/scss/index.scss",
|
|
30
28
|
"./layer.scss": "./layer.scss",
|
|
31
29
|
"./lib.scss": "./lib.scss",
|
|
32
30
|
"./themes/dark": {
|
|
@@ -56,9 +54,11 @@
|
|
|
56
54
|
"type": "git",
|
|
57
55
|
"url": "https://github.com/esportsplus/ui"
|
|
58
56
|
},
|
|
59
|
-
"sideEffects":
|
|
57
|
+
"sideEffects": [
|
|
58
|
+
"**/*.scss"
|
|
59
|
+
],
|
|
60
60
|
"type": "module",
|
|
61
|
-
"version": "0.
|
|
61
|
+
"version": "0.55.0",
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "run-s build:vite build:ts",
|
|
64
64
|
"build:ts": "tsc",
|
package/pnpm-workspace.yaml
CHANGED
|
@@ -11,12 +11,12 @@ allowBuilds:
|
|
|
11
11
|
# first-party upgrades (reactivity, template, ...) be consumed immediately
|
|
12
12
|
# instead of waiting out the release-age cutoff.
|
|
13
13
|
minimumReleaseAgeExclude:
|
|
14
|
-
- '@esportsplus/typescript@0.34.1 || 0.34.2 || 0.34.3 || 0.34.4'
|
|
14
|
+
- '@esportsplus/typescript@0.34.1 || 0.34.2 || 0.34.3 || 0.34.4 || 0.35.1'
|
|
15
15
|
- '@esportsplus/action@0.1.7 || 0.1.8'
|
|
16
16
|
- '@esportsplus/queue@0.4.5 || 0.4.6'
|
|
17
17
|
- '@esportsplus/reactivity@0.36.4 || 0.36.6 || 0.36.7'
|
|
18
|
-
- '@esportsplus/template@0.44.4 || 0.44.6 || 0.45.0 || 0.45.1 || 0.45.3 || 0.46.1 || 0.46.2 || 0.46.3 || 0.46.4'
|
|
19
|
-
- '@esportsplus/utilities@0.28.3 || 0.28.4'
|
|
18
|
+
- '@esportsplus/template@0.44.4 || 0.44.6 || 0.45.0 || 0.45.1 || 0.45.3 || 0.46.1 || 0.46.2 || 0.46.3 || 0.46.4 || 0.46.5 || 0.46.6 || 0.48.1 || 0.49.0 || 0.50.0'
|
|
19
|
+
- '@esportsplus/utilities@0.28.3 || 0.28.4 || 0.28.5'
|
|
20
20
|
- '@esportsplus/vite@0.14.2 || 0.14.5 || 0.14.6'
|
|
21
21
|
- '@esportsplus/*'
|
|
22
22
|
# browserslist's data packages (pulled transitively via autoprefixer) republish daily, so a
|
|
@@ -26,3 +26,4 @@ minimumReleaseAgeExclude:
|
|
|
26
26
|
- caniuse-lite
|
|
27
27
|
- electron-to-chromium
|
|
28
28
|
- '@types/node@26.6.2'
|
|
29
|
+
- 'sass@1.105.0'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { test } from 'node:test';
|
|
4
|
+
import { compileString } from 'sass';
|
|
5
|
+
|
|
6
|
+
const loadPaths = [fileURLToPath(new URL('../src/lib/scss/', import.meta.url))];
|
|
7
|
+
const compile = source => compileString(`@use 'css-variables' as lib; ${source}`, {
|
|
8
|
+
loadPaths,
|
|
9
|
+
style: 'compressed'
|
|
10
|
+
}).css;
|
|
11
|
+
|
|
12
|
+
test('preserves positional, named and mixed declaration calls', () => {
|
|
13
|
+
const expected = ':root{--font-weight-300: 400;--font-weight-500: 600}';
|
|
14
|
+
for (const args of [
|
|
15
|
+
'font-weight, (300: 400, 500: 600)',
|
|
16
|
+
'$prefix: font-weight, $tokens: (300: 400, 500: 600)',
|
|
17
|
+
'font-weight, $tokens: (300: 400, 500: 600)'
|
|
18
|
+
]) {
|
|
19
|
+
assert.equal(compile(`:root { @include lib.css-variables(${args}); }`), expected);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('three arguments wrap each custom-property value in its own class', () => {
|
|
24
|
+
const expected = '.--font-weight-300{--font-weight-300: 400}.--font-weight-500{--font-weight-500: 600}.--font-weight-600{--font-weight-600: 700}';
|
|
25
|
+
for (const args of [
|
|
26
|
+
"'--font-weight', font-weight, (300: 400, 500: 600, 600: 700)",
|
|
27
|
+
"$class: '--font-weight', $prefix: font-weight, $tokens: (300: 400, 500: 600, 600: 700)"
|
|
28
|
+
]) {
|
|
29
|
+
assert.equal(compile(`@include lib.css-variables(${args});`), expected);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('nested maps produce matching declaration and utility suffixes', () => {
|
|
34
|
+
assert.equal(compile(`
|
|
35
|
+
$colors: (blue: (300: #abc, 500: #123));
|
|
36
|
+
:root { @include lib.css-variables(color, $colors); }
|
|
37
|
+
@include lib.css-variables('--color', color, $colors);
|
|
38
|
+
`), ':root{--color-blue-300: #abc;--color-blue-500: #123}.--color-blue-300{--color-blue-300: #abc}.--color-blue-500{--color-blue-500: #123}');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('utility classes preserve a surrounding selector scope', () => {
|
|
42
|
+
assert.equal(compile(`.preview { @include lib.css-variables('--weight', font-weight, (500: 600)); }`),
|
|
43
|
+
'.preview .--weight-500{--font-weight-500: 600}');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('empty maps emit no CSS and invalid token arguments fail clearly', () => {
|
|
47
|
+
assert.equal(compile(':root { @include lib.css-variables(color, ()); }'), '');
|
|
48
|
+
assert.equal(compile("@include lib.css-variables('--color', color, ());"), '');
|
|
49
|
+
assert.throws(() => compile(':root { @include lib.css-variables(color, red); }'), /with a token map/);
|
|
50
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Standalone SCSS sorter
|
|
2
|
+
|
|
3
|
+
Run with Node 20+; no bundler, Sass compiler, or PostCSS configuration is used.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
node scripts/sort-scss.mjs --check path/to/styles
|
|
7
|
+
node scripts/sort-scss.mjs --write path/to/styles.scss
|
|
8
|
+
node scripts/sort-scss.mjs --write path/to/styles another/file.scss
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Paths resolve from the current working directory. To use elsewhere, copy
|
|
12
|
+
`sort-scss.mjs` into a project with `postcss` and `postcss-scss` installed, or invoke
|
|
13
|
+
this installed script by absolute path. Dependencies are declared in
|
|
14
|
+
`package.json` (development dependencies).
|
|
15
|
+
|
|
16
|
+
The sorter orders consecutive sibling selector blocks by their full selector
|
|
17
|
+
text and consecutive declarations by property name, recursively, using
|
|
18
|
+
case-sensitive code-unit order. Punctuation and vendor prefixes participate in
|
|
19
|
+
that order. Equal keys retain their original relative order. Comma-separated
|
|
20
|
+
selector lists remain intact.
|
|
21
|
+
|
|
22
|
+
Sass nested selectors such as `&-actions`, `&-inner`, and `&-nav` are sorted
|
|
23
|
+
within their parent too. Use `--write` to apply changes; `--check` only reports them.
|
|
24
|
+
|
|
25
|
+
Consecutive simple class selectors sharing a prefix are also grouped into Sass
|
|
26
|
+
nesting: `.spec-name`, `.spec-table`, and `.spec-value` become `.spec` with
|
|
27
|
+
`&-name`, `&-table`, and `&-value` children. This uses the segment before the
|
|
28
|
+
first hyphen and requires at least two matching siblings. Existing base rules
|
|
29
|
+
remain separate so their declarations and Sass scope are preserved. Complex
|
|
30
|
+
selectors, interpolation, and ordering boundaries are not crossed; groups inside
|
|
31
|
+
at-rules are handled within their own scope. Comments move with their rules.
|
|
32
|
+
|
|
33
|
+
Leading comments move with the following statement; same-line trailing comments
|
|
34
|
+
move with the preceding statement. Existing whitespace and value text are
|
|
35
|
+
retained where possible. This organizes source; it does not impose indentation
|
|
36
|
+
or line wrapping.
|
|
37
|
+
|
|
38
|
+
At-rules, Sass variable assignments, interpolated property/selector names, and
|
|
39
|
+
transitions between declarations and nested rules divide sorting runs. Statements
|
|
40
|
+
never move across these boundaries. Contents of at-rules are processed recursively;
|
|
41
|
+
keyframe steps retain their order while properties inside each step are sorted.
|
|
42
|
+
|
|
43
|
+
Sorting is strict within each run: overlapping selectors and shorthand/longhand
|
|
44
|
+
properties are alphabetized even when this changes the cascade. Sass function
|
|
45
|
+
evaluation order can also change. Duplicate declarations retain fallback order.
|
|
46
|
+
|
|
47
|
+
Directory traversal skips `.git`, `node_modules`, and symlinks. Explicit symlink
|
|
48
|
+
targets and non-SCSS file targets are rejected. All inputs are parsed before any
|
|
49
|
+
write. A malformed input prevents writes for the batch; filesystem write failures
|
|
50
|
+
are reported but do not roll back earlier successful writes.
|
|
51
|
+
|
|
52
|
+
Exit status is 0 for success, 1 for unsorted files in check mode, and 2 for invalid
|
|
53
|
+
arguments, parse failures, or I/O errors. Check mode never writes.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
node --test scripts/sort-scss.test.mjs
|
|
57
|
+
```
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as NodeFSP from "node:fs/promises";
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
4
|
+
import * as NodePath from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import scss from "postcss-scss";
|
|
7
|
+
|
|
8
|
+
const help = `Usage: node sort-scss.mjs --check|--write <file.scss|directory>...
|
|
9
|
+
|
|
10
|
+
Alphabetize sibling selectors and declaration properties recursively.
|
|
11
|
+
Group sibling .prefix-* classes into .prefix { &-* { ... } } blocks.
|
|
12
|
+
Sorting is strict and may change the cascade or Sass evaluation behavior.
|
|
13
|
+
At-rules, Sass assignments, and interpolated names remain ordering boundaries.
|
|
14
|
+
Duplicate properties retain their relative order. Keyframe steps stay in place.
|
|
15
|
+
Directories are recursive; .git and node_modules are excluded.
|
|
16
|
+
Exit codes: 0 = success, 1 = unsorted (--check), 2 = invalid input or I/O error.
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
function compare(left, right) {
|
|
20
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function sortableKind(node, keyframes) {
|
|
24
|
+
if (node.type === "decl" && !node.prop.includes("$") && !node.prop.includes("#{")) {
|
|
25
|
+
return "decl";
|
|
26
|
+
}
|
|
27
|
+
if (node.type === "rule" && !keyframes && !node.selector.includes("#{")) {
|
|
28
|
+
return "rule";
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function unitsFor(nodes) {
|
|
34
|
+
const units = [];
|
|
35
|
+
let comments = [];
|
|
36
|
+
for (const node of nodes) {
|
|
37
|
+
if (node.type === "comment") {
|
|
38
|
+
const previous = units.at(-1);
|
|
39
|
+
if (previous && comments.length === 0 && !/[\r\n]/.test(node.raws.before ?? "")) {
|
|
40
|
+
previous.nodes.push(node);
|
|
41
|
+
} else {
|
|
42
|
+
comments.push(node);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
units.push({ node, nodes: [...comments, node] });
|
|
46
|
+
comments = [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (comments.length) units.push({ node: null, nodes: comments });
|
|
50
|
+
return units;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sortContainer(container) {
|
|
54
|
+
if (!container.nodes) return;
|
|
55
|
+
for (const node of container.nodes) sortContainer(node);
|
|
56
|
+
const keyframes = container.type === "atrule" && /(?:^|-)keyframes$/i.test(container.name);
|
|
57
|
+
const units = unitsFor(container.nodes);
|
|
58
|
+
let changed = false;
|
|
59
|
+
for (let start = 0; start < units.length; ) {
|
|
60
|
+
const kind = units[start].node && sortableKind(units[start].node, keyframes);
|
|
61
|
+
if (!kind) {
|
|
62
|
+
start++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
let end = start + 1;
|
|
66
|
+
while (
|
|
67
|
+
end < units.length &&
|
|
68
|
+
units[end].node &&
|
|
69
|
+
sortableKind(units[end].node, keyframes) === kind
|
|
70
|
+
)
|
|
71
|
+
end++;
|
|
72
|
+
const original = units.slice(start, end);
|
|
73
|
+
const sorted = original.toSorted((a, b) =>
|
|
74
|
+
compare(
|
|
75
|
+
kind === "decl" ? a.node.prop : a.node.selector.trim(),
|
|
76
|
+
kind === "decl" ? b.node.prop : b.node.selector.trim(),
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
if (sorted.some((unit, index) => unit !== original[index])) {
|
|
80
|
+
// Keep spacing at each position while moving comments with their owner.
|
|
81
|
+
const spacing = original.map((unit) => unit.nodes[0].raws.before);
|
|
82
|
+
sorted.forEach((unit, index) => {
|
|
83
|
+
unit.nodes[0].raws.before = spacing[index];
|
|
84
|
+
});
|
|
85
|
+
units.splice(start, end - start, ...sorted);
|
|
86
|
+
changed = true;
|
|
87
|
+
}
|
|
88
|
+
start = end;
|
|
89
|
+
}
|
|
90
|
+
if (changed) {
|
|
91
|
+
container.removeAll();
|
|
92
|
+
for (const unit of units) container.append(unit.nodes);
|
|
93
|
+
// Moving a // comment must not comment out the next statement or closing brace.
|
|
94
|
+
for (let index = 1; index < container.nodes.length; index++) {
|
|
95
|
+
const previous = container.nodes[index - 1];
|
|
96
|
+
const node = container.nodes[index];
|
|
97
|
+
if (
|
|
98
|
+
previous.type === "comment" &&
|
|
99
|
+
previous.raws.inline &&
|
|
100
|
+
!/[\r\n]/.test(node.raws.before ?? "")
|
|
101
|
+
) {
|
|
102
|
+
node.raws.before = "\n" + (node.raws.before ?? "");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (
|
|
106
|
+
container.last?.type === "comment" &&
|
|
107
|
+
container.last.raws.inline &&
|
|
108
|
+
!/[\r\n]/.test(container.raws.after ?? "")
|
|
109
|
+
) {
|
|
110
|
+
container.raws.after = "\n" + (container.raws.after ?? "");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function nestPrefixes(container, indent, newline) {
|
|
116
|
+
if (!container.nodes) return;
|
|
117
|
+
for (const node of [...container.nodes]) nestPrefixes(node, indent, newline);
|
|
118
|
+
if (container.type === "atrule" && /(?:^|-)keyframes$/i.test(container.name)) return;
|
|
119
|
+
|
|
120
|
+
const units = unitsFor(container.nodes);
|
|
121
|
+
const prefix = (unit) => unit.node?.type === "rule"
|
|
122
|
+
? /^(\.[a-zA-Z_][\w]*)-[\w-]+$/.exec(unit.node.selector.trim())?.[1]
|
|
123
|
+
: undefined;
|
|
124
|
+
|
|
125
|
+
for (let start = 0; start < units.length; ) {
|
|
126
|
+
const name = prefix(units[start]);
|
|
127
|
+
let end = start + 1;
|
|
128
|
+
if (name) while (end < units.length && prefix(units[end]) === name) end++;
|
|
129
|
+
if (!name || end - start < 2) {
|
|
130
|
+
start = end;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const first = units[start].nodes[0];
|
|
135
|
+
const before = first.raws.before ?? "";
|
|
136
|
+
const baseIndent = /(?:^|\n)([\t ]*)$/.exec(before)?.[1] ?? "";
|
|
137
|
+
const wrapper = scss.parse(`${name} {}`).first;
|
|
138
|
+
wrapper.raws.before = before;
|
|
139
|
+
wrapper.raws.after = newline + baseIndent;
|
|
140
|
+
container.insertBefore(first, wrapper);
|
|
141
|
+
|
|
142
|
+
for (const unit of units.slice(start, end)) {
|
|
143
|
+
unit.node.selector = "&" + unit.node.selector.trim().slice(name.length);
|
|
144
|
+
for (const node of unit.nodes) {
|
|
145
|
+
const shift = (value) => value?.replace(/(\r?\n)([\t ]*)(?=\S)/g, `$1$2${indent}`);
|
|
146
|
+
const shiftBefore = (value) => value?.replace(/([\t ]*)$/, `$1${indent}`);
|
|
147
|
+
node.raws.before = shiftBefore(node.raws.before);
|
|
148
|
+
node.raws.after = /[\r\n]/.test(node.raws.after ?? "") ? shiftBefore(node.raws.after) : node.raws.after;
|
|
149
|
+
node.walk?.((child) => {
|
|
150
|
+
child.raws.before = shiftBefore(child.raws.before);
|
|
151
|
+
child.raws.after = /[\r\n]/.test(child.raws.after ?? "") ? shiftBefore(child.raws.after) : child.raws.after;
|
|
152
|
+
if (child.type === "rule") child.selector = shift(child.selector);
|
|
153
|
+
});
|
|
154
|
+
// Ensure standalone comments and inline input both start safely inside the wrapper.
|
|
155
|
+
if (!/[\r\n]/.test(node.raws.before ?? "")) {
|
|
156
|
+
node.raws.before = newline + baseIndent + indent;
|
|
157
|
+
}
|
|
158
|
+
wrapper.append(node);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
wrapper.first.raws.before = newline + baseIndent + indent;
|
|
162
|
+
start = end;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function sortScss(source, file = "input.scss") {
|
|
167
|
+
const root = scss.parse(source, { from: file });
|
|
168
|
+
sortContainer(root);
|
|
169
|
+
const indent = source.match(/\n([\t ]+)\S/)?.[1] ?? " ";
|
|
170
|
+
nestPrefixes(root, indent, source.includes("\r\n") ? "\r\n" : "\n");
|
|
171
|
+
sortContainer(root);
|
|
172
|
+
return root.toString(scss.stringify);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async function collect(paths) {
|
|
176
|
+
const files = new Set();
|
|
177
|
+
async function visit(path, explicit = false) {
|
|
178
|
+
const stat = await NodeFSP.lstat(path);
|
|
179
|
+
if (stat.isSymbolicLink()) {
|
|
180
|
+
if (explicit) throw new Error(`Refusing symlink: ${path}`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (stat.isDirectory()) {
|
|
184
|
+
for (const entry of await NodeFSP.readdir(path, { withFileTypes: true })) {
|
|
185
|
+
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
|
186
|
+
await visit(NodePath.join(path, entry.name));
|
|
187
|
+
}
|
|
188
|
+
} else if (stat.isFile() && NodePath.extname(path).toLowerCase() === ".scss") {
|
|
189
|
+
files.add(path);
|
|
190
|
+
} else if (explicit) {
|
|
191
|
+
throw new Error(`Expected an SCSS file or directory: ${path}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
for (const path of paths) await visit(NodePath.resolve(path), true);
|
|
195
|
+
if (!files.size) throw new Error("No SCSS files found.");
|
|
196
|
+
return [...files].sort(compare);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function main(args) {
|
|
200
|
+
if (args.length === 1 && args[0] === "--help") {
|
|
201
|
+
process.stdout.write(help);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const modes = args.filter((arg) => arg === "--check" || arg === "--write");
|
|
205
|
+
const paths = args.filter((arg) => !arg.startsWith("--"));
|
|
206
|
+
if (
|
|
207
|
+
modes.length !== 1 ||
|
|
208
|
+
paths.length === 0 ||
|
|
209
|
+
args.some((arg) => arg.startsWith("--") && !modes.includes(arg))
|
|
210
|
+
) {
|
|
211
|
+
throw new Error(help);
|
|
212
|
+
}
|
|
213
|
+
// Parse the entire batch before writing so a syntax error cannot leave a partial batch.
|
|
214
|
+
const changes = [];
|
|
215
|
+
for (const file of await collect(paths)) {
|
|
216
|
+
const source = await NodeFSP.readFile(file, "utf8");
|
|
217
|
+
const output = sortScss(source, file);
|
|
218
|
+
if (output !== source) changes.push({ file, output });
|
|
219
|
+
}
|
|
220
|
+
for (const { file, output } of changes) {
|
|
221
|
+
if (modes[0] === "--write") await NodeFSP.writeFile(file, output, "utf8");
|
|
222
|
+
console.log(`${modes[0] === "--write" ? "Sorted" : "Unsorted"}: ${file}`);
|
|
223
|
+
}
|
|
224
|
+
if (modes[0] === "--check" && changes.length) process.exitCode = 1;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Older Node versions do not define import.meta.main and silently skipped the CLI.
|
|
228
|
+
if (process.argv[1] && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url))) {
|
|
229
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
230
|
+
console.error(`sort-scss: ${error.message}`);
|
|
231
|
+
process.exitCode = 2;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import * as NodeAssert from "node:assert/strict";
|
|
2
|
+
import * as NodeChildProcess from "node:child_process";
|
|
3
|
+
import * as NodeFSP from "node:fs/promises";
|
|
4
|
+
import * as NodeOS from "node:os";
|
|
5
|
+
import * as NodePath from "node:path";
|
|
6
|
+
import * as NodeURL from "node:url";
|
|
7
|
+
import * as NodeTest from "node:test";
|
|
8
|
+
import scss from "postcss-scss";
|
|
9
|
+
import { compileString } from "sass";
|
|
10
|
+
import { sortScss } from "./sort-scss.mjs";
|
|
11
|
+
|
|
12
|
+
const script = NodeURL.fileURLToPath(new URL("./sort-scss.mjs", import.meta.url));
|
|
13
|
+
|
|
14
|
+
NodeTest.test("nests prefixed classes with equivalent CSS, comments and stable output", () => {
|
|
15
|
+
const input = `// Name\n.spec-name { color: red; }\n.spec-table { td { color: blue; } &:hover { opacity: 1; } }\n.spec-value { color: green; }\n`;
|
|
16
|
+
const output = sortScss(input);
|
|
17
|
+
const root = scss.parse(output);
|
|
18
|
+
NodeAssert.equal(root.first.selector, ".spec");
|
|
19
|
+
NodeAssert.deepEqual(root.first.nodes.filter(n => n.type === "rule").map(n => n.selector),
|
|
20
|
+
["&-name", "&-table", "&-value"]);
|
|
21
|
+
NodeAssert.match(output, /\/\/ Name\n/);
|
|
22
|
+
// Sorting already orders nested selectors; compare against that canonical CSS.
|
|
23
|
+
const canonical = input.replace('td { color: blue; } &:hover { opacity: 1; }', '&:hover { opacity: 1; } td { color: blue; }');
|
|
24
|
+
NodeAssert.equal(compileString(output, { style: "compressed" }).css, compileString(canonical, { style: "compressed" }).css);
|
|
25
|
+
NodeAssert.equal(sortScss(output), output);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
NodeTest.test("prefix grouping respects scopes, complex selectors and Sass boundaries", () => {
|
|
29
|
+
const input = `.spec-a { color: red; }\n$gap: 1px;\n.spec-b { color: blue; }\n.spec-c:hover { color: red; }\n.spec-d { color: green; }\n@media (width > 1px) { .item-a { color: red; } .item-b { color: blue; } }`;
|
|
30
|
+
const output = sortScss(input);
|
|
31
|
+
NodeAssert.equal(compileString(output, { style: "compressed" }).css, compileString(input, { style: "compressed" }).css);
|
|
32
|
+
NodeAssert.match(output, /\.spec-a/);
|
|
33
|
+
NodeAssert.match(output, /\.spec-b/);
|
|
34
|
+
NodeAssert.match(output, /\.spec-c:hover/);
|
|
35
|
+
NodeAssert.equal(scss.parse(output).last.first.selector, ".item");
|
|
36
|
+
NodeAssert.equal(sortScss(output), output);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
NodeTest.test("prefix grouping preserves CRLF and an existing base selector", () => {
|
|
40
|
+
const input = ".spec { color: black; }\r\n.spec-a { color: red; }\r\n.spec-b { color: blue; }\r\n";
|
|
41
|
+
const output = sortScss(input);
|
|
42
|
+
NodeAssert.equal(compileString(output, { style: "compressed" }).css, compileString(input, { style: "compressed" }).css);
|
|
43
|
+
NodeAssert.equal(output.replaceAll("\r\n", "").includes("\n"), false);
|
|
44
|
+
NodeAssert.equal(sortScss(output), output);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
NodeTest.test("prefix grouping indents multiline selectors without whitespace-only lines", () => {
|
|
48
|
+
const output = sortScss(".spec-a {\n td,\n th { color: red; }\n}\n\n.spec-b {\n color: blue;\n}\n");
|
|
49
|
+
NodeAssert.match(output, / td,\n th/);
|
|
50
|
+
NodeAssert.doesNotMatch(output, /^[\t ]+$/m);
|
|
51
|
+
NodeAssert.equal(sortScss(output), output);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
NodeTest.test("sorts Sass suffix selectors recursively and keeps media boundaries", () => {
|
|
55
|
+
const output = sortScss(`.header {
|
|
56
|
+
position: sticky;
|
|
57
|
+
&-inner { width: 100%; display: flex; }
|
|
58
|
+
&-nav {}
|
|
59
|
+
&-link { font-weight: 500; color: red; &-z {} &-a {} }
|
|
60
|
+
&-actions {}
|
|
61
|
+
&-icon {}
|
|
62
|
+
@media (max-width: 720px) { &-nav {} &-inner {} }
|
|
63
|
+
}`);
|
|
64
|
+
const nodes = scss.parse(output).first.nodes;
|
|
65
|
+
NodeAssert.deepEqual(nodes.map((node) => node.prop ?? node.selector ?? node.name),
|
|
66
|
+
["position", "&-actions", "&-icon", "&-inner", "&-link", "&-nav", "media"]);
|
|
67
|
+
NodeAssert.deepEqual(nodes[4].nodes.map((node) => node.prop ?? node.selector),
|
|
68
|
+
["color", "font-weight", "&-a", "&-z"]);
|
|
69
|
+
NodeAssert.deepEqual(nodes.at(-1).nodes.map((node) => node.selector),
|
|
70
|
+
["&-inner", "&-nav"]);
|
|
71
|
+
NodeAssert.equal(sortScss(output), output);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
NodeTest.test("inline comments cannot swallow a closing brace after sorting", () => {
|
|
75
|
+
const output = sortScss(".a {\n z-index: 1; // layer\n color: red; }");
|
|
76
|
+
const parsed = scss.parse(output);
|
|
77
|
+
NodeAssert.deepEqual(
|
|
78
|
+
parsed.first.nodes.filter((node) => node.type === "decl").map((node) => node.prop),
|
|
79
|
+
["color", "z-index"],
|
|
80
|
+
);
|
|
81
|
+
NodeAssert.equal(sortScss(output), output);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
NodeTest.test("retains BOM and CRLF in an already sorted file", () => {
|
|
85
|
+
const input = "\uFEFF.a {\r\n color: red;\r\n}\r\n";
|
|
86
|
+
NodeAssert.equal(sortScss(input), input);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
NodeTest.test("sorts selectors and properties recursively, including inside media queries", () => {
|
|
90
|
+
const output = sortScss(`.z { z-index: 1; color: red; &.z { width: 1px; color: red } &.a {} }
|
|
91
|
+
.a { width: 1px; display: block }
|
|
92
|
+
@media (width > 1px) { .z {} .a { width: 2px; color: blue } }`);
|
|
93
|
+
const root = scss.parse(output);
|
|
94
|
+
NodeAssert.deepEqual(
|
|
95
|
+
root.nodes.map((node) => node.selector ?? node.name),
|
|
96
|
+
[".a", ".z", "media"],
|
|
97
|
+
);
|
|
98
|
+
NodeAssert.deepEqual(
|
|
99
|
+
root.first.nodes.map((node) => node.prop),
|
|
100
|
+
["display", "width"],
|
|
101
|
+
);
|
|
102
|
+
NodeAssert.deepEqual(
|
|
103
|
+
root.nodes[1].nodes.map((node) => node.prop ?? node.selector),
|
|
104
|
+
["color", "z-index", "&.a", "&.z"],
|
|
105
|
+
);
|
|
106
|
+
NodeAssert.deepEqual(
|
|
107
|
+
root.last.nodes.map((node) => node.selector),
|
|
108
|
+
[".a", ".z"],
|
|
109
|
+
);
|
|
110
|
+
NodeAssert.equal(sortScss(output), output);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
NodeTest.test(
|
|
114
|
+
"keeps Sass boundaries and fallback order while sorting declarations on either side",
|
|
115
|
+
() => {
|
|
116
|
+
const output = sortScss(`.a {
|
|
117
|
+
z-index: 1; color: red;
|
|
118
|
+
$value: 2;
|
|
119
|
+
width: $value; display: -webkit-box; display: flex;
|
|
120
|
+
@include size;
|
|
121
|
+
padding: 0; color: blue;
|
|
122
|
+
}`);
|
|
123
|
+
const nodes = scss.parse(output).first.nodes;
|
|
124
|
+
NodeAssert.deepEqual(
|
|
125
|
+
nodes.map((node) => node.prop ?? `@${node.name}`),
|
|
126
|
+
["color", "z-index", "$value", "display", "display", "width", "@include", "color", "padding"],
|
|
127
|
+
);
|
|
128
|
+
NodeAssert.deepEqual(
|
|
129
|
+
nodes.filter((node) => node.prop === "display").map((node) => node.value),
|
|
130
|
+
["-webkit-box", "flex"],
|
|
131
|
+
);
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
NodeTest.test(
|
|
136
|
+
"moves leading and inline comments with their owners and preserves SCSS syntax",
|
|
137
|
+
() => {
|
|
138
|
+
const input = `// z selector
|
|
139
|
+
.z {
|
|
140
|
+
// width explanation
|
|
141
|
+
width: 1px; // width inline
|
|
142
|
+
color: red;
|
|
143
|
+
}
|
|
144
|
+
// a selector
|
|
145
|
+
.a { content: "braces {}; // text"; background: url("a;b.svg"); }
|
|
146
|
+
`;
|
|
147
|
+
const output = sortScss(input);
|
|
148
|
+
NodeAssert.ok(output.startsWith("// a selector\n.a"));
|
|
149
|
+
NodeAssert.match(
|
|
150
|
+
output,
|
|
151
|
+
/color: red;\n \/\/ width explanation\n width: 1px; \/\/ width inline/,
|
|
152
|
+
);
|
|
153
|
+
NodeAssert.ok(output.includes('"braces {}; // text"'));
|
|
154
|
+
NodeAssert.equal(sortScss(output), output);
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
NodeTest.test(
|
|
159
|
+
"preserves interpolated selectors, variable assignments and keyframe step order",
|
|
160
|
+
() => {
|
|
161
|
+
const input = `.z {} .#{$name} {} .a {}
|
|
162
|
+
@keyframes pulse { to { width: 1px; color: red } from { opacity: 0 } 50% { opacity: 1 } }`;
|
|
163
|
+
const root = scss.parse(sortScss(input));
|
|
164
|
+
NodeAssert.deepEqual(
|
|
165
|
+
root.nodes.slice(0, 3).map((node) => node.selector),
|
|
166
|
+
[".z", ".#{$name}", ".a"],
|
|
167
|
+
);
|
|
168
|
+
NodeAssert.deepEqual(
|
|
169
|
+
root.last.nodes.map((node) => node.selector),
|
|
170
|
+
["to", "from", "50%"],
|
|
171
|
+
);
|
|
172
|
+
NodeAssert.deepEqual(
|
|
173
|
+
root.last.first.nodes.map((node) => node.prop),
|
|
174
|
+
["color", "width"],
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
NodeTest.test("CLI checks without writing, writes recursively, then checks clean", async () => {
|
|
180
|
+
const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "sort-scss-"));
|
|
181
|
+
try {
|
|
182
|
+
const file = NodePath.join(dir, "sample.scss");
|
|
183
|
+
const input = ".z {}\n.a { width: 0; color: red }\n";
|
|
184
|
+
await NodeFSP.writeFile(file, input);
|
|
185
|
+
const run = (mode) =>
|
|
186
|
+
NodeChildProcess.spawnSync(process.execPath, [script, mode, dir], {
|
|
187
|
+
cwd: NodeOS.tmpdir(),
|
|
188
|
+
encoding: "utf8",
|
|
189
|
+
});
|
|
190
|
+
NodeAssert.equal(run("--check").status, 1);
|
|
191
|
+
NodeAssert.equal(await NodeFSP.readFile(file, "utf8"), input);
|
|
192
|
+
NodeAssert.equal(run("--write").status, 0);
|
|
193
|
+
NodeAssert.equal(await NodeFSP.readFile(file, "utf8"), ".a { color: red; width: 0 }\n.z {}\n");
|
|
194
|
+
NodeAssert.equal(run("--check").status, 0);
|
|
195
|
+
} finally {
|
|
196
|
+
await NodeFSP.rm(dir, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
NodeTest.test("CLI refuses invalid input before writing any file in the batch", async () => {
|
|
201
|
+
const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "sort-scss-"));
|
|
202
|
+
try {
|
|
203
|
+
const good = NodePath.join(dir, "a.scss");
|
|
204
|
+
const bad = NodePath.join(dir, "z.scss");
|
|
205
|
+
const input = ".z {} .a {}";
|
|
206
|
+
await NodeFSP.writeFile(good, input);
|
|
207
|
+
await NodeFSP.writeFile(bad, ".broken {");
|
|
208
|
+
const result = NodeChildProcess.spawnSync(process.execPath, [script, "--write", dir], {
|
|
209
|
+
encoding: "utf8",
|
|
210
|
+
});
|
|
211
|
+
NodeAssert.equal(result.status, 2);
|
|
212
|
+
NodeAssert.match(result.stderr, /Unclosed block/);
|
|
213
|
+
NodeAssert.equal(await NodeFSP.readFile(good, "utf8"), input);
|
|
214
|
+
} finally {
|
|
215
|
+
await NodeFSP.rm(dir, { recursive: true, force: true });
|
|
216
|
+
}
|
|
217
|
+
});
|
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { reactive } from '@esportsplus/reactivity';
|
|
2
|
+
import { html, component, type Attributes } from '@esportsplus/template';
|
|
3
3
|
import './scss/index.scss';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const OMIT = ['state'];
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export default component<A>(
|
|
13
|
-
function(attributes: A, content) {
|
|
14
|
-
let state = attributes.state;
|
|
15
|
-
|
|
6
|
+
export default component<Attributes & { state?: { active: boolean | number } }>(
|
|
7
|
+
function({ state = reactive({ active: false }), ...attributes }, content) {
|
|
16
8
|
return html`
|
|
17
9
|
<div
|
|
18
10
|
class='accordion'
|
|
19
|
-
${
|
|
11
|
+
${attributes}
|
|
20
12
|
${{
|
|
13
|
+
class: () => state.active && '--active',
|
|
21
14
|
inert: () => !state.active
|
|
22
15
|
}}
|
|
23
16
|
>
|
|
@@ -25,4 +18,4 @@ export default component<A>(
|
|
|
25
18
|
</div>
|
|
26
19
|
`;
|
|
27
20
|
}
|
|
28
|
-
);
|
|
21
|
+
);
|