/*
* This file is part of CSSTidy.
*
* CSSTidy is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* CSSTidy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CSSTidy; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "csspp_globals.hpp"
using namespace std;
string csstidy::_htmlsp(const string istring, const bool plain)
{
if (!plain) {
return htmlspecialchars(istring);
}
return istring;
}
void csstidy::_convert_raw_css()
{
csstokens = vector<token>();
css.sort();
for (css_struct::iterator i = css.begin(); i != css.end(); ++i)
{
if (settings["sort_selectors"]) i->second.sort();
if (i->first != "standard") {
add_token(AT_START, i->first, true);
}
for(sstore::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
if (settings["sort_properties"]) j->second.sort();
add_token(SEL_START, j->first, true);
for(umap<string,string>::iterator k = j->second.begin(); k != j->second.end(); ++k)
{
add_token(PROPERTY, k->first, true);
add_token(VALUE, k->second, true);
}
add_token(SEL_END, j->first, true);
}
if (i->first != "standard") {
add_token(AT_END, i->first, true);
}
}
}
int csstidy::_seeknocomment(const int key, int move)
{
int go = (move > 0) ? 1 : -1;
for (int i = key + 1; abs(key-i)-1 < abs(move); i += go) {
if (i < 0 || i > csstokens.size()) {
return -1;
}
if (csstokens[i].type == COMMENT) {
move += 1;
continue;
}
return csstokens[i].type;
}
}
void csstidy::print_css(string filename)
{
if(css.empty() && charset == "" && namesp == "" && import.empty() && csstokens.empty())
{
if(!settings["silent"]) cout << "Invalid CSS!" << endl;
return;
}
ofstream file_output;
if(filename != "")
{
file_output.open(filename.c_str(),ios::binary);
if(file_output.bad())
{
if(!settings["silent"]) cout << "Error when trying to save the output file!" << endl;
return;
}
}
if(!settings["preserve_css"]) {
_convert_raw_css();
}
if(!settings["allow_html_in_templates"])
{
for(int i = 0; i < csstemplate.size(); ++i)
{
csstemplate[i] = strip_tags(csstemplate[i]);
}
}
stringstream out;
if(charset != "")
{
out << csstemplate[0] << "@charset " << csstemplate[5] << charset << csstemplate[6];
}
if(import.size() > 0)
{
for(int i = 0; i < import.size(); i ++)
{
out << csstemplate[0] << "@import " << csstemplate[5] << import[i] << csstemplate[6];
}
}
if(namesp != "")
{
out << csstemplate[0] << "@namespace " << csstemplate[5] << namesp << csstemplate[6];
}
out << csstemplate[13];
bool in_at = false;
bool plain = !settings["allow_html_in_templates"];
for (int i = 0; i < csstokens.size(); ++i)
{
switch (csstokens[i].type)
{
case AT_START:
out << csstemplate[0] << _htmlsp(csstokens[i].data, plain) + csstemplate[1];
in_at = true;
break;
case SEL_START:
out << ((in_at) ? csstemplate[10] : "");
if(settings["lowercase_s"]) csstokens[i].data = strtolower(csstokens[i].data);
out << ((csstokens[i].data[0] != '@') ? csstemplate[2] + _htmlsp(csstokens[i].data, plain) : csstemplate[0] + _htmlsp(csstokens[i].data, plain));
out << csstemplate[3];
break;
case PROPERTY:
out << ((in_at) ? csstemplate[10] : "");
if(settings["case_properties"] == 2) csstokens[i].data = strtoupper(csstokens[i].data);
if(settings["case_properties"] == 1) csstokens[i].data = strtolower(csstokens[i].data);
out << csstemplate[4] << _htmlsp(csstokens[i].data, plain) << ":" << csstemplate[5];
break;
case VALUE:
out << _htmlsp(csstokens[i].data, plain);
if(_seeknocomment(i, 1) == SEL_END && settings["remove_last_;"]) {
out << str_replace(";", "", csstemplate[6]);
} else {
out << csstemplate[6];
}
break;
case SEL_END:
out << ((in_at) ? csstemplate[10] : "");
out << csstemplate[7];
if(_seeknocomment(i, 1) != AT_END) out << csstemplate[8];
break;
case AT_END:
out << csstemplate[9];
in_at = false;
break;
case COMMENT:
out << ((in_at) ? csstemplate[10] : "");
out << csstemplate[11] << "/*" << _htmlsp(csstokens[i].data, plain) << "*/" << csstemplate[12];
break;
}
}
string c,output;
while(out.good())
{
getline(out,c);
output += c + "\n";
}
output = trim(output);
if(!settings["silent"]) {
cout << endl << "Selectors: " << selectors << " | Properties: " << properties << endl;
float ratio = round(((input_size - (float) output.length())/input_size)*100,2);
float i_b = round(((float) input_size)/1024,3);
float o_b = round(((float) output.length())/1024,3);
cout << "Input size: " << i_b << "KiB Output size: " << o_b << "KiB Compression ratio: " << ratio << "%" << endl;
}
if(filename == "")
{
if(!settings["silent"]) cout << "-----------------------------------\n\n";
cout << output << "\n";
}
else
{
file_output << output;
}
if(logs.size() > 0 && !settings["silent"])
{
cout << "-----------------------------------\n\n";
for(map<int, vector<message> >::iterator j = logs.begin(); j != logs.end(); j++ )
{
for(int i = 0; i < j->second.size(); ++i)
{
cout << j->first << ": " << j->second[i].m << "\n" ;
}
}
}
if(!settings["silent"]) {
cout << "\n-----------------------------------" << endl << "CSSTidy " << CSSTIDY_VERSION << " by Florian Schmitz 2005" << endl;
}
file_output.close();
}