I have a regex puzzle for you all!
A week or so ago, I decided to change the formatting of my Sass file from this:
a {
color: red;
text-decoration: none;
&:hover: {
color: blue;
text-decoration: underline;
}
}
div { ... }
To this:
a {
color: red;
text-decoration: none;
&:hover: {
color: blue;
text-decoration: underline; } }
div { ... }
The second syntax seems nice -- it saves you lines and improves readability -- but it is actually a disaster for writing code. Imagine if I wanted to add another line after a:hover's text-decoration: I'd have to bring those two parentheses with me.
Anyway, I've been trying to find the perfect regex to change the formatting back but to no avail.
My thinking:
Match and capture 2 spaces since all closing brackets are indented at least one level: (\s{2})
Match and capture all additional spaces: (\s*)
Match and capture all other characters (my CSS code): (.*)
Match space + closing bracket: }
Replace that with two lines:
\1\2\3\n\2}
Doesn't exactly work quite yet. Appreciate any ideas.
Regex won't really work, as you've discovered, because the meaning/desired position depends on the parsing of the Document that has come before.
You need a parser or a filter for this job.
Fortunately, a standard JS beautifier, or a CSS indenter should whip that file right back into shape.
PS: Also consider more frequent backups and version control. (^_^)
Another easy way to do it is to do a quick replace on your editor, no regex, just make it match the spaces, replace with the new brackets/lines. Might not be as quick as using a css re-indenter though.
Related
I am refactoring some SCSS code, and want to make sure that the generated CSS code does not change semantically, even if it changes literally. The refactoring consists of creating a mixin and replacing a code fragment duplicated in many places with an include of the mixin.
The problem is that in some of the places attribute a was listed before attribute b, but in other places it was the reverse. Using the mixin of course produces a consistent order for all uses of it. So a simple text comparison produces a difference that I don't want it to.
For example, if I start out with this code:
.foo {
background: white;
color: brown;
}
.bar {
color: brown;
background: white;
}
...and then refactor it to:
#mixin my-colors {
background: white;
color: brown;
}
.foo {
#include my-colors
}
.bar {
#include my-colors
}
..then the generated text for .bar will change, even though the attributes as an unordered set did not. In other words, a text comparison will show that the CSS has changed when in fact it semantically has not.
Is there a way to compare the files such that these inconsistent orders can be ignored?
You could do it with a program. If you stick attributes into arrays for the before version, and subtract attributes from the array in the after version, a non-logically changed class would result in an empty array. Too easy in Ruby!
There are several ways to do that. If you are using a code editor such as Notepad++ it has a function to compare two opened filed. Every code editor has that. There are even online tools that can compare two texts/codes such as https://www.diffchecker.com.
In Bootstrap tutorials, when people create their own Sass variables in a custom style.scss, I see lots of them using trailing !important.
If you want to see an example of what I mean, start at 13:45 here:
https://www.youtube.com/watch?v=MDSkqQft92o&time_continue=24&app=desktop
.navbar {
width: 100%;
background none !important;
#media(max-width: 34em) {
background: black !important;
}
}
But then other code in the .scss file doesn't use !important. No explanation of why that is.
Anyone have some suggestions?
!important means that the style preceding it will be "forced" onto the element, despite what other styles may set on it. For example:
.element {
font-weight: bold;
}
.custom-class {
font-weight: normal !important;
}
If you have an <span class="custom-class element"></span>, it will be displaying a font-weight normal, not bold.
! important guarantees (or at least it tries) that the rule you're trying to apply is more important than others. So it overwrites other rules that might interfere with the new one. ! important is not necessary if the rules are ordered correctly because the last rules prevail over previous ones. ! important must be avoided as much as possible. Use it only if it's really necessary.
Which CSS authoring technique do rendering engines process more efficiently:
1) repeating the same style property/value pair in multiple selectors, or
2) grouping shared style properties in a single selector
Example 1: Duplicate font-size, but less rules
p {
font-size: 1em;
color: #000;
}
h1 {
font-size: 1em;
color: #fff;
}
or Example 2: More rules but one font-size
p, h1 {
font-size: 1em;
}
p {
color: #000;
}
h1 {
color: #fff;
}
This study by Dave Gregory is the best source I've found on this topic. It shows that duplicating property/value pairs is much worse for performance:
"Long" is what Gregory refers to as the "bloated" format where properties are repeated in multiple selectors.
for performance is better the second option, see this google advice, but take care of using declarations in just one place, you could finish with something like this, this is the problem with extend in css preprocessor like sass and stylus. However your first option could be more modular and makes your css modules more independent and reusable in other sites, you can then make use of a css minifier to group every declaration.
Organizing your css is really up to you and the number of elements you have.
If you are looking for optimization you should instead focus on useless whitespaces and duplicates.
Tools exist to merge the duplicates and minimize your code (here and here for example)
You may also read this article which is a bit old but still valuable I think.
I'm trying to learn SASS now, and I'm having trouble trying to visualize exactly how differently I would arrange my code. How would I, for instance, arrange the following code into SASS so that it avoids repetition?
a: link {color: #000; text-decoration: none;}
a: visited {color: #000; text-decoration: none;}
a: acive {color: #000; text-decoration: none;}
Currently the only way I can think of is adding two different variables with the following appropriate attributes, but that still seems repetitive to me. I have also considered mixins, but am unsure how exactly to incorporate them in this example.
��Thanks in advance for the help. Also, as far as I understand it, SASS isn't meant to enhance web performance, just workflow. Is this correct? I say this specifically because, when processed, the code ends up looking the same on CSS.
The repeated part of this is the a and the styles color: #000; text-decoration: none.
So, with SASS you can nest your styles so you only need to write a once. The syntax for :link etc, is &:link.
Therefore, you can write:
a {
&:link,
&:visited,
&:active {
color: #000;
text-decoration: none;
}
}
Or if you do have variables, e.g. $black: #000; you can swap them in. color: $black.
It's not only for workflow though. One of the main advantages of using SASS (or LESS) is that you can organise your SASS files separately e.g. _buttons.scss, _layout.scss etc, and then import (using #import) them all into one 'theme.scss' and then have SASS compile the 'theme.scss'.
How this compilation is done depends on your setup, but Compass (Compass.app for the UI lovers like me) is a very popular option. What you end up with is the browser only request 1 file for styles, rather than many.
#mixin links($color:#000,$tdec:none){
a{
&:link,&:visited,&:active{
color:#{$color};
text-decoration: #{$tdec};
}
}
}
Then use the mixin ;
#include links();
or
#include links(#fee,underline);
may be this is what you're looking for.
Yeah. SASS doesnt meant to enhance web performance. But im sure SASS can mess your CSS if you use it wrong way(unnecessary nesting etc).
When you get used to it, it'll save your coding time alot.
I want to remove all lines in a CSS file that contain the word "color".
This would include:
body {background-color:#000;}
div {color:#fff;}
How would you do that using the :%s/ command?
Should just be
:g/color/d
Is that such a wise idea? You could end up doing something you don't want if your CSS has sections like this
body {background-color: #000;
font-size: large;
}
p {
color: #fff; float: left;
}
You're better off removing only the properties containing color
s/\(\w\|-\)*color\w*\s*:.\{-}\(;\|$\)//
Update:
As too_much_php pointed out, the regex I didn't exactly work. I've fixed it, but it requires vim. It isn't feasible to forge a regex that only removes problem properties in vi. Because there are no character classes, you would have to do something like replacing the \w with \(a\|b\|c\|d\|....\Z\)
Standard ex sequence:
:/color/d
And just to give you a completely different answer:
:%!grep -v color
:)
This alludes to a larger bit of functionality; you can apply your knowledge of *nix commandline filters to editing your code. Want a list of enums sorted alphabetically? Visual select, :!sort and it's done.
You can use uniq, tac, etc, etc.
This did the trick for me:
:%s/.*color.*\n//