This monkey-patch doesn't seem to be working with Zeitwerk, and we were
only using it in one place, so the easiest way to solve the problem is
to remove it.
Note that, in the process, we're changing the operation so `* 100`
appears before the division, so it's consistent with other places where
we do similar things (like the `supports_percentage` method in the
proposals helper).
We use vendor/assets and app/assets; the purpose of lib/assets isn't
that clear, though. According to the Rails guides:
> lib/assets is for your own libraries' code that doesn't really fit
> into the scope of the application or those libraries which are shared
> across applications.
So it must be something for companies having several Rails applications,
which isn't our case. Furthermore, this text has been removed from the
Rails guides for version 7.1, so this folder might be a legacy folder.
Reading conditions in Ruby is much easier than reading them in ERB and,
since the block only had only HTML tag (the <span> tag for deleted
users) but was using Ruby in all other four cases, we're moving it to a
Ruby file.
The `alt` attribute is mandatory in image tags. In this case, we're
leaving it empty because we also display text showing whether comments
are made by administrators, moderators or organizations.
The initialjs-rails gem hasn't been maintained for years, and it
currently requires `railties < 7.0`, meaning we can't upgrade to Rails 7
while we depend on it.
Since the code in the gem is simple, and we were already rewriting its
most complex part (generating a background color), we can implement the
same code, only we're using Ruby instead of JavaScript. This way, the
avatars will be shown on browsers without JavaScript as well. Since
we're adding a component test that checks SVG images are displayed even
without JavaScript, we no longer need the test that checked images were
displayed after AJAX requests.
Now the tests show the user experience better; people don't care about
the internal name used to select the initial (which is what we were
checking); they care about the initial actually displayed.
Note initialjs generated an <img> tag using a `src="data:image/svg+xml;`
attribute. We're generating an <svg> tag instead, because it's easier.
For this reason, we need to change the code slightly, giving the <svg>
tag the `img` role and using `aria-label` so its contents won't be read
aloud by screen readers. We could give it a `presentation` role instead
and forget about `aria-label`, but then screen readers would read the
text anyway (or, at least, some of them would).
These images are always displayed next to a username, meaning people
using screen readers were hearing the same username twice in a row.
Even though we're about to replace the initialjs gem, we're making this
change in case so we've got one more test and we can check everything
keeps working after replacing the gem.
We were using generic names like `args` and `options` which don't really
add anything to `*` or `**` because Ruby required us to.
That's no longer the case in Ruby 3.2, so we can simplify the code a
bit.
As usual, we're updating the bundler version in our Gemfile.lock so it
uses the one included in Ruby 3.2.3, and we're also updating the
`parser` gem so it supports this version.
Note that the `budget` parameter was added to the `delete_path` method
so it works in the tests; on production, it worked because this
component is only rendered on pages which already have the `budget`
parameter.
Co-authored-by: Javi Martín <javim@elretirao.net>
We're using `@extend` with a placeholder selector to generate the code
related to the icons. That means the generated CSS code will look
similar to:
```
.something,
.something-else,
.in-favor-against button:not(:hover, :active),
.etcetera,
.more-etcetera {
/* Rules here */
}
```
That means that, if one selector isn't supported by the browser, none of
the specified selectors will apply these rules.
The `:not(:hover, :active)` selector, introduced in commit 3482e6e05, is
currently supported by 96%-98% of the browsers. Browsers like Internet
Explorer don't support it.
Since there's a simple solution for this issue which results in a big
gain for 2%-4% of the population, we're fixing the issue by avoiding the
non-universally supported selector.
Foundation added compatibility with Dart Sass by implementing a `divide`
function and using it instead of `/` to perform divisions [1]. However,
this made CSS compilation much slower, with the cause being the usage of
the `divide` function inside Foundation's recursive `nth-root` and `pow`
functions. Since the `nth-root` function is only called by the `pow`
function, overriding the `pow` function so it uses the `math.pow`
function provided by Dart Sass solves the issue.
[1] Pull request 12241 in https://github.com/foundation/foundation-sites
Note that the sticky plugin no longer works with `data-top-anchor="0"`.
Quoting from the Foundation documentation:
> It's important to note that sticky requires a bit of developer input
> to work properly. (...) It's also important to set the minimum
> top-anchor point to 1px, otherwise it'll never stick!
Also note that the foundation-sites package already depends on the
motion-ui package, so we don't have to explicitly include this
dependency anymore. Since now we're using Dart Sass, we can upgrade to
motion-ui 2.0.5.
Since this new version already defines variables before using `!global`
with them, we can remove the changes we did in commit 1e1edc02e.
Finally, note we aren't removing the "upgrade Foundation" part of the
comment in `config/initializers/sass.rb` because we're still getting one
Dart Sass warning due to Foundation's code:
```
Deprecation Warning: Passing percentage units to the global abs()
function is deprecated.
In the future, this will emit a CSS abs() function to be by the
ser.
To preserve current behavior: math.abs(100%)
To emit a CSS abs() now: abs(#{100%})
$divisor: abs($divisor);
```
This warning will be removed when we upgrade to Foundation 6.8.1. We
aren't upgrading to that version now for the same reason we don't
upgrade two minor Rails versions at once: it would increase the chance
of breaking something.
We're getting one warning when compiling the assets due to the code we
use from font-awesome-sass, and a lot of warnings due to the code we use
from foundation.
Since these warnings are very annoying, and we get them both when
deploying and every time we change an SCSS file in development, we're
silencing them.
I haven't found the way to pass the `quiet_deps` option to the Sprockets
processor, so I'm monkey-patching the Sass engine instead.
After moving to Dart Sass, we were getting warnings like:
```
Deprecation Warning: $saturation: Passing a number without unit % (78)
is deprecated
Deprecation Warning: $lightness: Passing a number without unit % (93) is
deprecated
```
So we're passing percentages to the hsla function instead of passing
numbers without units.
In the previous commit, we used the `calc` function when assiging CSS
properties in order to avoid warnings like:
```
Deprecation Warning: Using / for division outside of calc() is
deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($global-width, 2) or calc($global-width / 2)
```
In cases like dividing by two, there's a third alternative: multiplying
by 0.5. We're applying this principle to all variable assignments where
we were using divisions, since using the `calc` function here would
sometimes result in errors due to these variables being used in
arithmetical operations. We aren't using `math.div` because it makes the
code harder to read.
The division operator `/` from Sass is deprecated because `/` is used in
CSS for uses other than dividing numbers. That's why we were getting
many warnings like:
```
Deprecation Warning: Using / for division outside of calc() is
deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($line-height, 2) or calc($line-height / 2)
More info and automated migrator: https://sass-lang.com/d/slash-div
margin-top: $line-height / 2;
```
Since using math.div makes the code harder to read and `calc` is
universally supported by all browsers (although the implementation in
Internet Explorer doesn't work in certain cases), we're using `calc`
when assigning the value to a CSS property.
However, we're also using divisions when assigning Sass variables, and
in those cases using `calc` is trickier because sometimes these
variables are used in other operations. We'll handle these cases in the
next commit.
SassC/Libsass has been deprecated for years and has been replaced by
Dart Sass. However, the dartsass-rails gem, maintained by the Rails
team, doesn't support sprockets integration and doesn't allow glob
imports (using `@import something/**/*` or similar). In particular,
dartsass-rails needs to start a separate browser that makes it less
straightforward to change a file and reload the browser.
So we're using sassc-embedded, which provides Dart Sass integration with
sprockets. While there's no guarantee this gem will be maintained a few
years from now, we know for sure that SassC/Libsass won't be maintained
at all, so using sassc-embedded is an improvement over our current
situation.
On my machine, this change reduces compilation times by about 35%.
Note we still depend on the `sassc-rails` gem, for two reasons.
First, we're still importing CSS/Sass content from a couple of gems
(mainly, social-share-button and font-awesome) and we don't know how to
import this content without the `sassc-rails` gem.
And, second, it provides support for glob imports. Without it, we'd have
to manually add every single (S)CSS file we import to the
`application.scss` file instead of being able to write things like
`@import admin/**/*";`.
Note we're removing the `sass` gem from `Gemfile.lock`. We should have
done it as part of e210682ac, but when we developed that branch, it
didn't contain the changes where we removed another gem depending on the
`sass` gem (which we removed in commit 2fa713c64), so Bundler didn't
delete it. However, now that we're changing the Gemfile, Bundler is
finally removing the no-longer-needed `sass` gem and its dependencies.
This way we've been able to detect a bug where we were assigning a value
to the `$global-left` variable instead of assigning it to either the
`left` or `right` properties. This, however, was the right behavior,
since adding a `left` indentation to the link wasn't correct because its
parent element already had padding on the sides.
SCSS Lint was based on Ruby Sass, which has been deprecated since 2018
and doesn't support some of the latest features in Dart Sass.
Since we're going to migrate to Dart Sass, we're also migrating to
Stylelint. In order to provide all the funcionality SCSS Lint had, we
also need to install a few Stylelint plugins. We also need to install
the `postcss-scss` package so Stylelint can read SCSS files.
We're still getting the linting errors we used to get in
`legislation_process.scss` because of the `max-nesting-depth` and
`selector-max-compound-selectors` rules, as well as the warnings we used
to get in `layout.scss` because the `ssb-whatsapp_app` HTML class
contains undescores in their name.
We're also getting a couple of new linting errors, which could be false
positives:
* The `scss/no-unused-private-members` rule reports errors in
`_consul_settings.scss` because of the `$-zf-*` variables, but I'm not
too worried about this one because these lines won't be necessary after
updating Foundation.
* The `scss/selector-no-redundant-nesting-selector` reports an error in
`datepicker_overrides.scss`, but removing the unnecessary nesting
selector would make it harder to understand the code (assuming it'd
work in the first place).
We've changed some files due to few differences between SCSS Lint rules
and their Stylelint equivalents:
* The `@stylistic/string-quotes` rule detects a case in `admin.scss`
that StringQuotes didn't detect.
* The `function-url-quotes` rule detects a case in `mixins/icons.scss`
that UrlQuotes didn't detect.
* The `@stylistic/declaration-bang-space-before` rule detects a case in
`sdg/goals/show.scss` that BangFormat didn't detect.
There are also a couple of rules that don't behave exactly like they
used to:
* The equivalents of SpaceBetweenParens and SpaceAfterComma don't cover
parenthesis or commas in mixin parameters; we haven't found rules that
detect these cases.
* DisableLinterReason probably has an equivalent that behaves
differently but, since we never disable linters inline, we aren't
adding its equivalent rule.
Note we're removing the SpaceAfterVariableColon rule because its
equivalent, `scss/dollar-variable-colon-space-after`, reports cases
where we add spaces to indent several variable assignments (which we do
a lot in the `_consul_settings.scss` file). We might add this rule again
if we stop aligning consecutive assignments.
We're also removing the QualifyingElement rule because its equivalent,
`selector-no-qualifying-type: true`, behaves differently. For example,
in this code:
```
a.qualifying {
color: inherit;
}
p {
&.qualifying {
color: inherit;
}
}
```
With the QualifyingElement from SCSS Lint, the first rule is incorrect
but the second one is correct. With the selector-no-qualifying-type rule
from Stylelint, on the other hand, both rules are incorrect.
Personally, I never liked the QualifyingElement rule, and we were
working around it anyway, so we aren't applying
selector-no-qualifying-type.
For reference, here's a full list of the SCSS Lint rules we had enabled
and their Stylelint equivalents.
BangFormat
"@stylistic/declaration-bang-space-after": "never"
"@stylistic/declaration-bang-space-before": "always"
BorderZero
declaration-property-value-disallowed-list:
border:
- none
ColorKeyword
color-named: "never"
DebugStatement
at-rule-disallowed-list:
- debug
DeclarationOrder
order/order:
- dollar-variables
- custom-properties
- type: at-rule
name: extend
- type: at-rule
name: include
hasBlock: false
- declarations
- type: at-rule
name: include
hasBlock: true
- rules
ElsePlacement # Apparently replaced by the combination of:
scss/at-else-closing-brace-space-after: always-intermediate
scss/at-else-empty-line-before: never
scss/at-if-closing-brace-space-after: always-intermediate
scss/at-if-closing-brace-newline-after: always-last-in-chain
EmptyLineBetweenBlocks:
ignore_single_line_blocks: true
rule-empty-line-before:
- "always-multi-line"
- ignore:
- after-comment
- first-nested
EmptyRule:
block-no-empty: true
FinalNewline
"@stylistic/no-missing-end-of-source-newline": true
HexLength
color-hex-length: "short"
HexNotation
@stylistic/color-hex-case: "lower"
HexValidation
color-no-invalid-hex: true
IdSelector
selector-max-id: 0
ImportPath
scss/load-no-partial-leading-underscore: true
scss/at-import-partial-extension: never
Indentation
"@stylistic/indentation": 2
LeadingZero
@stylistic/number-leading-zero: "always"
NameFormat
scss/at-function-pattern: "^(-?[a-z][a-z0-9]*)(-[a-z0-9]+)*$"
scss/at-mixin-pattern: "^(-?[a-z][a-z0-9]*)(-[a-z0-9]+)*$"
scss/dollar-variable-pattern: "^(-?[a-z][a-z0-9]*)(-[a-z0-9]+)*$"
scss/percent-placeholder-pattern: "^(-?[a-z][a-z0-9]*)(-[a-z0-9]+)*$"
NestingDepth
max-nesting-depth: 4
PlaceholderInExtend
scss/at-extend-no-missing-placeholder: true
PrivateNamingConvention
scss/no-unused-private-members: true
PropertySpelling
property-no-unknown: true
PseudoElement
selector-pseudo-element-colon-notation: "double"
selector-pseudo-element-no-unknown: true
SelectorDepth
selector-max-compound-selectors: 5
SelectorFormat # Not always followed; ssb-whatsapp_app
custom-property-pattern: "^([a-z][a-z0-9]*)(-[a-z0-9]+)*$"
selector-class-pattern: "^([a-z][a-z0-9]*)(-[a-z0-9]+)*$"
Shorthand
shorthand-property-no-redundant-values: true
SingleLinePerProperty
"@stylistic/declaration-block-semicolon-newline-after": always-multi-line
SingleLinePerSelector
@stylistic/selector-list-comma-newline-after": always
SpaceAfterComma
"@stylistic/value-list-comma-space-after": always
SpaceAfterPropertyColon
"@stylistic/declaration-colon-space-after": always-single-line
SpaceAfterPropertyName
"@stylistic/declaration-colon-space-before": never
SpaceAfterVariableName
scss/dollar-variable-colon-space-before: never
SpaceAroundOperator
scss/operator-no-unspaced: true
SpaceBeforeBrace
@stylistic/block-opening-brace-space-before: always
SpaceBetweenParens
"@stylistic/function-parentheses-space-inside": never
"@stylistic/selector-attribute-brackets-space-inside": never
"@stylistic/selector-pseudo-class-parentheses-space-inside": never
"@stylistic/media-feature-parentheses-space-inside": never
StringQuotes
"@stylistic/string-quotes": double
TrailingSemicolon
"@stylistic/declaration-block-trailing-semicolon": always
TrailingWhitespace # Note it was enabled by the gem and not by us
"@stylistic/no-eol-whitespace": true
TrailingZero
"@stylistic/number-no-trailing-zeros": true
UnnecessaryMantissa
"@stylistic/number-no-trailing-zeros": true
UnnecessaryParentReference
scss/selector-no-redundant-nesting-selector: true
UrlQuotes
function-url-quotes: always
VendorPrefixes
value-no-vendor-prefix: true
selector-no-vendor-prefix: true
property-no-vendor-prefix: true
at-rule-no-vendor-prefix: true
media-feature-name-no-vendor-prefix: true
ZeroUnit:
length-zero-no-unit: true
This is the last version in the 9.x series and was released in February
2019.
We'll first try out this version before upgrading to version 10.32.0
(the latest version) because it's been a long time since we upgraded
this gem and so we're doing the upgrade in two steps.
Although the gem is called jquery-fileupload-rails, the node package is
called blueimp-file-upload.
Note we're using the same version as provided by the gem.
The jquery-fileupload gem provided a `basic.js` file (which we were
requiring), which had the following content:
```
//= require jquery-fileupload/vendor/jquery.ui.widget
//= require jquery-fileupload/jquery.iframe-transport
//= require jquery-fileupload/jquery.fileupload
``
This file isn't available in the Node.js package, so we're adapting its
contents in our application.js file. Since we're already requiring
jQuery UI widget, we're omitting that line.