christiaan / inlinestyle Goto Github PK
View Code? Open in Web Editor NEWTransform embedded and external stylesheets to style attributes on the HTML tags.
License: MIT License
Transform embedded and external stylesheets to style attributes on the HTML tags.
License: MIT License
If a stylesheet comes from a different location as the html file that is including it the urls to images are fetched relative to the stylesheet.
As the test shows url("someimage.jpg"); should be replaced with url("testfiles/someimage.jpg"); but only if it is a relative url.
The sortOnSpecificity
function returns 0 if two selectors match specificity exactly. However, as mentioned in the usort
docs, “If two members compare as equal, their relative order in the sorted array is undefined.” This means that sometimes rules get sorted reversed and therefore applied in the wrong cascading order. Simply returning 1 instead of 0 fixes the problem by making sure the later selector is always sorted after the earlier selector.
Hi, I have adapted Symfony CSSSelector class to work standalone, and trying to use InlineStyle Class together with Zend_Mail.
Not sure why this happens, but seems like InlineStyle is changing UTF-8 (local) characters to some strange encoding. Zend_Mail setBodyHtml or setBodyText then making possibly another conversion and finally the mail sent is full of improper symbols.
I've tried to define UTF-8 in all places, where string being loaded, but nothing helps.
Could you please point me(us) how to disable this encoding in InlineStyle to left it to Zend_Mail ?
Many thanks !
Ivan
The stylesheet parser is naive and assumes that there are never nested rules, which is not the case when CSS3 @media
is used. When one of these is encountered, the parser crashes. I don’t know that these actually need to be supported, but it would at least be good if they were safely ignored instead of causing a crash.
Hi,
I have a PHP error :
Fatal error: Uncaught exception 'Exception' with message 'Unknown psuedo-filter: before, in :before' in C:\wwwrootDev_mutualisation\spipsvn\extensions\indispensables\facteur\inline-style\CSSQuery.php on line 270
( ! ) Exception: Unknown psuedo-filter: before, in :before in C:\wwwrootDev_mutualisation\spipsvn\extensions\indispensables\facteur\inline-style\CSSQuery.php on line 270
http://zone.spip.org/trac/spip-zone/changeset/55173 prevents the error, but delete the pseudo tag...
Regards
With a simple template like this:
<head>
<meta charset="UTF-8" />
<style>
@import url('...');
</style>
</head>
<body></body>
I got this error on rendering:
[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Undefined offset: 1
Maybe related to #11.
InlineStyle doesn't appear to respect the media
attribute in <style>
tags, meaning that print stylesheets get processed and included beside regular stylesheets.
This issue only came to light for us once #28 was fixed, as our print stylesheets always come after our usual screen orientated stylesheets.
Example HTML:
<style type="text/css" media="print">
#header {
display:none;
}
</style>
It would be good if InlineStyle only processed screen and global stylesheets.
Hey @christiaan would you be able to create a release to capture the latest changes?
Hi there,
Getting this error when trying to use the code with the latest stable symfony:
ErrorException: The Symfony\Component\CssSelector\CssSelector class is deprecated since version 2.8 and will be removed in 3.0. Use directly the \Symfony\Component\CssSelector\CssSelectorConverter class instead.
Is this fixed in the rewrite and is there a plan for providing a compatible release at some point?
thanks.
Hi found this bug.
The file css wins in order of my inline style..
$content = '<p style="text-align:center">Hello World!</p>';
$htmldoc = new InlineStyle($content);
$htmldoc->applyStylesheet('p{
text-align: left;
}');
echo $htmldoc->getHTML();
this code will output;
<p style="text-align:left">Hello World!</p>
instead:
<p style="text-align:center">Hello World!</p>
If I use russian word where first char is 'И' and it's capital in my html template I have error like:
Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: input conversion failed due to input error, bytes 0x98 0xD0 0xBC 0xD1 in /opt/local/apache2/htdocs/work/eventcatalog/classes/InlineStyle.php on line 84
I got the above error. Does 'InlineStyle' works only with Symfony?
I believe the problem is with the recursion at line 353 of CSSQuery. I think it should be make sure the $new has something before recursing. I changed it to this and it seemed to work:
return (strlen($m[0]) < strlen($expression) && !empty($new))
Steps to reproduce:
$inlineStyleBody = new InlineStyle($body);
$cssDir = new DirectoryIterator("./css");
foreach ($cssDir as $cssFile) {
if ($cssFile->isDot() or $cssFile->getExtension() != 'css') {
continue;
};
$inlineStyleBody->applyStylesheet($cssFile->getPathname());
}
file_put_contents('testout.html', $inlineStyleBody->getHTML())
Expected behavior:
Create HTML-Document with inlined css
Actual behavior:
Returning following error:
Fatal error: Uncaught Error: __clone method called on non-object in /var/www/html/vendor/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php on line 397
Error: __clone method called on non-object in /var/www/html/vendor/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php on line 397
Call Stack:
[...]
0.2193 2416360 4. InlineStyle\InlineStyle->getHTML() /var/www/html/src/MyMail.php:91
0.2193 2416416 5. InlineStyle\InlineStyle->__clone() /var/www/html/vendor/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php:180
Process finished with exit code 255
It looks like InlineStyle.php#L210 and InlineStyle.php#L224 mess up the possibility to use more than one stylesheet.
I suspect this might have to do with removing children while looping through the node.
For now I have forked the project and removed those lines, it's fine for me that the stylesheets remain present in the output. But perhaps we can come up with a nice solution?
Hello there,
it looks like if you use variables inside quotes, they get escaped.
for example:
<a href="mailto:*|EMAIL|*">*|EMAIL|*</a>
The result would be:
<a href="mailto:*%7CEMAIL%7C*>[email protected]</a>
Any ideas on how to make it ignore specific chars inside quotes?
When the :active
selector is used (I know inlined pseudo selectors don't work with most browsers and renderers, but they do exist in Zurb's Ink css styles), we get a warning within the CssSelector
library. I did not have time to investigate whether this is due to the CssSelector
or otherwise, but I have tested using the master of CssSelector
and the issue still persists.
To reproduce:
$html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
a:active {
color: #2795b6 !important;
}
}
</style>
</head>
<body>
<a href="google.com">blah</a>
</body>
</html>';
$htmldoc = new InlineStyle\InlineStyle($html);
$htmldoc->applyStylesheet($htmldoc->extractStylesheets());
echo($htmldoc->getHTML());
The error we get:
Warning: array_map(): An error occurred while invoking the map callback in /work/test/CssSelector/XPath/Translator.php on line 137
I get the following notice:
Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead
Other than that, the inlining is working well.
Hi, first off thank you for writing a great library. Very useful.
I had some trouble with self-closing tags when using the InlineStyle. Everytime I used the getHTML() method my self-closing tags were left unclosed, and it was breaking some further XML parsing that I was doing with simplexml.
It turns out the issue was caused by DOMDocument->saveHTML() generating non-xHTML compliant markup (reference: http://stackoverflow.com/questions/3145237/why-doesnt-php-dom-include-slash-on-self-closing-tags).
My solution for this particular case was to extend the class and add a single method, getXML() which looked like this:
class foo extends InlineStyle {
function getXML() {
return return $this->_dom->saveXML();
}
}
I think it would be useful to include that in this class, especially since the _dom property is protected.
I'm using an older version and would like to get the most recent version without the symphony stuff. Any chance to get that?
This is not an issue rather the lack of knowledge:
How can I integrate this into my code?
function inline_style($html){
//some other stuff
require_once 'classes/libs/InlineStyle/InlineStyle.php'; //correct
$inlinedHtml = InlineStyle::inline($html, [
'formatOutput' => true,
'charset' => 'utf8',
'devices' => ['all', 'screen', 'handheld'],
'baseUrl' => 'http://example.com'
]);
//some other stuff
}
always causes a 500 error
getScoreForSelector treats pseudo-classes like pseudo-elements, but they actually have the same specificity as a regular class. It also does not handle :not()
correctly, and it does not handle attribute selectors at all. The diff below is not perfect but it improves the situation:
diff --git a/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php b/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php
index 4e22a29..74f1927 100644
--- a/protected/vendors/composer/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php
+++ b/protected/vendors/composer/inlinestyle/inlinestyle/InlineStyle/InlineStyle.php
@@ -270,9 +270,9 @@ class InlineStyle
public function getScoreForSelector($selector)
{
return array(
- preg_match_all('/#\w/i', $selector, $result), // ID's
- preg_match_all('/\.\w/i', $selector, $result), // Classes
- preg_match_all('/^\w|\ \w|\(\w|\:[^not]/i', $selector, $result) // Tags
+ preg_match_all('/#\w/i', $selector, $result), // IDs
+ preg_match_all('/\.\w|\[|(?<!:):(?!not\(|before|after|:)/i', $selector, $result), // Classes, attributes, and pseudo-classes
+ preg_match_all('/^\w|\ \w|\(\w|:(?::|before|after)/i', $selector, $result) // Tags and pseudo-elements
);
}
Create a CSS Selector interface which can be implemented by the various adapters.
Create a adapter for CSSQuery
Create a adapter for Zend_Dom_Query
http://framework.zend.com/manual/en/zend.dom.query.html
Should add more pseudo elements, in my case ':link' to prevent "Unknown psuedo-filter" errors
false === stripos($sel, ":active") &&
false === stripos($sel, ":link") && //add this at line 96
false === stripos($sel, ":visited")) {
InlineStyle->_styleToArray
assumes that the regular expression will always succeed to match a rule. However, this is not the case when a stylesheet contains technically invalid CSS (like CSS that uses the star hack). This function should check to see whether $matches
is empty before continuing.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.