Import Upstream version 1.2
HÃ¥vard Flaget Aasen
4 years ago
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 |
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("&","&",istring); | |
153 | istring = str_replace("<","<",istring); | |
154 | istring = str_replace(">",">",istring); | |
155 | if(quotes > 0) istring = str_replace("\"",""",istring); | |
156 | if(quotes > 1) istring = str_replace("'","'",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 | }; |