Regexp to find all CSS rules not ending with ";" - css

I'm trying to write regexp to find all rules in CSS filest that don't have semicolon at the end:
.abc {
height: 100%;
margin: auto;
text-align: center /* <-- like this one */
width: 100%;
}
i've tried this [^;\{\}]\n but it not excluding { and } from search. Any ideas?

What you need is a CSS parser.
However, if this is a one-off job, and your regex engine supports lookbehinds, you can use this regex:
^.*(?<![;{}])$
Visualization:
(?<![;{}]) is a negative lookbehind that asserts that the line should end with a character that's not ;, { or }.
Note that the regex is far from perfect and fails to match properly if a CSS block is used by more than one class/id or if every class/id is separated by a line break.
RegEx Demo

In perl you can easily do this,
e.g:
#!/usr/bin/perl
# open your file
open(FILE,"filename.css");
my #fileLines = <FILE>;
close FILE;
my $lineCount=1;
# check all lines of your file
foreach my $line(#fileLines){
# erase endline spaces
$line=~ s/\s+$//;
# erase begin of line
$line=~ s/^\s+//;
# simple perl regex, it doesn't watch for comments
if($line !~ /\;$/ && $line !~ /{$/ && $line !~/}$/){
print $lineCount.':'.$line.'\n';
}
$lineCount++;
}
This small program will show you lines which not finnish by ';'.

You could just run the file through http://csslint.net

Related

Find CSS class names that are not inside comments using Regular Expressions

I'm trying to replace all class names in a CSS file. I am using JavaScript/Node.js.
My current solution is this: /\.[a-z][a-z0-9-_]*/g.
At the end of the file is a comment that references the source map file: /*# sourceMappingURL=style.css.map */. Now the file extensions of that URL also get replaced.
Given the following input:
.text-center { text-align: center; }
table.simple{background:#fff;}.bg-white{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/
the result is:
.a { text-align: center; }
table.a{background:#fff;}.a{background:#fff;}
/*# sourceMappingURL=style.a.a */
/*
Example comment file.a
*/
what I want is:
.a { text-align: center; }
table.a{background:#fff;}.a{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/
How do I have to change my RegEx so it does only match class names, that are outside of comments (// comments are not relevant here)?
Try this regex:
\.[^{\s]*(?=\s*{)
and replace each match with .a
Click for Demo
Explanation:
\. - matches a .
[^{\n]* - matches 0+ occurrences of any character that is neither a white-space nor {
(?=\s*{) - positive lookahead to make sure that the current position is followed by 0+ whitespaces followed by {.
Now, the above regex would fail if we have comments of the format
/*# sourceMappingURL=style.css.map {*/
i.e, { present after css.map inside a comment. So, to handle such a case, you can use the following regex(almost similar to the previous regex. Just one more negative lookahead to the regex)
\.[^{\s]*(?=\s*{)(?!(?:(?!\/\*)[\s\S])*\*\/)
Click for Demo
Explanation:
\.[^{\s]*(?=\s*{) - similar to the previous regex
(?!(?:(?!\/\*)[\s\S])*\*\/) - Negative lookahead to make sure that the current position(position right after the .classname) is not present within a comment of the form /*...*/
(?!.... - negative lookahead
(?:(?!\/\*)[\s\S])* - tempered greedy token to match 0+ occurrences of any character greedily, which does not begin with the sequence /*
\*\/ - matches */
Both of these approaches work in different cases like classes between ids or multiple classes in selection:
.class-a, #id-a, .class-b:hover {}
First approach
In this first approach you can match both comment section and CSS classes then replace class names while they are matched and leave comments intact:
\/\*[\s\S]*?\*\/|(\.[a-z_-][\w-]*)(?=[^{}]*{)
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Match comments Match and capture classes
Breakdown:
\/\*[\s\S]*?\*\/ # Match a comment block
| # Or
( # Start of capturing group #1
\.[a-z_-][\w-]* # Match a CSS class name
) # End of CG #1
(?= # Start of a positive lookahead
[^{}]*{ # Class should be followed by a `{` (may not be immediately)
) # End of lookahead
JS code:
var str = `.text-center { text-align: center; }
table.simple{background:#fff;}.bg-white{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/`
console.log(str.replace(/\/\*[\s\S]*?\*\/|(\.[a-z_-][\w-]*)(?=[^{}]*{[^{}]*})/g,
function($0, $1) {
return $1 ? '.a' : $0; // If a class is matched ...
}
));
Second approach
If you don't think in comments such occurrences will exist:
/* style.css {css file} */
you can omit matching comments in first approach:
\.[a-z_-][\w-]*(?=[^{}]*{[^{}]*})
^^^^^^^
Added for a more strict selection
RegEx live demo
JS code:
var str = `.text-center { text-align: center; }
table.simple{background:#fff;}.bg-white{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/`
console.log(str.replace(/\.[a-z_-][\w-]*(?=[^{}]*{[^{}]*})/g, '.a'));
I've got it to work with the following RegEx in pcre flavor
/(\/\*)?(?(1)(.*\*\/)|(\.[a-z][a-z0-9-_]*))/g
I'm using a conditional statement. Whenever it detects a start of a comment, it does not look for a class name but for the end of the comment. However, this does not work for comments on multiple lines. The class names are the third capturing group. So to replace class names, only touch matches that contain the capturing group 3.
I didn't notice I was using pcre instead of javascript on regex101.com and ended up with a syntax error in my JS code. I'm now working on finding a solution that works for JS.
Edit:
I now ported it to JS:
/(?=\/\*)|(\.[a-z][a-z0-9-_]*)(?!.*\*\/)/g
I still have to find a way to get it to work with multiple lines.
With the following regex you should be able to extract all class-names from your css file, which are not in comment.
It´s important that the class name start with a dot (.)
Regex:
/^.[a-z][a-z0-9-_].*?[\s]/mg

css erase all between { } sublime text

it is possible to clean the contents of a CSS file, leaving only the class names and #medias with search and replace tool?
for example:
this:
#id .class {
width: 100%;
display: block;
}
leave it:
#id .class {
}
Thanks to all
Sure. You want to replace everything between { and } with a single empty line. The regular expression for this is
\{([^\}])+\}
^ ^ ^
{ | }
|
anything that's not a `}`
The replacement is {\n\n}.
Screenshot
If you have Emmet installed you can use Control + D. That will "Select Between Container" (You might have to press it multiple times depending on where your cursor starts).
There's also Control + Shift + Space that will do it all in one shot no matter where the cursor is.
I listed Control + D first because I find it a lot more useful.
I found an awesome article with a lot of nice shortcuts here:
https://viget.com/extend/my-overused-sublime-text-keyboard-shortcuts

How to change SASS output style in order to make a new line after each ending curly brace?

The processed code looks like this:
.body {
color: #eeeeee;
}
.someting {
color: #dddddd;
}
I want it to be:
.body {
color: #eeeeee;
}
.someting {
color: #dddddd;
}
Is there such a possibility? Google can't find an answer.
I bet you could write a simple regex find-replace looking for }'s and replacing with }\n, and have Grunt execute that on your css (post-compilation from SASS).
This looks like it'd do the trick:
https://npmjs.org/package/grunt-regex-replace
I think the closest you can get is expanded. The extra line break won't be there when you're nesting but your example code would output exactly like you demonstrated.
To answer this question, you can go to rubygems/gems/sass-3.4.9/lib/sass/tree/visitors/to_css.rb (or anywhere your to_css file is), and edit this:
output("}" + trailer) to output("}\n" + trailer)
And then remove this newline:
trailer = "\n" if node.group_end
It might have been an oversight when parsing the nesting, because the newline set on "trailer" applies to every other line (so you'd have double the lines without removing it if you don't nest anything).

RegEx help to change properties in CSS

I ned some help with RegEx, not sure what I am doing wrong.
What I would like to achieve is to change the value of one CSS property in a CSS file without altering anything within that CSS file.
<?php
$var = '
#css {
text-size: 14px;
color: red;
background: orange;
}
';
echo preg_replace('/#css(.*)color: (.*);(.*)}/is','#css$1color: black;$3 }',$var);
?>
The result I am hoping to see is this:
#css {
text-size: 14px;
color: red;
background: orange;
}
However what I get is this:
#css {
text-size: 14px;
color: black;
}
I am not an expert in RegEx at all but after reading manuals and examples online I thought I could use backreferences to do this and that $1 would be the result of the first match, $2 of the second, $3 of the third etc... In my example $1 matches everything between '#css' and 'color: ' and then $2 I don't use because I want to replace 'red' with 'black'. I thought $3 would be the result of everything between ';' and '}' but it gets lost somewhere or, more likely, I am lost somewhere ;-)
Thanks for the advice and support.
First of all, using the greedy .* is always problematic. In your case, it cosumes too much symbols so that you lose the background because it matches the last ; in your code (which comes after the background declaration). Instead use a negative character class which matches until the very next symbol you know should not be included in the match - in your case the ;. So the character class should look like: [^;]*. The same is true with matching the } symbol - use a negative character class instead.
Secondly, I would try to reduce the usage of capture groups.
And finally, I would reduce the clutter and put everything you don't want to replace into the capturegroups before and after so that you get a very simple result: '$1black$2'
Try the following regex:
preg_replace('/(#css.*?color:)[^;]*([^}]*)/is','$1black$2',$var);
See the demo
Note that this regex has one flaw: If you have different colors in your decplarations (background-color, border-color,...), it will break! So you should include an additional whitespace to make sure it only captures the "real" color declaration:
/(#css.*?\scolor:)[^;]*([^}]*)/is
This still might break if (which should not happen) per accident you have multiple color:xyz; declarations in your rule block. Only the first one gets replace then.
The problem here is that you're matching greedily for your second capture group. In doing so, it consumes everything up until the final semicolon in your text.
What you should be doing instead is using a lazy matching group instead which will match as few characters as possible. (eg. only up until the first semicolon, rather than the last)
preg_replace('/#css(.*)color: .*?;(.*)}/is','#css$1color: black;$2 }',$var);
As I understand your problem, I think this will solve your issue.
$var = '
#css {
text-size: 14px;
color: red;
background: orange;
}
';
preg_match_all('/(#css\s*\{[\sA-z0-9#:;-]*color\s*:\s*[A-z0-9#]*)/', $var, $output);
$temp = preg_replace('/(color\s*:\s*[A-z0-9#]*)/im', 'color: black', $output[0][0]);
echo preg_replace('/(#css\s*\{[\sA-z0-9#:;-]*color\s*:\s*[A-z0-9#]*)/im', $temp, $var);
?>

remove specific rules out of inline CSS

i'd like to remove some specific css rules (i.e. width and height) out of inline style attributes.
so i want to transform the following:
<table id="foo" style="border:1px #000 solid; width: 100px; height: 100px;">
into
<table id="foo" style="border:1px #000 solid">
is there a handy regex that solves my problem?
thank you all in advance
Maybe try this (tested in Vim and Ruby):
/(width|height):\s*\d+(px|%);?//
Of course you should use your editor's (or language's) syntax for regexps (for example in Vim you have to prepend backslash before '(','|',')' and '+'
Enable regex search in your editor and try:
width="[^"]*"
height="[^"]*"
Your question is not very specific, but how about /[\s;"']width: .+;/. You need to feed that to a replace function or something, but I can't help you there because I don't know what language you're in.
Beware: regular expressions cannot correctly parse HTML.
Use a parser instead.
#! /usr/bin/perl
use warnings;
use strict;
use HTML::Parser;
die "Usage: $0 html-file\n" unless #ARGV == 1;
sub start {
my($tag,$attr,$attrseq,$text,$skipped) = #_;
print $skipped;
unless ($attr->{style} && $attr->{style} =~ /width|height/) {
print $text;
return;
}
my %style = $attr->{style} =~ /
\s* # optional leading space
(.+?) : # property, e.g., width
\s* # optional separating space
([^;]+) # value, e.g., 100px
;? # optional separator
/gx;
delete #style{qw/ width height /};
$attr->{style} = join "; " =>
map "$_: $style{$_}",
keys %style;
print "<$tag ",
join(" " => map qq[$_="$attr->{$_}"], #$attrseq),
">";
}
my $p = HTML::Parser->new(
api_version => 3,
marked_sections => 1,
start_h => [ \&start => "tag, attr, attrseq, text, skipped_text" ],
end_h => [ sub { print #_ } => "skipped_text, text" ],
);
undef $/;
$p->parse(<>);
No, you generally cannot do all that in a regular expression, because HTML is not a regular language.
Use an HTML parser to get at the style attribute from table tags, then use the regular expressions width:.+?(;|$) and height:.+?(;|$).

Resources