Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
bc9c824
Beter .travis.yml file
tijsverkoyen Nov 20, 2015
2e811ee
use .dist-file
tijsverkoyen Nov 20, 2015
d914bfc
Gemfile isn't relevant
tijsverkoyen Nov 20, 2015
8834d44
The 2.0 version is a major overhaul, which is *not* backwards compati…
tijsverkoyen Nov 20, 2015
6588053
Trying to fix coverage
tijsverkoyen Nov 20, 2015
4c91066
Use PHPUnit 4.8 instead of 5.0 as it requires php 5.6
tijsverkoyen Nov 20, 2015
8ab9519
Added some badges
tijsverkoyen Nov 20, 2015
acff817
Fixed some issues detected with SensioLabsInsight
tijsverkoyen Nov 20, 2015
7fd7152
Added a test to check if the order is maintained based on #83
tijsverkoyen Nov 20, 2015
4e7c36c
Added some more test to check if all media-queries are stripped.
tijsverkoyen Nov 20, 2015
8e20106
Use the container based infrastructure
tijsverkoyen Nov 23, 2015
c6359dc
More readable code for converting a string into a property
tijsverkoyen Nov 23, 2015
ea182c6
Fixed issue with comparing Specificity
tijsverkoyen Nov 23, 2015
e3b7322
Fixed some PHPDoc
tijsverkoyen Nov 23, 2015
d1452b4
Skip empty properties
tijsverkoyen Nov 23, 2015
d48d4f3
More performant code
tijsverkoyen Nov 23, 2015
b383440
Better method-name
tijsverkoyen Nov 23, 2015
fa040ce
Fixed a stupid mistake where I called a method twice
tijsverkoyen Nov 23, 2015
06dd977
: doesn't have a cased variant
tijsverkoyen Nov 24, 2015
10ec2eb
Better PHPdoc
tijsverkoyen Nov 24, 2015
e1d0d5e
Use inline styles if they are present in $html
tijsverkoyen Nov 24, 2015
5e3d8d4
Fixed typo
tijsverkoyen Nov 24, 2015
83dd16b
Tests!
tijsverkoyen Nov 24, 2015
22e6c63
Tests
tijsverkoyen Nov 24, 2015
ec045ca
Append to existing rules
tijsverkoyen Nov 27, 2015
e6d3d62
Rewrote a big part to respect specificity
tijsverkoyen Dec 8, 2015
560c9f7
Cleanup tests
tijsverkoyen Dec 8, 2015
b1c0d16
Scrutinizer Auto-Fixes
scrutinizer-auto-fixer Dec 8, 2015
a2d94cc
Merge pull request #116 from tijsverkoyen/scrutinizer-patch-1
tijsverkoyen Dec 8, 2015
174bb9e
Processed some feedback
tijsverkoyen Dec 8, 2015
b09df2a
Extend Symfony\Component\CssSelector\Node\Specificity
tijsverkoyen Dec 8, 2015
21d03f6
Don't use getValue() anymore
tijsverkoyen Dec 8, 2015
2480865
Don't extend the Symfony class anymore, as calculating the Specificit…
tijsverkoyen Dec 8, 2015
e22d569
Fixed some PHPDoc
tijsverkoyen Dec 8, 2015
de745ff
Added a branch-alias
tijsverkoyen Dec 8, 2015
2851b4a
Allow 5.1 also
tijsverkoyen Dec 8, 2015
b016b8d
Allow Symfony/CssSelector v3.0
tijsverkoyen Dec 8, 2015
f622480
Cleanup
tijsverkoyen Dec 8, 2015
af10a75
Use ParseException instead of SyntaxErrorException
barryvdh Dec 8, 2015
c82c919
Use ExceptionInterface instead of ParseException
barryvdh Dec 8, 2015
4b9c31b
Merge pull request #119 from barryvdh/patch-4
tijsverkoyen Dec 8, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
/vendor
composer.lock
Gemfile.lock
28 changes: 16 additions & 12 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
language: php

php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm

matrix:
include:
- php: 5.4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd recommend dropping php 5.4 support too tbh

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe set the min version to 5.5.9?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

travis lets you test on 5.5.9 as well as 5.5.x

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 174bb9e

- php: 5.5
- php: 5.6
- php: 7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7.0 would be better

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 174bb9e

- php: nightly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nightly's not really needed

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 174bb9e

- php: hhvm
allow_failures:
- php: 7.0
- php: nightly
- php: hhvm

before_script:
- travis_retry composer self-update
- travis_retry composer install --no-interaction --prefer-source --dev
- composer self-update
- composer install --prefer-source --no-interaction --no-scripts

script:
- vendor/bin/phpunit --verbose --coverage-text
- vendor/bin/phpunit --verbose --coverage-clover=coverage.clover

after_success:
- if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]] && [[ "$TRAVIS_PHP_VERSION" != "nightly" ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi
- if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]] && [[ "$TRAVIS_PHP_VERSION" != "nightly" ]]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Changelog since 1.5.4

The 2.0 version is a major overhaul, which is *not* backwards compatible.

* From now on you can re-use the class for multiple mails.
* A lot less complicated options, as in: no more options at all.
* More separate classes which handle their own (tested) methods.
* A lot more tests

The reason why I did this was to made the class more usable.

# Changelog since 1.5.3

* Fix properties split on base64 encoded url content, thx to [tguyard](https://github.com/Giga-gg),
Expand Down
3 changes: 0 additions & 3 deletions Gemfile

This file was deleted.

25 changes: 13 additions & 12 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ modification, are permitted provided that the following conditions are met:
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

This software is provided by the author "as is" and any express or implied
warranties, including, but not limited to, the implied warranties of
merchantability and fitness for a particular purpose are disclaimed. In no event
shall the author be liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to, procurement
of substitute goods or services; loss of use, data, or profits; or business
interruption) however caused and on any theory of liability, whether in
contract, strict liability, or tort (including negligence or otherwise) arising
in any way out of the use of this software, even if advised of the possibility
of such damage.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 changes: 12 additions & 21 deletions README.md
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# CssToInlineStyles class

[![Build Status](https://travis-ci.org/tijsverkoyen/CssToInlineStyles.svg?branch=master)](https://travis-ci.org/tijsverkoyen/CssToInlineStyles)
[![Build Status](https://travis-ci.org/tijsverkoyen/CssToInlineStyles.svg?branch=master)](https://travis-ci.org/tijsverkoyen/CssToInlineStyles) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/tijsverkoyen/CssToInlineStyles/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/tijsverkoyen/CssToInlineStyles/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/tijsverkoyen/CssToInlineStyles/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/tijsverkoyen/CssToInlineStyles/?branch=master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/5c0ce94f-de6d-403e-9e0a-431268deb75c/mini.png)](https://insight.sensiolabs.com/projects/5c0ce94f-de6d-403e-9e0a-431268deb75c)

## Installation

> CssToInlineStyles is a class that enables you to convert HTML-pages/files into
> HTML-pages/files with inline styles. This is very usefull when you're sending
Expand All @@ -22,28 +24,17 @@ $ composer require tijsverkoyen/css-to-inline-styles

use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;

// Convert HTML + CSS to HTML with inlined CSS
$cssToInlineStyles= new CssToInlineStyles();
$cssToInlineStyles->setHTML($html);
$cssToInlineStyles->setCSS($css);
$html = $cssToInlineStyles->convert();

// Or use inline-styles blocks from the HTML as CSS
$cssToInlineStyles = new CssToInlineStyles($html);
$cssToInlineStyles->setUseInlineStylesBlock(true);
$html = $cssToInlineStyles->convert();


## Documentation
// create instance
$cssToInlineStyles = new CssToInlineStyles();

The following properties exists and have get/set methods available:
$html = file_get_contents(__DIR__ . '/examples/sumo/index.htm');
$css = file_get_contents(__DIR__ . '/examples/sumo/style.css');

Property | Default | Description
-------|---------|------------
cleanup|false|Should the generated HTML be cleaned?
useInlineStylesBlock |false|Use inline-styles block as CSS.
stripOriginalStyleTags |false|Strip original style tags.
excludeMediaQueries |true|Exclude the media queries from the inlined styles.
// output
echo $cssToInlineStyles->convert(
$html,
$css
);

## Known issues

Expand Down
28 changes: 11 additions & 17 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
{
"name": "tijsverkoyen/css-to-inline-styles",
"type": "library",
"name": "tijsverkoyen/css-to-inline-styles",
"type": "library",
"description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.",
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
"license": "BSD",
"authors": [
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Tijs Verkoyen",
"name": "Tijs Verkoyen",
"email": "[email protected]",
"role": "Developer"
"role": "Developer"
}
],
"require": {
"php": ">=5.3.0",
"symfony/css-selector": "~2.1"
"require": {
"symfony/css-selector": "^2.7"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should keep the PHP requirement to specify the min version

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it, because in the real world there are a lot of outdated servers. I won't support issues with those older version, but I don't want to force them also.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👎

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should defintely keep it

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you guys handle outdated hosting? Do you force everyone to upgrade their servers?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People will never update hosting if libraries keep supporting them. I'm also 👍 for forcing a minimum php version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Laravel, Symfony, Twig, Guzzle, Drupal 8 etc all require 5.5. PHP 5.5 is already security updates only; http://php.net/supported-versions.php

If people need to use old hosting, they can still use the current version.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the 1.x branch supports Symfony 3 now. Your 2.0 version should support it too

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in b016b8d

},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.8"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should also allow phpunit 5, not only 4.8 (4.8 does not officially support PHP 7, even if it mostly works)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 2851b4a

},
"autoload": {
"autoload": {
"psr-4": {
"TijsVerkoyen\\CssToInlineStyles\\": "src"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.5.x-dev"
}
}
}
8 changes: 0 additions & 8 deletions example/config.php

This file was deleted.

9 changes: 4 additions & 5 deletions example/index.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php

require_once 'config.php';
require_once __DIR__ . '/../vendor/autoload.php';

use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
Expand All @@ -11,8 +10,8 @@
$html = file_get_contents(__DIR__ . '/examples/sumo/index.htm');
$css = file_get_contents(__DIR__ . '/examples/sumo/style.css');

$cssToInlineStyles->setHTML($html);
$cssToInlineStyles->setCSS($css);

// output
echo $cssToInlineStyles->convert();
echo $cssToInlineStyles->convert(
$html,
$css
);
5 changes: 2 additions & 3 deletions phpunit.xml → phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
cacheTokens="true"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
Expand All @@ -19,9 +17,10 @@
</testsuites>

<filter>
<whitelist addUncoveredFilesFromWhitelist="false">
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
<exclude>
<directory suffix=".php">tests</directory>
<directory suffix=".php">vendor</directory>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this exclude rules are useless, as tests and vendor are not inside src

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 174bb9e

</exclude>
</whitelist>
Expand Down
42 changes: 42 additions & 0 deletions src/Css/Processor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace TijsVerkoyen\CssToInlineStyles\Css;

use TijsVerkoyen\CssToInlineStyles\Css\Rule\Processor as RuleProcessor;

class Processor
{
/**
* Get the rules from a given CSS-string
*
* @param string $css
* @return array
*/
public function getRules($css)
{
$css = $this->doCleanup($css);
$rulesProcessor = new RuleProcessor();
$rules = $rulesProcessor->splitIntoSeparateRules($css);

return $rulesProcessor->convertArrayToObjects($rules);
}

/**
* @param $css
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing type here

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in e3b7322

* @return mixed|string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the return value is always a string

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

*/
protected function doCleanup($css)
{
// remove media queries
$css = preg_replace('/@media [^{]*{([^{}]|{[^{}]*})*}/', '', $css);

$css = str_replace(array("\r", "\n"), '', $css);
$css = str_replace(array("\t"), ' ', $css);
$css = str_replace('"', '\'', $css);
$css = preg_replace('|/\*.*?\*/|', '', $css);
$css = preg_replace('/\s\s+/', ' ', $css);
$css = trim($css);

return $css;
}
}
108 changes: 108 additions & 0 deletions src/Css/Property/Processor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

namespace TijsVerkoyen\CssToInlineStyles\Css\Property;

class Processor
{
/**
* Split a string into seperate properties
*
* @param string $propertiesString
* @return array
*/
public function splitIntoSeparateProperties($propertiesString)
{
$propertiesString = $this->cleanup($propertiesString);

$properties = (array) explode(';', $propertiesString);
$keysToRemove = array();
$numberOfProperties = count($properties);

for ($i = 0; $i < $numberOfProperties; $i++) {
$properties[$i] = trim($properties[$i]);

// if the new property begins with base64 it is part of the current property
if (isset($properties[$i + 1]) && strpos(trim($properties[$i + 1]), 'base64,') === 0) {
$properties[$i] .= ';' . trim($properties[$i + 1]);
$keysToRemove[] = $i + 1;
}
}

if (!empty($keysToRemove)) {
foreach ($keysToRemove as $key) {
unset($properties[$key]);
}
}

return array_values($properties);
}

/**
* @param $string
* @return mixed|string
*/
protected function cleanup($string)
{
$string = str_replace(array("\r", "\n"), '', $string);
$string = str_replace(array("\t"), ' ', $string);
$string = str_replace('"', '\'', $string);
$string = preg_replace('|/\*.*?\*/|', '', $string);
$string = preg_replace('/\s\s+/', ' ', $string);

$string = trim($string);
$string = rtrim($string, ';');

return $string;
}

/**
* Convert a property-string into an object
*
* @param string $property
* @return Property|null
*/
public function convertToObject($property)
{
$chunks = (array) explode(':', $property, 2);

if (!isset($chunks[1]) || $chunks[1] == '') {
return null;
}

return new Property(trim($chunks[0]), trim($chunks[1]));
}

/**
* Convert an array of property-strings into objects
*
* @param array $properties
* @return array
*/
public function convertArrayToObjects(array $properties)
{
$objects = array();

foreach ($properties as $property) {
$objects[] = $this->convertToObject($property);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't you skip it in case null is returned, to be sure to have only Property objects ?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in d1452b4

}

return $objects;
}

/**
* Build the property-string for multiple properties
*
* @param array $properties
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest documenting it as Property[], which is more specific than array

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e3b7322

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not fixed here (you may have fixed a different place, but not this one)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in e22d569

* @return string
*/
public function buildPropertiesString(array $properties)
{
$chunks = array();

foreach ($properties as $property) {
$chunks[] = $property->toString();
}

return implode(' ', $chunks);
}
}
Loading