Mohsen
Mohsen

Reputation: 65805

RegEx to beautify minified CSS

I am trying to beautify CSS code using JavaScript.

A minified CSS code looks like this:

str = 'body{margin:0;padding:0;}section,article,.class{font-size:2em;}'

So far I could beautify the code by using multiple replaces:

str.replace(/{/g, " {\n")
    .replace(/}/g, "}\n")
    .replace(/;/g,";\n")
    .replace(/,/g, ",\n")

This is working but I want to improve it

Upvotes: 4

Views: 1155

Answers (2)

user428517
user428517

Reputation: 4193

I don't know if CSS is a regular language (my guess is yes), but this should doable with regex regardless.

There's no need to match a last property, whether it contains a semicolon or not. First match all closing curly braces, like you've done, except add a newline both before and after each:

.replace(/}/g, "\n}\n")

Then match all semicolons except those that come before a newline (which were inserted by the regex above) and add a newline and tab using the \t character after each:

.replace(/;([^\n])/g, ";\n\t$1")


This is just the tip of the iceberg, unfortunately. Don't forget to look for all the different types of selectors, such as those containing : or >, if you plan to add spaces around those. There's probably lots of other stuff you'll need to consider, too.

Upvotes: 1

Martin Ender
Martin Ender

Reputation: 44269

I think it's hard to reduce the number of regular expressions, since sometimes you need only a line break, sometimes you need a tab, too. Sometimes you need to write back one and sometimes two characters. But here is a list of replacements that makes the CSS look quite nice:

str.replace(/\{/g, " {\n\t")        // Line-break and tab after opening {
   .replace(/;([^}])/g, ";\n\t$1")  // Line-break and tab after every ; except
                                    // for the last one
   .replace(/;\}/g, ";\n}\n\n")     // Line-break only after the last ; then two
                                    // line-breaks after the }
   .replace(/([^\n])\}/g, "$1;\n}") // Line-break before and two after } that
                                    // have not been affected yet
   .replace(/,/g, ",\n")            // line break after comma
   .trim()                          // remove leading and trailing whitespace

Makes this:

 str = 'body{margin:0;padding:0}section,article,.class{font-size:2em;}'

Look like this:

body {
    margin:0;
    padding:0;
}

section,
article,
.class {
    font-size:2em;
}

If you don't care about those omitted semicolons being put back in place, you can shorten this a bit though, by changing the order:

str.replace(/\{/g, " {\n\t")
   .replace(/\}/g, "\n}\n\n")    // 1 \n before and 2 \n after each }
   .replace(/;(?!\n)/g, ";\n\t") // \n\t after each ; that was not affected
   .replace(/,/g, ",\n")
   .trim()

Upvotes: 3

Related Questions