Skip to content
This repository was archived by the owner on Jan 1, 2025. It is now read-only.

Commit 7f8b09b

Browse files
committed
CSS minifier
0 parents  commit 7f8b09b

File tree

6 files changed

+206
-0
lines changed

6 files changed

+206
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.o
2+
example.min.css
3+
minify
4+
*~

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright 2022 Pushkar Raj <px86@protonmail.com>
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CXX=g++
2+
CXXFLAGS=-Wall -Werror -Wpedantic -std=c++11
3+
LIBS=
4+
5+
minify: minify.cpp
6+
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
7+
8+
test: example.css minify
9+
./minify example.css example.min.css
10+
11+
clean:
12+
rm -rf example.min.css minify

README.org

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#+TITLE: Minify - A CSS minifier
2+
#+AUTHOR: Pushkar Raj
3+
#+DATE: [2022-02-03 Thu]
4+
5+
Remove comments and unnecessary whitespaces from a CSS file.
6+
7+
* Compilation
8+
9+
It's very simple.
10+
11+
#+begin_src shell
12+
g++ -std=c++11 -o minify minify.cpp
13+
#+end_src
14+
15+
or, if you have =GNU Make= installed, run =make= to compile the program, and =make test= for running the program on the =example.css= file.
16+
17+
#+begin_src shell
18+
make test
19+
#+end_src
20+
21+
* Usage
22+
23+
#+begin_src shell
24+
minify <path-to-a-css-file> <ouput-file-path>
25+
#+end_src

example.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Don't look, you will hurt your eye.
3+
It's horrible.
4+
*/
5+
6+
7+
8+
:root {
9+
margin: 0;
10+
padding: 0;
11+
box-sizing: border-box;
12+
font-size: 16px;
13+
14+
--font-serif:
15+
'Noto Serif', serif;
16+
--font-sans-serif: 'Lato',
17+
sans-serif;
18+
--font-monospace: 'Fantasque Sans Mono', monospace;
19+
20+
21+
22+
}
23+
24+
body ul li > a {
25+
background: var(--color-dark-primary);
26+
color: #ffffff;
27+
font-family: var(--font-sans-serif);
28+
min-height: 100vh;
29+
margin-left: 30ch;
30+
31+
32+
border : 0 0 10px black ;
33+
}

minify.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#include <cstdlib>
2+
#include <fstream>
3+
#include <iostream>
4+
#include <stdexcept>
5+
6+
auto read_file(const char *path) -> std::string;
7+
void minify_file(const char *, const char *);
8+
auto minify(const std::string &css) -> std::string;
9+
10+
int main(int argc, char **argv) {
11+
if (argc != 3) {
12+
std::cerr << "Usage: " << argv[0] << " CSSFILE OUTPUTFILE\n";
13+
return 1;
14+
}
15+
const char *filepath = argv[1];
16+
const char *outpath = argv[2];
17+
18+
// TODO: add support for optional OUTFILE, where output filename is derieved from the css filename.
19+
// Should print an error and exit if a file with the derieved name already exists.
20+
21+
minify_file(filepath, outpath);
22+
return 0;
23+
}
24+
25+
auto read_file(const char *path) -> std::string {
26+
constexpr auto read_size = std::size_t(4096); // <- Exactly what a typical modern C++ programmer would do.
27+
auto stream = std::ifstream(path);
28+
stream.exceptions(std::ios_base::badbit);
29+
30+
auto out = std::string();
31+
auto buf = std::string(read_size, '\0');
32+
while (stream.read(&buf[0], read_size)) {
33+
out.append(buf, 0, stream.gcount());
34+
}
35+
out.append(buf, 0, stream.gcount());
36+
37+
return out;
38+
}
39+
40+
void minify_file(const char *cssfilepath, const char *outfilepath) {
41+
auto css = read_file(cssfilepath);
42+
auto minicss = minify(css);
43+
auto out = std::ofstream(outfilepath);
44+
out << minicss;
45+
}
46+
47+
auto minify(const std::string& css) -> std::string {
48+
auto minicss = std::string();
49+
minicss.reserve(css.size());
50+
51+
bool last_was_space = true; // 'true' to deal with the whitespaces at the very beginning of the file.
52+
char c;
53+
try {
54+
for (size_t i = 0; i < css.size(); ++i) {
55+
c = css.at(i);
56+
switch (c) {
57+
case '\t':
58+
case ' ' :
59+
{
60+
// Replace a sequence of whitespaces with a single space character.
61+
// Note: make sure to set last_was_space to false, everywhere else where a not whitespace
62+
// character has been appended to 'minicss'.
63+
if (!last_was_space) {
64+
minicss += ' ';
65+
last_was_space = true;
66+
}
67+
} break;
68+
case '\n': break; // no newlines allowed!
69+
case ':':
70+
case ';':
71+
case ',':
72+
case '>':
73+
case '{':
74+
case '}':
75+
{
76+
// Make sure that no whitespace is present before the above characters.
77+
if (minicss.back() == ' ') minicss.back() = c;
78+
else minicss += c;
79+
// Consume all whitespace after the above characters.
80+
while (i < css.size()-1 && std::isspace(css.at(i+1))) i++;
81+
last_was_space = false;
82+
} break;
83+
case '\'':
84+
case '"' :
85+
{
86+
// Preseve the whitespaces in strings.
87+
// TODO: this fails if there is an escaped quote between the string. (Is it allowed?)
88+
minicss += c;
89+
while (i < css.size()-1 && css.at(++i) != c) minicss += css.at(i);
90+
minicss += c;
91+
last_was_space = false;
92+
} break;
93+
case '/' :
94+
{
95+
// Consume the comment.
96+
if (css.at(++i) == '*') {
97+
while (!(css.at(++i) == '*' && css.at(++i) == '/')) {}
98+
}
99+
else minicss += '/';
100+
} break;
101+
102+
default: minicss += c; last_was_space = false;
103+
}
104+
}
105+
} catch (std::out_of_range &e) {
106+
std::cerr << "Unexpected end of file reached, possible syntax error.\n";
107+
std::exit(1);
108+
}
109+
110+
minicss.shrink_to_fit();
111+
return minicss;
112+
}

0 commit comments

Comments
 (0)