Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check string for valid CSS using Regex

I need to check a user's input to be valid CSS syntax (the input string is basically a CSS file). It can contain classes, selectors, !important etc.

I didn't start working on it, because I was hoping there is already some regex syntax out there, so I don't have to start from scratch.

I tried googling but all I've found is partial css matching strings, not a regex that validates all possible css.

like image 323
Shimmy Weitzhandler Avatar asked Jan 19 '14 22:01

Shimmy Weitzhandler


2 Answers

Ok, so I came up with a regex that matches valid css styles..

([#.@]?[\w.:> ]+)[\s]{[\r\n]?([A-Za-z\- \r\n\t]+[:][\s]*[\w .\/()\-!]+;[\r\n]*(?:[A-Za-z\- \r\n\t]+[:][\s]*[\w .\/()\-!]+;[\r\n]*(?2)*)*)}

Working example here:

http://regex101.com/r/fK9mY3

Keep in mind.. After examining my example link above, you see this regex works for common, basic CSS2 styling, however, to match ALL CSS3 styling variations, pertaining to http://www.w3.org/TR/css3-syntax/#detailed-grammar, this regex would need some tweaking... The above regex IS a starting point however..

like image 199
Bryan Elliott Avatar answered Sep 27 '22 20:09

Bryan Elliott


Adding to Bryan's answer. And adding a note

  • javascript support: there was an error with the (?2)
  • multiple classes: .class, .class2 {...}
  • class delimeters: .class-name, .class_name
  • empty class: .class {}
  • percentages: width: 100%;
  • quoted urls: background: url("/img.jpg");
const multi = /((?:^\s*)([\w#.@*,:\-.:>,*\s]+)\s*{(?:[\s]*)((?:[A-Za-z\- \s]+[:]\s*['"0-9\w .,\/()\-!%]+;?)*)*\s*}(?:\s*))/mi

const example = `
div.css-class-10_9::hover, .active {
  width: 100%;
  background: rgba(1.0,0,1,1); 
  background-url: url("http://img.jpg");   
}

div.css-class-10_9::hover,
.active {
  width: 100%;
  background: rgba(1.0,0,1,1);
  background-url: url("http://img.jpg");
}

html {
  background: white;
}
`

let out = example.replace(multi, '')
// "
// div.css-class-... {...}
// html {...}
// "

out = out.replace(multi, '')
// "html {...}"

out = out.replace(multi, '')
// ""

You can also add global to replace all at once

const global_re = /((?:^\s*)([\w#.@*,:\-.:>,*\s]+)\s*{(?:[\s]*)((?:[A-Za-z\- \s]+[:]\s*['"0-9\w .,\/()\-!%]+;?)*)*\s*}(?:\s*))/gmi


example.replace(global_re, '');
// ""


example.replace(global_re,'$1') // group 1 all css
//
// div.css-class-...{
//   width...
//   rest_css...
// }
//
// ...
//
// html {
//   ...
// }

Class Names

example.replace(global_re,'$2\n\n') // group 1 all class names
// "
// div.css-class-10_9::hover, .active 
// 
// div.css-class-10_9::hover,
// .active 
// 
// html  
// "

Class bodies (replace everything but class bodies)

example.replace(global_re,'$3\n')
// "
// width: 100%;
// background: rgba(1.0,0,1,1); 
// background-url: url("http://img.jpg");   
// 
// 
// width: 100%;
// background: rgba(1.0,0,1,1);
// background-url: url("http://img.jpg");
// 
// 
// background: white;
// 
// "

https://regex101.com/r/fK9mY3/55

(Disclaimer: this definitely doesn't validate css)

ex: '............a {}' comes out true

like image 32
duality Avatar answered Sep 27 '22 20:09

duality