mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 15:34:12 +01:00
N°3851 Update Emogrifier to a version supporting iTop PHP versions range
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
"combodo/tcpdf": "6.3.5",
|
||||
"nikic/php-parser": "^4.12.0",
|
||||
"pear/archive_tar": "1.4.13",
|
||||
"pelago/emogrifier": "2.1.0",
|
||||
"pelago/emogrifier": "3.1.0",
|
||||
"scssphp/scssphp": "1.0.6",
|
||||
"swiftmailer/swiftmailer": "5.4.12",
|
||||
"symfony/console": "3.4.*",
|
||||
|
||||
56
composer.lock
generated
56
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "75f17b71005971207815906ec7e9cf67",
|
||||
"content-hash": "fb56686981ee4945791fe5b93735b022",
|
||||
"packages": [
|
||||
{
|
||||
"name": "combodo/tcpdf",
|
||||
@@ -411,34 +411,34 @@
|
||||
},
|
||||
{
|
||||
"name": "pelago/emogrifier",
|
||||
"version": "v2.1.0",
|
||||
"version": "v3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/emogrifier.git",
|
||||
"reference": "40c3d4f475d44ffc7265a760d1dd0e81f579f96f"
|
||||
"reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/40c3d4f475d44ffc7265a760d1dd0e81f579f96f",
|
||||
"reference": "40c3d4f475d44ffc7265a760d1dd0e81f579f96f",
|
||||
"url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/f6a5c7d44612d86c3901c93f1592f5440e6b2cd8",
|
||||
"reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": "^5.5.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0",
|
||||
"symfony/css-selector": "^3.4.0 || ^4.0.0"
|
||||
"php": "^5.6 || ~7.0 || ~7.1 || ~7.2 || ~7.3 || ~7.4",
|
||||
"symfony/css-selector": "^2.8 || ^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.2.0",
|
||||
"phpmd/phpmd": "^2.6.0",
|
||||
"phpunit/phpunit": "^4.8.0",
|
||||
"squizlabs/php_codesniffer": "^3.3.2"
|
||||
"friendsofphp/php-cs-fixer": "^2.15.3",
|
||||
"phpmd/phpmd": "^2.7.0",
|
||||
"phpunit/phpunit": "^5.7.27",
|
||||
"squizlabs/php_codesniffer": "^3.5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev"
|
||||
"dev-master": "4.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -451,16 +451,6 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "John Reeve",
|
||||
"email": "jreeve@pelagodesign.com"
|
||||
},
|
||||
{
|
||||
"name": "Cameron Brooks"
|
||||
},
|
||||
{
|
||||
"name": "Jaime Prado"
|
||||
},
|
||||
{
|
||||
"name": "Oliver Klee",
|
||||
"email": "github@oliverklee.de"
|
||||
@@ -469,9 +459,19 @@
|
||||
"name": "Zoli Szabó",
|
||||
"email": "zoli.szabo+github@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "John Reeve",
|
||||
"email": "jreeve@pelagodesign.com"
|
||||
},
|
||||
{
|
||||
"name": "Jake Hotson",
|
||||
"email": "jake@qzdesign.co.uk"
|
||||
},
|
||||
{
|
||||
"name": "Cameron Brooks"
|
||||
},
|
||||
{
|
||||
"name": "Jaime Prado"
|
||||
}
|
||||
],
|
||||
"description": "Converts CSS styles into inline style attributes in your HTML code",
|
||||
@@ -481,7 +481,11 @@
|
||||
"email",
|
||||
"pre-processing"
|
||||
],
|
||||
"time": "2018-12-08T13:55:46+00:00"
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/emogrifier/issues",
|
||||
"source": "https://github.com/MyIntervals/emogrifier"
|
||||
},
|
||||
"time": "2019-12-26T19:37:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
@@ -2609,7 +2613,7 @@
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.3",
|
||||
"php": ">=7.1.3 <8.0.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
@@ -2620,7 +2624,7 @@
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.2.0"
|
||||
"php": "7.1.3"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Pelago\Emogrifier\CssInliner;
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
|
||||
|
||||
Swift_Preferences::getInstance()->setCharset('UTF-8');
|
||||
|
||||
|
||||
@@ -335,8 +339,9 @@ class EMail
|
||||
{
|
||||
if (($sMimeType === 'text/html') && ($sCustomStyles !== null))
|
||||
{
|
||||
$emogrifier = new \Pelago\Emogrifier($sBody, $sCustomStyles);
|
||||
$sBody = $emogrifier->emogrify(); // Adds html/body tags if not already present
|
||||
$oDomDocument = CssInliner::fromHtml($sBody)->inlineCss($sCustomStyles)->getDomDocument();
|
||||
HtmlPruner::fromDomDocument($oDomDocument)->removeElementsWithDisplayNone();
|
||||
$sBody = CssToAttributeConverter::fromDomDocument($oDomDocument)->convertCssToVisualAttributes()->render(); // Adds html/body tags if not already present
|
||||
}
|
||||
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
|
||||
$this->m_oMessage->setBody($sBody, $sMimeType);
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Composer\Autoload;
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
@@ -57,6 +59,13 @@ class ClassLoader
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
@@ -300,6 +309,17 @@ class ClassLoader
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,13 +328,17 @@ class ClassLoader
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
@@ -323,6 +347,8 @@ class ClassLoader
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,6 +393,16 @@ class ClassLoader
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,6 @@ return array(
|
||||
'AttributeBoolean' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeCaseLog' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeClass' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeClassAttCodeSet' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeClassState' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeCustomFields' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeDBField' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
@@ -51,7 +50,6 @@ return array(
|
||||
'AttributeEmailAddress' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeEncryptedString' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeEnum' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeEnumSet' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeExternalField' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeExternalKey' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeFinalClass' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
@@ -74,14 +72,12 @@ return array(
|
||||
'AttributePercentage' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributePhoneNumber' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributePropertySet' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeQueryAttCodeSet' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeRedundancySettings' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeSet' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeStopWatch' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeString' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeSubItem' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeTable' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeTagSet' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeTemplateHTML' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeTemplateString' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
'AttributeTemplateText' => $baseDir . '/core/attributedef.class.inc.php',
|
||||
@@ -388,17 +384,9 @@ return array(
|
||||
'DashboardMenuNode' => $baseDir . '/application/menunode.class.inc.php',
|
||||
'Dashlet' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletBadge' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletEmptyCell' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupBy' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupByBars' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupByPie' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupByTable' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletHeaderDynamic' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletHeaderStatic' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletObjectList' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletPlainText' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletProxy' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DashletUnknown' => $baseDir . '/application/dashlet.class.inc.php',
|
||||
'DataTable' => $baseDir . '/application/datatable.class.inc.php',
|
||||
'DataTableConfig' => $baseDir . '/sources/application/UI/Base/Component/DataTable/DataTableConfig/DataTableConfig.php',
|
||||
'Datamatrix' => $vendorDir . '/combodo/tcpdf/include/barcodes/datamatrix.php',
|
||||
@@ -410,21 +398,9 @@ return array(
|
||||
'DeleteException' => $baseDir . '/application/exceptions/DeleteException.php',
|
||||
'DeletionPlan' => $baseDir . '/core/deletionplan.class.inc.php',
|
||||
'DeprecatedCallsLog' => $baseDir . '/core/log.class.inc.php',
|
||||
'DesignerBooleanField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerComboField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerForm' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerFormField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerFormSelectorField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerHiddenField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerIconSelectionField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerIntegerField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerLabelField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerLongTextField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerSortableField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerStaticTextField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerSubFormField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerTabularForm' => $baseDir . '/application/forms.class.inc.php',
|
||||
'DesignerTextField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'Dict' => $baseDir . '/core/dict.class.inc.php',
|
||||
'DictException' => $baseDir . '/application/exceptions/dict/DictException.php',
|
||||
'DictExceptionMissingString' => $baseDir . '/application/exceptions/dict/DictExceptionMissingString.php',
|
||||
@@ -451,6 +427,7 @@ return array(
|
||||
'EventWebService' => $baseDir . '/core/event.class.inc.php',
|
||||
'ExcelBulkExport' => $baseDir . '/core/excelbulkexport.class.inc.php',
|
||||
'ExcelExporter' => $baseDir . '/application/excelexporter.class.inc.php',
|
||||
'ExceptionLog' => $baseDir . '/core/log.class.inc.php',
|
||||
'ExecAsyncTask' => $baseDir . '/core/asynctask.class.inc.php',
|
||||
'ExecutionKPI' => $baseDir . '/core/kpi.class.inc.php',
|
||||
'Expression' => $baseDir . '/core/oql/expression.class.inc.php',
|
||||
@@ -569,11 +546,13 @@ return array(
|
||||
'Page' => $baseDir . '/sources/application/WebPage/Page.php',
|
||||
'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
|
||||
'Pelago\\Emogrifier' => $vendorDir . '/pelago/emogrifier/src/Emogrifier.php',
|
||||
'Pelago\\Emogrifier\\CssConcatenator' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/CssConcatenator.php',
|
||||
'Pelago\\Emogrifier\\CssInliner' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/CssInliner.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\AbstractHtmlProcessor' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/AbstractHtmlProcessor.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\CssToAttributeConverter' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/CssToAttributeConverter.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\HtmlNormalizer' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/HtmlNormalizer.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\HtmlPruner' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/HtmlPruner.php',
|
||||
'Pelago\\Emogrifier\\Utilities\\ArrayIntersector' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/Utilities/ArrayIntersector.php',
|
||||
'Pelago\\Emogrifier\\Utilities\\CssConcatenator' => $vendorDir . '/pelago/emogrifier/src/Emogrifier/Utilities/CssConcatenator.php',
|
||||
'PhpParser\\Builder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder.php',
|
||||
'PhpParser\\BuilderFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php',
|
||||
'PhpParser\\BuilderHelpers' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php',
|
||||
@@ -864,8 +843,6 @@ return array(
|
||||
'RowStatus_Modify' => $baseDir . '/core/bulkchange.class.inc.php',
|
||||
'RowStatus_NewObj' => $baseDir . '/core/bulkchange.class.inc.php',
|
||||
'RowStatus_NoChange' => $baseDir . '/core/bulkchange.class.inc.php',
|
||||
'RunTimeIconSelectionField' => $baseDir . '/application/forms.class.inc.php',
|
||||
'RuntimeDashboard' => $baseDir . '/application/dashboard.class.inc.php',
|
||||
'SQLExpression' => $baseDir . '/core/oql/expression.class.inc.php',
|
||||
'SQLObjectQuery' => $baseDir . '/core/sqlobjectquery.class.inc.php',
|
||||
'SQLObjectQueryBuilder' => $baseDir . '/core/sqlobjectquerybuilder.class.inc.php',
|
||||
|
||||
@@ -22,10 +22,8 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'));
|
||||
|
||||
$includePaths = require __DIR__ . '/include_paths.php';
|
||||
|
||||
@@ -266,7 +266,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'AttributeBoolean' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeCaseLog' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeClassAttCodeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeClassState' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeCustomFields' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeDBField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
@@ -281,7 +280,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'AttributeEmailAddress' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeEncryptedString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeEnum' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeEnumSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeExternalField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeExternalKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeFinalClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
@@ -304,14 +302,12 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'AttributePercentage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributePhoneNumber' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributePropertySet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeQueryAttCodeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeRedundancySettings' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeStopWatch' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeSubItem' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeTable' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeTagSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeTemplateHTML' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeTemplateString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
'AttributeTemplateText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
|
||||
@@ -618,17 +614,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'DashboardMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php',
|
||||
'Dashlet' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletBadge' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletEmptyCell' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupBy' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupByBars' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupByPie' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletGroupByTable' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletHeaderDynamic' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletHeaderStatic' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletObjectList' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletPlainText' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletProxy' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DashletUnknown' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php',
|
||||
'DataTable' => __DIR__ . '/../..' . '/application/datatable.class.inc.php',
|
||||
'DataTableConfig' => __DIR__ . '/../..' . '/sources/application/UI/Base/Component/DataTable/DataTableConfig/DataTableConfig.php',
|
||||
'Datamatrix' => __DIR__ . '/..' . '/combodo/tcpdf/include/barcodes/datamatrix.php',
|
||||
@@ -640,21 +628,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'DeleteException' => __DIR__ . '/../..' . '/application/exceptions/DeleteException.php',
|
||||
'DeletionPlan' => __DIR__ . '/../..' . '/core/deletionplan.class.inc.php',
|
||||
'DeprecatedCallsLog' => __DIR__ . '/../..' . '/core/log.class.inc.php',
|
||||
'DesignerBooleanField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerComboField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerForm' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerFormField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerFormSelectorField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerHiddenField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerIconSelectionField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerIntegerField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerLabelField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerLongTextField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerSortableField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerStaticTextField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerSubFormField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerTabularForm' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'DesignerTextField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'Dict' => __DIR__ . '/../..' . '/core/dict.class.inc.php',
|
||||
'DictException' => __DIR__ . '/../..' . '/application/exceptions/dict/DictException.php',
|
||||
'DictExceptionMissingString' => __DIR__ . '/../..' . '/application/exceptions/dict/DictExceptionMissingString.php',
|
||||
@@ -681,6 +657,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'EventWebService' => __DIR__ . '/../..' . '/core/event.class.inc.php',
|
||||
'ExcelBulkExport' => __DIR__ . '/../..' . '/core/excelbulkexport.class.inc.php',
|
||||
'ExcelExporter' => __DIR__ . '/../..' . '/application/excelexporter.class.inc.php',
|
||||
'ExceptionLog' => __DIR__ . '/../..' . '/core/log.class.inc.php',
|
||||
'ExecAsyncTask' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php',
|
||||
'ExecutionKPI' => __DIR__ . '/../..' . '/core/kpi.class.inc.php',
|
||||
'Expression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
|
||||
@@ -799,11 +776,13 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'Page' => __DIR__ . '/../..' . '/sources/application/WebPage/Page.php',
|
||||
'ParseError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
|
||||
'Pelago\\Emogrifier' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier.php',
|
||||
'Pelago\\Emogrifier\\CssConcatenator' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/CssConcatenator.php',
|
||||
'Pelago\\Emogrifier\\CssInliner' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/CssInliner.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\AbstractHtmlProcessor' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/AbstractHtmlProcessor.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\CssToAttributeConverter' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/CssToAttributeConverter.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\HtmlNormalizer' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/HtmlNormalizer.php',
|
||||
'Pelago\\Emogrifier\\HtmlProcessor\\HtmlPruner' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/HtmlProcessor/HtmlPruner.php',
|
||||
'Pelago\\Emogrifier\\Utilities\\ArrayIntersector' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/Utilities/ArrayIntersector.php',
|
||||
'Pelago\\Emogrifier\\Utilities\\CssConcatenator' => __DIR__ . '/..' . '/pelago/emogrifier/src/Emogrifier/Utilities/CssConcatenator.php',
|
||||
'PhpParser\\Builder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder.php',
|
||||
'PhpParser\\BuilderFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php',
|
||||
'PhpParser\\BuilderHelpers' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php',
|
||||
@@ -1094,8 +1073,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'RowStatus_Modify' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php',
|
||||
'RowStatus_NewObj' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php',
|
||||
'RowStatus_NoChange' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php',
|
||||
'RunTimeIconSelectionField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
|
||||
'RuntimeDashboard' => __DIR__ . '/../..' . '/application/dashboard.class.inc.php',
|
||||
'SQLExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
|
||||
'SQLObjectQuery' => __DIR__ . '/../..' . '/core/sqlobjectquery.class.inc.php',
|
||||
'SQLObjectQueryBuilder' => __DIR__ . '/../..' . '/core/sqlobjectquerybuilder.class.inc.php',
|
||||
|
||||
@@ -418,36 +418,36 @@
|
||||
},
|
||||
{
|
||||
"name": "pelago/emogrifier",
|
||||
"version": "v2.1.0",
|
||||
"version_normalized": "2.1.0.0",
|
||||
"version": "v3.1.0",
|
||||
"version_normalized": "3.1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/emogrifier.git",
|
||||
"reference": "40c3d4f475d44ffc7265a760d1dd0e81f579f96f"
|
||||
"reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/40c3d4f475d44ffc7265a760d1dd0e81f579f96f",
|
||||
"reference": "40c3d4f475d44ffc7265a760d1dd0e81f579f96f",
|
||||
"url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/f6a5c7d44612d86c3901c93f1592f5440e6b2cd8",
|
||||
"reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": "^5.5.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0",
|
||||
"symfony/css-selector": "^3.4.0 || ^4.0.0"
|
||||
"php": "^5.6 || ~7.0 || ~7.1 || ~7.2 || ~7.3 || ~7.4",
|
||||
"symfony/css-selector": "^2.8 || ^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.2.0",
|
||||
"phpmd/phpmd": "^2.6.0",
|
||||
"phpunit/phpunit": "^4.8.0",
|
||||
"squizlabs/php_codesniffer": "^3.3.2"
|
||||
"friendsofphp/php-cs-fixer": "^2.15.3",
|
||||
"phpmd/phpmd": "^2.7.0",
|
||||
"phpunit/phpunit": "^5.7.27",
|
||||
"squizlabs/php_codesniffer": "^3.5.0"
|
||||
},
|
||||
"time": "2018-12-08T13:55:46+00:00",
|
||||
"time": "2019-12-26T19:37:31+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev"
|
||||
"dev-master": "4.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
@@ -461,16 +461,6 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "John Reeve",
|
||||
"email": "jreeve@pelagodesign.com"
|
||||
},
|
||||
{
|
||||
"name": "Cameron Brooks"
|
||||
},
|
||||
{
|
||||
"name": "Jaime Prado"
|
||||
},
|
||||
{
|
||||
"name": "Oliver Klee",
|
||||
"email": "github@oliverklee.de"
|
||||
@@ -479,9 +469,19 @@
|
||||
"name": "Zoli Szabó",
|
||||
"email": "zoli.szabo+github@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "John Reeve",
|
||||
"email": "jreeve@pelagodesign.com"
|
||||
},
|
||||
{
|
||||
"name": "Jake Hotson",
|
||||
"email": "jake@qzdesign.co.uk"
|
||||
},
|
||||
{
|
||||
"name": "Cameron Brooks"
|
||||
},
|
||||
{
|
||||
"name": "Jaime Prado"
|
||||
}
|
||||
],
|
||||
"description": "Converts CSS styles into inline style attributes in your HTML code",
|
||||
@@ -491,6 +491,10 @@
|
||||
"email",
|
||||
"pre-processing"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/emogrifier/issues",
|
||||
"source": "https://github.com/MyIntervals/emogrifier"
|
||||
},
|
||||
"install-path": "../pelago/emogrifier"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,444 +1,437 @@
|
||||
<?php return array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd9ccac3aeaa3cb91f0e1b78b091f496b7c689166',
|
||||
'name' => '__root__',
|
||||
'dev' => true,
|
||||
),
|
||||
'reference' => 'c8dd8c3806d92e19b5a67c16be9d64ceaa2e0524',
|
||||
'name' => '__root__',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c8dd8c3806d92e19b5a67c16be9d64ceaa2e0524',
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd9ccac3aeaa3cb91f0e1b78b091f496b7c689166',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'combodo/tcpdf' => array(
|
||||
'pretty_version' => '6.3.5',
|
||||
'version' => '6.3.5.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../combodo/tcpdf',
|
||||
'aliases' => array(),
|
||||
'reference' => 'aedd4b7b8cf7fcc24e617c405c9d3304150f4b94',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'nikic/php-parser' => array(
|
||||
'pretty_version' => 'v4.12.0',
|
||||
'version' => '4.12.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nikic/php-parser',
|
||||
'aliases' => array(),
|
||||
'reference' => '6608f01670c3cc5079e18c1dab1104e002579143',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'paragonie/random_compat' => array(
|
||||
'pretty_version' => 'v2.0.18',
|
||||
'version' => '2.0.18.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||
'aliases' => array(),
|
||||
'reference' => '0a58ef6e3146256cc3dc7cc393927bcc7d1b72db',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'pear/archive_tar' => array(
|
||||
'pretty_version' => '1.4.13',
|
||||
'version' => '1.4.13.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../pear/archive_tar',
|
||||
'aliases' => array(),
|
||||
'reference' => '19bb8e95490d3e3ad92fcac95500ca80bdcc7495',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'pear/console_getopt' => array(
|
||||
'pretty_version' => 'v1.4.3',
|
||||
'version' => '1.4.3.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../pear/console_getopt',
|
||||
'aliases' => array(),
|
||||
'reference' => 'a41f8d3e668987609178c7c4a9fe48fecac53fa0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'pear/pear-core-minimal' => array(
|
||||
'pretty_version' => 'v1.10.10',
|
||||
'version' => '1.10.10.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../pear/pear-core-minimal',
|
||||
'aliases' => array(),
|
||||
'reference' => '625a3c429d9b2c1546438679074cac1b089116a7',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'pear/pear_exception' => array(
|
||||
'pretty_version' => 'v1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'type' => 'class',
|
||||
'install_path' => __DIR__ . '/../pear/pear_exception',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b14fbe2ddb0b9f94f5b24cf08783d599f776fff0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'pelago/emogrifier' => array(
|
||||
'pretty_version' => 'v3.1.0',
|
||||
'version' => '3.1.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../pelago/emogrifier',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f6a5c7d44612d86c3901c93f1592f5440e6b2cd8',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/cache' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/cache',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/cache-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/container',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/container-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '1.1.2',
|
||||
'version' => '1.1.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'reference' => '446d54b4cb6bf489fc9d75f55843658e6f25d801',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/simple-cache' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/simple-cache',
|
||||
'aliases' => array(),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/simple-cache-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'rsky/pear-core-min' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => 'v1.10.10',
|
||||
),
|
||||
),
|
||||
'scssphp/scssphp' => array(
|
||||
'pretty_version' => '1.0.6',
|
||||
'version' => '1.0.6.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../scssphp/scssphp',
|
||||
'aliases' => array(),
|
||||
'reference' => '5b3c9d704950d8f9637f5110c36c281ec47dc13c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'swiftmailer/swiftmailer' => array(
|
||||
'pretty_version' => 'v5.4.12',
|
||||
'version' => '5.4.12.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../swiftmailer/swiftmailer',
|
||||
'aliases' => array(),
|
||||
'reference' => '181b89f18a90f8925ef805f950d47a7190e9b950',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/cache' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/cache',
|
||||
'aliases' => array(),
|
||||
'reference' => '3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/class-loader' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/class-loader',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e212b06996819a2bce026a63da03b7182d05a690',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/config' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/config',
|
||||
'aliases' => array(),
|
||||
'reference' => 'a599a867d0e4a07c342b5f1e656b3915a540ddbe',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/console' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/console',
|
||||
'aliases' => array(),
|
||||
'reference' => '1ee23b3b659b06c622f2bd2492a229e416eb4586',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/css-selector' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/css-selector',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f819f71ae3ba6f396b4c015bd5895de7d2f1f85f',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/debug' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/debug',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f72e33fdb1170b326e72c3157f0cd456351dd086',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/dependency-injection' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/dependency-injection',
|
||||
'aliases' => array(),
|
||||
'reference' => '0d201916bfb3af939fec3c0c8815ea16c60ac1a2',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/dotenv' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/dotenv',
|
||||
'aliases' => array(),
|
||||
'reference' => 'c7e8e471fea74e868ae797970b383dea89ae548a',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/event-dispatcher' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/event-dispatcher',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f9031c22ec127d4a2450760f81a8677fe8a10177',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/filesystem' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/filesystem',
|
||||
'aliases' => array(),
|
||||
'reference' => '00cdad0936d06fab136944bc2342b762b1c3a4a2',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/finder' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/finder',
|
||||
'aliases' => array(),
|
||||
'reference' => '290ae21279b37bfd287cdcce640d51204e84afdf',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/framework-bundle' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'symfony-bundle',
|
||||
'install_path' => __DIR__ . '/../symfony/framework-bundle',
|
||||
'aliases' => array(),
|
||||
'reference' => '0d61117c7a770da0bd8bbe7ccfa34d8063f272ea',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/http-foundation' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/http-foundation',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd2d0cfe8e319d9df44c4cca570710fcf221d4593',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/http-kernel' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/http-kernel',
|
||||
'aliases' => array(),
|
||||
'reference' => 'c42c8339acb28cfff0fb1786948db4d23d609ff7',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-apcu' => array(
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-apcu',
|
||||
'aliases' => array(),
|
||||
'reference' => 'a8e961c841b9ec52927a87914f8820a1ad8f8116',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-ctype' => array(
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f8f0b461be3385e56d6de3dbb5a0df24c0c275e3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'reference' => '7b4aab9743c30be783b73de055d24a39cf4b954f',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php56' => array(
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php56',
|
||||
'aliases' => array(),
|
||||
'reference' => '53dd1cdf3cb986893ccf2b96665b25b3abb384f4',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php70' => array(
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php70',
|
||||
'aliases' => array(),
|
||||
'reference' => 'af23c7bb26a73b850840823662dda371484926c4',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-util' => array(
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-util',
|
||||
'aliases' => array(),
|
||||
'reference' => '964a67f293b66b95883a5ed918a65354fcd2258f',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/routing' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/routing',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b689ccd48e234ea404806d94b07eeb45f9f6f06a',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/stopwatch' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/stopwatch',
|
||||
'aliases' => array(),
|
||||
'reference' => 'efe0af281ad336bc3b10375c88b117499f1d8494',
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
'symfony/twig-bridge' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'symfony-bridge',
|
||||
'install_path' => __DIR__ . '/../symfony/twig-bridge',
|
||||
'aliases' => array(),
|
||||
'reference' => '49b824ddc7f2d250a1f172349cd9a111d63287c0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/twig-bundle' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'symfony-bundle',
|
||||
'install_path' => __DIR__ . '/../symfony/twig-bundle',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd39ed8f5df62aeeeb27a6f3bf7f58a6c02a58ea9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/var-dumper' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||
'aliases' => array(),
|
||||
'reference' => '569e261461600810845a8305ca3f64abd3e712c0',
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
'symfony/web-profiler-bundle' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'symfony-bundle',
|
||||
'install_path' => __DIR__ . '/../symfony/web-profiler-bundle',
|
||||
'aliases' => array(),
|
||||
'reference' => '3ae27cf1b2776cd68aa15fdb57089970f78bcf11',
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
'symfony/yaml' => array(
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/yaml',
|
||||
'aliases' => array(),
|
||||
'reference' => 'dab657db15207879217fc81df4f875947bf68804',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tecnickcom/tcpdf' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '6.3.5',
|
||||
),
|
||||
),
|
||||
'twig/twig' => array(
|
||||
'pretty_version' => 'v1.42.4',
|
||||
'version' => '1.42.4.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../twig/twig',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e587180584c3d2d6cb864a0454e777bb6dcb6152',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
'combodo/tcpdf' =>
|
||||
array (
|
||||
'pretty_version' => '6.3.5',
|
||||
'version' => '6.3.5.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'aedd4b7b8cf7fcc24e617c405c9d3304150f4b94',
|
||||
),
|
||||
'nikic/php-parser' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.12.0',
|
||||
'version' => '4.12.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '6608f01670c3cc5079e18c1dab1104e002579143',
|
||||
),
|
||||
'paragonie/random_compat' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.0.18',
|
||||
'version' => '2.0.18.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '0a58ef6e3146256cc3dc7cc393927bcc7d1b72db',
|
||||
),
|
||||
'pear/archive_tar' =>
|
||||
array (
|
||||
'pretty_version' => '1.4.13',
|
||||
'version' => '1.4.13.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '19bb8e95490d3e3ad92fcac95500ca80bdcc7495',
|
||||
),
|
||||
'pear/console_getopt' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.4.3',
|
||||
'version' => '1.4.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a41f8d3e668987609178c7c4a9fe48fecac53fa0',
|
||||
),
|
||||
'pear/pear-core-minimal' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.10.10',
|
||||
'version' => '1.10.10.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '625a3c429d9b2c1546438679074cac1b089116a7',
|
||||
),
|
||||
'pear/pear_exception' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b14fbe2ddb0b9f94f5b24cf08783d599f776fff0',
|
||||
),
|
||||
'pelago/emogrifier' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.1.0',
|
||||
'version' => '2.1.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '40c3d4f475d44ffc7265a760d1dd0e81f579f96f',
|
||||
),
|
||||
'psr/cache' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
|
||||
),
|
||||
'psr/cache-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
|
||||
),
|
||||
'psr/container-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/log' =>
|
||||
array (
|
||||
'pretty_version' => '1.1.2',
|
||||
'version' => '1.1.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '446d54b4cb6bf489fc9d75f55843658e6f25d801',
|
||||
),
|
||||
'psr/log-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/simple-cache' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
),
|
||||
'psr/simple-cache-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'rsky/pear-core-min' =>
|
||||
array (
|
||||
'replaced' =>
|
||||
array (
|
||||
0 => 'v1.10.10',
|
||||
),
|
||||
),
|
||||
'scssphp/scssphp' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.6',
|
||||
'version' => '1.0.6.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5b3c9d704950d8f9637f5110c36c281ec47dc13c',
|
||||
),
|
||||
'swiftmailer/swiftmailer' =>
|
||||
array (
|
||||
'pretty_version' => 'v5.4.12',
|
||||
'version' => '5.4.12.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '181b89f18a90f8925ef805f950d47a7190e9b950',
|
||||
),
|
||||
'symfony/cache' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3',
|
||||
),
|
||||
'symfony/class-loader' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'e212b06996819a2bce026a63da03b7182d05a690',
|
||||
),
|
||||
'symfony/config' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a599a867d0e4a07c342b5f1e656b3915a540ddbe',
|
||||
),
|
||||
'symfony/console' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '1ee23b3b659b06c622f2bd2492a229e416eb4586',
|
||||
),
|
||||
'symfony/css-selector' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f819f71ae3ba6f396b4c015bd5895de7d2f1f85f',
|
||||
),
|
||||
'symfony/debug' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f72e33fdb1170b326e72c3157f0cd456351dd086',
|
||||
),
|
||||
'symfony/dependency-injection' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '0d201916bfb3af939fec3c0c8815ea16c60ac1a2',
|
||||
),
|
||||
'symfony/dotenv' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c7e8e471fea74e868ae797970b383dea89ae548a',
|
||||
),
|
||||
'symfony/event-dispatcher' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f9031c22ec127d4a2450760f81a8677fe8a10177',
|
||||
),
|
||||
'symfony/filesystem' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '00cdad0936d06fab136944bc2342b762b1c3a4a2',
|
||||
),
|
||||
'symfony/finder' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '290ae21279b37bfd287cdcce640d51204e84afdf',
|
||||
),
|
||||
'symfony/framework-bundle' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '0d61117c7a770da0bd8bbe7ccfa34d8063f272ea',
|
||||
),
|
||||
'symfony/http-foundation' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd2d0cfe8e319d9df44c4cca570710fcf221d4593',
|
||||
),
|
||||
'symfony/http-kernel' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c42c8339acb28cfff0fb1786948db4d23d609ff7',
|
||||
),
|
||||
'symfony/polyfill-apcu' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a8e961c841b9ec52927a87914f8820a1ad8f8116',
|
||||
),
|
||||
'symfony/polyfill-ctype' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f8f0b461be3385e56d6de3dbb5a0df24c0c275e3',
|
||||
),
|
||||
'symfony/polyfill-mbstring' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '7b4aab9743c30be783b73de055d24a39cf4b954f',
|
||||
),
|
||||
'symfony/polyfill-php56' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '53dd1cdf3cb986893ccf2b96665b25b3abb384f4',
|
||||
),
|
||||
'symfony/polyfill-php70' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'af23c7bb26a73b850840823662dda371484926c4',
|
||||
),
|
||||
'symfony/polyfill-util' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '964a67f293b66b95883a5ed918a65354fcd2258f',
|
||||
),
|
||||
'symfony/routing' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b689ccd48e234ea404806d94b07eeb45f9f6f06a',
|
||||
),
|
||||
'symfony/stopwatch' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'efe0af281ad336bc3b10375c88b117499f1d8494',
|
||||
),
|
||||
'symfony/twig-bridge' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '49b824ddc7f2d250a1f172349cd9a111d63287c0',
|
||||
),
|
||||
'symfony/twig-bundle' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd39ed8f5df62aeeeb27a6f3bf7f58a6c02a58ea9',
|
||||
),
|
||||
'symfony/var-dumper' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '569e261461600810845a8305ca3f64abd3e712c0',
|
||||
),
|
||||
'symfony/web-profiler-bundle' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '3ae27cf1b2776cd68aa15fdb57089970f78bcf11',
|
||||
),
|
||||
'symfony/yaml' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.36',
|
||||
'version' => '3.4.36.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'dab657db15207879217fc81df4f875947bf68804',
|
||||
),
|
||||
'tecnickcom/tcpdf' =>
|
||||
array (
|
||||
'replaced' =>
|
||||
array (
|
||||
0 => '6.3.5',
|
||||
),
|
||||
),
|
||||
'twig/twig' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.42.4',
|
||||
'version' => '1.42.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'e587180584c3d2d6cb864a0454e777bb6dcb6152',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70103)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.3". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
25
lib/pelago/emogrifier/.gitignore
vendored
25
lib/pelago/emogrifier/.gitignore
vendored
@@ -1,25 +0,0 @@
|
||||
#########################
|
||||
# global ignore file
|
||||
########################
|
||||
# ignoring temporary files (left by e.g. vim)
|
||||
# ignoring by common IDE's used directories/files
|
||||
# dont ignore .rej and .orig as we want to see/clean files after conflict resolution
|
||||
#
|
||||
# for local exclude patterns please edit .git/info/exclude
|
||||
#
|
||||
*~
|
||||
*.bak
|
||||
*.idea
|
||||
*.project
|
||||
*.swp
|
||||
.buildpath
|
||||
.cache
|
||||
.project
|
||||
.session
|
||||
.settings
|
||||
.TemporaryItems
|
||||
.webprj
|
||||
nbproject
|
||||
/.php_cs.cache
|
||||
/vendor/
|
||||
composer.lock
|
||||
@@ -1,65 +0,0 @@
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
- $HOME/.composer/cache
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- DEPENDENCIES_PREFERENCE="--prefer-lowest"
|
||||
- DEPENDENCIES_PREFERENCE=""
|
||||
|
||||
before_install:
|
||||
- phpenv config-rm xdebug.ini || echo "xdebug not available"
|
||||
|
||||
install:
|
||||
- >
|
||||
export IGNORE_PLATFORM_REQS="$(composer php:version |grep -q '^7.3' && printf -- --ignore-platform-reqs)";
|
||||
echo;
|
||||
echo "Updating the dependencies";
|
||||
composer update $IGNORE_PLATFORM_REQS --with-dependencies $DEPENDENCIES_PREFERENCE;
|
||||
composer show;
|
||||
|
||||
script:
|
||||
- >
|
||||
echo;
|
||||
echo "Validating the composer.json";
|
||||
composer validate --no-check-all --no-check-lock --strict;
|
||||
|
||||
- >
|
||||
echo;
|
||||
echo "Linting all PHP files";
|
||||
composer ci:php:lint;
|
||||
|
||||
- >
|
||||
echo;
|
||||
echo "Running the unit tests";
|
||||
composer ci:tests:unit;
|
||||
|
||||
- >
|
||||
echo;
|
||||
echo "Running PHPMD";
|
||||
composer ci:php:md;
|
||||
|
||||
- >
|
||||
echo;
|
||||
function version_gte() { test "$(printf '%s\n' "$@" | sort -n -t. -r | head -n 1)" = "$1"; };
|
||||
if version_gte $(composer php:version) 7; then
|
||||
echo "Installing slevomat/coding-standard only for PHP 7.x";
|
||||
composer require $IGNORE_PLATFORM_REQS --dev slevomat/coding-standard:^4.0 $DEPENDENCIES_PREFERENCE;
|
||||
echo "Running PHP_CodeSniffer";
|
||||
composer ci:php:sniff;
|
||||
else
|
||||
echo "Skipped PHP_CodeSniffer due to insufficient PHP version: $(composer php:version)";
|
||||
fi;
|
||||
@@ -15,6 +15,200 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Fixed
|
||||
|
||||
## 3.1.0
|
||||
|
||||
### Added
|
||||
- Add support for PHP 7.4
|
||||
([#821](https://github.com/MyIntervals/emogrifier/pull/821),
|
||||
[#829](https://github.com/MyIntervals/emogrifier/pull/829))
|
||||
|
||||
### Changed
|
||||
- Upgrade to Symfony 5.0
|
||||
([#822](https://github.com/MyIntervals/emogrifier/pull/820)
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Added
|
||||
- Test and document excluding entire subtree with `addExcludedSelector()`
|
||||
([#347](https://github.com/MyIntervals/emogrifier/issues/347),
|
||||
[#768](https://github.com/MyIntervals/emogrifier/pull/768))
|
||||
- Test that rules with `:optional` or `:required` are copied to the `<style>`
|
||||
element ([#748](https://github.com/MyIntervals/emogrifier/issues/748),
|
||||
[#765](https://github.com/MyIntervals/emogrifier/pull/765))
|
||||
- Test that rules with `:only-of-type` are copied to the `<style>` element
|
||||
([#748](https://github.com/MyIntervals/emogrifier/issues/748),
|
||||
[#760](https://github.com/MyIntervals/emogrifier/pull/760))
|
||||
- Support `:last-of-type`
|
||||
([#748](https://github.com/MyIntervals/emogrifier/issues/748),
|
||||
[#758](https://github.com/MyIntervals/emogrifier/pull/758))
|
||||
- Support `:first-of-type`
|
||||
([#748](https://github.com/MyIntervals/emogrifier/issues/748),
|
||||
[#757](https://github.com/MyIntervals/emogrifier/pull/757))
|
||||
- Support `:empty`
|
||||
([#748](https://github.com/MyIntervals/emogrifier/issues/748),
|
||||
[#756](https://github.com/MyIntervals/emogrifier/pull/756))
|
||||
- Test that rules with `:any-link` are copied to the `<style>` element
|
||||
([#748](https://github.com/MyIntervals/emogrifier/issues/748),
|
||||
[#755](https://github.com/MyIntervals/emogrifier/pull/755))
|
||||
- Support and test `:only-child`
|
||||
([#747](https://github.com/MyIntervals/emogrifier/issues/747),
|
||||
[#754](https://github.com/MyIntervals/emogrifier/pull/754))
|
||||
- Support and test `:nth-last-of-type`
|
||||
([#747](https://github.com/MyIntervals/emogrifier/issues/747),
|
||||
[#751](https://github.com/MyIntervals/emogrifier/pull/751))
|
||||
- Support and test `:nth-last-child`
|
||||
([#747](https://github.com/MyIntervals/emogrifier/issues/747),
|
||||
[#750](https://github.com/MyIntervals/emogrifier/pull/750))
|
||||
- Support and test general sibling combinator
|
||||
([#723](https://github.com/MyIntervals/emogrifier/issues/723),
|
||||
[#745](https://github.com/MyIntervals/emogrifier/pull/745))
|
||||
- Test universal selector with combinators
|
||||
([#723](https://github.com/MyIntervals/emogrifier/issues/723),
|
||||
[#743](https://github.com/MyIntervals/emogrifier/pull/743))
|
||||
- Preserve `display: none` elements with `-emogrifier-keep` class
|
||||
([#252](https://github.com/MyIntervals/emogrifier/issues/252),
|
||||
[#737](https://github.com/MyIntervals/emogrifier/pull/737))
|
||||
- Preserve valid `@import` rules
|
||||
([#338](https://github.com/MyIntervals/emogrifier/issues/338),
|
||||
[#334](https://github.com/MyIntervals/emogrifier/pull/334),
|
||||
[#732](https://github.com/MyIntervals/emogrifier/pull/732),
|
||||
[#735](https://github.com/MyIntervals/emogrifier/pull/735))
|
||||
- Add `HtmlPruner::removeRedundantClassesAfterCssInlined`
|
||||
([#380](https://github.com/MyIntervals/emogrifier/issues/380),
|
||||
[#724](https://github.com/MyIntervals/emogrifier/pull/724))
|
||||
- Check on Travis that PHP-CS-Fixer will not change anything
|
||||
[#727](https://github.com/MyIntervals/emogrifier/pull/727))
|
||||
- Support `:not(…)` as an entire selector
|
||||
([#469](https://github.com/MyIntervals/emogrifier/issues/469),
|
||||
[#725](https://github.com/MyIntervals/emogrifier/pull/725))
|
||||
- Add `HtmlPruner::removeRedundantClasses`
|
||||
([#380](https://github.com/MyIntervals/emogrifier/issues/380),
|
||||
[#708](https://github.com/MyIntervals/emogrifier/pull/708))
|
||||
- Support multiple attributes selectors
|
||||
([#385](https://github.com/MyIntervals/emogrifier/issues/385),
|
||||
[#721](https://github.com/MyIntervals/emogrifier/pull/721))
|
||||
- Support `> :first-child` and `> :last-child` in selectors
|
||||
([#384](https://github.com/MyIntervals/emogrifier/issues/384),
|
||||
[#720](https://github.com/MyIntervals/emogrifier/pull/720))
|
||||
- Add an `ArrayIntersector` class
|
||||
([#708](https://github.com/MyIntervals/emogrifier/pull/708),
|
||||
[#710](https://github.com/MyIntervals/emogrifier/pull/710))
|
||||
- Add `CssInliner::getMatchingUninlinableSelectors`
|
||||
([#380](https://github.com/MyIntervals/emogrifier/issues/380),
|
||||
[#707](https://github.com/MyIntervals/emogrifier/pull/707))
|
||||
- Add tests for `:nth-child` and `:nth-of-type`
|
||||
([#71](https://github.com/MyIntervals/emogrifier/issues/71),
|
||||
[#698](https://github.com/MyIntervals/emogrifier/pull/698))
|
||||
|
||||
### Changed
|
||||
- Relax the dependency on `symfony/css-selector`
|
||||
([#762](https://github.com/MyIntervals/emogrifier/pull/762))
|
||||
- Rename `HtmlPruner::removeInvisibleNodes` to
|
||||
`HtmlPruner::removeElementsWithDisplayNone`
|
||||
([#717](https://github.com/MyIntervals/emogrifier/issues/717),
|
||||
[#718](https://github.com/MyIntervals/emogrifier/pull/718))
|
||||
- Mark the utility classes as internal
|
||||
([#715](https://github.com/MyIntervals/emogrifier/pull/715))
|
||||
- Move utility classes to the `Pelago\Emogrifier\Utilities` namespace
|
||||
([#712](https://github.com/MyIntervals/emogrifier/pull/712))
|
||||
- Make the `$css` parameter of the `inlineCss` method optional
|
||||
([#700](https://github.com/MyIntervals/emogrifier/pull/700))
|
||||
- Update the development dependencies
|
||||
([#691](https://github.com/MyIntervals/emogrifier/pull/691))
|
||||
|
||||
### Deprecated
|
||||
- Support for PHP 5.6 will be removed in Emogrifier 4.0.
|
||||
- Deprecate the `Emogrifier` class
|
||||
([#701](https://github.com/MyIntervals/emogrifier/pull/701))
|
||||
|
||||
### Removed
|
||||
- Drop `enableCssToHtmlMapping` and `disableInvisibleNodeRemoval`
|
||||
([#692](https://github.com/MyIntervals/emogrifier/pull/692))
|
||||
- Drop support for PHP 5.5
|
||||
([#690](https://github.com/MyIntervals/emogrifier/pull/690))
|
||||
|
||||
### Fixed
|
||||
- Fix PhpStorm code inspection warnings
|
||||
([#729](https://github.com/MyIntervals/emogrifier/issues/729),
|
||||
[#770](https://github.com/MyIntervals/emogrifier/pull/770))
|
||||
- Uppercase type combined with class or ID in selector
|
||||
([#590](https://github.com/MyIntervals/emogrifier/issues/590),
|
||||
[#769](https://github.com/MyIntervals/emogrifier/pull/769))
|
||||
- Dynamic pseudo-class combined with static one (rules copied to `<style>`
|
||||
element, [#746](https://github.com/MyIntervals/emogrifier/pull/746))
|
||||
- Descendant attribute selectors (such as `html input[disabled]`)
|
||||
([#375](https://github.com/MyIntervals/emogrifier/pull/375),
|
||||
[#709](https://github.com/MyIntervals/emogrifier/pull/709))
|
||||
- Attribute selectors with hyphen in attribute name
|
||||
([#284](https://github.com/MyIntervals/emogrifier/issues/284),
|
||||
[#540](https://github.com/MyIntervals/emogrifier/pull/540),
|
||||
[#704](https://github.com/MyIntervals/emogrifier/pull/702))
|
||||
- Attribute selectors with space, hyphen, colon, semicolon or (most) other
|
||||
non-alphanumeric characters in attribute value
|
||||
([#284](https://github.com/MyIntervals/emogrifier/issues/284),
|
||||
[#333](https://github.com/MyIntervals/emogrifier/issues/333),
|
||||
[#550](https://github.com/MyIntervals/emogrifier/issues/550),
|
||||
[#540](https://github.com/MyIntervals/emogrifier/pull/540),
|
||||
[#704](https://github.com/MyIntervals/emogrifier/pull/702))
|
||||
- Don’t create empty `style` attributes for unparsable declarations
|
||||
([#259](https://github.com/MyIntervals/emogrifier/issues/259),
|
||||
[#702](https://github.com/MyIntervals/emogrifier/pull/702))
|
||||
- Allow `:not(:behavioural-pseudo-class)` in selectors
|
||||
([#697](https://github.com/MyIntervals/emogrifier/pull/697),
|
||||
[#703](https://github.com/MyIntervals/emogrifier/pull/703))
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Added
|
||||
- Add a `HtmlPruner` class
|
||||
([#679](https://github.com/MyIntervals/emogrifier/pull/679))
|
||||
- Add `AbstractHtmlProcessor::fromDomDocument`
|
||||
([#676](https://github.com/MyIntervals/emogrifier/pull/676))
|
||||
- Add `AbstractHtmlProcessor::fromHtml`
|
||||
([#675](https://github.com/MyIntervals/emogrifier/pull/675))
|
||||
|
||||
### Changed
|
||||
- Make the closures static
|
||||
([#674](https://github.com/MyIntervals/emogrifier/pull/674))
|
||||
- Keep `<wbr>` elements by default with `CssInliner`
|
||||
([#665](https://github.com/MyIntervals/emogrifier/pull/665))
|
||||
- Make the `CssInliner` inherit `AbstractHtmlProcessor`
|
||||
([#660](https://github.com/MyIntervals/emogrifier/pull/660))
|
||||
- Separate `CssInliner::inlineCss` and the rendering
|
||||
([#654](https://github.com/MyIntervals/emogrifier/pull/654))
|
||||
|
||||
### Removed
|
||||
- Drop the removal of unprocessable tags from `CssInliner`
|
||||
([#685](https://github.com/MyIntervals/emogrifier/pull/685))
|
||||
- Drop the removal of invisible nodes from `CssInliner`
|
||||
([#684](https://github.com/MyIntervals/emogrifier/pull/684))
|
||||
|
||||
### Fixed
|
||||
- Remove opening `<body>` tag from `body` content when element has attribute(s)
|
||||
([#677](https://github.com/MyIntervals/emogrifier/issues/677),
|
||||
[#683](https://github.com/MyIntervals/emogrifier/pull/683))
|
||||
- Keep development files out of the Composer packages
|
||||
([#678](https://github.com/MyIntervals/emogrifier/pull/678))
|
||||
- Call all static methods statically in `CssConcatenator`
|
||||
([#670](https://github.com/MyIntervals/emogrifier/pull/670))
|
||||
- Support all HTML5 self-closing tags, including `<embed>`, `<source>`,
|
||||
`<track>` and `<wbr>`
|
||||
([#653](https://github.com/MyIntervals/emogrifier/pull/653))
|
||||
- Remove all "unprocessable" (e.g. `<wbr>`) tags
|
||||
([#650](https://github.com/MyIntervals/emogrifier/pull/650))
|
||||
- Correct translated xpath of `:nth-child` selector
|
||||
([#648](https://github.com/MyIntervals/emogrifier/pull/648))
|
||||
|
||||
## 2.1.1
|
||||
|
||||
### Changed
|
||||
- Add a test that a missing document type gets added
|
||||
([#641](https://github.com/MyIntervals/emogrifier/pull/641))
|
||||
|
||||
### Fixed
|
||||
- Keep the `style` element the `head`
|
||||
([#642](https://github.com/MyIntervals/emogrifier/pull/642))
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Added
|
||||
@@ -26,7 +220,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
([#633](https://github.com/MyIntervals/emogrifier/pull/633))
|
||||
- Add a `getDomDocument()` method
|
||||
([#630](https://github.com/MyIntervals/emogrifier/pull/630))
|
||||
- Add a Composer script for PHP CS Fixer
|
||||
- Add a Composer script for PHP CS Fixer
|
||||
([#607](https://github.com/MyIntervals/emogrifier/pull/607))
|
||||
- Copy matching rules with dynamic pseudo-classes or pseudo-elements in
|
||||
selectors to the style element
|
||||
@@ -34,18 +228,18 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
[#562](https://github.com/MyIntervals/emogrifier/pull/562),
|
||||
[#567](https://github.com/MyIntervals/emogrifier/pull/567))
|
||||
- Add a CssToAttributeConverter
|
||||
([#546](https://github.com/jjriv/emogrifier/pull/546))
|
||||
([#546](https://github.com/MyIntervals/emogrifier/pull/546))
|
||||
- Expose the DOMDocument in AbstractHtmlProcessor
|
||||
([#520](https://github.com/jjriv/emogrifier/pull/520))
|
||||
([#520](https://github.com/MyIntervals/emogrifier/pull/520))
|
||||
- Add an HtmlNormalizer class
|
||||
([#513](https://github.com/jjriv/emogrifier/pull/513),
|
||||
[#516](https://github.com/jjriv/emogrifier/pull/516))
|
||||
([#513](https://github.com/MyIntervals/emogrifier/pull/513),
|
||||
[#516](https://github.com/MyIntervals/emogrifier/pull/516))
|
||||
- Add a CssInliner class
|
||||
([#514](https://github.com/jjriv/emogrifier/pull/514),
|
||||
[#522](https://github.com/jjriv/emogrifier/pull/522))
|
||||
([#514](https://github.com/MyIntervals/emogrifier/pull/514),
|
||||
[#522](https://github.com/MyIntervals/emogrifier/pull/522))
|
||||
- Composer scripts for the various CI build steps
|
||||
- Validate the composer.json on Travis
|
||||
([#476](https://github.com/jjriv/emogrifier/pull/476))
|
||||
([#476](https://github.com/MyIntervals/emogrifier/pull/476))
|
||||
|
||||
### Changed
|
||||
- Mark the work-in-progress classes as `@internal`
|
||||
@@ -62,20 +256,20 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Add type hint checking to the code sniffs
|
||||
([#566](https://github.com/MyIntervals/emogrifier/pull/566))
|
||||
- Check the code with PHPMD
|
||||
([#561](https://github.com/jjriv/emogrifier/pull/561))
|
||||
([#561](https://github.com/MyIntervals/emogrifier/pull/561))
|
||||
- Add the cyclomatic complexity to the checked code sniffs
|
||||
([#558](https://github.com/jjriv/emogrifier/pull/558))
|
||||
([#558](https://github.com/MyIntervals/emogrifier/pull/558))
|
||||
- Use the Symfony CSS selector component
|
||||
([#540](https://github.com/jjriv/emogrifier/pull/540))
|
||||
([#540](https://github.com/MyIntervals/emogrifier/pull/540))
|
||||
|
||||
### Deprecated
|
||||
- Support for PHP 5.5 will be removed in Emogrifier 3.0.
|
||||
- Support for PHP 5.6 will be removed in Emogrifier 4.0.
|
||||
- The removal of invisible nodes will be removed in Emogrifier 3.0.
|
||||
([#473](https://github.com/jjriv/emogrifier/pull/473))
|
||||
([#473](https://github.com/MyIntervals/emogrifier/pull/473))
|
||||
- Converting CSS styles to (non-CSS) HTML attributes will be removed
|
||||
in Emogrifier 3.0. Please use the new CssToAttributeConverter instead.
|
||||
([#474](https://github.com/jjriv/emogrifier/pull/474))
|
||||
([#474](https://github.com/MyIntervals/emogrifier/pull/474))
|
||||
- Emogrifier 3.x.y will be the last release that supports usage without
|
||||
Composer (i.e., you can still require the class file).
|
||||
Starting with version 4.0, Emogrifier will only work with Composer.
|
||||
@@ -114,7 +308,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
ignored, [#507](https://github.com/MyIntervals/emogrifier/pull/507))
|
||||
- Allow attribute selectors in descendants
|
||||
([#506](https://github.com/MyIntervals/emogrifier/pull/506),
|
||||
[#381](https://github.com/MyIntervals/emogrifier/issues/381))
|
||||
[#381](https://github.com/MyIntervals/emogrifier/issues/381),
|
||||
[#443](https://github.com/MyIntervals/emogrifier/issues/443))
|
||||
- Allow adjacent sibling CSS selector combinator in minified CSS
|
||||
([#505](https://github.com/MyIntervals/emogrifier/pull/505))
|
||||
- Allow CSS property values containing newlines
|
||||
@@ -124,7 +319,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Added
|
||||
- Support for CSS :not() selector
|
||||
([#431](https://github.com/jjriv/emogrifier/pull/431))
|
||||
([#431](https://github.com/MyIntervals/emogrifier/pull/431))
|
||||
- Automatically remove !important annotations from final inline style declarations
|
||||
([#420](https://github.com/MyIntervals/emogrifier/pull/420))
|
||||
- Automatically move `<style>` block from `<head>` to `<body>`
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age,
|
||||
body size, disability, ethnicity, gender identity and expression, level of
|
||||
experience, nationality, personal appearance, race, religion, or sexual
|
||||
identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an
|
||||
appointed representative at an online or offline event. Representation of a
|
||||
project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at (emogrifier at myintervals dot com).
|
||||
All complaints will be reviewed and investigated and will result in a response
|
||||
that is deemed necessary and appropriate to the circumstances. The project team
|
||||
is obligated to maintain confidentiality with regard to the reporter of an
|
||||
incident. Further details of specific enforcement policies may be posted
|
||||
separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at
|
||||
[http://contributor-covenant.org/version/1/4/][version].
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -30,11 +30,9 @@ into inline style attributes in your HTML code.
|
||||
- [How it works](#how-it-works)
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
- [Options](#options)
|
||||
- [Installing with Composer](#installing-with-composer)
|
||||
- [Supported CSS selectors](#supported-css-selectors)
|
||||
- [Caveats](#caveats)
|
||||
- [Processing HTML](#processing-html)
|
||||
- [Steps to release a new version](#steps-to-release-a-new-version)
|
||||
- [Maintainers](#maintainers)
|
||||
|
||||
## How it Works
|
||||
@@ -45,15 +43,212 @@ selectors.
|
||||
|
||||
## Installation
|
||||
|
||||
For installing emogrifier, either add pelago/emogrifier to your
|
||||
project's composer.json, or you can use composer as below:
|
||||
For installing emogrifier, either add `pelago/emogrifier` to the `require`
|
||||
section in your project's `composer.json`, or you can use composer as below:
|
||||
|
||||
```bash
|
||||
composer require pelago/emogrifier
|
||||
```
|
||||
|
||||
See https://getcomposer.org/ for more information and documentation.
|
||||
|
||||
## Usage
|
||||
|
||||
### Inlining Css
|
||||
|
||||
The most basic way to use the `CssInliner` class is to create an instance with
|
||||
the original HTML, inline the external CSS, and then get back the resulting
|
||||
HTML:
|
||||
|
||||
```php
|
||||
use Pelago\Emogrifier\CssInliner;
|
||||
|
||||
…
|
||||
|
||||
$visualHtml = CssInliner::fromHtml($html)->inlineCss($css)->render();
|
||||
```
|
||||
|
||||
If there is no external CSS file and all CSS is located within `<style>`
|
||||
elements in the HTML, you can omit the `$css` parameter:
|
||||
|
||||
```php
|
||||
$visualHtml = CssInliner::fromHtml($html)->inlineCss()->render();
|
||||
```
|
||||
|
||||
If you would like to get back only the content of the `<body>` element instead of
|
||||
the complete HTML document, you can use the `renderBodyContent` method instead:
|
||||
|
||||
```php
|
||||
$bodyContent = $visualHtml = CssInliner::fromHtml($html)->inlineCss()
|
||||
->renderBodyContent();
|
||||
```
|
||||
|
||||
If you would like to modify the inlining process with any of the available
|
||||
[options](#options), you will need to call the corresponding methods
|
||||
before inlining the CSS. The code then would look like this:
|
||||
|
||||
```php
|
||||
$visualHtml = CssInliner::fromHtml($html)->disableStyleBlocksParsing()
|
||||
->inlineCss($css)->render();
|
||||
```
|
||||
|
||||
There are also some other HTML-processing classes available
|
||||
(all of which are subclasses of `AbstractHtmlProcessor`) which you can use
|
||||
to further change the HTML after inlining the CSS.
|
||||
(For more details on the classes, please have a look at the sections below.)
|
||||
`CssInliner` and all HTML-processing classes can share the same `DOMDocument`
|
||||
instance to work on:
|
||||
|
||||
```php
|
||||
use Pelago\Emogrifier\CssInliner;
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
|
||||
|
||||
…
|
||||
|
||||
$cssInliner = CssInliner::fromHtml($html)->inlineCss($css);
|
||||
$domDocument = $cssInliner->getDomDocument();
|
||||
HtmlPruner::fromDomDocument($domDocument)->removeElementsWithDisplayNone()
|
||||
->removeRedundantClassesAfterCssInlined($cssInliner);
|
||||
$finalHtml = CssToAttributeConverter::fromDomDocument($domDocument)
|
||||
->convertCssToVisualAttributes()->render();
|
||||
```
|
||||
|
||||
### Normalizing and cleaning up HTML
|
||||
|
||||
The `HtmlNormalizer` class normalizes the given HTML in the following ways:
|
||||
|
||||
- add a document type (HTML5) if missing
|
||||
- disentangle incorrectly nested tags
|
||||
- add HEAD and BODY elements (if they are missing)
|
||||
- reformat the HTML
|
||||
|
||||
The class can be used like this:
|
||||
|
||||
```php
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlNormalizer;
|
||||
|
||||
…
|
||||
|
||||
$cleanHtml = HtmlNormalizer::fromHtml($rawHtml)->render();
|
||||
```
|
||||
|
||||
### Converting CSS styles to visual HTML attributes
|
||||
|
||||
The `CssToAttributeConverter` converts a few style attributes values to visual
|
||||
HTML attributes. This allows to get at least a bit of visual styling for email
|
||||
clients that do not support CSS well. For example, `style="width: 100px"`
|
||||
will be converted to `width="100"`.
|
||||
|
||||
The class can be used like this:
|
||||
|
||||
```php
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
|
||||
|
||||
…
|
||||
|
||||
$visualHtml = CssToAttributeConverter::fromHtml($rawHtml)
|
||||
->convertCssToVisualAttributes()->render();
|
||||
```
|
||||
|
||||
You can also have the `CssToAttributeConverter` work on a `DOMDocument`:
|
||||
|
||||
```php
|
||||
$visualHtml = CssToAttributeConverter::fromDomDocument($domDocument)
|
||||
->convertCssToVisualAttributes()->render();
|
||||
```
|
||||
|
||||
### Removing redundant content and attributes from the HTML
|
||||
|
||||
The `HtmlPruner` class can reduce the size of the HTML by removing elements with
|
||||
a `display: none` style declaration, and/or removing classes from `class`
|
||||
attributes that are not required.
|
||||
|
||||
It can be used like this:
|
||||
|
||||
```php
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
|
||||
|
||||
…
|
||||
|
||||
$prunedHtml = HtmlPruner::fromHtml($html)->removeElementsWithDisplayNone()
|
||||
->removeRedundantClasses($classesToKeep)->render();
|
||||
```
|
||||
|
||||
The `removeRedundantClasses` method accepts a whitelist of names of classes that
|
||||
should be retained. If this is a post-processing step after inlining CSS, you
|
||||
can alternatively use `removeRedundantClassesAfterCssInlined`, passing it the
|
||||
`CssInliner` instance that has inlined the CSS (and having the `HtmlPruner` work
|
||||
on the `DOMDocument`). This will use information from the `CssInliner` to
|
||||
determine which classes are still required (namely, those used in uninlinable
|
||||
rules that have been copied to a `<style>` element):
|
||||
|
||||
```php
|
||||
$prunedHtml = HtmlPruner::fromDomDocument($cssInliner->getDomDocument())
|
||||
->removeElementsWithDisplayNone()
|
||||
->removeRedundantClassesAfterCssInlined($cssInliner)->render();
|
||||
```
|
||||
|
||||
The `removeElementsWithDisplayNone` method will not remove any elements which
|
||||
have the class `-emogrifier-keep`. So if, for example, there are elements which
|
||||
by default have `display: none` but are revealed by an `@media` rule, or which
|
||||
are intended as a preheader, you can add that class to those elements. The
|
||||
paragraph in this HTML snippet will not be removed even though it has
|
||||
`display: none` (which has presumably been applied by `CssInliner::inlineCss()`
|
||||
from a CSS rule `.preheader { display: none; }`):
|
||||
|
||||
```html
|
||||
<p class="preheader -emogrifier-keep" style="display: none;">
|
||||
Hello World!
|
||||
</p>
|
||||
```
|
||||
|
||||
The `removeRedundantClassesAfterCssInlined` (or `removeRedundantClasses`)
|
||||
method, if invoked after `removeElementsWithDisplayNone`, will remove the
|
||||
`-emogrifier-keep` class.
|
||||
|
||||
### Options
|
||||
|
||||
There are several options that you can set on the `CssInliner` instance before
|
||||
calling the `inlineCss` method (or on the `Emogrifier` instance before calling
|
||||
the `emogrify` method):
|
||||
|
||||
* `->disableStyleBlocksParsing()` - By default, `CssInliner` will grab
|
||||
all `<style>` blocks in the HTML and will apply the CSS styles as inline
|
||||
"style" attributes to the HTML. The `<style>` blocks will then be removed
|
||||
from the HTML. If you want to disable this functionality so that `CssInliner`
|
||||
leaves these `<style>` blocks in the HTML and does not parse them, you should
|
||||
use this option. If you use this option, the contents of the `<style>` blocks
|
||||
will _not_ be applied as inline styles and any CSS you want `CssInliner` to
|
||||
use must be passed in as described in the [Usage section](#usage) above.
|
||||
* `->disableInlineStylesParsing()` - By default, `CssInliner`
|
||||
preserves all of the "style" attributes on tags in the HTML you pass to it.
|
||||
However if you want to discard all existing inline styles in the HTML before
|
||||
the CSS is applied, you should use this option.
|
||||
* `->addAllowedMediaType(string $mediaName)` - By default, `CssInliner`
|
||||
will keep only media types `all`, `screen` and `print`. If you want to keep
|
||||
some others, you can use this method to define them.
|
||||
* `->removeAllowedMediaType(string $mediaName)` - You can use this
|
||||
method to remove media types that Emogrifier keeps.
|
||||
* `->addExcludedSelector(string $selector)` - Keeps elements from
|
||||
being affected by CSS inlining. Note that only elements matching the supplied
|
||||
selector(s) will be excluded from CSS inlining, not necessarily their
|
||||
descendants. If you wish to exclude an entire subtree, you should provide
|
||||
selector(s) which will match all elements in the subtree, for example by using
|
||||
the universal selector:
|
||||
```php
|
||||
$cssInliner->addExcludedSelector('.message-preview');
|
||||
$cssInliner->addExcludedSelector('.message-preview *');
|
||||
```
|
||||
|
||||
### Using the legacy Emogrifier class
|
||||
|
||||
In version 3.0.0, the `Emogrifier` class has been deprecated, and it will be
|
||||
removed for version 4.0.0. Please update your code to use the new
|
||||
`CssInliner` class instead.
|
||||
|
||||
If you are still using the deprecated class, here is how to use it:
|
||||
|
||||
First, you provide Emogrifier with the HTML and CSS you would like to merge.
|
||||
This can happen directly during instantiation:
|
||||
|
||||
@@ -92,74 +287,48 @@ the complete HTML document, you can use the `emogrifyBodyContent` instead:
|
||||
$bodyContent = $emogrifier->emogrifyBodyContent();
|
||||
```
|
||||
|
||||
## Options
|
||||
### Migrating from `Emogrifier` to `CssInliner`
|
||||
|
||||
There are several options that you can set on the Emogrifier object before
|
||||
calling the `emogrify` method:
|
||||
#### Minimal example
|
||||
|
||||
* `$emogrifier->disableStyleBlocksParsing()` - By default, Emogrifier will grab
|
||||
all `<style>` blocks in the HTML and will apply the CSS styles as inline
|
||||
"style" attributes to the HTML. The `<style>` blocks will then be removed
|
||||
from the HTML. If you want to disable this functionality so that Emogrifier
|
||||
leaves these `<style>` blocks in the HTML and does not parse them, you should
|
||||
use this option. If you use this option, the contents of the `<style>` blocks
|
||||
will _not_ be applied as inline styles and any CSS you want Emogrifier to
|
||||
use must be passed in as described in the [Usage section](#usage) above.
|
||||
* `$emogrifier->disableInlineStylesParsing()` - By default, Emogrifier
|
||||
preserves all of the "style" attributes on tags in the HTML you pass to it.
|
||||
However if you want to discard all existing inline styles in the HTML before
|
||||
the CSS is applied, you should use this option.
|
||||
* `$emogrifier->disableInvisibleNodeRemoval()` - By default, Emogrifier removes
|
||||
elements from the DOM that have the style attribute `display: none;`. If
|
||||
you would like to keep invisible elements in the DOM, use this option.
|
||||
Note: This option will be removed in Emogrifier 3.0. HTML tags with
|
||||
`display: none;` then will always be retained.
|
||||
* `$emogrifier->addAllowedMediaType(string $mediaName)` - By default, Emogrifier
|
||||
will keep only media types `all`, `screen` and `print`. If you want to keep
|
||||
some others, you can use this method to define them.
|
||||
* `$emogrifier->removeAllowedMediaType(string $mediaName)` - You can use this
|
||||
method to remove media types that Emogrifier keeps.
|
||||
* `$emogrifier->addExcludedSelector(string $selector)` - Keeps elements from
|
||||
being affected by emogrification.
|
||||
* `$emogrifier->enableCssToHtmlMapping()` - Some email clients don't support CSS
|
||||
well, even if inline and prefer HTML attributes. This function allows you to
|
||||
put properties such as height, width, background color and font color in your
|
||||
CSS while the transformed content will have all the available HTML
|
||||
attributes set. This option will be removed in Emogrifier 3.0. Please use the
|
||||
`CssToAttributeConverter` class instead.
|
||||
Old code using `Emogrifier`:
|
||||
|
||||
## Installing with Composer
|
||||
|
||||
Download the [`composer.phar`](https://getcomposer.org/composer.phar) locally
|
||||
or install [Composer](https://getcomposer.org/) globally:
|
||||
|
||||
```bash
|
||||
curl -s https://getcomposer.org/installer | php
|
||||
```php
|
||||
$emogrifier = new Emogrifier($html);
|
||||
$html = $emogrifier->emogrify();
|
||||
```
|
||||
|
||||
Run the following command for a local installation:
|
||||
New code using `CssInliner`:
|
||||
|
||||
```bash
|
||||
php composer.phar require pelago/emogrifier:^2.1.0
|
||||
```php
|
||||
$html = CssInliner::fromHtml($html)->inlineCss()->render();
|
||||
```
|
||||
|
||||
Or for a global installation, run the following command:
|
||||
NB: In this example, the old code removes elements with `display: none;`
|
||||
while the new code does not, as the default behaviors of the old and
|
||||
the new class differ in this regard.
|
||||
|
||||
```bash
|
||||
composer require pelago/emogrifier:^2.1.0
|
||||
#### More complex example
|
||||
|
||||
Old code using `Emogrifier`:
|
||||
|
||||
```php
|
||||
$emogrifier = new Emogrifier($html, $css);
|
||||
$emogrifier->enableCssToHtmlMapping();
|
||||
|
||||
$html = $emogrifier->emogrify();
|
||||
```
|
||||
|
||||
You can also add follow lines to your `composer.json` and run the
|
||||
`composer update` command:
|
||||
New code using `CssInliner` and family:
|
||||
|
||||
```json
|
||||
"require": {
|
||||
"pelago/emogrifier": "^2.1.0"
|
||||
}
|
||||
```php
|
||||
$domDocument = CssInliner::fromHtml($html)->inlineCss($css)->getDomDocument();
|
||||
|
||||
HtmlPruner::fromDomDocument($domDocument)->removeElementsWithDisplayNone(),
|
||||
$html = CssToAttributeConverter::fromDomDocument($domDocument)
|
||||
->convertCssToVisualAttributes()->render();
|
||||
```
|
||||
|
||||
See https://getcomposer.org/ for more information and documentation.
|
||||
|
||||
## Supported CSS selectors
|
||||
|
||||
Emogrifier currently supports the following
|
||||
@@ -168,7 +337,8 @@ Emogrifier currently supports the following
|
||||
* [type](https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors)
|
||||
* [class](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors)
|
||||
* [ID](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors)
|
||||
* [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors):
|
||||
* [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors)
|
||||
(partial support)
|
||||
* [attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors):
|
||||
* presence
|
||||
* exact value match
|
||||
@@ -178,42 +348,103 @@ Emogrifier currently supports the following
|
||||
* value with `$` (suffix match)
|
||||
* value with `*` (substring match)
|
||||
* [adjacent](https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors)
|
||||
* [general sibling](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator)
|
||||
* [child](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors)
|
||||
* [descendant](https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors)
|
||||
* [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes):
|
||||
* [empty](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty)
|
||||
* [first-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child)
|
||||
* [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type)
|
||||
(with a type, e.g. `p:first-of-type` but not `*:first-of-type` which will
|
||||
behave as `*:first-child`)
|
||||
* [last-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child)
|
||||
* [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type)
|
||||
(with a type)
|
||||
* [not()](https://developer.mozilla.org/en-US/docs/Web/CSS/:not)
|
||||
* [nth-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child)
|
||||
* [nth-last-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-child)
|
||||
* [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type)
|
||||
(with a type)
|
||||
* [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type)
|
||||
(with a type)
|
||||
* [only-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child)
|
||||
|
||||
The following selectors are not implemented yet:
|
||||
|
||||
* [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors)
|
||||
* [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors):
|
||||
* with
|
||||
[child combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator)
|
||||
* as ancestor with
|
||||
[descendant combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator)
|
||||
(e.g. `p *` is supported but `* p` is not)
|
||||
* [case-insensitive attribute value](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors#case-insensitive)
|
||||
* [general sibling](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors)
|
||||
* [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
|
||||
(some of them will never be supported)
|
||||
* static [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes):
|
||||
* [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type)
|
||||
without a type (will behave as `:first-child`)
|
||||
* [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type)
|
||||
without a type (will behave as `:last-child`)
|
||||
* [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type)
|
||||
without a type (will behave as `:nth-last-child()`)
|
||||
* [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type)
|
||||
without a type (will behave as `:nth-child()`)
|
||||
* any pseudo-classes not listed above as supported – rules involving them
|
||||
will nonetheless be preserved and copied to a `<style>` element in the
|
||||
HTML – including (but not necessarily limited to) the following:
|
||||
* [any-link](https://developer.mozilla.org/en-US/docs/Web/CSS/:any-link)
|
||||
* [only-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type)
|
||||
* [optional](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional)
|
||||
* [required](https://developer.mozilla.org/en-US/docs/Web/CSS/:required)
|
||||
|
||||
Rules involving the following selectors cannot be applied as inline styles.
|
||||
They will, however, be preserved and copied to a `<style>` element in the HTML:
|
||||
|
||||
* dynamic [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
|
||||
(such as `:hover`)
|
||||
* [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)
|
||||
(such as `::after`)
|
||||
|
||||
## Caveats
|
||||
|
||||
* Emogrifier requires the HTML and the CSS to be UTF-8. Encodings like
|
||||
ISO8859-1 or ISO8859-15 are not supported.
|
||||
* Emogrifier now preserves all valuable @media queries. Media queries
|
||||
can be very useful in responsive email design. See
|
||||
* Emogrifier preserves all valuable `@media` rules. Media queries can be very
|
||||
useful in responsive email design. See
|
||||
[media query support](https://litmus.com/help/email-clients/media-query-support/).
|
||||
However, in order for them to be effective, you may need to add `!important`
|
||||
to some of the declarations within them so that they will override CSS styles
|
||||
that have been inlined. For example, with the following CSS, the `font-size`
|
||||
declaration in the `@media` rule would not override the font size for `p`
|
||||
elements from the preceding rule after that has been inlined as
|
||||
`<p style="font-size: 16px;">` in the HTML, without the `!important` directive
|
||||
(even though `!important` would not be necessary if the CSS were not inlined):
|
||||
```css
|
||||
p {
|
||||
font-size: 16px;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
p {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
* Emogrifier cannot inline CSS rules involving selectors with pseudo-elements
|
||||
(such as `::after`) or dynamic pseudo-classes (such as `:hover`) – it is
|
||||
impossible. However, such rules will be preserved and copied to a `<style>`
|
||||
element, as for `@media` rules. The same caveat about the possible need for
|
||||
the `!important` directive also applies with pseudo-classes.
|
||||
* Emogrifier will grab existing inline style attributes _and_ will
|
||||
grab `<style>` blocks from your HTML, but it will not grab CSS files
|
||||
referenced in <link> elements. (The problem email clients are going to ignore
|
||||
these tags anyway, so why leave them in your HTML?)
|
||||
referenced in `<link>` elements or `@import` rules (though it will leave them
|
||||
intact for email clients that support them).
|
||||
* Even with styles inline, certain CSS properties are ignored by certain email
|
||||
clients. For more information, refer to these resources:
|
||||
* [http://www.email-standards.org/](http://www.email-standards.org/)
|
||||
* [https://www.campaignmonitor.com/css/](https://www.campaignmonitor.com/css/)
|
||||
* [http://templates.mailchimp.com/resources/email-client-css-support/](http://templates.mailchimp.com/resources/email-client-css-support/)
|
||||
* All CSS attributes that apply to a node will be applied, even if they are
|
||||
* All CSS attributes that apply to an element will be applied, even if they are
|
||||
redundant. For example, if you define a font attribute _and_ a font-size
|
||||
attribute, both attributes will be applied to that node (in other words, the
|
||||
more specific attribute will not be combined into the more general
|
||||
attribute, both attributes will be applied to that element (in other words,
|
||||
the more specific attribute will not be combined into the more general
|
||||
attribute).
|
||||
* There's a good chance you might encounter problems if your HTML is not
|
||||
well-formed and valid (DOMDocument might complain). If you get problems like
|
||||
@@ -223,53 +454,6 @@ The following selectors are not implemented yet:
|
||||
* Emogrifier automatically converts the provided (X)HTML into HTML5, i.e.,
|
||||
self-closing tags will lose their slash. To keep your HTML valid, it is
|
||||
recommended to use HTML5 instead of one of the XHTML variants.
|
||||
* Emogrifier only supports CSS1 level selectors and a few CSS2 level selectors
|
||||
(but not all of them). It does not support pseudo selectors. (Emogrifier
|
||||
works by converting CSS selectors to XPath selectors, and pseudo selectors
|
||||
cannot be converted accurately).
|
||||
|
||||
## Processing HTML
|
||||
|
||||
The Emogrifier package also provides classes for (post-)processing the HTML
|
||||
generated by `emogrify` (and it also works on any other HTML).
|
||||
|
||||
### Normalizing and cleaning up HTML
|
||||
|
||||
The `HtmlNormalizer` class normalizes the given HTML in the following ways:
|
||||
|
||||
- add a document type (HTML5) if missing
|
||||
- disentangle incorrectly nested tags
|
||||
- add HEAD and BODY elements (if they are missing)
|
||||
- reformat the HTML
|
||||
|
||||
The class can be used like this:
|
||||
|
||||
```php
|
||||
$normalizer = new \Pelago\Emogrifier\HtmlProcessor\HtmlNormalizer($rawHtml);
|
||||
$cleanHtml = $normalizer->render();
|
||||
```
|
||||
|
||||
### Converting CSS styles to visual HTML attributes
|
||||
|
||||
The `CssToAttributeConverter` converts a few style attributes values to visual
|
||||
HTML attributes. This allows to get at least a bit of visual styling for email
|
||||
clients that do not support CSS well. For example, `style="width: 100px"`
|
||||
will be converted to `width="100"`.
|
||||
|
||||
The class can be used like this:
|
||||
|
||||
```php
|
||||
$converter = new \Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter($rawHtml);
|
||||
$visualHtml = $converter->convertCssToVisualAttributes()->render();
|
||||
```
|
||||
|
||||
### Technology preview of new classes
|
||||
|
||||
Currently, a refactoring effort is underway, aiming towards replacing the
|
||||
grown-over-time `Emogrifier` class with the new `CssInliner` class and moving
|
||||
additional HTML processing into separate `CssProcessor` classes (which will
|
||||
inherit from `AbstractHtmlProcessor`). You can try the new classes, but be
|
||||
aware that the APIs of the new classes still are subject to change.
|
||||
|
||||
## Steps to release a new version
|
||||
|
||||
@@ -277,11 +461,11 @@ aware that the APIs of the new classes still are subject to change.
|
||||
changes.
|
||||
1. In the [composer.json](composer.json), update the `branch-alias` entry to
|
||||
point to the release _after_ the upcoming release.
|
||||
1. In the [README.md](README.md), update the version numbers in the section
|
||||
[Installing with Composer](#installing-with-composer).
|
||||
1. In the [CHANGELOG.md](CHANGELOG.md), set the version number and remove any
|
||||
empty sections.
|
||||
1. In the [CHANGELOG.md](CHANGELOG.md), create a new section with subheadings
|
||||
for changes _after_ the upcoming release, set the version number for the
|
||||
upcoming release, and remove any empty sections.
|
||||
1. Have the pull request reviewed and merged.
|
||||
1. Tag the new release.
|
||||
1. In the [Releases tab](https://github.com/MyIntervals/emogrifier/releases),
|
||||
create a new release and copy the change log entries to the new release.
|
||||
1. Post about the new release on social media.
|
||||
|
||||
@@ -37,16 +37,16 @@
|
||||
"source": "https://github.com/MyIntervals/emogrifier"
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0",
|
||||
"php": "^5.6 || ~7.0 || ~7.1 || ~7.2 || ~7.3 || ~7.4",
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"symfony/css-selector": "^3.4.0 || ^4.0.0"
|
||||
"symfony/css-selector": "^2.8 || ^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.2.0",
|
||||
"squizlabs/php_codesniffer": "^3.3.2",
|
||||
"phpmd/phpmd": "^2.6.0",
|
||||
"phpunit/phpunit": "^4.8.0"
|
||||
"friendsofphp/php-cs-fixer": "^2.15.3",
|
||||
"squizlabs/php_codesniffer": "^3.5.0",
|
||||
"phpmd/phpmd": "^2.7.0",
|
||||
"phpunit/phpunit": "^5.7.27"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -69,6 +69,7 @@
|
||||
"php:fix": "php-cs-fixer --config=config/php-cs-fixer.php fix config/ src/ tests/",
|
||||
"ci:php:lint": "find config src tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l",
|
||||
"ci:php:sniff": "phpcs config src tests",
|
||||
"ci:php:fixer": "php-cs-fixer --config=config/php-cs-fixer.php fix --dry-run -v --show-progress=dots --diff-format=udiff config/ src/ tests/",
|
||||
"ci:php:md": "phpmd src text config/phpmd.xml",
|
||||
"ci:tests:unit": "phpunit tests/",
|
||||
"ci:tests": [
|
||||
@@ -80,6 +81,7 @@
|
||||
"ci:static": [
|
||||
"@ci:php:lint",
|
||||
"@ci:php:sniff",
|
||||
"@ci:php:fixer",
|
||||
"@ci:php:md"
|
||||
],
|
||||
"ci": [
|
||||
@@ -89,7 +91,7 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev"
|
||||
"dev-master": "4.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
die('This script supports command line usage only. Please check your command.');
|
||||
}
|
||||
|
||||
return \PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(
|
||||
[
|
||||
// copied from the TYPO3 Core
|
||||
'@PSR2' => true,
|
||||
'@DoctrineAnnotation' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_trailing_comma_in_singleline_array' => true,
|
||||
'no_singleline_whitespace_before_semicolons' => true,
|
||||
'no_unused_imports' => true,
|
||||
'concat_space' => ['spacing' => 'one'],
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'ordered_imports' => true,
|
||||
'single_quote' => true,
|
||||
'no_empty_statement' => true,
|
||||
'no_extra_consecutive_blank_lines' => true,
|
||||
'phpdoc_no_package' => true,
|
||||
'phpdoc_scalar' => true,
|
||||
'no_blank_lines_after_phpdoc' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'whitespace_after_comma_in_array' => true,
|
||||
'function_typehint_space' => true,
|
||||
'hash_to_slash_comment' => true,
|
||||
'no_alias_functions' => true,
|
||||
'lowercase_cast' => true,
|
||||
'no_leading_namespace_whitespace' => true,
|
||||
'native_function_casing' => true,
|
||||
'no_short_bool_cast' => true,
|
||||
'no_unneeded_control_parentheses' => true,
|
||||
'phpdoc_trim' => true,
|
||||
'no_superfluous_elseif' => true,
|
||||
'no_useless_else' => true,
|
||||
'phpdoc_types' => true,
|
||||
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
|
||||
'return_type_declaration' => ['space_before' => 'none'],
|
||||
'cast_spaces' => ['space' => 'none'],
|
||||
'declare_equal_normalize' => ['space' => 'single'],
|
||||
'dir_constant' => true,
|
||||
|
||||
// additional rules
|
||||
'combine_consecutive_issets' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'compact_nullable_typehint' => true,
|
||||
// PHP >= 7.0
|
||||
// 'declare_strict_types' => true,
|
||||
'elseif' => true,
|
||||
'encoding' => true,
|
||||
'escape_implicit_backslashes' => ['single_quoted' => true],
|
||||
'is_null' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'magic_constant_casing' => true,
|
||||
'method_separation' => true,
|
||||
'modernize_types_casting' => true,
|
||||
// not yet, but maybe later to improve performance
|
||||
// 'native_function_invocation' => true,
|
||||
'new_with_braces' => true,
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'no_empty_comment' => true,
|
||||
'no_empty_phpdoc' => true,
|
||||
'no_extra_blank_lines' => true,
|
||||
'no_multiline_whitespace_before_semicolons' => true,
|
||||
'no_php4_constructor' => true,
|
||||
'no_short_echo_tag' => true,
|
||||
'no_spaces_after_function_name' => true,
|
||||
'no_spaces_inside_parenthesis' => true,
|
||||
'no_unneeded_curly_braces' => true,
|
||||
'no_useless_return' => true,
|
||||
'no_whitespace_before_comma_in_array' => true,
|
||||
'php_unit_construct' => true,
|
||||
'php_unit_fqcn_annotation' => true,
|
||||
'php_unit_set_up_tear_down_visibility' => true,
|
||||
'phpdoc_add_missing_param_annotation' => true,
|
||||
'phpdoc_indent' => true,
|
||||
'phpdoc_separation' => true,
|
||||
'semicolon_after_instruction' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'space_after_semicolon' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'psr4' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
// PHP >= 7.0
|
||||
// 'ternary_to_null_coalescing' => true,
|
||||
'trailing_comma_in_multiline_array' => true,
|
||||
'unary_operator_spaces' => true,
|
||||
]
|
||||
);
|
||||
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="phpList">
|
||||
<description>
|
||||
PHPMD rules for Emogrifier
|
||||
</description>
|
||||
|
||||
<!-- The commented-out rules will be enabled once the code does not generate any warnings anymore. -->
|
||||
|
||||
<rule ref="rulesets/cleancode.xml/BooleanArgumentFlag"/>
|
||||
<rule ref="rulesets/cleancode.xml/StaticAccess"/>
|
||||
|
||||
<rule ref="rulesets/codesize.xml/CyclomaticComplexity"/>
|
||||
<rule ref="rulesets/codesize.xml/NPathComplexity"/>
|
||||
<rule ref="rulesets/codesize.xml/ExcessiveMethodLength"/>
|
||||
<!--<rule ref="rulesets/codesize.xml/ExcessiveClassLength"/>-->
|
||||
<!--<rule ref="rulesets/codesize.xml/ExcessiveParameterList"/>-->
|
||||
<rule ref="rulesets/codesize.xml/ExcessivePublicCount"/>
|
||||
<!--<rule ref="rulesets/codesize.xml/TooManyFields"/>-->
|
||||
<!--<rule ref="rulesets/codesize.xml/TooManyMethods"/>-->
|
||||
<!--<rule ref="rulesets/codesize.xml/TooManyPublicMethods"/>-->
|
||||
<!--<rule ref="rulesets/codesize.xml/ExcessiveClassComplexity"/>-->
|
||||
|
||||
<rule ref="rulesets/controversial.xml/Superglobals"/>
|
||||
<rule ref="rulesets/controversial.xml/CamelCaseClassName"/>
|
||||
<rule ref="rulesets/controversial.xml/CamelCasePropertyName"/>
|
||||
<rule ref="rulesets/controversial.xml/CamelCaseMethodName"/>
|
||||
<rule ref="rulesets/controversial.xml/CamelCaseParameterName"/>
|
||||
<rule ref="rulesets/controversial.xml/CamelCaseVariableName"/>
|
||||
|
||||
<rule ref="rulesets/design.xml/ExitExpression"/>
|
||||
<rule ref="rulesets/design.xml/EvalExpression"/>
|
||||
<rule ref="rulesets/design.xml/GotoStatement"/>
|
||||
<rule ref="rulesets/design.xml/NumberOfChildren"/>
|
||||
<rule ref="rulesets/design.xml/DepthOfInheritance"/>
|
||||
<rule ref="rulesets/design.xml/CouplingBetweenObjects"/>
|
||||
<rule ref="rulesets/design.xml/DevelopmentCodeFragment"/>
|
||||
|
||||
<!--<rule ref="rulesets/naming.xml/ShortVariable"/>-->
|
||||
<!--<rule ref="rulesets/naming.xml/LongVariable"/>-->
|
||||
<rule ref="rulesets/naming.xml/ShortMethodName"/>
|
||||
<rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass"/>
|
||||
<rule ref="rulesets/naming.xml/ConstantNamingConventions"/>
|
||||
<rule ref="rulesets/naming.xml/BooleanGetMethodName"/>
|
||||
|
||||
<rule ref="rulesets/unusedcode.xml/UnusedPrivateField"/>
|
||||
<rule ref="rulesets/unusedcode.xml/UnusedLocalVariable"/>
|
||||
<!--<rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod"/>-->
|
||||
<!--<rule ref="rulesets/unusedcode.xml/UnusedFormalParameter"/>-->
|
||||
</ruleset>
|
||||
@@ -1,140 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ruleset name="Coding Standard">
|
||||
<description>
|
||||
This standard requires PHP_CodeSniffer >= 3.2.0.
|
||||
</description>
|
||||
|
||||
<config name="installed_paths" value="../../slevomat/coding-standard"/>
|
||||
|
||||
<!--The complete PSR-2 ruleset-->
|
||||
<rule ref="PSR2"/>
|
||||
|
||||
<!-- Arrays -->
|
||||
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||
<rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
|
||||
<rule ref="Squiz.Arrays.ArrayDeclaration.NoCommaAfterLast"/>
|
||||
|
||||
<!-- Classes -->
|
||||
<rule ref="Generic.Classes.DuplicateClassName"/>
|
||||
<rule ref="Squiz.Classes.ClassFileName"/>
|
||||
<rule ref="Squiz.Classes.DuplicateProperty"/>
|
||||
<rule ref="Squiz.Classes.LowercaseClassKeywords"/>
|
||||
<rule ref="Squiz.Classes.SelfMemberReference"/>
|
||||
|
||||
<!-- Code analysis -->
|
||||
<rule ref="Generic.CodeAnalysis.EmptyStatement"/>
|
||||
<rule ref="Generic.CodeAnalysis.AssignmentInCondition"/>
|
||||
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
|
||||
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
|
||||
<rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
|
||||
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
|
||||
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
|
||||
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
|
||||
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
|
||||
|
||||
<!-- Commenting -->
|
||||
<rule ref="Generic.Commenting.Fixme"/>
|
||||
<rule ref="Generic.Commenting.Todo"/>
|
||||
<rule ref="PEAR.Commenting.InlineComment"/>
|
||||
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
|
||||
<rule ref="Squiz.Commenting.EmptyCatchComment"/>
|
||||
<rule ref="Squiz.Commenting.FunctionComment">
|
||||
<!-- Allow PHP-5-compatible type hinting. -->
|
||||
<exclude name="Squiz.Commenting.FunctionComment.ScalarTypeHintMissing"/>
|
||||
<!-- Allow no comment for self-describing parameter and exception class names. -->
|
||||
<exclude name="Squiz.Commenting.FunctionComment.MissingParamComment"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.EmptyThrows"/>
|
||||
<!-- Allow "int" rather than "integer", etc., in PHPDoc. -->
|
||||
<exclude name="Squiz.Commenting.FunctionComment.IncorrectParamVarName"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.InvalidReturn"/>
|
||||
<!-- Allow "@return" to be omitted (for methods which do not return a value). -->
|
||||
<exclude name="Squiz.Commenting.FunctionComment.MissingReturn"/>
|
||||
<!-- Allow parameter type, name and comment not all vertically aligned. -->
|
||||
<exclude name="Squiz.Commenting.FunctionComment.SpacingAfterParamType"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.SpacingAfterParamName"/>
|
||||
<!-- Allow parameter and exception descriptions which are not full sentences. -->
|
||||
<exclude name="Squiz.Commenting.FunctionComment.ParamCommentNotCapital"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.ParamCommentFullStop"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.ThrowsNotCapital"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.ThrowsNoFullStop"/>
|
||||
</rule>
|
||||
<rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>
|
||||
<rule ref="Squiz.Commenting.PostStatementComment"/>
|
||||
|
||||
<!-- Control structures -->
|
||||
<rule ref="PEAR.ControlStructures.ControlSignature"/>
|
||||
|
||||
<!-- Debug -->
|
||||
<rule ref="Generic.Debug.ClosureLinter"/>
|
||||
|
||||
<!-- Files -->
|
||||
<rule ref="Generic.Files.OneClassPerFile"/>
|
||||
<rule ref="Generic.Files.OneInterfacePerFile"/>
|
||||
<rule ref="Generic.Files.OneObjectStructurePerFile"/>
|
||||
<rule ref="Zend.Files.ClosingTag"/>
|
||||
|
||||
<!-- Formatting -->
|
||||
<rule ref="Generic.Formatting.NoSpaceAfterCast"/>
|
||||
<rule ref="PEAR.Formatting.MultiLineAssignment"/>
|
||||
|
||||
<!-- Functions -->
|
||||
<rule ref="Generic.Functions.CallTimePassByReference"/>
|
||||
<rule ref="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions"/>
|
||||
<rule ref="Squiz.Functions.FunctionDuplicateArgument"/>
|
||||
<rule ref="Squiz.Functions.GlobalFunction"/>
|
||||
|
||||
<!-- Metrics -->
|
||||
<rule ref="Generic.Metrics.CyclomaticComplexity"/>
|
||||
<rule ref="Generic.Metrics.NestingLevel"/>
|
||||
|
||||
<!-- Naming conventions -->
|
||||
<rule ref="Generic.NamingConventions.ConstructorName"/>
|
||||
<rule ref="PEAR.NamingConventions.ValidClassName"/>
|
||||
|
||||
<!-- Objects -->
|
||||
<rule ref="Squiz.Objects.ObjectMemberComma"/>
|
||||
|
||||
<!-- Operators -->
|
||||
<rule ref="Squiz.Operators.IncrementDecrementUsage"/>
|
||||
<rule ref="Squiz.Operators.ValidLogicalOperators"/>
|
||||
|
||||
<!-- PHP -->
|
||||
<rule ref="Generic.PHP.BacktickOperator"/>
|
||||
<rule ref="Generic.PHP.CharacterBeforePHPOpeningTag"/>
|
||||
<rule ref="Generic.PHP.DeprecatedFunctions"/>
|
||||
<rule ref="Generic.PHP.DisallowAlternativePHPTags"/>
|
||||
<rule ref="Generic.PHP.DisallowShortOpenTag"/>
|
||||
<rule ref="Generic.PHP.DiscourageGoto"/>
|
||||
<rule ref="Generic.PHP.ForbiddenFunctions"/>
|
||||
<rule ref="Generic.PHP.NoSilencedErrors"/>
|
||||
<rule ref="Squiz.PHP.CommentedOutCode">
|
||||
<properties>
|
||||
<property name="maxPercentage" value="70"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Squiz.PHP.DisallowMultipleAssignments"/>
|
||||
<rule ref="Squiz.PHP.DisallowSizeFunctionsInLoops"/>
|
||||
<rule ref="Squiz.PHP.DiscouragedFunctions"/>
|
||||
<rule ref="Squiz.PHP.Eval"/>
|
||||
<rule ref="Squiz.PHP.GlobalKeyword"/>
|
||||
<rule ref="Squiz.PHP.Heredoc"/>
|
||||
<rule ref="Squiz.PHP.InnerFunctions"/>
|
||||
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
|
||||
<rule ref="Squiz.PHP.NonExecutableCode"/>
|
||||
|
||||
<!-- Scope -->
|
||||
<rule ref="Squiz.Scope.MemberVarScope"/>
|
||||
<rule ref="Squiz.Scope.StaticThisUsage"/>
|
||||
|
||||
<!--Strings-->
|
||||
<rule ref="Squiz.Strings.DoubleQuoteUsage"/>
|
||||
|
||||
<!-- Whitespace -->
|
||||
<rule ref="PEAR.WhiteSpace.ObjectOperatorIndent"/>
|
||||
<rule ref="PEAR.WhiteSpace.ScopeClosingBrace"/>
|
||||
<rule ref="Squiz.WhiteSpace.CastSpacing"/>
|
||||
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
|
||||
<rule ref="Squiz.WhiteSpace.OperatorSpacing"/>
|
||||
<rule ref="Squiz.WhiteSpace.PropertyLabelSpacing"/>
|
||||
<rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
|
||||
</ruleset>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,6 @@ namespace Pelago\Emogrifier\HtmlProcessor;
|
||||
*
|
||||
* The "vanilla" subclass is the HtmlNormalizer.
|
||||
*
|
||||
* @internal This class currently is a new technology preview, and its API is still in flux. Don't use it in production.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
abstract class AbstractHtmlProcessor
|
||||
@@ -23,17 +21,44 @@ abstract class AbstractHtmlProcessor
|
||||
*/
|
||||
const CONTENT_TYPE_META_TAG = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
|
||||
|
||||
/**
|
||||
* @var string Regular expression part to match tag names that PHP's DOMDocument implementation is not aware are
|
||||
* self-closing. These are mostly HTML5 elements, but for completeness <command> (obsolete) and <keygen>
|
||||
* (deprecated) are also included.
|
||||
*
|
||||
* @see https://bugs.php.net/bug.php?id=73175
|
||||
*/
|
||||
const PHP_UNRECOGNIZED_VOID_TAGNAME_MATCHER = '(?:command|embed|keygen|source|track|wbr)';
|
||||
|
||||
/**
|
||||
* @var \DOMDocument
|
||||
*/
|
||||
protected $domDocument = null;
|
||||
|
||||
/**
|
||||
* @var \DOMXPath
|
||||
*/
|
||||
protected $xPath = null;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* Please use ::fromHtml instead.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new instance from the given HTML.
|
||||
*
|
||||
* @param string $unprocessedHtml raw HTML, must be UTF-encoded, must not be empty
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @throws \InvalidArgumentException if $unprocessedHtml is anything other than a non-empty string
|
||||
*/
|
||||
public function __construct($unprocessedHtml)
|
||||
public static function fromHtml($unprocessedHtml)
|
||||
{
|
||||
if (!\is_string($unprocessedHtml)) {
|
||||
throw new \InvalidArgumentException('The provided HTML must be a string.', 1515459744);
|
||||
@@ -42,7 +67,25 @@ abstract class AbstractHtmlProcessor
|
||||
throw new \InvalidArgumentException('The provided HTML must not be empty.', 1515763647);
|
||||
}
|
||||
|
||||
$this->setHtml($unprocessedHtml);
|
||||
$instance = new static();
|
||||
$instance->setHtml($unprocessedHtml);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new instance from the given DOM document.
|
||||
*
|
||||
* @param \DOMDocument $document a DOM document returned by getDomDocument() of another instance
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function fromDomDocument(\DOMDocument $document)
|
||||
{
|
||||
$instance = new static();
|
||||
$instance->setDomDocument($document);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,6 +110,17 @@ abstract class AbstractHtmlProcessor
|
||||
return $this->domDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMDocument $domDocument
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function setDomDocument(\DOMDocument $domDocument)
|
||||
{
|
||||
$this->domDocument = $domDocument;
|
||||
$this->xPath = new \DOMXPath($this->domDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the normalized and processed HTML.
|
||||
*
|
||||
@@ -74,7 +128,9 @@ abstract class AbstractHtmlProcessor
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return $this->domDocument->saveHTML();
|
||||
$htmlWithPossibleErroneousClosingTags = $this->domDocument->saveHTML();
|
||||
|
||||
return $this->removeSelfClosingTagsClosingTags($htmlWithPossibleErroneousClosingTags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,9 +140,22 @@ abstract class AbstractHtmlProcessor
|
||||
*/
|
||||
public function renderBodyContent()
|
||||
{
|
||||
$bodyNodeHtml = $this->domDocument->saveHTML($this->getBodyElement());
|
||||
$htmlWithPossibleErroneousClosingTags = $this->domDocument->saveHTML($this->getBodyElement());
|
||||
$bodyNodeHtml = $this->removeSelfClosingTagsClosingTags($htmlWithPossibleErroneousClosingTags);
|
||||
|
||||
return \str_replace(['<body>', '</body>'], '', $bodyNodeHtml);
|
||||
return \preg_replace('%</?+body(?:\\s[^>]*+)?+>%', '', $bodyNodeHtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eliminates any invalid closing tags for void elements from the given HTML.
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function removeSelfClosingTagsClosingTags($html)
|
||||
{
|
||||
return \preg_replace('%</' . static::PHP_UNRECOGNIZED_VOID_TAGNAME_MATCHER . '>%', '', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,11 +202,11 @@ abstract class AbstractHtmlProcessor
|
||||
\libxml_clear_errors();
|
||||
\libxml_use_internal_errors($libXmlState);
|
||||
|
||||
$this->domDocument = $domDocument;
|
||||
$this->setDomDocument($domDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML with added document type and Content-Type meta tag if needed,
|
||||
* Returns the HTML with added document type, Content-Type meta tag, and self-closing slashes, if needed,
|
||||
* ensuring that the HTML will be good for creating a DOM document from it.
|
||||
*
|
||||
* @param string $html
|
||||
@@ -146,7 +215,8 @@ abstract class AbstractHtmlProcessor
|
||||
*/
|
||||
private function prepareHtmlForDomConversion($html)
|
||||
{
|
||||
$htmlWithDocumentType = $this->ensureDocumentType($html);
|
||||
$htmlWithSelfClosingSlashes = $this->ensurePhpUnrecognizedSelfClosingTagsAreXml($html);
|
||||
$htmlWithDocumentType = $this->ensureDocumentType($htmlWithSelfClosingSlashes);
|
||||
|
||||
return $this->addContentTypeMetaTag($htmlWithDocumentType);
|
||||
}
|
||||
@@ -171,6 +241,8 @@ abstract class AbstractHtmlProcessor
|
||||
/**
|
||||
* Adds a Content-Type meta tag for the charset.
|
||||
*
|
||||
* This method also ensures that there is a HEAD element.
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @return string the HTML with the meta tag added
|
||||
@@ -202,10 +274,29 @@ abstract class AbstractHtmlProcessor
|
||||
return $reworkedHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that any self-closing tags not recognized as such by PHP's DOMDocument implementation have a
|
||||
* self-closing slash.
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @return string HTML with problematic tags converted.
|
||||
*/
|
||||
private function ensurePhpUnrecognizedSelfClosingTagsAreXml($html)
|
||||
{
|
||||
return \preg_replace(
|
||||
'%<' . static::PHP_UNRECOGNIZED_VOID_TAGNAME_MATCHER . '\\b[^>]*+(?<!/)(?=>)%',
|
||||
'$0/',
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that $this->domDocument has a BODY element and adds it if it is missing.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
private function ensureExistenceOfBodyElement()
|
||||
{
|
||||
@@ -214,6 +305,9 @@ abstract class AbstractHtmlProcessor
|
||||
}
|
||||
|
||||
$htmlElement = $this->domDocument->getElementsByTagName('html')->item(0);
|
||||
if ($htmlElement === null) {
|
||||
throw new \UnexpectedValueException('There is no HTML element although there should be one.', 1569930853);
|
||||
}
|
||||
$htmlElement->appendChild($this->domDocument->createElement('body'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@ namespace Pelago\Emogrifier\HtmlProcessor;
|
||||
*
|
||||
* To trigger the conversion, call the convertCssToVisualAttributes method.
|
||||
*
|
||||
* @internal This class currently is a new technology preview, and its API is still in flux. Don't use it in production.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
@@ -52,7 +50,7 @@ class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
/**
|
||||
* Maps the CSS from the style nodes to visual HTML attributes.
|
||||
*
|
||||
* @return CssToAttributeConverter fluent interface
|
||||
* @return self fluent interface
|
||||
*/
|
||||
public function convertCssToVisualAttributes()
|
||||
{
|
||||
@@ -72,9 +70,7 @@ class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
*/
|
||||
private function getAllNodesWithStyleAttribute()
|
||||
{
|
||||
$xPath = new \DOMXPath($this->domDocument);
|
||||
|
||||
return $xPath->query('//*[@style]');
|
||||
return $this->xPath->query('//*[@style]');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,9 +99,7 @@ class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
}
|
||||
|
||||
$properties = [];
|
||||
$declarations = \preg_split('/;(?!base64|charset)/', $cssDeclarationsBlock);
|
||||
|
||||
foreach ($declarations as $declaration) {
|
||||
foreach (\preg_split('/;(?!base64|charset)/', $cssDeclarationsBlock) as $declaration) {
|
||||
$matches = [];
|
||||
if (!\preg_match('/^([A-Za-z\\-]+)\\s*:\\s*(.+)$/s', \trim($declaration), $matches)) {
|
||||
continue;
|
||||
@@ -176,13 +170,12 @@ class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
$mapping = $this->cssToHtmlMap[$property];
|
||||
$nodesMatch = !isset($mapping['nodes']) || \in_array($node->nodeName, $mapping['nodes'], true);
|
||||
$valuesMatch = !isset($mapping['values']) || \in_array($value, $mapping['values'], true);
|
||||
if (!$nodesMatch || !$valuesMatch) {
|
||||
return false;
|
||||
$canBeMapped = $nodesMatch && $valuesMatch;
|
||||
if ($canBeMapped) {
|
||||
$node->setAttribute($mapping['attribute'], $value);
|
||||
}
|
||||
|
||||
$node->setAttribute($mapping['attribute'], $value);
|
||||
|
||||
return true;
|
||||
return $canBeMapped;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,12 +217,14 @@ class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
private function mapBackgroundProperty(\DOMElement $node, $value)
|
||||
{
|
||||
// parse out the color, if any
|
||||
$styles = \explode(' ', $value);
|
||||
$styles = \explode(' ', $value, 2);
|
||||
$first = $styles[0];
|
||||
if (!\is_numeric($first[0]) && \strpos($first, 'url') !== 0) {
|
||||
// as this is not a position or image, assume it's a color
|
||||
$node->setAttribute('bgcolor', $first);
|
||||
if (\is_numeric($first[0]) || \strncmp($first, 'url', 3) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// as this is not a position or image, assume it's a color
|
||||
$node->setAttribute('bgcolor', $first);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,6 +302,7 @@ class CssToAttributeConverter extends AbstractHtmlProcessor
|
||||
*/
|
||||
private function parseCssShorthandValue($value)
|
||||
{
|
||||
/** @var string[] $values */
|
||||
$values = \preg_split('/\\s+/', $value);
|
||||
|
||||
$css = [];
|
||||
|
||||
@@ -9,8 +9,6 @@ namespace Pelago\Emogrifier\HtmlProcessor;
|
||||
* - add HEAD and BODY elements (if they are missing)
|
||||
* - reformat the HTML
|
||||
*
|
||||
* @internal This class currently is a new technology preview, and its API is still in flux. Don't use it in production.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
*/
|
||||
class HtmlNormalizer extends AbstractHtmlProcessor
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Emogrifier\HtmlProcessor;
|
||||
|
||||
use Pelago\Emogrifier\CssInliner;
|
||||
use Pelago\Emogrifier\Utilities\ArrayIntersector;
|
||||
|
||||
/**
|
||||
* This class can remove things from HTML.
|
||||
*
|
||||
* @author Oliver Klee <github@oliverklee.de>
|
||||
* @author Jake Hotson <jake.github@qzdesign.co.uk>
|
||||
*/
|
||||
class HtmlPruner extends AbstractHtmlProcessor
|
||||
{
|
||||
/**
|
||||
* We need to look for display:none, but we need to do a case-insensitive search. Since DOMDocument only
|
||||
* supports XPath 1.0, lower-case() isn't available to us. We've thus far only set attributes to lowercase,
|
||||
* not attribute values. Consequently, we need to translate() the letters that would be in 'NONE' ("NOE")
|
||||
* to lowercase.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DISPLAY_NONE_MATCHER
|
||||
= '//*[@style and contains(translate(translate(@style," ",""),"NOE","noe"),"display:none")'
|
||||
. ' and not(@class and contains(concat(" ", normalize-space(@class), " "), " -emogrifier-keep "))]';
|
||||
|
||||
/**
|
||||
* Removes elements that have a "display: none;" style.
|
||||
*
|
||||
* @return self fluent interface
|
||||
*/
|
||||
public function removeElementsWithDisplayNone()
|
||||
{
|
||||
$elementsWithStyleDisplayNone = $this->xPath->query(self::DISPLAY_NONE_MATCHER);
|
||||
if ($elementsWithStyleDisplayNone->length === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @var \DOMNode $element */
|
||||
foreach ($elementsWithStyleDisplayNone as $element) {
|
||||
$parentNode = $element->parentNode;
|
||||
if ($parentNode !== null) {
|
||||
$parentNode->removeChild($element);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes classes that are no longer required (e.g. because there are no longer any CSS rules that reference them)
|
||||
* from `class` attributes.
|
||||
*
|
||||
* Note that this does not inspect the CSS, but expects to be provided with a list of classes that are still in use.
|
||||
*
|
||||
* This method also has the (presumably beneficial) side-effect of minifying (removing superfluous whitespace from)
|
||||
* `class` attributes.
|
||||
*
|
||||
* @param string[] $classesToKeep names of classes that should not be removed
|
||||
*
|
||||
* @return self fluent interface
|
||||
*/
|
||||
public function removeRedundantClasses(array $classesToKeep = [])
|
||||
{
|
||||
$elementsWithClassAttribute = $this->xPath->query('//*[@class]');
|
||||
|
||||
if ($classesToKeep !== []) {
|
||||
$this->removeClassesFromElements($elementsWithClassAttribute, $classesToKeep);
|
||||
} else {
|
||||
// Avoid unnecessary processing if there are no classes to keep.
|
||||
$this->removeClassAttributeFromElements($elementsWithClassAttribute);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes classes from the `class` attribute of each element in `$elements`, except any in `$classesToKeep`,
|
||||
* removing the `class` attribute itself if the resultant list is empty.
|
||||
*
|
||||
* @param \DOMNodeList $elements
|
||||
* @param string[] $classesToKeep
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeClassesFromElements(\DOMNodeList $elements, array $classesToKeep)
|
||||
{
|
||||
$classesToKeepIntersector = new ArrayIntersector($classesToKeep);
|
||||
|
||||
/** @var \DOMNode $element */
|
||||
foreach ($elements as $element) {
|
||||
$elementClasses = \preg_split('/\\s++/', \trim($element->getAttribute('class')));
|
||||
$elementClassesToKeep = $classesToKeepIntersector->intersectWith($elementClasses);
|
||||
if ($elementClassesToKeep !== []) {
|
||||
$element->setAttribute('class', \implode(' ', $elementClassesToKeep));
|
||||
} else {
|
||||
$element->removeAttribute('class');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the `class` attribute from each element in `$elements`.
|
||||
*
|
||||
* @param \DOMNodeList $elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeClassAttributeFromElements(\DOMNodeList $elements)
|
||||
{
|
||||
/** @var \DOMNode $element */
|
||||
foreach ($elements as $element) {
|
||||
$element->removeAttribute('class');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After CSS has been inlined, there will likely be some classes in `class` attributes that are no longer referenced
|
||||
* by any remaining (uninlinable) CSS. This method removes such classes.
|
||||
*
|
||||
* Note that it does not inspect the remaining CSS, but uses information readily available from the `CssInliner`
|
||||
* instance about the CSS rules that could not be inlined.
|
||||
*
|
||||
* @param CssInliner $cssInliner object instance that performed the CSS inlining
|
||||
*
|
||||
* @return self fluent interface
|
||||
*
|
||||
* @throws \BadMethodCallException if `inlineCss` has not first been called on `$cssInliner`
|
||||
*/
|
||||
public function removeRedundantClassesAfterCssInlined(CssInliner $cssInliner)
|
||||
{
|
||||
$classesToKeepAsKeys = [];
|
||||
foreach ($cssInliner->getMatchingUninlinableSelectors() as $selector) {
|
||||
\preg_match_all('/\\.(-?+[_a-zA-Z][\\w\\-]*+)/', $selector, $matches);
|
||||
$classesToKeepAsKeys += \array_fill_keys($matches[1], true);
|
||||
}
|
||||
|
||||
$this->removeRedundantClasses(\array_keys($classesToKeepAsKeys));
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Emogrifier\Utilities;
|
||||
|
||||
/**
|
||||
* When computing many array intersections using the same array, it is more efficient to use `array_flip()` first and
|
||||
* then `array_intersect_key()`, than `array_intersect()`. See the discussion at
|
||||
* {@link https://stackoverflow.com/questions/6329211/php-array-intersect-efficiency Stack Overflow} for more
|
||||
* information.
|
||||
*
|
||||
* Of course, this is only possible if the arrays contain integer or string values, and either don't contain duplicates,
|
||||
* or that fact that duplicates will be removed does not matter.
|
||||
*
|
||||
* This class takes care of the detail.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Jake Hotson <jake.github@qzdesign.co.uk>
|
||||
*/
|
||||
class ArrayIntersector
|
||||
{
|
||||
/**
|
||||
* the array with which the object was constructed, with all its keys exchanged with their associated values
|
||||
*
|
||||
* @var (int|string)[]
|
||||
*/
|
||||
private $invertedArray;
|
||||
|
||||
/**
|
||||
* Constructs the object with the array that will be reused for many intersection computations.
|
||||
*
|
||||
* @param (int|string)[] $array
|
||||
*/
|
||||
public function __construct(array $array)
|
||||
{
|
||||
$this->invertedArray = \array_flip($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the intersection of `$array` and the array with which this object was constructed.
|
||||
*
|
||||
* @param (int|string)[] $array
|
||||
*
|
||||
* @return (int|string)[] Returns an array containing all of the values in `$array` whose values exist in the array
|
||||
* with which this object was constructed. Note that keys are preserved, order is maintained, but
|
||||
* duplicates are removed.
|
||||
*/
|
||||
public function intersectWith(array $array)
|
||||
{
|
||||
$invertedArray = \array_flip($array);
|
||||
|
||||
$invertedIntersection = \array_intersect_key($invertedArray, $this->invertedArray);
|
||||
|
||||
return \array_flip($invertedIntersection);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Pelago\Emogrifier;
|
||||
namespace Pelago\Emogrifier\Utilities;
|
||||
|
||||
/**
|
||||
* Facilitates building a CSS string by appending rule blocks one at a time, checking whether the media query,
|
||||
@@ -33,6 +33,8 @@ namespace Pelago\Emogrifier;
|
||||
* ` }
|
||||
* ` }
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Jake Hotson <jake.github@qzdesign.co.uk>
|
||||
*/
|
||||
class CssConcatenator
|
||||
@@ -72,7 +74,7 @@ class CssConcatenator
|
||||
$lastRuleBlock->selectorsAsKeys += $selectorsAsKeys;
|
||||
} else {
|
||||
$hasSameSelectorsAsLastRule = $lastRuleBlock !== false
|
||||
&& static::hasEquivalentSelectors($selectorsAsKeys, $lastRuleBlock->selectorsAsKeys);
|
||||
&& self::hasEquivalentSelectors($selectorsAsKeys, $lastRuleBlock->selectorsAsKeys);
|
||||
if ($hasSameSelectorsAsLastRule) {
|
||||
$lastDeclarationsBlockWithoutSemicolon = \rtrim(\rtrim($lastRuleBlock->declarationsBlock), ';');
|
||||
$lastRuleBlock->declarationsBlock = $lastDeclarationsBlockWithoutSemicolon . ';' . $declarationsBlock;
|
||||
@@ -87,7 +89,7 @@ class CssConcatenator
|
||||
*/
|
||||
public function getCss()
|
||||
{
|
||||
return \implode('', \array_map([$this, 'getMediaRuleCss'], $this->mediaRules));
|
||||
return \implode('', \array_map([self::class, 'getMediaRuleCss'], $this->mediaRules));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +135,7 @@ class CssConcatenator
|
||||
*/
|
||||
private static function getMediaRuleCss(\stdClass $mediaRule)
|
||||
{
|
||||
$css = \implode('', \array_map([static::class, 'getRuleBlockCss'], $mediaRule->ruleBlocks));
|
||||
$css = \implode('', \array_map([self::class, 'getRuleBlockCss'], $mediaRule->ruleBlocks));
|
||||
if ($mediaRule->media !== '') {
|
||||
$css = $mediaRule->media . '{' . $css . '}';
|
||||
}
|
||||
Reference in New Issue
Block a user