Codebase list csstidy / 51d8761
Import Upstream version 1.2 HÃ¥vard Flaget Aasen 4 years ago
34 changed file(s) with 4277 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 GNU GENERAL PUBLIC LICENSE
1 Version 2, June 1991
2
3 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
4 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The licenses for most software are designed to take away your
11 freedom to share and change it. By contrast, the GNU General Public
12 License is intended to guarantee your freedom to share and change free
13 software--to make sure the software is free for all its users. This
14 General Public License applies to most of the Free Software
15 Foundation's software and to any other program whose authors commit to
16 using it. (Some other Free Software Foundation software is covered by
17 the GNU Library General Public License instead.) You can apply it to
18 your programs, too.
19
20 When we speak of free software, we are referring to freedom, not
21 price. Our General Public Licenses are designed to make sure that you
22 have the freedom to distribute copies of free software (and charge for
23 this service if you wish), that you receive source code or can get it
24 if you want it, that you can change the software or use pieces of it
25 in new free programs; and that you know you can do these things.
26
27 To protect your rights, we need to make restrictions that forbid
28 anyone to deny you these rights or to ask you to surrender the rights.
29 These restrictions translate to certain responsibilities for you if you
30 distribute copies of the software, or if you modify it.
31
32 For example, if you distribute copies of such a program, whether
33 gratis or for a fee, you must give the recipients all the rights that
34 you have. You must make sure that they, too, receive or can get the
35 source code. And you must show them these terms so they know their
36 rights.
37
38 We protect your rights with two steps: (1) copyright the software, and
39 (2) offer you this license which gives you legal permission to copy,
40 distribute and/or modify the software.
41
42 Also, for each author's protection and ours, we want to make certain
43 that everyone understands that there is no warranty for this free
44 software. If the software is modified by someone else and passed on, we
45 want its recipients to know that what they have is not the original, so
46 that any problems introduced by others will not reflect on the original
47 authors' reputations.
48
49 Finally, any free program is threatened constantly by software
50 patents. We wish to avoid the danger that redistributors of a free
51 program will individually obtain patent licenses, in effect making the
52 program proprietary. To prevent this, we have made it clear that any
53 patent must be licensed for everyone's free use or not licensed at all.
54
55 The precise terms and conditions for copying, distribution and
56 modification follow.
57
58 GNU GENERAL PUBLIC LICENSE
59 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
60
61 0. This License applies to any program or other work which contains
62 a notice placed by the copyright holder saying it may be distributed
63 under the terms of this General Public License. The "Program", below,
64 refers to any such program or work, and a "work based on the Program"
65 means either the Program or any derivative work under copyright law:
66 that is to say, a work containing the Program or a portion of it,
67 either verbatim or with modifications and/or translated into another
68 language. (Hereinafter, translation is included without limitation in
69 the term "modification".) Each licensee is addressed as "you".
70
71 Activities other than copying, distribution and modification are not
72 covered by this License; they are outside its scope. The act of
73 running the Program is not restricted, and the output from the Program
74 is covered only if its contents constitute a work based on the
75 Program (independent of having been made by running the Program).
76 Whether that is true depends on what the Program does.
77
78 1. You may copy and distribute verbatim copies of the Program's
79 source code as you receive it, in any medium, provided that you
80 conspicuously and appropriately publish on each copy an appropriate
81 copyright notice and disclaimer of warranty; keep intact all the
82 notices that refer to this License and to the absence of any warranty;
83 and give any other recipients of the Program a copy of this License
84 along with the Program.
85
86 You may charge a fee for the physical act of transferring a copy, and
87 you may at your option offer warranty protection in exchange for a fee.
88
89 2. You may modify your copy or copies of the Program or any portion
90 of it, thus forming a work based on the Program, and copy and
91 distribute such modifications or work under the terms of Section 1
92 above, provided that you also meet all of these conditions:
93
94 a) You must cause the modified files to carry prominent notices
95 stating that you changed the files and the date of any change.
96
97 b) You must cause any work that you distribute or publish, that in
98 whole or in part contains or is derived from the Program or any
99 part thereof, to be licensed as a whole at no charge to all third
100 parties under the terms of this License.
101
102 c) If the modified program normally reads commands interactively
103 when run, you must cause it, when started running for such
104 interactive use in the most ordinary way, to print or display an
105 announcement including an appropriate copyright notice and a
106 notice that there is no warranty (or else, saying that you provide
107 a warranty) and that users may redistribute the program under
108 these conditions, and telling the user how to view a copy of this
109 License. (Exception: if the Program itself is interactive but
110 does not normally print such an announcement, your work based on
111 the Program is not required to print an announcement.)
112
113 These requirements apply to the modified work as a whole. If
114 identifiable sections of that work are not derived from the Program,
115 and can be reasonably considered independent and separate works in
116 themselves, then this License, and its terms, do not apply to those
117 sections when you distribute them as separate works. But when you
118 distribute the same sections as part of a whole which is a work based
119 on the Program, the distribution of the whole must be on the terms of
120 this License, whose permissions for other licensees extend to the
121 entire whole, and thus to each and every part regardless of who wrote it.
122
123 Thus, it is not the intent of this section to claim rights or contest
124 your rights to work written entirely by you; rather, the intent is to
125 exercise the right to control the distribution of derivative or
126 collective works based on the Program.
127
128 In addition, mere aggregation of another work not based on the Program
129 with the Program (or with a work based on the Program) on a volume of
130 a storage or distribution medium does not bring the other work under
131 the scope of this License.
132
133 3. You may copy and distribute the Program (or a work based on it,
134 under Section 2) in object code or executable form under the terms of
135 Sections 1 and 2 above provided that you also do one of the following:
136
137 a) Accompany it with the complete corresponding machine-readable
138 source code, which must be distributed under the terms of Sections
139 1 and 2 above on a medium customarily used for software interchange; or,
140
141 b) Accompany it with a written offer, valid for at least three
142 years, to give any third party, for a charge no more than your
143 cost of physically performing source distribution, a complete
144 machine-readable copy of the corresponding source code, to be
145 distributed under the terms of Sections 1 and 2 above on a medium
146 customarily used for software interchange; or,
147
148 c) Accompany it with the information you received as to the offer
149 to distribute corresponding source code. (This alternative is
150 allowed only for noncommercial distribution and only if you
151 received the program in object code or executable form with such
152 an offer, in accord with Subsection b above.)
153
154 The source code for a work means the preferred form of the work for
155 making modifications to it. For an executable work, complete source
156 code means all the source code for all modules it contains, plus any
157 associated interface definition files, plus the scripts used to
158 control compilation and installation of the executable. However, as a
159 special exception, the source code distributed need not include
160 anything that is normally distributed (in either source or binary
161 form) with the major components (compiler, kernel, and so on) of the
162 operating system on which the executable runs, unless that component
163 itself accompanies the executable.
164
165 If distribution of executable or object code is made by offering
166 access to copy from a designated place, then offering equivalent
167 access to copy the source code from the same place counts as
168 distribution of the source code, even though third parties are not
169 compelled to copy the source along with the object code.
170
171 4. You may not copy, modify, sublicense, or distribute the Program
172 except as expressly provided under this License. Any attempt
173 otherwise to copy, modify, sublicense or distribute the Program is
174 void, and will automatically terminate your rights under this License.
175 However, parties who have received copies, or rights, from you under
176 this License will not have their licenses terminated so long as such
177 parties remain in full compliance.
178
179 5. You are not required to accept this License, since you have not
180 signed it. However, nothing else grants you permission to modify or
181 distribute the Program or its derivative works. These actions are
182 prohibited by law if you do not accept this License. Therefore, by
183 modifying or distributing the Program (or any work based on the
184 Program), you indicate your acceptance of this License to do so, and
185 all its terms and conditions for copying, distributing or modifying
186 the Program or works based on it.
187
188 6. Each time you redistribute the Program (or any work based on the
189 Program), the recipient automatically receives a license from the
190 original licensor to copy, distribute or modify the Program subject to
191 these terms and conditions. You may not impose any further
192 restrictions on the recipients' exercise of the rights granted herein.
193 You are not responsible for enforcing compliance by third parties to
194 this License.
195
196 7. If, as a consequence of a court judgment or allegation of patent
197 infringement or for any other reason (not limited to patent issues),
198 conditions are imposed on you (whether by court order, agreement or
199 otherwise) that contradict the conditions of this License, they do not
200 excuse you from the conditions of this License. If you cannot
201 distribute so as to satisfy simultaneously your obligations under this
202 License and any other pertinent obligations, then as a consequence you
203 may not distribute the Program at all. For example, if a patent
204 license would not permit royalty-free redistribution of the Program by
205 all those who receive copies directly or indirectly through you, then
206 the only way you could satisfy both it and this License would be to
207 refrain entirely from distribution of the Program.
208
209 If any portion of this section is held invalid or unenforceable under
210 any particular circumstance, the balance of the section is intended to
211 apply and the section as a whole is intended to apply in other
212 circumstances.
213
214 It is not the purpose of this section to induce you to infringe any
215 patents or other property right claims or to contest validity of any
216 such claims; this section has the sole purpose of protecting the
217 integrity of the free software distribution system, which is
218 implemented by public license practices. Many people have made
219 generous contributions to the wide range of software distributed
220 through that system in reliance on consistent application of that
221 system; it is up to the author/donor to decide if he or she is willing
222 to distribute software through any other system and a licensee cannot
223 impose that choice.
224
225 This section is intended to make thoroughly clear what is believed to
226 be a consequence of the rest of this License.
227
228 8. If the distribution and/or use of the Program is restricted in
229 certain countries either by patents or by copyrighted interfaces, the
230 original copyright holder who places the Program under this License
231 may add an explicit geographical distribution limitation excluding
232 those countries, so that distribution is permitted only in or among
233 countries not thus excluded. In such case, this License incorporates
234 the limitation as if written in the body of this License.
235
236 9. The Free Software Foundation may publish revised and/or new versions
237 of the General Public License from time to time. Such new versions will
238 be similar in spirit to the present version, but may differ in detail to
239 address new problems or concerns.
240
241 Each version is given a distinguishing version number. If the Program
242 specifies a version number of this License which applies to it and "any
243 later version", you have the option of following the terms and conditions
244 either of that version or of any later version published by the Free
245 Software Foundation. If the Program does not specify a version number of
246 this License, you may choose any version ever published by the Free Software
247 Foundation.
248
249 10. If you wish to incorporate parts of the Program into other free
250 programs whose distribution conditions are different, write to the author
251 to ask for permission. For software which is copyrighted by the Free
252 Software Foundation, write to the Free Software Foundation; we sometimes
253 make exceptions for this. Our decision will be guided by the two goals
254 of preserving the free status of all derivatives of our free software and
255 of promoting the sharing and reuse of software generally.
256
257 NO WARRANTY
258
259 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
260 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
261 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
262 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
263 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
264 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
265 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
266 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
267 REPAIR OR CORRECTION.
268
269 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
270 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
271 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
272 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
273 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
274 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
275 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
276 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
277 POSSIBILITY OF SUCH DAMAGES.
278
279 END OF TERMS AND CONDITIONS
280
281 How to Apply These Terms to Your New Programs
282
283 If you develop a new program, and you want it to be of the greatest
284 possible use to the public, the best way to achieve this is to make it
285 free software which everyone can redistribute and change under these terms.
286
287 To do so, attach the following notices to the program. It is safest
288 to attach them to the start of each source file to most effectively
289 convey the exclusion of warranty; and each file should have at least
290 the "copyright" line and a pointer to where the full notice is found.
291
292 <one line to give the program's name and a brief idea of what it does.>
293 Copyright (C) <year> <name of author>
294
295 This program is free software; you can redistribute it and/or modify
296 it under the terms of the GNU General Public License as published by
297 the Free Software Foundation; either version 2 of the License, or
298 (at your option) any later version.
299
300 This program is distributed in the hope that it will be useful,
301 but WITHOUT ANY WARRANTY; without even the implied warranty of
302 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
303 GNU General Public License for more details.
304
305 You should have received a copy of the GNU General Public License
306 along with this program; if not, write to the Free Software
307 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
308
309
310 Also add information on how to contact you by electronic and paper mail.
311
312 If the program is interactive, make it output a short notice like this
313 when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) year name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320 The hypothetical commands `show w' and `show c' should show the appropriate
321 parts of the General Public License. Of course, the commands you use may
322 be called something other than `show w' and `show c'; they could even be
323 mouse-clicks or menu items--whatever suits your program.
324
325 You should also get your employer (if you work as a programmer) or your
326 school, if any, to sign a "copyright disclaimer" for the program, if
327 necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 <signature of Ty Coon>, 1 April 1989
333 Ty Coon, President of Vice
334
335 This General Public License does not permit incorporating your program into
336 proprietary programs. If your program is a subroutine library, you may
337 consider it more useful to permit linking proprietary applications with the
338 library. If this is what you want to do, use the GNU Library General
339 Public License instead of this License.
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19 using namespace std;
20 extern map<string,string> background_prop_default;
21
22 map<string,string> dissolve_short_bg(string istring)
23 {
24 vector<string> repeat,attachment,clip,origin,pos,str_values;
25
26 repeat.push_back("repeat"); repeat.push_back("repeat-x"); repeat.push_back("repeat-y");
27 repeat.push_back("no-repeat"); repeat.push_back("space");
28 attachment.push_back("scroll"); attachment.push_back("fixed"); attachment.push_back("local");
29 clip.push_back("border"); clip.push_back("padding");
30 origin.push_back("border"); origin.push_back("padding"); origin.push_back("content");
31 pos.push_back("top"); pos.push_back("center"); pos.push_back("bottom"); pos.push_back("left"); pos.push_back("right");
32 string important = "";
33
34 map<string,string> ret;
35 map<string,bool> have;
36 ret["background-image"] = "";
37 ret["background-size"] = "";
38 ret["background-repeat"] = "";
39 ret["background-position"] = "";
40 ret["background-attachment"] = "";
41 ret["background-clip"] = "";
42 ret["background-origin"] = "";
43 ret["background-color"] = "";
44
45 if(is_important(istring))
46 {
47 important = " !important";
48 istring = gvw_important(istring);
49 }
50
51 str_values = explode_ws(',',istring);
52 for(int i = 0; i < str_values.size(); i++)
53 {
54 have["clip"] = false; have["pos"] = false;
55 have["color"] = false; have["bg"] = false;
56
57 vector<string> temp_values = explode_ws(' ',trim(str_values[i]));
58
59 for(int j = 0; j < temp_values.size(); j++)
60 {
61 if(have["bg"] == false && ((temp_values[j]).substr(0,4) == "url(" || temp_values[j] == "none"))
62 {
63 ret["background-image"] += temp_values[j];
64 ret["background-image"] += ",";
65 have["bg"] = true;
66 }
67 else if(in_str_array(repeat,temp_values[j]))
68 {
69 ret["background-repeat"] += temp_values[j];
70 ret["background-repeat"] += ",";
71 }
72 else if(in_str_array(attachment,temp_values[j]))
73 {
74 ret["background-attachment"] += temp_values[j];
75 ret["background-attachment"] += ",";
76 }
77 else if(in_str_array(clip,temp_values[j]) && !have["clip"])
78 {
79 ret["background-clip"] += temp_values[j];
80 ret["background-clip"] += ",";
81 have["clip"] = true;
82 }
83 else if(in_str_array(origin,temp_values[j]))
84 {
85 ret["background-origin"] += temp_values[j];
86 ret["background-origin"] += ",";
87 }
88 else if(temp_values[j][0] == '(')
89 {
90 ret["background-size"] += (temp_values[j]).substr(1,temp_values[j].length()-2);
91 ret["background-size"] += ",";
92 }
93 else if(in_str_array(pos,temp_values[j]) || isdigit(temp_values[j][0]) || temp_values[j][0] == 0)
94 {
95 ret["background-position"] += temp_values[j];
96 if(!have["pos"]) ret["background-position"] += " "; else ret["background-position"] += ",";
97 have["pos"] = true;
98 }
99 else if(!have["color"])
100 {
101 ret["background-color"] += temp_values[j];
102 ret["background-color"] += ",";
103 have["color"] = true;
104 }
105 }
106 }
107
108 for(map<string,string>::iterator it = background_prop_default.begin(); it != background_prop_default.end(); it++ )
109 {
110 if(ret[it->first] != "")
111 {
112 ret[it->first] = (ret[it->first]).substr(0,ret[it->first].length()-1);
113 ret[it->first] += important;
114 }
115 else
116 {
117 ret[it->first] = it->second;
118 ret[it->first] += important;
119 }
120 }
121
122 return ret;
123 }
124
125 vector<string> explode_ws(char sep,string istring)
126 {
127 // 1 = st // 2 = str
128 int status = 1;
129 char to;
130
131 vector<string> output;
132 output.push_back("");
133 int num = 0;
134 int len = istring.length();
135 for(int i = 0;i < len; i++)
136 {
137 switch(status)
138 {
139 case 1:
140 if(istring[i] == sep && !escaped(istring,i))
141 {
142 ++num;
143 output.push_back("");
144 }
145 else if(istring[i] == '"' || istring[i] == '\'' || istring[i] == '(' && !escaped(istring,i))
146 {
147 status = 2;
148 to = (istring[i] == '(') ? ')' : istring[i];
149 output[num] += istring[i];
150 }
151 else
152 {
153 output[num] += istring[i];
154 }
155 break;
156
157 case 2:
158 if(istring[i] == to && !escaped(istring,i))
159 {
160 status = 1;
161 }
162 output[num] += istring[i];
163 break;
164 }
165 }
166
167 return output;
168 }
169
170 void merge_bg(umap<string,string>& css_input)
171 {
172 // Max number of background images. CSS3 not yet fully implemented
173 int number_of_values = max((explode_ws(',',css_input["background-image"]).size()),(explode_ws(',',css_input["background-color"])).size());
174 // Array with background images to check if BG image exists
175 vector<string> bg_img_array = explode_ws(',',gvw_important(css_input["background-image"]));
176 string new_bg_value,important = "";
177
178 for(int i = 0; i < number_of_values; i++)
179 {
180 for(map<string,string>::iterator it = background_prop_default.begin(); it != background_prop_default.end(); it++ )
181 {
182 // Skip if property does not exist
183 if(!css_input.has(it->first))
184 {
185 continue;
186 }
187
188 string cur_value = css_input[it->first];
189
190 // Skip some properties if there is no background image
191 if((bg_img_array.size() <= i || bg_img_array[i] == "none")
192 && (it->first == "background-size" || it->first == "background-position"
193 || it->first == "background-attachment" || it->first == "background-repeat"))
194 {
195 continue;
196 }
197
198 // Remove !important
199 if(is_important(cur_value))
200 {
201 important = " !important";
202 cur_value = gvw_important(cur_value);
203 }
204
205 // Do not add default values
206 if(cur_value == it->second)
207 {
208 continue;
209 }
210
211 vector<string> temp = explode_ws(',',cur_value);
212
213 if(temp.size() > i)
214 {
215 if(it->first == "background-size")
216 {
217 new_bg_value += "(";
218 new_bg_value += temp[i];
219 new_bg_value += ") ";
220 }
221 else
222 {
223 new_bg_value += temp[i];
224 new_bg_value += " ";
225 }
226 }
227 }
228
229 new_bg_value = trim(new_bg_value);
230 if(i != number_of_values-1) new_bg_value += ",";
231 }
232
233 // Delete all background-properties
234 for(map<string,string>::iterator it = background_prop_default.begin(); it != background_prop_default.end(); it++ )
235 {
236 css_input.erase(it->first);
237 }
238
239 // Add new background property
240 if(new_bg_value != "")
241 {
242 css_input["background"] = new_bg_value + important;
243 }
244 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_BACKGROUND
19 #define HEADER_CSS_BACKGROUND
20
21 // Dissolves the background property
22 map<string,string> dissolve_short_bg(const string istring);
23
24 // Same as explode, but not within a string
25 vector<string> explode_ws(char sep,string istring);
26
27 void merge_bg(umap<string,string>& css_input);
28
29 #endif // HEADER_CSS_BACKGROUND
0 g++ -g3 background.cpp -g3 conversions.cpp -g3 csstidy.cpp -g3 cssopt.cpp -g3 file_functions.cpp -g3 important.cpp -g3 main.cpp -g3 misc.cpp -g3 parse_css.cpp -g3 print_css.cpp -g3 prepare.cpp -g3 trim.cpp -o csstidy
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19
20 string strtolower(string istring)
21 {
22 int str_size = istring.length();
23 for(int i = 0; i < str_size; i++)
24 {
25 istring[i] = chartolower(istring[i]);
26 }
27 return istring;
28 }
29
30 char chartolower(const char c)
31 {
32 switch(c)
33 {
34 case 'A': return 'a';
35 case 'B': return 'b';
36 case 'C': return 'c';
37 case 'D': return 'd';
38 case 'E': return 'e';
39 case 'F': return 'f';
40 case 'G': return 'g';
41 case 'H': return 'h';
42 case 'I': return 'i';
43 case 'J': return 'j';
44 case 'K': return 'k';
45 case 'L': return 'l';
46 case 'M': return 'm';
47 case 'N': return 'n';
48 case 'O': return 'o';
49 case 'P': return 'p';
50 case 'Q': return 'q';
51 case 'R': return 'r';
52 case 'S': return 's';
53 case 'T': return 't';
54 case 'U': return 'u';
55 case 'V': return 'v';
56 case 'W': return 'w';
57 case 'X': return 'x';
58 case 'Y': return 'y';
59 case 'Z': return 'z';
60 default: return c;
61 }
62 }
63
64 string strtoupper(string istring)
65 {
66 int str_size = istring.length();
67 for(int i = 0; i < str_size; i++)
68 {
69 istring[i] = chartoupper(istring[i]);
70 }
71 return istring;
72 }
73
74 char chartoupper(const char c)
75 {
76 switch(c)
77 {
78 case 'a': return 'A';
79 case 'b': return 'B';
80 case 'c': return 'C';
81 case 'd': return 'D';
82 case 'e': return 'E';
83 case 'f': return 'F';
84 case 'g': return 'G';
85 case 'h': return 'H';
86 case 'i': return 'I';
87 case 'j': return 'J';
88 case 'k': return 'K';
89 case 'l': return 'L';
90 case 'm': return 'M';
91 case 'n': return 'N';
92 case 'o': return 'O';
93 case 'p': return 'P';
94 case 'q': return 'Q';
95 case 'r': return 'R';
96 case 's': return 'S';
97 case 't': return 'T';
98 case 'u': return 'U';
99 case 'v': return 'V';
100 case 'w': return 'W';
101 case 'x': return 'X';
102 case 'y': return 'Y';
103 case 'z': return 'Z';
104 default: return c;
105 }
106 }
107
108 /* Didn't find any usable function for this, so here is my version :) */
109 string dechex(const int i)
110 {
111 stringstream sstream;
112 sstream << hex << i;
113 return sstream.str();
114 }
115
116 double hexdec(string istring)
117 {
118 double ret = 0;
119 istring = trim(istring);
120 for(int i = istring.length()-1; i >= 0; --i)
121 {
122 int num = 0;
123 switch(tolower(istring[i]))
124 {
125 case 'a': num = 10; break;
126 case 'b': num = 11; break;
127 case 'c': num = 12; break;
128 case 'd': num = 13; break;
129 case 'e': num = 14; break;
130 case 'f': num = 15; break;
131 case '1': num = 1; break;
132 case '2': num = 2; break;
133 case '3': num = 3; break;
134 case '4': num = 4; break;
135 case '5': num = 5; break;
136 case '6': num = 6; break;
137 case '7': num = 7; break;
138 case '8': num = 8; break;
139 case '9': num = 9; break;
140 case '0': num = 0; break;
141 }
142 ret += num*pow((double) 16, (double) istring.length()-i-1);
143 }
144 return ret;
145 }
146
147 string f2str(const float f)
148 {
149 stringstream sstream;
150 sstream << f;
151 return sstream.str();
152 }
153
154 float str2f(const string istring)
155 {
156 return atof(istring.c_str());
157 }
158
159 string char2str(const char c)
160 {
161 string ret = "";
162 ret += c;
163 return ret;
164 }
165
166 string char2str(const char *c)
167 {
168 stringstream sstream;
169 sstream << c;
170 return sstream.str();
171 }
172
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_CONVERT
19 #define HEADER_CSS_CONVERT
20
21 // Returns the lowercase version of a string
22 string strtolower(string istring);
23 // Apparently faster replacement for tolower
24 char chartolower(const char c);
25
26 // Returns the uppercase version of a string
27 string strtoupper(string istring);
28 char chartoupper(const char c);
29
30 // Converts an integer to a hex-string
31 string dechex(const int i);
32
33 // Converts a hexadecimal number (string) to a decimal number
34 double hexdec(string istring);
35
36 // Converts float to string
37 string f2str(const float f);
38
39 // Converts a string to float
40 float str2f(const string istring);
41
42 // Converts a char to a string
43 string char2str(const char c);
44
45 #endif // HEADER_CSS_CONVERT
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19 using namespace std;
20
21 extern vector<string> number_values,color_values;
22 extern map<string,string> replace_colors,all_properties;
23
24 string shorthand(string value)
25 {
26 string important = "";
27
28 if(is_important(value))
29 {
30 value = gvw_important(value);
31 important = " !important";
32 }
33
34 vector<string> values = explode(" ",value);
35 switch(values.size())
36 {
37 case 4:
38 if(values[0] == values[1] && values[0] == values[2] && values[0] == values[3])
39 {
40 return values[0] + important;
41 }
42 else if(values[1] == values[3] && values[0] == values[2])
43 {
44 return values[0] + " " + values[1] + important;
45 }
46 else if(values[1] == values[3])
47 {
48 return values[0] + " " + values[1] + " " + values[2] + important;
49 }
50 else return value + important;
51 break;
52
53 case 3:
54 if(values[0] == values[1] && values[0] == values[2])
55 {
56 return values[0] + important;
57 }
58 else if(values[0] == values[2])
59 {
60 return values[0] + " " + values[1] + important;
61 }
62 else return value + important;
63 break;
64
65 case 2:
66 if(values[0] == values[1])
67 {
68 return values[0] + important;
69 }
70 else return value + important;
71 break;
72
73 default:
74 return value + important;
75 }
76 }
77
78 string compress_numbers(string subvalue, string property)
79 {
80 string units[] = {"in", "cm", "mm", "pt", "pc", "px", "rem", "%", "ex", "gd", "em", "vw", "vh",
81 "vm", "deg", "grad", "rad", "ms", "s", "khz", "hz" }; // sync for loop
82
83 vector<string> temp;
84 if(property == "font")
85 {
86 temp = explode("/",subvalue);
87 }
88 else
89 {
90 temp.push_back(subvalue);
91 }
92
93 for (int i = 0; i < temp.size(); ++i)
94 {
95 if(!(temp[i].length() > 0 && (ctype_digit(temp[i][0]) || temp[i][0] == '+' || temp[i][0] == '-' ) ))
96 {
97 continue;
98 }
99
100 if(in_str_array(color_values,property))
101 {
102 temp[i] = "#" + temp[i];
103 }
104
105 if(str2f(temp[i]) == 0)
106 {
107 temp[i] = "0";
108 }
109 else
110 {
111 bool unit_found = false;
112 temp[i] = strtolower(temp[i]);
113 for(int j = 0; j < 21; ++j )
114 {
115 if(temp[i].find(units[j]) != string::npos)
116 {
117 temp[i] = f2str(str2f(temp[i])) + units[j];
118 unit_found = true;
119 break;
120 }
121 }
122 if(!unit_found && !in_str_array(number_values,property))
123 {
124 temp[i] = f2str(str2f(temp[i]));
125 temp[i] += "px";
126 }
127 else if(!unit_found)
128 {
129 temp[i] = f2str(str2f(temp[i]));
130 }
131 }
132 }
133 return (temp.size() > 1) ? temp[0] + "/" + temp[1] : temp[0];
134 }
135
136 bool property_is_next(string istring, int pos)
137 {
138 istring = istring.substr(pos,istring.length()-pos);
139 pos = istring.find_first_of(':',0);
140 if(pos == string::npos)
141 {
142 return false;
143 }
144 istring = strtolower(trim(istring.substr(0,pos)));
145 return (all_properties.count(istring) > 0);
146 }
147
148 string cut_color(string color)
149 {
150 if(strtolower(color.substr(0,4)) == "rgb(")
151 {
152 vector<string> color_tmp = explode(",",color.substr(4,color.length()-5));
153
154 for (int i = 0; i < color_tmp.size(); ++i)
155 {
156 color_tmp[i] = trim(color_tmp[i]);
157 if(color_tmp[i].at(color_tmp[i].length()-1) == '%')
158 {
159 color_tmp[i] = f2str(round(255 * atoi(color_tmp[i].c_str())/100,0));
160 }
161 if(atoi(color_tmp[i].c_str()) > 255) color_tmp[i] = 255;
162 }
163
164 color = "#";
165 for (int i = 0; i < color_tmp.size(); ++i)
166 {
167 if(atoi(color_tmp[i].c_str()) < 16)
168 {
169 color += "0" + dechex(atoi(color_tmp[i].c_str()));
170 }
171 else
172 {
173 color += dechex(atoi(color_tmp[i].c_str()));
174 }
175 }
176 }
177
178 // Fix bad color names
179 if(replace_colors.count(strtolower(color)) > 0)
180 {
181 color = replace_colors[strtolower(color)];
182 }
183
184 if(color.length() == 7)
185 {
186 string color_temp = strtoupper(color);
187
188 if(color_temp[0] == '#' && color_temp[1] == color_temp[2] && color_temp[3] == color_temp[4] && color_temp[5] == color_temp[6])
189 {
190 color = "#";
191 color += color_temp[2];
192 color += color_temp[3];
193 color += color_temp[5];
194 }
195 }
196
197 string temp = strtolower(color);
198 /* color name -> hex code */
199 if(temp == "black") return "#000";
200 if(temp == "fuchsia") return "#F0F";
201 if(temp == "white") return "#FFF";
202 if(temp == "yellow") return "#FF0";
203 /* hex code -> color name */
204 if(temp == "#800000") return "maroon";
205 if(temp == "#ffa500") return "orange";
206 if(temp == "#808000") return "olive";
207 if(temp == "#800080") return "purple";
208 if(temp == "#008000") return "green";
209 if(temp == "#000080") return "navy";
210 if(temp == "#008080") return "teal";
211 if(temp == "#c0c0c0") return "silver";
212 if(temp == "#808080") return "gray";
213 if(temp == "#f00") return "red";
214
215 return color;
216 }
217
218 int c_font_weight(string& value)
219 {
220 string important = "";
221 if(is_important(value))
222 {
223 important = " !important";
224 value = gvw_important(value);
225 }
226 if(value == "bold")
227 {
228 value = "700"+important;
229 return 700;
230 }
231 else if(value == "normal")
232 {
233 value = "400"+important;
234 return 400;
235 }
236 return 0;
237 }
238
239
240 void merge_selectors(sstore& input)
241 {
242 for(sstore::iterator i = input.begin(), e = input.end(); i != e;)
243 {
244 string newsel = "";
245
246 // Check if properties also exist in another selector
247 vector<string> keys;
248 for(sstore::iterator j = input.begin(); j != input.end(); j++ )
249 {
250 if(j->first == i->first)
251 {
252 continue;
253 }
254
255 if(input[j->first] == input[i->first])
256 {
257 keys.push_back(j->first);
258 }
259 }
260
261 if(keys.size() > 0)
262 {
263 newsel = i->first;
264
265 for(int k = 0; k < keys.size(); ++k)
266 {
267 input.erase(keys[k]);
268 newsel += "," + keys[k];
269 }
270
271 input[newsel] = i->second;
272
273 input.erase(i);
274 e = input.end();
275 } else {
276 i++;
277 }
278 }
279 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_OPT
19 #define HEADER_CSS_OPT
20
21 // Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces color names and codes.
22 string cut_color(string color);
23
24 // Compresses shorthand values. Example: margin:1px 1px 1px 1px -> margin:1px
25 string shorthand(string value);
26
27 // Compresses numbers (ie. 1.0 -> 1 or 1.100 -> 1.1
28 string compress_numbers(string subvalue, string property = "");
29
30 // Checks if the next word in a string from pos is a CSS property
31 bool property_is_next(string istring, const int pos);
32
33 // Compress font-weight
34 int c_font_weight(string& value);
35
36 // Merges selectors which have the same properties
37 void merge_selectors(sstore& input);
38
39 #endif // HEADER_CSS_OPT
(New empty file)
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #define CSSTIDY_VERSION "1.2"
19 #include <cstdlib>
20 #include <string>
21 #include <iterator>
22 #include <vector>
23 #include <math.h>
24 #include <time.h>
25 #include <sstream>
26 #include <iostream>
27 #include <fstream>
28 #include <map>
29 #include <algorithm>
30
31 #include "umap.hpp"
32 #include "datastruct.hpp"
33
34 #include "trim.hpp"
35 #include "conversions.hpp"
36 #include "misc.hpp"
37 #include "important.hpp"
38 #include "file_functions.hpp"
39
40 #include "cssopt.hpp"
41 #include "csstidy.hpp"
42
43 #include "parse_css.hpp"
44 #include "background.hpp"
0 /* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
1 /* DO NOT EDIT ! */
2
3 #ifndef CSSPP_PRIVATE_H
4 #define CSSPP_PRIVATE_H
5
6 /* VERSION DEFINITIONS */
7 #define VER_STRING "1.2.0.2230"
8 #define VER_MAJOR 1
9 #define VER_MINOR 2
10 #define VER_RELEASE 0
11 #define VER_BUILD 2230
12 #define COMPANY_NAME ""
13 #define FILE_VERSION "1.2"
14 #define FILE_DESCRIPTION "CSS Parser and Optimiser"
15 #define INTERNAL_NAME ""
16 #define LEGAL_COPYRIGHT ""
17 #define LEGAL_TRADEMARKS ""
18 #define ORIGINAL_FILENAME ""
19 #define PRODUCT_NAME "CSSTidy"
20 #define PRODUCT_VERSION "1.2"
21
22 #endif /*CSSPP_PRIVATE_H*/
0 /* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
1 /* DO NOT EDIT! */
2
3 #include <windows.h> // include for version info constants
4
5
6 //
7 // TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS...
8 //
9 1 VERSIONINFO
10 FILEVERSION 1,2,0,2230
11 PRODUCTVERSION 1,2,0,2230
12 FILETYPE VFT_APP
13 {
14 BLOCK "StringFileInfo"
15 {
16 BLOCK "080904E4"
17 {
18 VALUE "CompanyName", ""
19 VALUE "FileVersion", "1.2"
20 VALUE "FileDescription", "CSS Parser and Optimiser"
21 VALUE "InternalName", ""
22 VALUE "LegalCopyright", ""
23 VALUE "LegalTrademarks", ""
24 VALUE "OriginalFilename", ""
25 VALUE "ProductName", "CSSTidy"
26 VALUE "ProductVersion", "1.2"
27 }
28 }
29 BLOCK "VarFileInfo"
30 {
31 VALUE "Translation", 0x0809, 1252
32 }
33 }
34
Binary diff not shown
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19 extern map< string, vector<string> > shorthands;
20
21 csstidy::csstidy()
22 {
23 properties = 0;
24 selectors = 0;
25 charset = "";
26 namesp = "";
27 line = 1;
28 tokens = "{};:()@='\"/,\\!$%&*+.<>?[]^`|~";
29 css_level = "CSS2.1";
30
31 settings["remove_bslash"] = 1;
32 settings["compress_colors"] = 1;
33 settings["compress_font-weight"] = 1;
34 settings["lowercase_s"] = 0;
35 settings["optimise_shorthands"] = 1;
36 settings["remove_last_;"] = 0;
37 settings["case_properties"] = 0;
38 settings["sort_properties"] = 0;
39 settings["sort_selectors"] = 0;
40 settings["merge_selectors"] = 2;
41 settings["discard_invalid_properties"] = 0;
42 settings["allow_html_in_templates"] = 0;
43 settings["silent"] = 0;
44 settings["preserve_css"] = 0;
45 settings["timestamp"] = 0;
46
47 csstemplate.push_back("<span class=\"at\">"); //string before @rule
48 csstemplate.push_back("</span> <span class=\"format\">{</span>\n"); //bracket after @-rule
49 csstemplate.push_back("<span class=\"selector\">"); //string before selector
50 csstemplate.push_back("</span> <span class=\"format\">{</span>\n"); //bracket after selector
51 csstemplate.push_back("<span class=\"property\">"); //string before property
52 csstemplate.push_back("</span><span class=\"value\">"); //string after property+before value
53 csstemplate.push_back("</span><span class=\"format\">;</span>\n"); //string after value
54 csstemplate.push_back("<span class=\"format\">}</span>"); //closing bracket - selector
55 csstemplate.push_back("\n\n"); //space between blocks {...}
56 csstemplate.push_back("\n<span class=\"format\">}</span>\n\n"); //closing bracket @-rule
57 csstemplate.push_back(""); //indent in @-rule
58 csstemplate.push_back("<span class=\"comment\">"); // before comment
59 csstemplate.push_back("</span>\n"); //after comment
60 csstemplate.push_back("\n"); // after last line @-rule
61 }
62
63 void csstidy::add_token(const token_type ttype, const string data, const bool force)
64 {
65 if(settings["preserve_css"] || force) {
66 token temp;
67 temp.type = ttype;
68 temp.data = (ttype == COMMENT) ? data : trim(data);
69 csstokens.push_back(temp);
70 }
71 }
72
73 void csstidy::copy(const string media, const string selector, const string media_new, const string selector_new)
74 {
75 for(int k = 0; k < css[media][selector].size(); k++)
76 {
77 string property = css[media][selector].at(k);
78 string value = css[media][selector][property];
79 add(media_new,selector_new,property,value);
80 }
81 }
82
83 void csstidy::add(const string& media, const string& selector, const string& property, const string& value)
84 {
85 if(settings["preserve_css"]) {
86 return;
87 }
88
89 if(css[media][selector].has(property))
90 {
91 if( !is_important(css[media][selector][property]) || (is_important(css[media][selector][property]) && is_important(value)) )
92 {
93 css[media][selector].erase(property);
94 css[media][selector][property] = trim(value);
95 }
96 }
97 else
98 {
99 css[media][selector][property] = trim(value);
100 }
101 }
102
103 void csstidy::log(const string msg, const message_type type, int iline)
104 {
105 message new_msg;
106 new_msg.m = msg;
107 new_msg.t = type;
108 if(iline == 0)
109 {
110 iline = line;
111 }
112 if(logs.count(line) > 0)
113 {
114 for(int i = 0; i < logs[line].size(); ++i)
115 {
116 if(logs[line][i].m == new_msg.m && logs[line][i].t == new_msg.t)
117 {
118 return;
119 }
120 }
121 }
122 logs[line].push_back(new_msg);
123 }
124
125 string csstidy::unicode(string& istring,int& i)
126 {
127 ++i;
128 string add = "";
129 bool replaced = false;
130
131 while(i < istring.length() && (ctype_xdigit(istring[i]) || ctype_space(istring[i])) && add.length()< 6)
132 {
133 add += istring[i];
134
135 if(ctype_space(istring[i]))
136 {
137 break;
138 }
139 i++;
140 }
141
142 if(hexdec(add) > 47 && hexdec(add) < 58 || hexdec(add) > 64 && hexdec(add) < 91 || hexdec(add) > 96 && hexdec(add) < 123)
143 {
144 string msg = "Replaced unicode notation: Changed \\" + rtrim(add) + " to ";
145 add = static_cast<int>(hexdec(add));
146 msg += add;
147 log(msg,Information);
148 replaced = true;
149 }
150 else
151 {
152 add = trim("\\" + add);
153 }
154
155 if(ctype_xdigit(istring[i+1]) && ctype_space(istring[i]) && !replaced || !ctype_space(istring[i]))
156 {
157 i--;
158 }
159
160 if(add != "\\" || !settings["remove_bslash"] || in_str_array(tokens,istring[i+1]))
161 {
162 return add;
163 }
164 if(add == "\\")
165 {
166 log("Removed unnecessary backslash",Information);
167 }
168 return "";
169 }
170
171 bool csstidy::is_token(string& istring,const int i)
172 {
173 return (in_str_array(tokens,istring[i]) && !escaped(istring,i));
174 }
175
176 void csstidy::merge_4value_shorthands(string media, string selector)
177 {
178 for(map< string, vector<string> >::iterator i = shorthands.begin(); i != shorthands.end(); ++i )
179 {
180 string temp;
181
182 if(css[media][selector].has(i->second[0]) && css[media][selector].has(i->second[1])
183 && css[media][selector].has(i->second[2]) && css[media][selector].has(i->second[3]))
184 {
185 string important = "";
186 for(int j = 0; j < 4; ++j)
187 {
188 string val = css[media][selector][i->second[j]];
189 if(is_important(val))
190 {
191 important = " !important";
192 temp += gvw_important(val)+ " ";
193 }
194 else
195 {
196 temp += val + " ";
197 }
198 css[media][selector].erase(i->second[j]);
199 }
200 add(media, selector, i->first, shorthand(trim(temp + important)));
201 }
202 }
203 }
204
205 map<string,string> csstidy::dissolve_4value_shorthands(string property, string value)
206 {
207 map<string, string> ret;
208 extern map< string, vector<string> > shorthands;
209
210 if(shorthands[property][0] == "0")
211 {
212 ret[property] = value;
213 return ret;
214 }
215
216 string important = "";
217 if(is_important(value))
218 {
219 value = gvw_important(value);
220 important = " !important";
221 }
222 vector<string> values = explode(" ",value);
223
224 if(values.size() == 4)
225 {
226 for(int i=0; i < 4; ++i)
227 {
228 ret[shorthands[property][i]] = values[i] + important;
229 }
230 }
231 else if(values.size() == 3)
232 {
233 ret[shorthands[property][0]] = values[0] + important;
234 ret[shorthands[property][1]] = values[1] + important;
235 ret[shorthands[property][3]] = values[1] + important;
236 ret[shorthands[property][2]] = values[2] + important;
237 }
238 else if(values.size() == 2)
239 {
240 for(int i = 0; i < 4; ++i)
241 {
242 ret[shorthands[property][i]] = ((i % 2 != 0)) ? values[1] + important : values[0] + important;
243 }
244 }
245 else
246 {
247 for(int i = 0; i < 4; ++i)
248 {
249 ret[shorthands[property][i]] = values[0] + important;
250 }
251 }
252
253 return ret;
254 }
255
256 void csstidy::explode_selectors()
257 {
258 // Explode multiple selectors
259 if (settings["merge_selectors"] == 1)
260 {
261 vector<string> new_sels;
262 int lastpos = 0;
263 sel_separate.push_back(cur_selector.length());
264
265 for (int i = 0; i < sel_separate.size(); ++i)
266 {
267 if (i == sel_separate.size()-1) {
268 sel_separate[i] += 1;
269 }
270
271 new_sels.push_back(cur_selector.substr(lastpos,sel_separate[i]-lastpos-1));
272 lastpos = sel_separate[i];
273 }
274
275 if (new_sels.size() > 1)
276 {
277 for (int i = 0; i < new_sels.size(); ++i)
278 {
279 for (pstore::iterator j = css[cur_at][cur_selector].begin(); j != css[cur_at][cur_selector].end(); ++j)
280 {
281 add(cur_at, new_sels[i], j->first, j->second);
282 }
283 }
284 css[cur_at].erase(cur_selector);
285 }
286 }
287 sel_separate = vector<int>();
288 }
0 [Project]
1 FileName=csstidy.dev
2 Name=csstidy
3 UnitCount=26
4 Type=1
5 Ver=1
6 ObjFiles=
7 Includes=
8 Libs=
9 PrivateResource=csspp_private.rc
10 ResourceIncludes=
11 MakeIncludes=
12 Compiler=
13 CppCompiler=
14 Linker=
15 IsCpp=1
16 Icon=
17 ExeOutput=
18 ObjectOutput=
19 OverrideOutput=0
20 OverrideOutputName=csstidy.exe
21 HostApplication=
22 Folders=
23 CommandLine=test.txt
24 UseCustomMakefile=0
25 CustomMakefile=
26 IncludeVersionInfo=1
27 SupportXPThemes=0
28 CompilerSet=0
29 CompilerSettings=1000000001000101000000
30
31 [Unit1]
32 FileName=main.cpp
33 CompileCpp=1
34 Folder=
35 Compile=1
36 Link=1
37 Priority=1000
38 OverrideBuildCmd=0
39 BuildCmd=
40
41 [VersionInfo]
42 Major=1
43 Minor=2
44 Release=0
45 Build=2230
46 LanguageID=2057
47 CharsetID=1252
48 CompanyName=
49 FileVersion=1.2
50 FileDescription=CSS Parser and Optimiser
51 InternalName=
52 LegalCopyright=
53 LegalTrademarks=
54 OriginalFilename=
55 ProductName=CSSTidy
56 ProductVersion=1.2
57 AutoIncBuildNr=1
58
59 [Unit2]
60 FileName=datastruct.hpp
61 CompileCpp=1
62 Folder=
63 Compile=1
64 Link=1
65 Priority=1000
66 OverrideBuildCmd=0
67 BuildCmd=
68
69 [Unit5]
70 FileName=cssopt.hpp
71 CompileCpp=1
72 Folder=
73 Compile=1
74 Link=1
75 Priority=1000
76 OverrideBuildCmd=0
77 BuildCmd=
78
79 [Unit6]
80 FileName=important.hpp
81 CompileCpp=1
82 Folder=
83 Compile=1
84 Link=1
85 Priority=1000
86 OverrideBuildCmd=0
87 BuildCmd=
88
89 [Unit8]
90 FileName=csspp_globals.hpp
91 CompileCpp=1
92 Folder=
93 Compile=1
94 Link=1
95 Priority=1000
96 OverrideBuildCmd=0
97 BuildCmd=
98
99 [Unit9]
100 FileName=trim.cpp
101 CompileCpp=1
102 Folder=
103 Compile=1
104 Link=1
105 Priority=1000
106 OverrideBuildCmd=0
107 BuildCmd=
108
109 [Unit11]
110 FileName=file_functions.cpp
111 CompileCpp=1
112 Folder=
113 Compile=1
114 Link=1
115 Priority=1000
116 OverrideBuildCmd=0
117 BuildCmd=
118
119 [Unit12]
120 FileName=print_css.cpp
121 CompileCpp=1
122 Folder=
123 Compile=1
124 Link=1
125 Priority=1000
126 OverrideBuildCmd=0
127 BuildCmd=
128
129 [Unit13]
130 FileName=conversions.hpp
131 CompileCpp=1
132 Folder=
133 Compile=1
134 Link=1
135 Priority=1000
136 OverrideBuildCmd=0
137 BuildCmd=
138
139 [Unit14]
140 FileName=conversions.cpp
141 CompileCpp=1
142 Folder=
143 Compile=1
144 Link=1
145 Priority=1000
146 OverrideBuildCmd=0
147 BuildCmd=
148
149 [Unit15]
150 FileName=misc.cpp
151 CompileCpp=1
152 Folder=
153 Compile=1
154 Link=1
155 Priority=1000
156 OverrideBuildCmd=0
157 BuildCmd=
158
159 [Unit16]
160 FileName=cssopt.cpp
161 CompileCpp=1
162 Folder=
163 Compile=1
164 Link=1
165 Priority=1000
166 OverrideBuildCmd=0
167 BuildCmd=
168
169 [Unit17]
170 FileName=parse_css.cpp
171 CompileCpp=1
172 Folder=
173 Compile=1
174 Link=1
175 Priority=1000
176 OverrideBuildCmd=0
177 BuildCmd=
178
179 [Unit18]
180 FileName=csspp_globals.cpp
181 CompileCpp=1
182 Folder=
183 Compile=1
184 Link=1
185 Priority=1000
186 OverrideBuildCmd=0
187 BuildCmd=
188
189 [Unit19]
190 FileName=prepare.hpp
191 CompileCpp=1
192 Folder=
193 Compile=1
194 Link=1
195 Priority=1000
196 OverrideBuildCmd=0
197 BuildCmd=
198
199 [Unit21]
200 FileName=background.hpp
201 CompileCpp=1
202 Folder=
203 Compile=1
204 Link=1
205 Priority=1000
206 OverrideBuildCmd=0
207 BuildCmd=
208
209 [Unit22]
210 FileName=background.cpp
211 CompileCpp=1
212 Folder=
213 Compile=1
214 Link=1
215 Priority=1000
216 OverrideBuildCmd=0
217 BuildCmd=
218
219 [Unit10]
220 FileName=trim.hpp
221 CompileCpp=1
222 Folder=
223 Compile=1
224 Link=1
225 Priority=1000
226 OverrideBuildCmd=0
227 BuildCmd=
228
229 [Unit23]
230 FileName=umap.cpp
231 CompileCpp=1
232 Folder=
233 Compile=1
234 Link=1
235 Priority=1000
236 OverrideBuildCmd=0
237 BuildCmd=
238
239 [Unit24]
240 FileName=umap.hpp
241 CompileCpp=1
242 Folder=
243 Compile=1
244 Link=1
245 Priority=1000
246 OverrideBuildCmd=0
247 BuildCmd=
248
249 [Unit25]
250 FileName=csstidy.hpp
251 CompileCpp=1
252 Folder=
253 Compile=1
254 Link=1
255 Priority=1000
256 OverrideBuildCmd=0
257 BuildCmd=
258
259 [Unit26]
260 FileName=csstidy.cpp
261 CompileCpp=1
262 Folder=
263 Compile=1
264 Link=1
265 Priority=1000
266 OverrideBuildCmd=0
267 BuildCmd=
268
269 [Unit27]
270 FileName=csstidy.cpp
271 CompileCpp=1
272 Folder=
273 Compile=1
274 Link=1
275 Priority=1000
276 OverrideBuildCmd=0
277 BuildCmd=
278
279 [Unit3]
280 FileName=file_functions.hpp
281 CompileCpp=1
282 Folder=
283 Compile=1
284 Link=1
285 Priority=1000
286 OverrideBuildCmd=0
287 BuildCmd=
288
289 [Unit4]
290 FileName=misc.hpp
291 CompileCpp=1
292 Folder=
293 Compile=1
294 Link=1
295 Priority=1000
296 OverrideBuildCmd=0
297 BuildCmd=
298
299 [Unit29]
300 FileName=csstidy_print.cpp
301 CompileCpp=1
302 Folder=
303 Compile=1
304 Link=1
305 Priority=1000
306 OverrideBuildCmd=0
307 BuildCmd=
308
309 [Unit20]
310 FileName=prepare.cpp
311 CompileCpp=1
312 Folder=
313 Compile=1
314 Link=1
315 Priority=1000
316 OverrideBuildCmd=0
317 BuildCmd=
318
319 [Unit7]
320 FileName=important.cpp
321 CompileCpp=1
322 Folder=
323 Compile=1
324 Link=1
325 Priority=1000
326 OverrideBuildCmd=0
327 BuildCmd=
328
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSSTIDY
19 #define HEADER_CSSTIDY
20
21 class csstidy
22 {
23 public:
24 int properties,selectors,input_size,output_size;
25 string charset,namesp, css_level;
26 vector<string> import, csstemplate;
27 map<int, vector<message> > logs;
28 map<string, int> settings;
29
30 private:
31 css_struct css;
32 vector<token> csstokens;
33 string tokens, cur_selector, cur_at, cur_property, cur_sub_value, cur_value;
34 int line;
35 vector<int> sel_separate;
36
37 void add_token(const token_type ttype, const string data, const bool force = false);
38 void _convert_raw_css();
39
40 // Add a message to the message log
41 void log(const string msg, const message_type type, int iline = 0);
42
43 int _seeknocomment(const int key, const int move);
44 string _htmlsp(const string istring, const bool plain);
45 string optimise_subvalue(string subvalue, const string property);
46 void explode_selectors();
47
48 // Parses unicode notations
49 string unicode(string& istring,int& i);
50
51 // Checks if the chat in istring at i is a token
52 bool is_token(string& istring,const int i);
53
54 public:
55 csstidy();
56
57 // Adds a property-value pair to an existing CSS structure
58 void add(const string& media, const string& selector, const string& property, const string& value);
59 void copy(const string media, const string selector, const string media_new, const string selector_new);
60
61 // Prints CSS code
62 void print_css(string filename = "");
63
64 // Parse a piece of CSS code
65 void parse_css(string css_input);
66
67 /* Merges properties like margin */
68 void merge_4value_shorthands(string media, string selector);
69
70 /* Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;... */
71 map<string,string> dissolve_4value_shorthands(string property, string value);
72 };
73
74 #endif // HEADER_CSSTIDY
0 [Editor_6]
1 CursorCol=1
2 CursorRow=21
3 TopLine=1
4 LeftChar=1
5 Open=1
6 Top=0
7 [Editors]
8 Focused=13
9 Order=11,14,3,0,25,24,16,19,7,12,13,4,15,20,21,1,5,18,6,17
10 [Editor_0]
11 Open=1
12 Top=0
13 CursorCol=1
14 CursorRow=77
15 TopLine=1
16 LeftChar=1
17 [Editor_1]
18 Open=1
19 Top=0
20 CursorCol=1
21 CursorRow=1
22 TopLine=6
23 LeftChar=1
24 [Editor_2]
25 Open=0
26 Top=0
27 [Editor_3]
28 Open=1
29 Top=0
30 CursorCol=1
31 CursorRow=1
32 TopLine=7
33 LeftChar=1
34 [Editor_4]
35 Open=1
36 Top=0
37 CursorCol=1
38 CursorRow=1
39 TopLine=1
40 LeftChar=1
41 [Editor_5]
42 Open=1
43 Top=0
44 CursorCol=1
45 CursorRow=1
46 TopLine=1
47 LeftChar=1
48 [Editor_7]
49 Open=1
50 Top=0
51 CursorCol=19
52 CursorRow=28
53 TopLine=1
54 LeftChar=1
55 [Editor_8]
56 Open=0
57 Top=0
58 [Editor_9]
59 Open=0
60 Top=0
61 [Editor_10]
62 Open=0
63 Top=0
64 [Editor_11]
65 Open=1
66 Top=0
67 CursorCol=9
68 CursorRow=114
69 TopLine=94
70 LeftChar=1
71 [Editor_12]
72 Open=1
73 Top=0
74 CursorCol=1
75 CursorRow=1
76 TopLine=1
77 LeftChar=1
78 [Editor_13]
79 Open=1
80 Top=1
81 CursorCol=23
82 CursorRow=114
83 TopLine=1
84 LeftChar=1
85 [Editor_14]
86 Open=1
87 Top=0
88 CursorCol=1
89 CursorRow=1
90 TopLine=1
91 LeftChar=1
92 [Editor_15]
93 Open=1
94 Top=0
95 CursorCol=3
96 CursorRow=181
97 TopLine=1
98 LeftChar=1
99 [Editor_16]
100 Open=1
101 Top=0
102 CursorCol=110
103 CursorRow=221
104 TopLine=451
105 LeftChar=1
106 [Editor_17]
107 Open=1
108 Top=0
109 CursorCol=1
110 CursorRow=1
111 TopLine=1
112 LeftChar=1
113 [Editor_18]
114 Open=1
115 Top=0
116 CursorCol=1
117 CursorRow=1
118 TopLine=1
119 LeftChar=1
120 [Editor_19]
121 Open=1
122 Top=0
123 CursorCol=34
124 CursorRow=52
125 TopLine=295
126 LeftChar=1
127 [Editor_20]
128 Open=1
129 Top=0
130 CursorCol=1
131 CursorRow=1
132 TopLine=1
133 LeftChar=1
134 [Editor_21]
135 Open=1
136 Top=0
137 CursorCol=1
138 CursorRow=1
139 TopLine=198
140 LeftChar=1
141 [Editor_22]
142 Open=0
143 Top=0
144 [Editor_23]
145 Open=0
146 Top=0
147 [Editor_24]
148 Open=1
149 Top=0
150 CursorCol=59
151 CursorRow=34
152 TopLine=27
153 LeftChar=1
154 [Editor_25]
155 Open=1
156 Top=0
157 CursorCol=27
158 CursorRow=46
159 TopLine=1
160 LeftChar=1
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 using namespace std;
19 #ifndef HEADER_CSS_STRUCT
20 #define HEADER_CSS_STRUCT
21
22 typedef umap<string, string> pstore;
23 typedef umap<string, pstore > sstore;
24 typedef umap<string, sstore> css_struct;
25
26 enum parse_status
27 {
28 is,ip,iv,instr,ic,at
29 };
30
31 enum message_type
32 {
33 Information,Warning,Error
34 };
35
36 enum token_type
37 {
38 AT_START, AT_END, SEL_START, SEL_END, PROPERTY, VALUE, COMMENT
39 };
40
41 struct token
42 {
43 token_type type;
44 string data;
45 };
46
47 struct message
48 {
49 string m;
50 message_type t;
51 };
52
53 #endif // HEADER_CSS_STRUCT
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19 using namespace std;
20
21 string file_get_contents(const string filename)
22 {
23 ifstream file_input(filename.c_str(),ios::binary);
24 string line, file_contents = "";
25
26 if(file_input.bad())
27 {
28 return "";
29 }
30 else
31 {
32 while(file_input.good())
33 {
34 getline(file_input,line);
35 file_contents += (line + "\n");
36 }
37 }
38 file_input.close();
39
40 return file_contents;
41 }
42
43 bool file_exists(const char *filename)
44 {
45 ifstream file_input(filename);
46
47 if(file_input.is_open())
48 {
49 file_input.close();
50 return true;
51 }
52
53 file_input.close();
54 return false;
55 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_FILE
19 #define HEADER_CSS_FILE
20
21 // Get contents of a file
22 string file_get_contents(const string filename);
23
24 // Checks if a file exists
25 bool file_exists(const char *filename);
26
27 #endif // HEADER_CSS_FILE
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19 using namespace std;
20
21
22 bool is_important(string value)
23 {
24 // Remove whitespaces
25 value = rtrim(strtolower(value));
26
27 if(value.length() > 9 && value.substr(value.length()-9,9) == "important")
28 {
29 value = rtrim(value.substr(0,value.length()-9));
30 if(value.substr(value.length()-1,1) == "!") {
31 return true;
32 }
33 }
34 return false;
35 }
36
37
38 string gvw_important(string value)
39 {
40 if(is_important(value))
41 {
42 value = trim(value);
43 value = value.substr(0,value.length()-9);
44 value = trim(value);
45 value = value.substr(0,value.length()-1);
46 value = trim(value);
47 }
48 return value;
49 }
50
51 string c_important(string value)
52 {
53 if(is_important(value))
54 {
55 value = gvw_important(value) + " !important";
56 }
57 return value;
58 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_IMPORTANT
19 #define HEADER_CSS_IMPORTANT
20
21 // Checks if value is important
22 bool is_important(string value);
23
24 // Get value without !important
25 string gvw_important(string value);
26
27 // Compresses !important (for example if someone uses "! important")
28 string c_important(string value);
29
30 #endif //HEADER_CSS_IMPORTANT
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 using namespace std;
19
20 #include "csspp_globals.hpp"
21
22 #include "prepare.hpp"
23
24 map< string, vector<string> > predefined_templates;
25
26
27 int main(int argc, char *argv[])
28 {
29 prepare();
30 predefined_templates["high"].push_back("<span class=\"at\">");
31 predefined_templates["high"].push_back("</span> <span class=\"format\">{</span>\n");
32 predefined_templates["high"].push_back("<span class=\"selector\">");
33 predefined_templates["high"].push_back("</span><span class=\"format\">{</span>");
34 predefined_templates["high"].push_back("<span class=\"property\">");
35 predefined_templates["high"].push_back("</span><span class=\"value\">");
36 predefined_templates["high"].push_back("</span><span class=\"format\">;</span>");
37 predefined_templates["high"].push_back("<span class=\"format\">}</span>");
38 predefined_templates["high"].push_back("\n");
39 predefined_templates["high"].push_back("\n<span class=\"format\">}\n</span>");
40 predefined_templates["high"].push_back("");
41 predefined_templates["high"].push_back("<span class=\"comment\">"); // before comment
42 predefined_templates["high"].push_back("</span>"); //after comment
43 predefined_templates["high"].push_back("\n"); // after last line @-rule
44
45 predefined_templates["highest"].push_back("<span class=\"at\">");
46 predefined_templates["highest"].push_back("</span><span class=\"format\">{</span>");
47 predefined_templates["highest"].push_back("<span class=\"selector\">");
48 predefined_templates["highest"].push_back("</span><span class=\"format\">{</span>");
49 predefined_templates["highest"].push_back("<span class=\"property\">");
50 predefined_templates["highest"].push_back("</span><span class=\"value\">");
51 predefined_templates["highest"].push_back("</span><span class=\"format\">;</span>");
52 predefined_templates["highest"].push_back("<span class=\"format\">}</span>");
53 predefined_templates["highest"].push_back("");
54 predefined_templates["highest"].push_back("<span class=\"format\">}</span>");
55 predefined_templates["highest"].push_back("");
56 predefined_templates["highest"].push_back("<span class=\"comment\">"); // before comment
57 predefined_templates["highest"].push_back("</span>"); //after comment
58 predefined_templates["highest"].push_back(""); // after last line @-rule
59
60 predefined_templates["low"].push_back("<span class=\"at\">");
61 predefined_templates["low"].push_back("</span> <span class=\"format\">{</span>\n");
62 predefined_templates["low"].push_back("<span class=\"selector\">");
63 predefined_templates["low"].push_back("</span>\n<span class=\"format\">{</span>\n");
64 predefined_templates["low"].push_back("\t<span class=\"property\">");
65 predefined_templates["low"].push_back("</span><span class=\"value\">");
66 predefined_templates["low"].push_back("</span><span class=\"format\">;</span>\n");
67 predefined_templates["low"].push_back("<span class=\"format\">}</span>");
68 predefined_templates["low"].push_back("\n\n");
69 predefined_templates["low"].push_back("\n<span class=\"format\">}</span>\n\n");
70 predefined_templates["low"].push_back("\t");
71 predefined_templates["low"].push_back("<span class=\"comment\">"); // before comment
72 predefined_templates["low"].push_back("</span>\n"); //after comment
73 predefined_templates["low"].push_back("\n"); // after last line @-rule
74
75 csstidy csst;
76
77 if(argc > 1)
78 {
79 string filein = argv[1];
80 if(filein != "-" && !file_exists(argv[1]))
81 {
82 cout << "The file \"" << filein << "\" does not exist." << endl;
83 return EXIT_FAILURE;
84 }
85
86 string output_filename;
87
88 for(int i = 2; i < argc; ++i)
89 {
90 bool output_file = true;
91 for(map<string,int>::iterator j = csst.settings.begin(); j != csst.settings.end(); ++j )
92 {
93 if(trim(argv[i]) == "--" + j->first + "=false" || trim(argv[i]) == "--" + j->first + "=0")
94 {
95 csst.settings[j->first] = 0;
96 output_file = false;
97 }
98 else if(trim(argv[i]) == "--" + j->first + "=true" || trim(argv[i]) == "--" + j->first + "=1")
99 {
100 csst.settings[j->first] = 1;
101 output_file = false;
102 }
103 else if(trim(argv[i]) == "--" + j->first + "=2")
104 {
105 csst.settings[j->first] = 2;
106 output_file = false;
107 }
108 }
109 if(trim(argv[i]).substr(0,12) == "--css_level=")
110 {
111 csst.css_level = strtoupper(trim(argv[i]).substr(12));
112 output_file = false;
113 }
114 else if(trim(argv[i]).substr(0,11) == "--template=")
115 {
116 string template_value = trim(argv[i]).substr(11);
117 if(template_value == "high" || template_value == "highest" || template_value == "low")
118 {
119 csst.csstemplate = predefined_templates[template_value];
120 }
121 else if(template_value != "default")
122 {
123 string tpl_content = file_get_contents(template_value);
124 if(tpl_content != "")
125 {
126 vector<string> tpl_arr = explode("|",tpl_content,true);
127 csst.csstemplate = tpl_arr;
128 }
129 }
130 output_file = false;
131 }
132 if(output_file)
133 {
134 output_filename = trim(argv[i]);
135 }
136 }
137
138 string css_file;
139 if(filein == "-") {
140 string temp;
141 do {
142 getline(cin, temp, '\n');
143 css_file += (temp + "\n");
144 } while(cin);
145 } else {
146 css_file = file_get_contents(argv[1]);
147 }
148
149 csst.parse_css(css_file);
150
151 // Print CSS to screen if no output file is specified
152 if(output_filename == "")
153 {
154 csst.print_css();
155 }
156 else
157 {
158 csst.print_css(output_filename);
159 }
160
161 return EXIT_SUCCESS;
162 }
163
164 cout << endl << "Usage:" << endl << endl << "csstidy input_filename [\n";
165 for(map<string,int>::iterator j = csst.settings.begin(); j != csst.settings.end(); ++j )
166 {
167 if (j->first == "optimise_shorthands" || j->first == "merge_selectors") {
168 continue;
169 }
170
171 cout << " --" << j->first;
172 if(j->second == true)
173 {
174 cout << "=[true|false] |\n";
175 }
176 else
177 {
178 cout << "=[false|true] |\n";
179 }
180 }
181 cout << " --merge_selectors=[2|1|0] |\n";
182 cout << " --optimise_shorthands=[1|2|0] |\n";
183 cout << " --template=[default|filename|low|high|highest] |\n";
184 cout << " output_filename ]*" << endl;
185
186 return EXIT_SUCCESS;
187 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19
20 bool escaped(const string &istring, const int pos)
21 {
22 return !(s_at(istring,pos-1) != '\\' || escaped(istring,pos-1));
23 }
24
25 // Save replacement for .at()
26 char s_at(const string &istring, const int pos)
27 {
28 if(pos > (istring.length()-1) && pos < 0)
29 {
30 return 0;
31 }
32 else
33 {
34 return istring[pos];
35 }
36 }
37
38 vector<string> explode(const string e,string s, const bool check)
39 {
40 vector<string> ret;
41 int iPos = s.find(e, 0);
42 int iPit = e.length();
43
44 while(iPos > -1)
45 {
46 if(iPos != 0 || check)
47 {
48 ret.push_back(s.substr(0,iPos));
49 }
50 s.erase(0,iPos+iPit);
51 iPos = s.find(e, 0);
52 }
53
54 if(s != "" || check)
55 {
56 ret.push_back(s);
57 }
58 return ret;
59 }
60
61 string implode(const string e,const vector<string> s)
62 {
63 string ret;
64 for(int i = 0; i < s.size(); i++)
65 {
66 ret += s[i];
67 if(i != (s.size()-1)) ret += e;
68 }
69 return ret;
70 }
71
72 float round(const float &number, const int num_digits)
73 {
74 float doComplete5i, doComplete5(number * powf(10.0f, (float) (num_digits + 1)));
75
76 if(number < 0.0f)
77 doComplete5 -= 5.0f;
78 else
79 doComplete5 += 5.0f;
80
81 doComplete5 /= 10.0f;
82 modff(doComplete5, &doComplete5i);
83
84 return doComplete5i / powf(10.0f, (float) num_digits);
85 }
86
87
88 string str_replace(const string find, const string replace, string str)
89 {
90 int len = find.length();
91 int replace_len = replace.length();
92 int pos = str.find(find);
93
94 while(pos != string::npos)
95 {
96 str.replace(pos, len, replace);
97 pos = str.find(find, pos + replace_len);
98 }
99 return str;
100 }
101
102 string str_replace(const vector<string>& find, const string replace, string str)
103 {
104 int replace_len = replace.length();
105
106 for(int i = 0; i < find.size(); ++i)
107 {
108 int len = find[i].length();
109 int pos = str.find(find[i]);
110
111 while(pos != string::npos)
112 {
113 str.replace(pos, len, replace);
114 pos = str.find(find[i], pos + replace_len);
115 }
116 }
117 return str;
118 }
119
120
121 bool in_char_arr(const char* haystack, const char needle)
122 {
123 for(int i = 0; i < strlen(haystack); ++i)
124 {
125 if(haystack[i] == needle)
126 {
127 return true;
128 }
129 }
130 return false;
131 }
132
133 bool in_str_array(const string& haystack, const char needle)
134 {
135 return (haystack.find_first_of(needle,0) != string::npos);
136 }
137
138 bool in_str_array(const vector<string>& haystack, const string needle)
139 {
140 for(int i = 0; i < haystack.size(); ++i)
141 {
142 if(haystack[i] == needle)
143 {
144 return true;
145 }
146 }
147 return false;
148 }
149
150 string htmlspecialchars(string istring, int quotes)
151 {
152 istring = str_replace("&","&amp;",istring);
153 istring = str_replace("<","&lt;",istring);
154 istring = str_replace(">","&gt;",istring);
155 if(quotes > 0) istring = str_replace("\"","&quot;",istring);
156 if(quotes > 1) istring = str_replace("'","&#039;",istring);
157 return istring;
158 }
159
160 int max(const int i1, const int i2)
161 {
162 if(i1 > i2)
163 {
164 return i1;
165 }
166 else
167 {
168 return i2;
169 }
170 }
171
172 bool ctype_space(const char c)
173 {
174 return (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11);
175 }
176
177 bool ctype_digit(const char c)
178 {
179 return (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9');
180 }
181
182 vector<string> unserialise_sa(const string istring)
183 {
184 int strlen = istring.length();
185 int strpos = 0;
186 vector<string> ret;
187
188 while(strlen > 0)
189 {
190 string digit_tmp = "";
191 for(int i = strpos; ctype_digit(s_at(istring,i)); i++)
192 {
193 digit_tmp += istring[i];
194 --strlen; ++strpos;
195 }
196 // :
197 --strlen; ++strpos;
198
199 int next_length = static_cast<int>(str2f(digit_tmp));
200 next_length += strpos;
201
202 string string_tmp = "";
203 for(int i = strpos; (i<istring.length() && i < next_length); i++)
204 {
205 string_tmp += istring[i];
206 --strlen; ++strpos;
207 }
208 ret.push_back(string_tmp);
209 }
210 return ret;
211 }
212
213 string serialise_sa(const string istring)
214 {
215 return f2str(istring.length()) + ":" + istring;
216 }
217
218 bool ctype_xdigit(char c)
219 {
220 c = chartolower(c);
221 return (ctype_digit(c) || c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f');
222 }
223
224 bool ctype_alpha(char c)
225 {
226 c = chartolower(c);
227 return (c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f' || c == 'g' || c == 'h' || c == 'i' || c == 'j' ||
228 c == 'k' || c == 'l' || c == 'm' || c == 'n' || c == 'o' || c == 'p' || c == 'q' || c == 'r' || c == 's' || c == 't' ||
229 c == 'u' || c == 'v' || c == 'w' || c == 'x' || c == 'y' || c == 'z');
230 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_MISC
19 #define HEADER_CSS_MISC
20
21 // Checks if a charcter is escaped
22 bool escaped(const string &istring, int pos);
23
24 // Returns a char of a string at pos but checks the string-length before
25 char s_at(const string &istring, int pos);
26
27 // Splits a string at e
28 vector<string> explode(const string e, string s, const bool check = false);
29
30 // Implodes a string at e
31 std::string implode(const string e, const vector<string> s);
32
33 // Replaces <find> with <replace> in <str>
34 string str_replace(const string find, const string replace, string str);
35
36 // Replaces all values of <find> with <replace> in <str>
37 string str_replace(const vector<string>& find, const string replace, string str);
38
39 // Checks if a string exists in a string-array
40 bool in_char_arr(const char* haystack, const char needle);
41 bool in_str_array(const string& haystack, const char needle);
42 bool in_str_array(const vector<string>& haystack, const string needle);
43
44 // Replaces certain chars with their entities
45 string htmlspecialchars(string istring, int quotes = 0);
46
47 // Rounds a float value
48 float round(const float &number, const int num_digits);
49
50 // Replacement for max (so that I don't have to include unnecessary things)
51 int max(const int i1, const int i2);
52
53 /* isspace() and isdigit() do not work correctly with UTF-8 strings */
54 bool ctype_space(const char c);
55 bool ctype_digit(const char c);
56 bool ctype_xdigit(char c);
57 bool ctype_alpha(char c);
58
59 /* Unserialise string arrays */
60 vector<string> unserialise_sa(const string istring);
61
62 /* Serialise a string */
63 string serialise_sa(const string istring);
64
65 #endif // HEADER_CSS_MISC
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19
20 using namespace std;
21
22 /* is = in selector
23 * ip = in property
24 * iv = in value
25 * instr = in string (-> ",',( => ignore } and ; etc.)
26 * ic = in comment (ignore everything)
27 * at = in @-block
28 */
29
30 extern map<string,string> all_properties,replace_colors;
31 extern map< string, vector<string> > shorthands;
32 extern map<string,parse_status> at_rules;
33
34 void csstidy::parse_css(string css_input)
35 {
36 input_size = css_input.length();
37 css_input = str_replace("\r\n","\n",css_input); // Replace all double-newlines
38 css_input += "\n";
39 parse_status status = is, from;
40 cur_property = ""; // if you can explain the need for this please do so
41
42 string temp_add,cur_comment,temp;
43
44 vector<string> cur_sub_value_arr;
45 char str_char;
46 bool str_in_str = false;
47 bool invalid_at = false;
48 bool pn = false;
49
50 int str_size = css_input.length();
51 for(int i = 0; i < str_size; ++i)
52 {
53 if(css_input[i] == '\n' || css_input[i] == '\r')
54 {
55 ++line;
56 }
57
58 switch(status)
59 {
60 /* Case in-at-block */
61 case at:
62 if(is_token(css_input,i))
63 {
64 if(css_input[i] == '/' && s_at(css_input,i+1) == '*')
65 {
66 status = ic; i += 2;
67 from = at;
68 }
69 else if(css_input[i] == '{')
70 {
71 status = is;
72 add_token(AT_START, cur_at);
73 }
74 else if(css_input[i] == ',')
75 {
76 cur_at += trim(cur_at) + ",";
77 }
78 else if(css_input[i] == '\\')
79 {
80 cur_at += unicode(css_input,i);
81 }
82 }
83 else
84 {
85 int lastpos = cur_at.length()-1;
86 if(lastpos == -1 || !( (ctype_space(cur_at[lastpos]) || is_token(cur_at,lastpos) && cur_at[lastpos] == ',') && ctype_space(css_input[i])))
87 {
88 cur_at += css_input[i];
89 }
90 }
91 break;
92
93 /* Case in-selector */
94 case is:
95 if(is_token(css_input,i))
96 {
97 if(css_input[i] == '/' && s_at(css_input,i+1) == '*' && trim(cur_selector) == "")
98 {
99 status = ic; ++i;
100 from = is;
101 }
102 else if(css_input[i] == '@' && trim(cur_selector) == "")
103 {
104 // Check for at-rule
105 invalid_at = true;
106 for(map<string,parse_status>::iterator j = at_rules.begin(); j != at_rules.end(); ++j )
107 {
108 if(strtolower(css_input.substr(i+1,j->first.length())) == j->first)
109 {
110 (j->second == at) ? cur_at = "@" + j->first : cur_selector = "@" + j->first;
111 status = j->second;
112 i += j->first.length();
113 invalid_at = false;
114 }
115 }
116 if(invalid_at)
117 {
118 cur_selector = "@";
119 string invalid_at_name = "";
120 for(int j = i+1; j < str_size; ++j)
121 {
122 if(!ctype_alpha(css_input[j]))
123 {
124 break;
125 }
126 invalid_at_name += css_input[j];
127 }
128 log("Invalid @-rule: " + invalid_at_name + " (removed)",Warning);
129 }
130 }
131 else if(css_input[i] == '"' || css_input[i] == '\'')
132 {
133 cur_selector += css_input[i];
134 status = instr;
135 str_char = css_input[i];
136 from = is;
137 }
138 else if(invalid_at && css_input[i] == ';')
139 {
140 invalid_at = false;
141 status = is;
142 }
143 else if(css_input[i] == '{')
144 {
145 status = ip;
146 add_token(SEL_START, cur_selector);
147 ++selectors;
148 }
149 else if(css_input[i] == '}')
150 {
151 add_token(AT_END, cur_at);
152 cur_at = "";
153 cur_selector = "";
154 sel_separate = vector<int>();
155 }
156 else if(css_input[i] == ',')
157 {
158 cur_selector = trim(cur_selector) + ",";
159 sel_separate.push_back(cur_selector.length());
160 }
161 else if(css_input[i] == '\\')
162 {
163 cur_selector += unicode(css_input,i);
164 }
165 else cur_selector += css_input[i];
166 }
167 else
168 {
169 int lastpos = cur_selector.length()-1;
170 if(!( (ctype_space(cur_selector[lastpos]) || is_token(cur_selector,lastpos) && cur_selector[lastpos] == ',') && ctype_space(css_input[i])))
171 {
172 cur_selector += css_input[i];
173 }
174 }
175 break;
176
177 /* Case in-property */
178 case ip:
179 if(is_token(css_input,i))
180 {
181 if(css_input[i] == ':' || css_input[i] == '=' && cur_property != "") // IE really accepts =, so csstidy will fix those mistakes
182 {
183 status = iv;
184 bool valid = (all_properties.count(cur_property) > 0 && all_properties[cur_property].find(css_level,0) != string::npos);
185 if(valid || !settings["discard_invalid_properties"]) {
186 add_token(PROPERTY, cur_property);
187 }
188 }
189 else if(css_input[i] == '/' && s_at(css_input,i+1) == '*' && cur_property == "")
190 {
191 status = ic; ++i;
192 from = ip;
193 }
194 else if(css_input[i] == '}')
195 {
196 explode_selectors();
197 status = is;
198 invalid_at = false;
199 add_token(SEL_END, cur_selector);
200 cur_selector = "";
201 cur_property = "";
202 }
203 else if(css_input[i] == ';')
204 {
205 cur_property = "";
206 }
207 else if(css_input[i] == '\\')
208 {
209 cur_property += unicode(css_input,i);
210 }
211 }
212 else if(!ctype_space(css_input[i]))
213 {
214 cur_property += css_input[i];
215 }
216 break;
217
218 /* Case in-value */
219 case iv:
220 pn = ((css_input[i] == '\n' || css_input[i] == '\r') && property_is_next(css_input,i+1) || i == str_size-1);
221 if(pn)
222 {
223 log("Added semicolon to the end of declaration",Warning);
224 }
225 if(is_token(css_input,i) || pn)
226 {
227 if(css_input[i] == '/' && s_at(css_input,i+1) == '*')
228 {
229 status = ic; ++i;
230 from = iv;
231 }
232 else if(css_input[i] == '"' || css_input[i] == '\'' || css_input[i] == '(')
233 {
234 cur_sub_value += css_input[i];
235 str_char = (css_input[i] == '(') ? ')' : css_input[i];
236 status = instr;
237 from = iv;
238 }
239 else if(css_input[i] == '\\')
240 {
241 cur_sub_value += unicode(css_input,i);
242 }
243 else if(css_input[i] == ';' || pn)
244 {
245 if(cur_selector.substr(0,1) == "@" && at_rules.count(cur_selector.substr(1)) > 0 && at_rules[cur_selector.substr(1)] == iv)
246 {
247 cur_sub_value_arr.push_back(trim(cur_sub_value));
248 status = is;
249
250 if(cur_selector == "@charset") charset = cur_sub_value_arr[0];
251 if(cur_selector == "@namespace") namesp = implode(" ",cur_sub_value_arr);
252 if(cur_selector == "@import") import.push_back(implode(" ",cur_sub_value_arr));
253
254 cur_sub_value_arr.clear();
255 cur_sub_value = "";
256 cur_selector = "";
257 sel_separate = vector<int>();
258 }
259 else
260 {
261 status = ip;
262 }
263 }
264 else if(css_input[i] != '}')
265 {
266 cur_sub_value += css_input[i];
267 }
268 if( (css_input[i] == '}' || css_input[i] == ';' || pn) && !cur_selector.empty())
269 {
270 ++properties;
271
272 if(cur_at == "")
273 {
274 cur_at = "standard";
275 }
276
277 // Kill all whitespace
278 cur_at = trim(cur_at); cur_selector = trim(cur_selector);
279 cur_value = trim(cur_value); cur_property = trim(cur_property);
280 cur_sub_value = trim(cur_sub_value);
281
282 // case settings
283 if(settings["lowercase_s"])
284 {
285 cur_selector = strtolower(cur_selector);
286 }
287 cur_property = strtolower(cur_property);
288
289
290 if(cur_sub_value != "")
291 {
292 cur_sub_value = optimise_subvalue(cur_sub_value,cur_property);
293 cur_sub_value_arr.push_back(cur_sub_value);
294 cur_sub_value = "";
295 }
296
297 cur_value = implode(" ",cur_sub_value_arr);
298
299 // Compress !important
300 temp = c_important(cur_value);
301 if(temp != cur_value)
302 {
303 log("Optimised !important",Information);
304 }
305 cur_value = temp;
306
307 // Optimise shorthand properties
308 if(shorthands.count(cur_property) > 0)
309 {
310 temp = shorthand(cur_value);
311 if(temp != cur_value)
312 {
313 log("Optimised shorthand notation (" + cur_property + "): Changed \"" + cur_value + "\" to \"" + temp + "\"",Information);
314 }
315 cur_value = temp;
316 }
317
318 // Compress font-weight (tiny compression)
319 if(cur_property == "font-weight" && settings["compress_font-weight"])
320 {
321 int c_fw = c_font_weight(cur_value);
322 if(c_fw == 400)
323 {
324 log("Optimised font-weight: Changed \"bold\" to \"700\"",Information);
325 }
326 else if(c_fw == 700)
327 {
328 log("Optimised font-weight: Changed \"normal\" to \"400\"",Information);
329 }
330 }
331
332 bool valid = (all_properties.count(cur_property) > 0 && all_properties[cur_property].find(css_level,0) != string::npos);
333 if((!invalid_at || settings["preserve_css"]) && (!settings["discard_invalid_properties"] || valid))
334 {
335 add(cur_at,cur_selector,cur_property,cur_value);
336 add_token(VALUE, cur_value);
337
338 // Further Optimisation
339 if(cur_property == "background" && settings["optimise_shorthands"] > 1)
340 {
341 map<string,string> temp = dissolve_short_bg(cur_value);
342 css[cur_at][cur_selector].erase("background");
343 for(map<string,string>::iterator it = temp.begin(); it != temp.end(); ++it )
344 {
345 add(cur_at,cur_selector,it->first,it->second);
346 }
347 }
348 if(shorthands.count(cur_property) > 0 && settings["optimise_shorthands"] > 0)
349 {
350 map<string,string> temp = dissolve_4value_shorthands(cur_property,cur_value);
351 for(map<string,string>::iterator it = temp.begin(); it != temp.end(); ++it )
352 {
353 add(cur_at,cur_selector,it->first,it->second);
354 }
355 if(shorthands[cur_property][0] != "0")
356 {
357 css[cur_at][cur_selector].erase(cur_property);
358 }
359 }
360 }
361 if(!valid)
362 {
363 if(settings["discard_invalid_properties"])
364 {
365 log("Removed invalid property: " + cur_property,Warning);
366 }
367 else
368 {
369 log("Invalid property in " + strtoupper(css_level) + ": " + cur_property,Warning);
370 }
371 }
372
373 //Split multiple selectors here if necessary
374 cur_property = "";
375 cur_sub_value_arr.clear();
376 cur_value = "";
377 }
378 if(css_input[i] == '}')
379 {
380 explode_selectors();
381 add_token(SEL_END, cur_selector);
382 status = is;
383 invalid_at = false;
384 cur_selector = "";
385 }
386 }
387 else if(!pn)
388 {
389 cur_sub_value += css_input[i];
390
391 if(ctype_space(css_input[i]))
392 {
393 if(trim(cur_sub_value) != "")
394 {
395 cur_sub_value = optimise_subvalue(cur_sub_value,cur_property);
396 cur_sub_value_arr.push_back(trim(cur_sub_value));
397 }
398 cur_sub_value = "";
399 }
400 }
401 break;
402
403 /* Case in-string */
404 case instr:
405 if(str_char == ')' && css_input[i] == '"' && str_in_str == false && !escaped(css_input,i))
406 {
407 str_in_str = true;
408 }
409 else if(str_char == ')' && css_input[i] == '"' && str_in_str == true && !escaped(css_input,i))
410 {
411 str_in_str = false;
412 }
413 if(css_input[i] == str_char && !escaped(css_input,i) && str_in_str == false)
414 {
415 status = from;
416 }
417 temp_add = ""; temp_add += css_input[i];
418 if( (css_input[i] == '\n' || css_input[i] == '\r') && !(css_input[i-1] == '\\' && !escaped(css_input,i-1)) )
419 {
420 temp_add = "\\A ";
421 log("Fixed incorrect newline in string",Warning);
422 }
423 if(from == iv)
424 {
425 cur_sub_value += temp_add;
426 }
427 else if(from == is)
428 {
429 cur_selector += temp_add;
430 }
431 break;
432
433 /* Case in-comment */
434 case ic:
435 if(css_input[i] == '*' && s_at(css_input,i+1) == '/')
436 {
437 status = from;
438 ++i;
439 add_token(COMMENT, cur_comment);
440 cur_comment = "";
441 }
442 else
443 {
444 cur_comment += css_input[i];
445 }
446 break;
447 }
448 }
449
450 if(settings["merge_selectors"] > 1)
451 {
452 for(css_struct::iterator i = css.begin(); i != css.end(); i++ )
453 {
454 merge_selectors(i->second);
455 }
456 }
457
458 if(settings["optimise_shorthands"] > 0)
459 {
460 for(css_struct::iterator i = css.begin(); i != css.end(); ++i )
461 {
462 for(sstore::iterator j = i->second.begin(); j != i->second.end();)
463 {
464 merge_4value_shorthands(i->first,j->first);
465 if(settings["optimise_shorthands"] > 1) {
466 merge_bg(j->second);
467 }
468
469 if(j->second.size() == 0) {
470 i->second.erase(j);
471 } else {
472 ++j;
473 }
474 }
475 }
476 }
477 }
478
479 string csstidy::optimise_subvalue(string subvalue, const string property)
480 {
481 subvalue = trim(subvalue);
482 string temp = compress_numbers(subvalue,property);
483 if(temp != subvalue)
484 {
485 if(temp.length() > subvalue.length())
486 {
487 log("Fixed invalid number: Changed \"" + subvalue + "\" to \"" + temp + "\"",Warning);
488 }
489 else
490 {
491 log("Optimised number: Changed \"" + subvalue + "\" to \"" + temp + "\"",Information);
492 }
493 subvalue = temp;
494 }
495 if(settings["compress_colors"])
496 {
497 temp = cut_color(subvalue);
498 if(temp != subvalue)
499 {
500 if(replace_colors.count(subvalue) > 0)
501 {
502 log("Fixed invalid color name: Changed \"" + subvalue + "\" to \"" + temp + "\"",Warning);
503 }
504 else
505 {
506 log("Optimised color: Changed \"" + subvalue + "\" to \"" + temp + "\"",Information);
507 }
508 subvalue = temp;
509 }
510 }
511 return subvalue;
512 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_PARSE
19 #define HEADER_CSS_PARSE
20
21 // Parses CSS
22 //css_manage parse_css(const string css_input);
23
24 #endif // HEADER_CSS_PARSE
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19
20 map<string,bool> settings;
21 map< string, vector<string> > shorthands;
22 map<string,string> background_prop_default,replace_colors,all_properties;
23 vector<string> number_values,color_values;
24 map<string,parse_status> at_rules;
25
26 void prepare()
27 {
28 number_values.push_back("line-height");
29 number_values.push_back("pitch-range");
30 number_values.push_back("richness");
31 number_values.push_back("speech-rate");
32 number_values.push_back("stress");
33 number_values.push_back("volume");
34 number_values.push_back("font");
35 number_values.push_back("font-weight");
36 number_values.push_back("z-index");
37 number_values.push_back("counter-increment");
38 number_values.push_back("counter-reset");
39 number_values.push_back("orphans");
40 number_values.push_back("widows");
41
42
43 color_values.push_back("color");
44 color_values.push_back("background-color");
45 color_values.push_back("border-color");
46 color_values.push_back("border-top-color");
47 color_values.push_back("border-right-color");
48 color_values.push_back("border-bottom-color");
49 color_values.push_back("border-left-color");
50 color_values.push_back("border-color");
51 color_values.push_back("color");
52 color_values.push_back("outline-color");
53
54 replace_colors["aliceblue"] = "#F0F8FF";
55 replace_colors["antiquewhite"] = "#FAEBD7";
56 replace_colors["aquamarine"] = "#7FFFD4";
57 replace_colors["azure"] = "#F0FFFF";
58 replace_colors["beige"] = "#F5F5DC";
59 replace_colors["bisque"] = "#FFE4C4";
60 replace_colors["blanchedalmond"] = "#FFEBCD";
61 replace_colors["blueviolet"] = "#8A2BE2";
62 replace_colors["brown"] = "#A52A2A";
63 replace_colors["burlywood"] = "#DEB887";
64 replace_colors["cadetblue"] = "#5F9EA0";
65 replace_colors["chartreuse"] = "#7FFF00";
66 replace_colors["chocolate"] = "#D2691E";
67 replace_colors["coral"] = "#FF7F50";
68 replace_colors["cornflowerblue"] = "#6495ED";
69 replace_colors["cornsilk"] = "#FFF8DC";
70 replace_colors["crimson"] = "#DC143C";
71 replace_colors["cyan"] = "#00FFFF";
72 replace_colors["darkblue"] = "#00008B";
73 replace_colors["darkcyan"] = "#008B8B";
74 replace_colors["darkgoldenrod"] = "#B8860B";
75 replace_colors["darkgray"] = "#A9A9A9";
76 replace_colors["darkgreen"] = "#006400";
77 replace_colors["darkkhaki"] = "#BDB76B";
78 replace_colors["darkmagenta"] = "#8B008B";
79 replace_colors["darkolivegreen"] = "#556B2F";
80 replace_colors["darkorange"] = "#FF8C00";
81 replace_colors["darkorchid"] = "#9932CC";
82 replace_colors["darkred"] = "#8B0000";
83 replace_colors["darksalmon"] = "#E9967A";
84 replace_colors["darkseagreen"] = "#8FBC8F";
85 replace_colors["darkslateblue"] = "#483D8B";
86 replace_colors["darkslategray"] = "#2F4F4F";
87 replace_colors["darkturquoise"] = "#00CED1";
88 replace_colors["darkviolet"] = "#9400D3";
89 replace_colors["deeppink"] = "#FF1493";
90 replace_colors["deepskyblue"] = "#00BFFF";
91 replace_colors["dimgray"] = "#696969";
92 replace_colors["dodgerblue"] = "#1E90FF";
93 replace_colors["feldspar"] = "#D19275";
94 replace_colors["firebrick"] = "#B22222";
95 replace_colors["floralwhite"] = "#FFFAF0";
96 replace_colors["forestgreen"] = "#228B22";
97 replace_colors["gainsboro"] = "#DCDCDC";
98 replace_colors["ghostwhite"] = "#F8F8FF";
99 replace_colors["gold"] = "#FFD700";
100 replace_colors["goldenrod"] = "#DAA520";
101 replace_colors["greenyellow"] = "#ADFF2F";
102 replace_colors["honeydew"] = "#F0FFF0";
103 replace_colors["hotpink"] = "#FF69B4";
104 replace_colors["indianred"] = "#CD5C5C";
105 replace_colors["indigo"] = "#4B0082";
106 replace_colors["ivory"] = "#FFFFF0";
107 replace_colors["khaki"] = "#F0E68C";
108 replace_colors["lavender"] = "#E6E6FA";
109 replace_colors["lavenderblush"] = "#FFF0F5";
110 replace_colors["lawngreen"] = "#7CFC00";
111 replace_colors["lemonchiffon"] = "#FFFACD";
112 replace_colors["lightblue"] = "#ADD8E6";
113 replace_colors["lightcoral"] = "#F08080";
114 replace_colors["lightcyan"] = "#E0FFFF";
115 replace_colors["lightgoldenrodyellow"] = "#FAFAD2";
116 replace_colors["lightgrey"] = "#D3D3D3";
117 replace_colors["lightgreen"] = "#90EE90";
118 replace_colors["lightpink"] = "#FFB6C1";
119 replace_colors["lightsalmon"] = "#FFA07A";
120 replace_colors["lightseagreen"] = "#20B2AA";
121 replace_colors["lightskyblue"] = "#87CEFA";
122 replace_colors["lightslateblue"] = "#8470FF";
123 replace_colors["lightslategray"] = "#778899";
124 replace_colors["lightsteelblue"] = "#B0C4DE";
125 replace_colors["lightyellow"] = "#FFFFE0";
126 replace_colors["limegreen"] = "#32CD32";
127 replace_colors["linen"] = "#FAF0E6";
128 replace_colors["magenta"] = "#FF00FF";
129 replace_colors["mediumaquamarine"] = "#66CDAA";
130 replace_colors["mediumblue"] = "#0000CD";
131 replace_colors["mediumorchid"] = "#BA55D3";
132 replace_colors["mediumpurple"] = "#9370D8";
133 replace_colors["mediumseagreen"] = "#3CB371";
134 replace_colors["mediumslateblue"] = "#7B68EE";
135 replace_colors["mediumspringgreen"] = "#00FA9A";
136 replace_colors["mediumturquoise"] = "#48D1CC";
137 replace_colors["mediumvioletred"] = "#C71585";
138 replace_colors["midnightblue"] = "#191970";
139 replace_colors["mintcream"] = "#F5FFFA";
140 replace_colors["mistyrose"] = "#FFE4E1";
141 replace_colors["moccasin"] = "#FFE4B5";
142 replace_colors["navajowhite"] = "#FFDEAD";
143 replace_colors["oldlace"] = "#FDF5E6";
144 replace_colors["olivedrab"] = "#6B8E23";
145 replace_colors["orangered"] = "#FF4500";
146 replace_colors["orchid"] = "#DA70D6";
147 replace_colors["palegoldenrod"] = "#EEE8AA";
148 replace_colors["palegreen"] = "#98FB98";
149 replace_colors["paleturquoise"] = "#AFEEEE";
150 replace_colors["palevioletred"] = "#D87093";
151 replace_colors["papayawhip"] = "#FFEFD5";
152 replace_colors["peachpuff"] = "#FFDAB9";
153 replace_colors["peru"] = "#CD853F";
154 replace_colors["pink"] = "#FFC0CB";
155 replace_colors["plum"] = "#DDA0DD";
156 replace_colors["powderblue"] = "#B0E0E6";
157 replace_colors["rosybrown"] = "#BC8F8F";
158 replace_colors["royalblue"] = "#4169E1";
159 replace_colors["saddlebrown"] = "#8B4513";
160 replace_colors["salmon"] = "#FA8072";
161 replace_colors["sandybrown"] = "#F4A460";
162 replace_colors["seagreen"] = "#2E8B57";
163 replace_colors["seashell"] = "#FFF5EE";
164 replace_colors["sienna"] = "#A0522D";
165 replace_colors["skyblue"] = "#87CEEB";
166 replace_colors["slateblue"] = "#6A5ACD";
167 replace_colors["slategray"] = "#708090";
168 replace_colors["snow"] = "#FFFAFA";
169 replace_colors["springgreen"] = "#00FF7F";
170 replace_colors["steelblue"] = "#4682B4";
171 replace_colors["tan"] = "#D2B48C";
172 replace_colors["thistle"] = "#D8BFD8";
173 replace_colors["tomato"] = "#FF6347";
174 replace_colors["turquoise"] = "#40E0D0";
175 replace_colors["violet"] = "#EE82EE";
176 replace_colors["violetred"] = "#D02090";
177 replace_colors["wheat"] = "#F5DEB3";
178 replace_colors["whitesmoke"] = "#F5F5F5";
179 replace_colors["yellowgreen"] = "#9ACD32";
180
181 shorthands["border-color"].push_back("border-top-color");
182 shorthands["border-color"].push_back("border-right-color");
183 shorthands["border-color"].push_back("border-bottom-color");
184 shorthands["border-color"].push_back("border-left-color");
185 shorthands["border-style"].push_back("border-top-style");
186 shorthands["border-style"].push_back("border-right-style");
187 shorthands["border-style"].push_back("border-bottom-style");
188 shorthands["border-style"].push_back("border-left-style");
189 shorthands["border-width"].push_back("border-top-width");
190 shorthands["border-width"].push_back("border-right-width");
191 shorthands["border-width"].push_back("border-bottom-width");
192 shorthands["border-width"].push_back("border-left-width");
193 shorthands["margin"].push_back("margin-top");
194 shorthands["margin"].push_back("margin-right");
195 shorthands["margin"].push_back("margin-bottom");
196 shorthands["margin"].push_back("margin-left");
197 shorthands["padding"].push_back("padding-top");
198 shorthands["padding"].push_back("padding-right");
199 shorthands["padding"].push_back("padding-bottom");
200 shorthands["padding"].push_back("padding-left");
201 shorthands["-moz-border-radius"].push_back("0");
202
203 all_properties["background"] = "CSS1.0,CSS2.0,CSS2.1";
204 all_properties["background-color"] = "CSS1.0,CSS2.0,CSS2.1";
205 all_properties["background-image"] = "CSS1.0,CSS2.0,CSS2.1";
206 all_properties["background-repeat"] = "CSS1.0,CSS2.0,CSS2.1";
207 all_properties["background-attachment"] = "CSS1.0,CSS2.0,CSS2.1";
208 all_properties["background-position"] = "CSS1.0,CSS2.0,CSS2.1";
209 all_properties["border"] = "CSS1.0,CSS2.0,CSS2.1";
210 all_properties["border-top"] = "CSS1.0,CSS2.0,CSS2.1";
211 all_properties["border-right"] = "CSS1.0,CSS2.0,CSS2.1";
212 all_properties["border-bottom"] = "CSS1.0,CSS2.0,CSS2.1";
213 all_properties["border-left"] = "CSS1.0,CSS2.0,CSS2.1";
214 all_properties["border-color"] = "CSS1.0,CSS2.0,CSS2.1";
215 all_properties["border-top-color"] = "CSS2.0,CSS2.1";
216 all_properties["border-bottom-color"] = "CSS2.0,CSS2.1";
217 all_properties["border-left-color"] = "CSS2.0,CSS2.1";
218 all_properties["border-right-color"] = "CSS2.0,CSS2.1";
219 all_properties["border-style"] = "CSS1.0,CSS2.0,CSS2.1";
220 all_properties["border-top-style"] = "CSS2.0,CSS2.1";
221 all_properties["border-right-style"] = "CSS2.0,CSS2.1";
222 all_properties["border-left-style"] = "CSS2.0,CSS2.1";
223 all_properties["border-bottom-style"] = "CSS2.0,CSS2.1";
224 all_properties["border-width"] = "CSS1.0,CSS2.0,CSS2.1";
225 all_properties["border-top-width"] = "CSS1.0,CSS2.0,CSS2.1";
226 all_properties["border-right-width"] = "CSS1.0,CSS2.0,CSS2.1";
227 all_properties["border-left-width"] = "CSS1.0,CSS2.0,CSS2.1";
228 all_properties["border-bottom-width"] = "CSS1.0,CSS2.0,CSS2.1";
229 all_properties["border-collapse"] = "CSS2.0,CSS2.1";
230 all_properties["border-spacing"] = "CSS2.0,CSS2.1";
231 all_properties["bottom"] = "CSS2.0,CSS2.1";
232 all_properties["caption-side"] = "CSS2.0,CSS2.1";
233 all_properties["content"] = "CSS2.0,CSS2.1";
234 all_properties["clear"] = "CSS1.0,CSS2.0,CSS2.1";
235 all_properties["clip"] = "CSS1.0,CSS2.0,CSS2.1";
236 all_properties["color"] = "CSS1.0,CSS2.0,CSS2.1";
237 all_properties["counter-reset"] = "CSS2.0,CSS2.1";
238 all_properties["counter-increment"] = "CSS2.0,CSS2.1";
239 all_properties["cursor"] = "CSS2.0,CSS2.1";
240 all_properties["empty-cells"] = "CSS2.0,CSS2.1";
241 all_properties["display"] = "CSS1.0,CSS2.0,CSS2.1";
242 all_properties["direction"] = "CSS2.0,CSS2.1";
243 all_properties["float"] = "CSS1.0,CSS2.0,CSS2.1";
244 all_properties["font"] = "CSS1.0,CSS2.0,CSS2.1";
245 all_properties["font-family"] = "CSS1.0,CSS2.0,CSS2.1";
246 all_properties["font-style"] = "CSS1.0,CSS2.0,CSS2.1";
247 all_properties["font-variant"] = "CSS1.0,CSS2.0,CSS2.1";
248 all_properties["font-weight"] = "CSS1.0,CSS2.0,CSS2.1";
249 all_properties["font-stretch"] = "CSS2.0";
250 all_properties["font-size-adjust"] = "CSS2.0";
251 all_properties["font-size"] = "CSS1.0,CSS2.0,CSS2.1";
252 all_properties["height"] = "CSS1.0,CSS2.0,CSS2.1";
253 all_properties["left"] = "CSS1.0,CSS2.0,CSS2.1";
254 all_properties["line-height"] = "CSS1.0,CSS2.0,CSS2.1";
255 all_properties["list-style"] = "CSS1.0,CSS2.0,CSS2.1";
256 all_properties["list-style-type"] = "CSS1.0,CSS2.0,CSS2.1";
257 all_properties["list-style-image"] = "CSS1.0,CSS2.0,CSS2.1";
258 all_properties["list-style-position"] = "CSS1.0,CSS2.0,CSS2.1";
259 all_properties["margin"] = "CSS1.0,CSS2.0,CSS2.1";
260 all_properties["margin-top"] = "CSS1.0,CSS2.0,CSS2.1";
261 all_properties["margin-right"] = "CSS1.0,CSS2.0,CSS2.1";
262 all_properties["margin-bottom"] = "CSS1.0,CSS2.0,CSS2.1";
263 all_properties["margin-left"] = "CSS1.0,CSS2.0,CSS2.1";
264 all_properties["marks"] = "CSS1.0,CSS2.0";
265 all_properties["marker-offset"] = "CSS2.0";
266 all_properties["max-height"] = "CSS2.0,CSS2.1";
267 all_properties["max-width"] = "CSS2.0,CSS2.1";
268 all_properties["min-height"] = "CSS2.0,CSS2.1";
269 all_properties["min-width"] = "CSS2.0,CSS2.1";
270 all_properties["overflow"] = "CSS1.0,CSS2.0,CSS2.1";
271 all_properties["orphans"] = "CSS2.0,CSS2.1";
272 all_properties["outline"] = "CSS2.0,CSS2.1";
273 all_properties["outline-width"] = "CSS2.0,CSS2.1";
274 all_properties["outline-style"] = "CSS2.0,CSS2.1";
275 all_properties["outline-color"] = "CSS2.0,CSS2.1";
276 all_properties["padding"] = "CSS1.0,CSS2.0,CSS2.1";
277 all_properties["padding-top"] = "CSS1.0,CSS2.0,CSS2.1";
278 all_properties["padding-right"] = "CSS1.0,CSS2.0,CSS2.1";
279 all_properties["padding-bottom"] = "CSS1.0,CSS2.0,CSS2.1";
280 all_properties["padding-left"] = "CSS1.0,CSS2.0,CSS2.1";
281 all_properties["page-break-before"] = "CSS1.0,CSS2.0,CSS2.1";
282 all_properties["page-break-after"] = "CSS1.0,CSS2.0,CSS2.1";
283 all_properties["page-break-inside"] = "CSS2.0,CSS2.1";
284 all_properties["page"] = "CSS2.0";
285 all_properties["position"] = "CSS1.0,CSS2.0,CSS2.1";
286 all_properties["quotes"] = "CSS2.0,CSS2.1";
287 all_properties["right"] = "CSS2.0,CSS2.1";
288 all_properties["size"] = "CSS1.0,CSS2.0";
289 all_properties["speak-header"] = "CSS2.0,CSS2.1";
290 all_properties["table-layout"] = "CSS2.0,CSS2.1";
291 all_properties["top"] = "CSS1.0,CSS2.0,CSS2.1";
292 all_properties["text-indent"] = "CSS1.0,CSS2.0,CSS2.1";
293 all_properties["text-align"] = "CSS1.0,CSS2.0,CSS2.1";
294 all_properties["text-decoration"] = "CSS1.0,CSS2.0,CSS2.1";
295 all_properties["text-shadow"] = "CSS2.0";
296 all_properties["letter-spacing"] = "CSS1.0,CSS2.0,CSS2.1";
297 all_properties["word-spacing"] = "CSS1.0,CSS2.0,CSS2.1";
298 all_properties["text-transform"] = "CSS1.0,CSS2.0,CSS2.1";
299 all_properties["white-space"] = "CSS1.0,CSS2.0,CSS2.1";
300 all_properties["unicode-bidi"] = "CSS2.0,CSS2.1";
301 all_properties["vertical-align"] = "CSS1.0,CSS2.0,CSS2.1";
302 all_properties["visibility"] = "CSS1.0,CSS2.0,CSS2.1";
303 all_properties["width"] = "CSS2.0,CSS2.1";
304 all_properties["widows"] = "CSS2.0,CSS2.1";
305 all_properties["z-index"] = "CSS1.0,CSS2.0,CSS2.1";
306 /* Speech */
307 all_properties["volume"] = "CSS2.0,CSS2.1";
308 all_properties["speak"] = "CSS2.0,CSS2.1";
309 all_properties["pause"] = "CSS2.0,CSS2.1";
310 all_properties["pause-before"] = "CSS2.0,CSS2.1";
311 all_properties["pause-after"] = "CSS2.0,CSS2.1";
312 all_properties["cue"] = "CSS2.0,CSS2.1";
313 all_properties["cue-before"] = "CSS2.0,CSS2.1";
314 all_properties["cue-after"] = "CSS2.0,CSS2.1";
315 all_properties["play-during"] = "CSS2.0,CSS2.1";
316 all_properties["azimuth"] = "CSS2.0,CSS2.1";
317 all_properties["elevation"] = "CSS2.0,CSS2.1";
318 all_properties["speech-rate"] = "CSS2.0,CSS2.1";
319 all_properties["voice-family"] = "CSS2.0,CSS2.1";
320 all_properties["pitch"] = "CSS2.0,CSS2.1";
321 all_properties["pitch-range"] = "CSS2.0,CSS2.1";
322 all_properties["stress"] = "CSS2.0,CSS2.1";
323 all_properties["richness"] = "CSS2.0,CSS2.1";
324 all_properties["speak-punctuation"] = "CSS2.0,CSS2.1";
325 all_properties["speak-numeral"] = "CSS2.0,CSS2.1";
326
327 background_prop_default["background-image"] = "none";
328 background_prop_default["background-size"] = "auto";
329 background_prop_default["background-repeat"] = "repeat";
330 background_prop_default["background-position"] = "0 0";
331 background_prop_default["background-attachment"] = "scroll";
332 background_prop_default["background-clip"] = "border";
333 background_prop_default["background-origin"] = "padding";
334 background_prop_default["background-color"] = "transparent";
335
336 at_rules["page"] = is;
337 at_rules["font-face"] = is;
338 at_rules["charset"] = iv;
339 at_rules["import"] = iv;
340 at_rules["namespace"] = iv;
341 at_rules["media"] = at;
342 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_PREPARE
19 #define HEADER_CSS_PREPARE
20
21 void prepare();
22
23 #endif // HEADER_CSS_PREPARE
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19
20 using namespace std;
21
22 string csstidy::_htmlsp(const string istring, const bool plain)
23 {
24 if (!plain) {
25 return htmlspecialchars(istring);
26 }
27 return istring;
28 }
29
30 void csstidy::_convert_raw_css()
31 {
32 csstokens = vector<token>();
33
34 css.sort();
35
36 for (css_struct::iterator i = css.begin(); i != css.end(); ++i)
37 {
38 if (settings["sort_selectors"]) i->second.sort();
39 if (i->first != "standard") {
40 add_token(AT_START, i->first, true);
41 }
42
43 for(sstore::iterator j = i->second.begin(); j != i->second.end(); ++j)
44 {
45 if (settings["sort_properties"]) j->second.sort();
46 add_token(SEL_START, j->first, true);
47
48 for(umap<string,string>::iterator k = j->second.begin(); k != j->second.end(); ++k)
49 {
50 add_token(PROPERTY, k->first, true);
51 add_token(VALUE, k->second, true);
52 }
53
54 add_token(SEL_END, j->first, true);
55 }
56
57 if (i->first != "standard") {
58 add_token(AT_END, i->first, true);
59 }
60 }
61 }
62
63 int csstidy::_seeknocomment(const int key, int move)
64 {
65 int go = (move > 0) ? 1 : -1;
66 for (int i = key + 1; abs(key-i)-1 < abs(move); i += go) {
67 if (i < 0 || i > csstokens.size()) {
68 return -1;
69 }
70 if (csstokens[i].type == COMMENT) {
71 move += 1;
72 continue;
73 }
74 return csstokens[i].type;
75 }
76 }
77
78 void csstidy::print_css(string filename)
79 {
80 if(css.empty() && charset == "" && namesp == "" && import.empty() && csstokens.empty())
81 {
82 if(!settings["silent"]) cout << "Invalid CSS!" << endl;
83 return;
84 }
85
86 ofstream file_output;
87 if(filename != "")
88 {
89 file_output.open(filename.c_str(),ios::binary);
90 if(file_output.bad())
91 {
92 if(!settings["silent"]) cout << "Error when trying to save the output file!" << endl;
93 return;
94 }
95 }
96
97 if(!settings["preserve_css"]) {
98 _convert_raw_css();
99 }
100
101 if(!settings["allow_html_in_templates"])
102 {
103 for(int i = 0; i < csstemplate.size(); ++i)
104 {
105 csstemplate[i] = strip_tags(csstemplate[i]);
106 }
107 }
108
109 stringstream output, in_at_out;
110
111 if (settings["timestamp"]) {
112 time_t rawtime;
113 time(&rawtime);
114 token temp;
115 temp.data = " CSSTidy ";
116 temp.data += CSSTIDY_VERSION;
117 temp.data += ": " + rtrim(asctime (localtime ( &rawtime ))) + " ";
118 temp.type = COMMENT;
119 csstokens.insert(csstokens.begin(), temp);
120 }
121
122 if(charset != "")
123 {
124 output << csstemplate[0] << "@charset " << csstemplate[5] << charset << csstemplate[6];
125 }
126
127 if(import.size() > 0)
128 {
129 for(int i = 0; i < import.size(); i ++)
130 {
131 output << csstemplate[0] << "@import " << csstemplate[5] << import[i] << csstemplate[6];
132 }
133 }
134
135 if(namesp != "")
136 {
137 output << csstemplate[0] << "@namespace " << csstemplate[5] << namesp << csstemplate[6];
138 }
139
140 output << csstemplate[13];
141 stringstream* out =& output;
142
143 bool plain = !settings["allow_html_in_templates"];
144
145 for (int i = 0; i < csstokens.size(); ++i)
146 {
147 switch (csstokens[i].type)
148 {
149 case AT_START:
150 *out << csstemplate[0] << _htmlsp(csstokens[i].data, plain) + csstemplate[1];
151 out =& in_at_out;
152 break;
153
154 case SEL_START:
155 if(settings["lowercase_s"]) csstokens[i].data = strtolower(csstokens[i].data);
156 *out << ((csstokens[i].data[0] != '@') ? csstemplate[2] + _htmlsp(csstokens[i].data, plain) : csstemplate[0] + _htmlsp(csstokens[i].data, plain));
157 *out << csstemplate[3];
158 break;
159
160 case PROPERTY:
161 if(settings["case_properties"] == 2) csstokens[i].data = strtoupper(csstokens[i].data);
162 if(settings["case_properties"] == 1) csstokens[i].data = strtolower(csstokens[i].data);
163 *out << csstemplate[4] << _htmlsp(csstokens[i].data, plain) << ":" << csstemplate[5];
164 break;
165
166 case VALUE:
167 *out << _htmlsp(csstokens[i].data, plain);
168 if(_seeknocomment(i, 1) == SEL_END && settings["remove_last_;"]) {
169 *out << str_replace(";", "", csstemplate[6]);
170 } else {
171 *out << csstemplate[6];
172 }
173 break;
174
175 case SEL_END:
176 *out << csstemplate[7];
177 if(_seeknocomment(i, 1) != AT_END) *out << csstemplate[8];
178 break;
179
180 case AT_END:
181 out =& output;
182 *out << csstemplate[10] << str_replace("\n", "\n" + csstemplate[10], in_at_out.str());
183 in_at_out.str("");
184 *out << csstemplate[9];
185 break;
186
187 case COMMENT:
188 *out << csstemplate[11] << "/*" << _htmlsp(csstokens[i].data, plain) << "*/" << csstemplate[12];
189 break;
190 }
191 }
192
193 string output_string = trim(output.str());
194
195 if(!settings["silent"]) {
196 cout << endl << "Selectors: " << selectors << " | Properties: " << properties << endl;
197 float ratio = round(((input_size - (float) output_string.length())/input_size)*100,2);
198 float i_b = round(((float) input_size)/1024,3);
199 float o_b = round(((float) output_string.length())/1024,3);
200 cout << "Input size: " << i_b << "KiB Output size: " << o_b << "KiB Compression ratio: " << ratio << "%" << endl;
201 }
202
203 if(filename == "")
204 {
205 if(!settings["silent"]) cout << "-----------------------------------\n\n";
206 cout << output_string << "\n";
207 }
208 else
209 {
210 file_output << output_string;
211 }
212
213 if(logs.size() > 0 && !settings["silent"])
214 {
215 cout << "-----------------------------------\n\n";
216 for(map<int, vector<message> >::iterator j = logs.begin(); j != logs.end(); j++ )
217 {
218 for(int i = 0; i < j->second.size(); ++i)
219 {
220 cout << j->first << ": " << j->second[i].m << "\n" ;
221 }
222 }
223 }
224
225 if(!settings["silent"]) {
226 cout << "\n-----------------------------------" << endl << "CSSTidy " << CSSTIDY_VERSION << " by Florian Schmitz 2005, 2006" << endl;
227 }
228 file_output.close();
229 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include "csspp_globals.hpp"
19 using namespace std;
20
21 const string trim(const string istring)
22 {
23 std::string::size_type first = istring.find_first_not_of(" \n\t\r\0xb");
24 if (first == std::string::npos) {
25 return std::string();
26 }
27 else {
28 std::string::size_type last = istring.find_last_not_of(" \n\t\r\0xb");
29 return istring.substr( first, last - first + 1);
30 }
31 }
32
33 const string ltrim(const string istring)
34 {
35 std::string::size_type first = istring.find_first_not_of(" \n\t\r\0xb");
36 if (first == std::string::npos) {
37 return std::string();
38 }
39 else {
40 return istring.substr( first );
41 }
42 }
43
44
45 const string rtrim(const string istring)
46 {
47 std::string::size_type last = istring.find_last_not_of(" \n\t\r\0xb"); /// must succeed
48 return istring.substr( 0, last + 1);
49 }
50
51 const string rtrim(const string istring, const string chars)
52 {
53 std::string::size_type last = istring.find_last_not_of(chars); /// must succeed
54 return istring.substr( 0, last + 1);
55 }
56
57 string strip_tags(string istring)
58 {
59 bool intag = false;
60 string new_string;
61
62 for(int i = 0; i < istring.length(); i++)
63 {
64 if(istring[i] != '<' && !intag)
65 {
66 new_string += istring[i];
67 }
68 if(istring[i] == '<' && !intag)
69 {
70 intag = true;
71 }
72 if(istring[i] == '>' && intag)
73 {
74 intag = false;
75 }
76 }
77 return new_string;
78 }
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef HEADER_CSS_TRIM
19 #define HEADER_CSS_TRIM
20
21 // Removes whitespace at the end and beginning of a string
22 const string trim(const string istring);
23
24 // Removes whitespace at the beginning of a string
25 const string ltrim(const string istring);
26
27 // Removes whitespace at the end of a string
28 const string rtrim(const string istring);
29 const string rtrim(const string istring, const string chars);
30
31 // Removes HTML tags
32 string strip_tags(string istring);
33
34 #endif // HEADER_CSS_TRIM
0 /*
1 * This file is part of CSSTidy.
2 *
3 * CSSTidy is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * CSSTidy is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with CSSTidy; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include <cstdlib>
19 #include <iostream>
20 #include <string>
21 #include <vector>
22 #include <map>
23 #include <algorithm>
24 #include <iterator>
25 using namespace std;
26
27
28 template <class keyT, class valT>
29 class umap
30 {
31 typedef map<keyT,valT> StoreT;
32 typedef std::vector<typename StoreT::iterator> FifoT;
33 private:
34 FifoT sortv;
35 StoreT content;
36
37 public:
38 // Functions, same as map<> (simplified)
39 void erase(const keyT& key)
40 {
41 for (typename FifoT::iterator i = sortv.begin(), e = sortv.end(); i != e; ++i)
42 {
43 if( (*i)->first == key)
44 {
45 content.erase(*i);
46 sortv.erase(i);
47 return;
48 }
49 }
50 }
51
52 int size()
53 {
54 return content.size();
55 }
56
57 bool empty()
58 {
59 return content.empty();
60 }
61
62 void sort()
63 {
64 sortv.clear();
65 for(typename StoreT::iterator i = content.begin(), e = content.end(); i != e; ++i)
66 {
67 sortv.push_back(i);
68 }
69 }
70
71 // Checks if the map has the key
72 bool has(const keyT key)
73 {
74 return (content.find(key) != content.end());
75 }
76
77 void operator=(umap<keyT,valT>& set)
78 {
79 sortv.clear();
80 content = set.content;
81 for(typename map<keyT,valT>::iterator i = content.begin(); i != content.end(); ++i)
82 {
83 sortv.push_back(i);
84 }
85 }
86
87 bool operator==(umap<keyT,valT>& comp) const
88 {
89 if(sortv.size() != comp.sortv.size())
90 {
91 return false;
92 }
93
94 for(int i = 0; i < sortv.size(); ++i)
95 {
96 if(sortv[i]->first != comp.sortv[i]->first)
97 {
98 return false;
99 }
100 }
101
102 return (content == comp.content);
103 }
104
105 // Access the map per [] or at()
106 valT& operator[](keyT const& key )
107 {
108 typename StoreT::iterator mIt = content.find(key);
109 if (mIt == content.end())
110 {
111 mIt = content.insert(typename StoreT::value_type(key, valT())).first;
112 sortv.push_back(mIt);
113 }
114 return mIt->second;
115 }
116
117 valT& at(int index)
118 {
119 if(index < size() && index >= 0)
120 {
121 return sortv[index]->second;
122 }
123 }
124
125 // Iterator
126
127 class iterator
128 {
129 friend typename umap<keyT,valT>::iterator umap<keyT,valT>::begin();
130 friend typename umap<keyT,valT>::iterator umap<keyT,valT>::end();
131 friend void umap<keyT,valT>::erase(const typename umap<keyT,valT>::iterator& it);
132
133 private:
134 typename FifoT::iterator pos;
135 int num;
136 int size;
137
138 public:
139 iterator()
140 {
141 num = 0;
142 }
143
144 typename umap<keyT,valT>::iterator& operator= (const typename umap<keyT,valT>::iterator& iter)
145 {
146 pos = iter.pos;
147 num = 0;
148 size = 0;
149 return *this;
150 }
151
152 bool islast()
153 {
154 return (num == size-1);
155 }
156
157 void operator++()
158 {
159 ++pos;
160 ++num;
161 }
162
163 void operator++(int)
164 {
165 ++pos;
166 ++num;
167 }
168
169 bool operator!= (typename umap<keyT,valT>::iterator iter)
170 {
171 return (iter.pos != pos);
172 }
173
174 typename StoreT::iterator& operator->()
175 {
176 return *pos;
177 }
178 };
179
180 void erase(const typename umap<keyT,valT>::iterator& it)
181 {
182 content.erase(*it.pos);
183 sortv.erase(it.pos);
184 }
185
186 typename umap<keyT,valT>::iterator begin()
187 {
188 typename umap<keyT,valT>::iterator test;
189 test.pos = sortv.begin();
190 test.size = size();
191 return test;
192 }
193
194 typename umap<keyT,valT>::iterator end()
195 {
196 typename umap<keyT,valT>::iterator test;
197 test.pos = sortv.end();
198 test.size = size();
199 return test;
200 }
201 };