From: Mark Otto Date: Tue, 6 Jan 2026 06:45:30 +0000 (-0800) Subject: Add stylelint order plugin X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=82a17fd35983245db62811fe5b043be4a2a0554c;p=thirdparty%2Fbootstrap.git Add stylelint order plugin --- diff --git a/.stylelintrc.json b/.stylelintrc.json index 045dbeff4e..79bc4ab264 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -2,8 +2,23 @@ "extends": [ "stylelint-config-twbs-bootstrap" ], + "plugins": [ + "stylelint-order" + ], "reportInvalidScopeDisables": true, "reportNeedlessDisables": true, + "rules": { + "order/order": [ + [ + { "type": "at-rule", "name": "use" }, + { "type": "at-rule", "name": "forward" }, + "dollar-variables", + "custom-properties", + "declarations", + "rules" + ] + ] + }, "overrides": [ { "files": "**/*.scss", diff --git a/package-lock.json b/package-lock.json index 50be6e6090..4a8462ae35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -94,6 +94,7 @@ "shelljs": "^0.10.0", "stylelint": "^16.26.1", "stylelint-config-twbs-bootstrap": "^16.1.0", + "stylelint-order": "^7.0.1", "terser": "^5.44.1", "unist-util-visit": "^5.0.0", "zod": "^4.1.12" @@ -14514,9 +14515,9 @@ } }, "node_modules/postcss-sorting": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz", - "integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-9.1.0.tgz", + "integrity": "sha512-Mn8KJ45HNNG6JBpBizXcyf6LqY/qyqetGcou/nprDnFwBFBLGj0j/sNKV2lj2KMOVOwdXu14aEzqJv8CIV6e8g==", "dev": true, "license": "MIT", "peerDependencies": { @@ -17104,6 +17105,30 @@ "stylelint": ">=16" } }, + "node_modules/stylelint-config-recess-order/node_modules/postcss-sorting": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz", + "integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "postcss": "^8.4.20" + } + }, + "node_modules/stylelint-config-recess-order/node_modules/stylelint-order": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.4.tgz", + "integrity": "sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss": "^8.4.32", + "postcss-sorting": "^8.0.2" + }, + "peerDependencies": { + "stylelint": "^14.0.0 || ^15.0.0 || ^16.0.1" + } + }, "node_modules/stylelint-config-recommended": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", @@ -17232,17 +17257,20 @@ } }, "node_modules/stylelint-order": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.4.tgz", - "integrity": "sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-7.0.1.tgz", + "integrity": "sha512-GWPei1zBVDDjxM+/BmcSCiOcHNd8rSqW6FUZtqQGlTRpD0Z5nSzspzWD8rtKif5KPdzUG68DApKEV/y/I9VbTw==", "dev": true, "license": "MIT", "dependencies": { - "postcss": "^8.4.32", - "postcss-sorting": "^8.0.2" + "postcss": "^8.5.6", + "postcss-sorting": "^9.1.0" + }, + "engines": { + "node": ">=20.19.0" }, "peerDependencies": { - "stylelint": "^14.0.0 || ^15.0.0 || ^16.0.1" + "stylelint": "^16.18.0 || ^17.0.0" } }, "node_modules/stylelint-scss": { diff --git a/package.json b/package.json index 5d595676ee..ee42b9d79a 100644 --- a/package.json +++ b/package.json @@ -177,6 +177,7 @@ "shelljs": "^0.10.0", "stylelint": "^16.26.1", "stylelint-config-twbs-bootstrap": "^16.1.0", + "stylelint-order": "^7.0.1", "terser": "^5.44.1", "unist-util-visit": "^5.0.0", "zod": "^4.1.12" diff --git a/scss/_nav.scss b/scss/_nav.scss index 32d00fe602..fa849b19da 100644 --- a/scss/_nav.scss +++ b/scss/_nav.scss @@ -89,9 +89,9 @@ $nav-underline-link-active-color: var(--emphasis-color) !default; } &:focus-visible { + --focus-ring-offset: 1px; color: var(--nav-link-hover-color); @include focus-ring(true); - --focus-ring-offset: 1px; } &.active, diff --git a/scss/_root.scss b/scss/_root.scss index 2924962743..7d9defb0ee 100644 --- a/scss/_root.scss +++ b/scss/_root.scss @@ -11,9 +11,10 @@ @layer colors, theme, config, root, reboot, layout, content, forms, components, custom, helpers, utilities; :root { - color-scheme: light dark; - // scss-docs-start root-theme-variables + --black: #{$black}; + --white: #{$white}; + // Generate semantic theme colors @each $color-name, $color-map in $new-theme-colors { @each $key, $value in $color-map { @@ -32,15 +33,13 @@ @each $color, $value in $theme-borders { --border-#{$color}: #{$value}; } - - --black: #{$black}; - --white: #{$white}; // scss-docs-end root-theme-variables + + color-scheme: light dark; } :root, [data-bs-theme="light"] { - color-scheme: light; // Note: Custom variable values only support SassScript inside `#{}`. @@ -54,12 +53,6 @@ --font-sans-serif: #{meta.inspect($font-family-sans-serif)}; --font-monospace: #{meta.inspect($font-family-monospace)}; --gradient: #{$gradient}; - - // Root and body - // scss-docs-start root-body-variables - @if $font-size-root != null { - --root-font-size: #{$font-size-root}; - } --body-font-family: #{meta.inspect($font-family-base)}; // scss-docs-start root-font-size-variables @@ -91,9 +84,6 @@ --body-font-size: #{$font-size-base}; --body-font-weight: #{$font-weight-base}; --body-line-height: #{$line-height-base}; - @if $body-text-align != null { - --body-text-align: #{$body-text-align}; - } --body-color-rgb: #{to-rgb($body-color)}; --body-bg-rgb: #{to-rgb($body-bg)}; @@ -145,12 +135,21 @@ --form-valid-border-color: #{$form-valid-border-color}; --form-invalid-color: #{$form-invalid-color}; --form-invalid-border-color: #{$form-invalid-border-color}; + color-scheme: light; + + // Root and body + // scss-docs-start root-body-variables + @if $font-size-root != null { + --root-font-size: #{$font-size-root}; + } + @if $body-text-align != null { + --body-text-align: #{$body-text-align}; + } // scss-docs-end root-form-validation-variables } @if $enable-dark-mode { @include color-mode(dark, true) { - color-scheme: dark; // scss-docs-start root-dark-mode-vars --emphasis-color: #{$body-emphasis-color-dark}; @@ -164,6 +163,7 @@ --form-valid-border-color: #{$form-valid-border-color-dark}; --form-invalid-color: #{$form-invalid-color-dark}; --form-invalid-border-color: #{$form-invalid-border-color-dark}; + color-scheme: dark; // scss-docs-end root-dark-mode-vars } } diff --git a/scss/forms/_form-adorn.scss b/scss/forms/_form-adorn.scss index f38892befe..a5a97fcdac 100644 --- a/scss/forms/_form-adorn.scss +++ b/scss/forms/_form-adorn.scss @@ -51,9 +51,9 @@ $form-adorn-icon-color: var(--fg-2) !default; // Focus state when ghost input is focused &:focus-within { + --focus-ring-offset: -1px; border-color: $input-focus-border-color; @include focus-ring(true); - --focus-ring-offset: -1px; } // Ghost input fills remaining space diff --git a/scss/forms/_form-control.scss b/scss/forms/_form-control.scss index ff18bd102b..d383b56535 100644 --- a/scss/forms/_form-control.scss +++ b/scss/forms/_form-control.scss @@ -53,11 +53,11 @@ // Customize the `:focus` state to imitate native WebKit styles. &:focus-visible { + --focus-ring-offset: -1px; color: $input-focus-color; background-color: $input-focus-bg; border-color: $input-focus-border-color; @include focus-ring(true); - --focus-ring-offset: -1px; } &::-webkit-date-and-time-value { diff --git a/scss/forms/_input-group.scss b/scss/forms/_input-group.scss index 50cb0a1610..3e0eef1475 100644 --- a/scss/forms/_input-group.scss +++ b/scss/forms/_input-group.scss @@ -112,6 +112,8 @@ $input-group-addon-border-color: $input-border-color !default; // stylelint-disable-next-line no-duplicate-selectors .input-group { + + $validation-messages: ""; &:not(.has-validation) { > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), > .dropdown-toggle:nth-last-child(n + 3), @@ -130,11 +132,6 @@ $input-group-addon-border-color: $input-border-color !default; } } - $validation-messages: ""; - @each $state in map.keys($form-validation-states) { - $validation-messages: $validation-messages + ":not(." + string.unquote($state) + "-tooltip)" + ":not(." + string.unquote($state) + "-feedback)"; - } - > :not(:first-child):not(.dropdown-menu)#{$validation-messages} { margin-inline-start: calc(-1 * #{$input-border-width}); @include border-start-radius(0); @@ -144,5 +141,8 @@ $input-group-addon-border-color: $input-border-color !default; > .form-floating:not(:first-child) > .form-select { @include border-start-radius(0); } + @each $state in map.keys($form-validation-states) { + $validation-messages: $validation-messages + ":not(." + string.unquote($state) + "-tooltip)" + ":not(." + string.unquote($state) + "-feedback)"; + } } } diff --git a/scss/forms/_otp-input.scss b/scss/forms/_otp-input.scss index f23bc36fec..e43706b054 100644 --- a/scss/forms/_otp-input.scss +++ b/scss/forms/_otp-input.scss @@ -52,8 +52,8 @@ $otp-input-gap: .5rem !default; border-color: var(--form-valid-border-color); &:focus { - border-color: var(--form-valid-border-color); --focus-ring-color: rgba(var(--success-rgb), .25); + border-color: var(--form-valid-border-color); } } @@ -62,8 +62,8 @@ $otp-input-gap: .5rem !default; border-color: var(--form-invalid-border-color); &:focus { - border-color: var(--form-invalid-border-color); --focus-ring-color: rgba(var(--danger-rgb), .25); + border-color: var(--form-invalid-border-color); } } } diff --git a/scss/layout/_containers.scss b/scss/layout/_containers.scss index b508411bc2..465d5f5340 100644 --- a/scss/layout/_containers.scss +++ b/scss/layout/_containers.scss @@ -30,13 +30,13 @@ } @include media-breakpoint-up($breakpoint, $grid-breakpoints) { + // Extend each breakpoint which is smaller or equal to the current breakpoint + $extend-breakpoint: true; + %responsive-container-#{$breakpoint} { max-width: $container-max-width; } - // Extend each breakpoint which is smaller or equal to the current breakpoint - $extend-breakpoint: true; - @each $name, $width in $grid-breakpoints { @if ($extend-breakpoint) { .container#{breakpoint-infix($name, $grid-breakpoints)} { diff --git a/site/src/scss/_syntax.scss b/site/src/scss/_syntax.scss index e537635b68..55de5daef8 100644 --- a/site/src/scss/_syntax.scss +++ b/site/src/scss/_syntax.scss @@ -13,11 +13,11 @@ } .astro-code { + --bs-font-monospace: "Geist Mono"; display: flex; padding: var(--bd-example-padding); margin-bottom: 0; line-height: 20px; - --bs-font-monospace: "Geist Mono"; background-color: var(--bd-pre-bg) !important; // stylelint-disable-line declaration-no-important }