Stardict: Isolate resources stylesheets

This commit is contained in:
Abs62 2013-05-23 18:01:50 +04:00
parent 9f1e2c1d63
commit f4734c076c
6 changed files with 150 additions and 130 deletions

View file

@ -21,6 +21,7 @@
#include <QImage>
#include <QPainter>
#include <QRegExp>
namespace Dictionary {
@ -248,6 +249,122 @@ bool Class::loadIconFromFile( QString const & _filename, bool isFullName )
return false;
}
void Class::isolateCSS( QString & css )
{
if( css.isEmpty() )
return;
int currentPos = 0;
QString newCSS;
QString prefix( "span#gdfrom-" );
prefix += QString::fromLatin1( getId().c_str() );
// Strip comments
css.replace( QRegExp( "\\/\\*[^*]*\\*+([^/][^*]*\\*+)*\\/" ), QString() );
for( ; ; )
{
if( currentPos >= css.length() )
break;
QChar ch = css[ currentPos ];
if( ch == '@' )
{
// @ rules
int n = currentPos;
if( css.mid( currentPos, 7 ).compare( "@import", Qt::CaseInsensitive ) == 0 )
{
// Copy rule as is.
n = css.indexOf( ';', currentPos );
int n2 = css.indexOf( '{', currentPos );
if( n2 > 0 && n > n2 )
n = n2 - 1;
}
else
if( css.mid( currentPos, 6 ).compare( "@media", Qt::CaseInsensitive ) == 0 )
{
// We must to parse it content to isolate it.
// Copy all up to '{' and continue parse inside.
n = css.indexOf( '{', currentPos );
}
else
if( css.mid( currentPos, 5 ).compare( "@page", Qt::CaseInsensitive ) == 0 )
{
// Don't copy rule. GD use own page layout.
n = css.indexOf( '}', currentPos );
if( n < 0 )
break;
currentPos = n + 1;
continue;
}
else
{
// Copy rule as is.
n = css.indexOf( '}', currentPos );
}
newCSS.append( css.mid( currentPos, n < 0 ? n : n - currentPos + 1 ) );
if( n < 0 )
break;
currentPos = n + 1;
continue;
}
if( ch == '{' )
{
// Selector declaration block.
// We copy it up to '}' as is.
int n = css.indexOf( '}', currentPos );
newCSS.append( css.mid( currentPos, n == -1 ? n : n - currentPos + 1 ) );
if( n < 0 )
break;
currentPos = n + 1;
continue;
}
if( ch.isLetter() || ch == '.' || ch == '#' || ch == '*' || ch == '\\' )
{
// This is some selector.
// We must to add the isolate prefix to it.
int n = css.indexOf( QRegExp( "[ \\*\\>\\+,;:\\[\\{\\]]" ), currentPos + 1 );
QString s = css.mid( currentPos, n < 0 ? n : n - currentPos );
if( n < 0 )
{
newCSS.append( s );
break;
}
QString trimmed = s.trimmed();
if( trimmed.compare( "body", Qt::CaseInsensitive ) == 0
|| trimmed.compare( "html", Qt::CaseInsensitive ) == 0 )
{
newCSS.append( s + " " + prefix + " " );
currentPos += 4;
}
else
{
newCSS.append( prefix + " " );
}
n = css.indexOf( QRegExp( "[,;\\{]" ), currentPos );
s = css.mid( currentPos, n < 0 ? n : n - currentPos );
newCSS.append( s );
if( n < 0 )
break;
currentPos = n;
continue;
}
newCSS.append( ch );
++currentPos;
}
css = newCSS;
}
string makeDictionaryId( vector< string > const & dictionaryFiles ) throw()
{
std::vector< string > sortedList;

View file

@ -267,6 +267,9 @@ protected:
// else treat filename as name without extension
bool loadIconFromFile( QString const & filename, bool isFullName = false );
/// Make css content usable only for articles from this dictionary
void isolateCSS( QString & css );
public:
/// Creates a dictionary. The id should be made using

View file

@ -94,4 +94,12 @@ bool isNameOfTiff( string const & name )
endsWith( s, ".tiff" );
}
bool isNameOfCSS( string const & name )
{
string s = simplifyString( name );
return
endsWith( s, ".css" );
}
}

View file

@ -21,6 +21,8 @@ bool isNameOfPicture( string const & );
/// with .tif or tiff). We have this one separately since we need to reconvert
/// TIFF files as WebKit doesn't seem to support them.
bool isNameOfTiff( string const & );
/// Returns true if the name resembles the one of a .css file
bool isNameOfCSS( string const & );
}

129
mdx.cc
View file

@ -15,6 +15,7 @@
#include "audiolink.hh"
#include "ex.hh"
#include "mdictparser.hh"
#include "filetype.hh"
#include <map>
#include <set>
@ -263,9 +264,6 @@ private:
/// Process resource links (images, audios, etc)
QString & filterResource( QString const & articleId, QString & article );
/// Make css content usable only for articles from this dictionary
void isolateCSS( QString & css );
friend class MdxHeadwordsRequest;
friend class MdxArticleRequest;
friend class MddResourceRequest;
@ -737,11 +735,7 @@ void MddResourceRequest::run()
}
}
hasAnyData = true;
}
QString name = gd::toQString( resourceName );
if( name.endsWith( ".css" ) )
if( Filetype::isNameOfCSS( u8ResourceName ) )
{
QString css = QString::fromUtf8( data.data(), data.size() );
dict.isolateCSS( css );
@ -750,128 +744,15 @@ void MddResourceRequest::run()
memcpy( &data.front(), bytes.constData(), bytes.size() );
}
hasAnyData = true;
}
break;
}
finish();
}
void MdxDictionary::isolateCSS( QString & css )
{
if( css.isEmpty() )
return;
int currentPos = 0;
QString newCSS;
QString prefix( "span#gdfrom-" );
prefix += QString::fromLatin1( getId().c_str() );
// Strip comments
css.replace( QRegExp( "\\/\\*[^*]*\\*+([^/][^*]*\\*+)*\\/" ), QString() );
for( ; ; )
{
if( currentPos >= css.length() )
break;
QChar ch = css[ currentPos ];
if( ch == '@' )
{
// @ rules
int n = currentPos;
if( css.mid( currentPos, 7 ).compare( "@import", Qt::CaseInsensitive ) == 0 )
{
// Copy rule as is.
n = css.indexOf( ';', currentPos );
int n2 = css.indexOf( '{', currentPos );
if( n2 > 0 && n > n2 )
n = n2 - 1;
}
else
if( css.mid( currentPos, 6 ).compare( "@media", Qt::CaseInsensitive ) == 0 )
{
// We must to parse it content to isolate it.
// Copy all up to '{' and continue parse inside.
n = css.indexOf( '{', currentPos );
}
else
if( css.mid( currentPos, 5 ).compare( "@page", Qt::CaseInsensitive ) == 0 )
{
// Don't copy rule. GD use own page layout.
n = css.indexOf( '}', currentPos );
if( n < 0 )
break;
currentPos = n + 1;
continue;
}
else
{
// Copy rule as is.
n = css.indexOf( '}', currentPos );
}
newCSS.append( css.mid( currentPos, n < 0 ? n : n - currentPos + 1 ) );
if( n < 0 )
break;
currentPos = n + 1;
continue;
}
if( ch == '{' )
{
// Selector declaration block.
// We copy it up to '}' as is.
int n = css.indexOf( '}', currentPos );
newCSS.append( css.mid( currentPos, n == -1 ? n : n - currentPos + 1 ) );
if( n < 0 )
break;
currentPos = n + 1;
continue;
}
if( ch.isLetter() || ch == '.' || ch == '#' || ch == '*' || ch == '\\' )
{
// This is some selector.
// We must to add the isolate prefix to it.
int n = css.indexOf( QRegExp( "[ \\*\\>\\+,;:\\[\\{\\]]" ), currentPos + 1 );
QString s = css.mid( currentPos, n < 0 ? n : n - currentPos );
if( n < 0 )
{
newCSS.append( s );
break;
}
QString trimmed = s.trimmed();
if( trimmed.compare( "body", Qt::CaseInsensitive ) == 0
|| trimmed.compare( "html", Qt::CaseInsensitive ) == 0 )
{
newCSS.append( s + " " + prefix + " " );
currentPos += 4;
}
else
{
newCSS.append( prefix + " " );
}
n = css.indexOf( QRegExp( "[,;\\{]" ), currentPos );
s = css.mid( currentPos, n < 0 ? n : n - currentPos );
newCSS.append( s );
if( n < 0 )
break;
currentPos = n;
continue;
}
newCSS.append( ch );
++currentPos;
}
css = newCSS;
}
sptr<Dictionary::DataRequest> MdxDictionary::getResource( const string & name ) throw( std::exception )
{
return new MddResourceRequest( *this, name );

View file

@ -1084,8 +1084,17 @@ void StardictResourceRequest::run()
}
}
if( Filetype::isNameOfCSS( resourceName ) )
{
Mutex::Lock _( dataMutex );
QString css = QString::fromUtf8( data.data(), data.size() );
dict.isolateCSS( css );
QByteArray bytes = css.toUtf8();
data.resize( bytes.size() );
memcpy( &data.front(), bytes.constData(), bytes.size() );
}
hasAnyData = true;
}
catch( File::Ex & )