Файловый менеджер - Редактировать - /home/clickysoft/public_html/jmapi5.clickysoft.net/tijsverkoyen.tar
Назад
css-to-inline-styles/composer.json 0000644 00000002020 15021223360 0013257 0 ustar 00 { "name": "tijsverkoyen/css-to-inline-styles", "type": "library", "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "license": "BSD-3-Clause", "authors": [ { "name": "Tijs Verkoyen", "email": "css_to_inline_styles@verkoyen.eu", "role": "Developer" } ], "require": { "php": "^5.5 || ^7.0 || ^8.0", "ext-dom": "*", "ext-libxml": "*", "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" }, "autoload": { "psr-4": { "TijsVerkoyen\\CssToInlineStyles\\": "src" } }, "autoload-dev": { "psr-4": { "TijsVerkoyen\\CssToInlineStyles\\Tests\\": "tests" } }, "extra": { "branch-alias": { "dev-master": "2.2.x-dev" } } } css-to-inline-styles/LICENSE.md 0000644 00000002723 15021223360 0012153 0 ustar 00 Copyright (c) Tijs Verkoyen. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. css-to-inline-styles/src/Css/Rule/Rule.php 0000644 00000002711 15021223360 0014412 0 ustar 00 <?php namespace TijsVerkoyen\CssToInlineStyles\Css\Rule; use Symfony\Component\CssSelector\Node\Specificity; use TijsVerkoyen\CssToInlineStyles\Css\Property\Property; final class Rule { /** * @var string */ private $selector; /** * @var Property[] */ private $properties; /** * @var Specificity */ private $specificity; /** * @var integer */ private $order; /** * Rule constructor. * * @param string $selector * @param Property[] $properties * @param Specificity $specificity * @param int $order */ public function __construct($selector, array $properties, Specificity $specificity, $order) { $this->selector = $selector; $this->properties = $properties; $this->specificity = $specificity; $this->order = $order; } /** * Get selector * * @return string */ public function getSelector() { return $this->selector; } /** * Get properties * * @return Property[] */ public function getProperties() { return $this->properties; } /** * Get specificity * * @return Specificity */ public function getSpecificity() { return $this->specificity; } /** * Get order * * @return int */ public function getOrder() { return $this->order; } } css-to-inline-styles/src/Css/Rule/Processor.php 0000644 00000011732 15021223360 0015465 0 ustar 00 <?php namespace TijsVerkoyen\CssToInlineStyles\Css\Rule; use Symfony\Component\CssSelector\Node\Specificity; use \TijsVerkoyen\CssToInlineStyles\Css\Property\Processor as PropertyProcessor; class Processor { /** * Splits a string into separate rules * * @param string $rulesString * * @return string[] */ public function splitIntoSeparateRules($rulesString) { $rulesString = $this->cleanup($rulesString); return (array) explode('}', $rulesString); } /** * @param string $string * * @return string */ private function cleanup($string) { $string = str_replace(array("\r", "\n"), '', $string); $string = str_replace(array("\t"), ' ', $string); $string = str_replace('"', '\'', $string); $string = preg_replace('|/\*.*?\*/|', '', $string); $string = preg_replace('/\s\s+/', ' ', $string); $string = trim($string); $string = rtrim($string, '}'); return $string; } /** * Converts a rule-string into an object * * @param string $rule * @param int $originalOrder * * @return Rule[] */ public function convertToObjects($rule, $originalOrder) { $rule = $this->cleanup($rule); $chunks = explode('{', $rule); if (!isset($chunks[1])) { return array(); } $propertiesProcessor = new PropertyProcessor(); $rules = array(); $selectors = (array) explode(',', trim($chunks[0])); $properties = $propertiesProcessor->splitIntoSeparateProperties($chunks[1]); foreach ($selectors as $selector) { $selector = trim($selector); $specificity = $this->calculateSpecificityBasedOnASelector($selector); $rules[] = new Rule( $selector, $propertiesProcessor->convertArrayToObjects($properties, $specificity), $specificity, $originalOrder ); } return $rules; } /** * Calculates the specificity based on a CSS Selector string, * Based on the patterns from premailer/css_parser by Alex Dunae * * @see https://github.com/premailer/css_parser/blob/master/lib/css_parser/regexps.rb * * @param string $selector * * @return Specificity */ public function calculateSpecificityBasedOnASelector($selector) { $idSelectorsPattern = " \#"; $classAttributesPseudoClassesSelectorsPattern = " (\.[\w]+) # classes | \[(\w+) # attributes | (\:( # pseudo classes link|visited|active |hover|focus |lang |target |enabled|disabled|checked|indeterminate |root |nth-child|nth-last-child|nth-of-type|nth-last-of-type |first-child|last-child|first-of-type|last-of-type |only-child|only-of-type |empty|contains ))"; $typePseudoElementsSelectorPattern = " ((^|[\s\+\>\~]+)[\w]+ # elements | \:{1,2}( # pseudo-elements after|before |first-letter|first-line |selection ) )"; return new Specificity( preg_match_all("/{$idSelectorsPattern}/ix", $selector, $matches), preg_match_all("/{$classAttributesPseudoClassesSelectorsPattern}/ix", $selector, $matches), preg_match_all("/{$typePseudoElementsSelectorPattern}/ix", $selector, $matches) ); } /** * @param string[] $rules * @param Rule[] $objects * * @return Rule[] */ public function convertArrayToObjects(array $rules, array $objects = array()) { $order = 1; foreach ($rules as $rule) { $objects = array_merge($objects, $this->convertToObjects($rule, $order)); $order++; } return $objects; } /** * Sorts an array on the specificity element in an ascending way * Lower specificity will be sorted to the beginning of the array * * @param Rule $e1 The first element. * @param Rule $e2 The second element. * * @return int */ public static function sortOnSpecificity(Rule $e1, Rule $e2) { $e1Specificity = $e1->getSpecificity(); $value = $e1Specificity->compareTo($e2->getSpecificity()); // if the specificity is the same, use the order in which the element appeared if ($value === 0) { $value = $e1->getOrder() - $e2->getOrder(); } return $value; } } css-to-inline-styles/src/Css/Property/Property.php 0000644 00000003063 15021223360 0016245 0 ustar 00 <?php namespace TijsVerkoyen\CssToInlineStyles\Css\Property; use Symfony\Component\CssSelector\Node\Specificity; final class Property { /** * @var string */ private $name; /** * @var string */ private $value; /** * @var Specificity */ private $originalSpecificity; /** * Property constructor. * @param string $name * @param string $value * @param Specificity|null $specificity */ public function __construct($name, $value, Specificity $specificity = null) { $this->name = $name; $this->value = $value; $this->originalSpecificity = $specificity; } /** * Get name * * @return string */ public function getName() { return $this->name; } /** * Get value * * @return string */ public function getValue() { return $this->value; } /** * Get originalSpecificity * * @return Specificity */ public function getOriginalSpecificity() { return $this->originalSpecificity; } /** * Is this property important? * * @return bool */ public function isImportant() { return (stripos($this->value, '!important') !== false); } /** * Get the textual representation of the property * * @return string */ public function toString() { return sprintf( '%1$s: %2$s;', $this->name, $this->value ); } } css-to-inline-styles/src/Css/Property/Processor.php 0000644 00000006177 15021223360 0016411 0 ustar 00 <?php namespace TijsVerkoyen\CssToInlineStyles\Css\Property; use Symfony\Component\CssSelector\Node\Specificity; class Processor { /** * Split a string into separate properties * * @param string $propertiesString * * @return string[] */ public function splitIntoSeparateProperties($propertiesString) { $propertiesString = $this->cleanup($propertiesString); $properties = (array) explode(';', $propertiesString); $keysToRemove = array(); $numberOfProperties = count($properties); for ($i = 0; $i < $numberOfProperties; $i++) { $properties[$i] = trim($properties[$i]); // if the new property begins with base64 it is part of the current property if (isset($properties[$i + 1]) && strpos(trim($properties[$i + 1]), 'base64,') === 0) { $properties[$i] .= ';' . trim($properties[$i + 1]); $keysToRemove[] = $i + 1; } } if (!empty($keysToRemove)) { foreach ($keysToRemove as $key) { unset($properties[$key]); } } return array_values($properties); } /** * @param string $string * * @return string */ private function cleanup($string) { $string = str_replace(array("\r", "\n"), '', $string); $string = str_replace(array("\t"), ' ', $string); $string = str_replace('"', '\'', $string); $string = preg_replace('|/\*.*?\*/|', '', $string); $string = preg_replace('/\s\s+/', ' ', $string); $string = trim($string); $string = rtrim($string, ';'); return $string; } /** * Converts a property-string into an object * * @param string $property * * @return Property|null */ public function convertToObject($property, Specificity $specificity = null) { if (strpos($property, ':') === false) { return null; } list($name, $value) = explode(':', $property, 2); $name = trim($name); $value = trim($value); if ($value === '') { return null; } return new Property($name, $value, $specificity); } /** * Converts an array of property-strings into objects * * @param string[] $properties * * @return Property[] */ public function convertArrayToObjects(array $properties, Specificity $specificity = null) { $objects = array(); foreach ($properties as $property) { $object = $this->convertToObject($property, $specificity); if ($object === null) { continue; } $objects[] = $object; } return $objects; } /** * Build the property-string for multiple properties * * @param Property[] $properties * * @return string */ public function buildPropertiesString(array $properties) { $chunks = array(); foreach ($properties as $property) { $chunks[] = $property->toString(); } return implode(' ', $chunks); } } css-to-inline-styles/src/Css/Processor.php 0000644 00000003517 15021223360 0014560 0 ustar 00 <?php namespace TijsVerkoyen\CssToInlineStyles\Css; use TijsVerkoyen\CssToInlineStyles\Css\Rule\Processor as RuleProcessor; use TijsVerkoyen\CssToInlineStyles\Css\Rule\Rule; class Processor { /** * Get the rules from a given CSS-string * * @param string $css * @param Rule[] $existingRules * * @return Rule[] */ public function getRules($css, $existingRules = array()) { $css = $this->doCleanup($css); $rulesProcessor = new RuleProcessor(); $rules = $rulesProcessor->splitIntoSeparateRules($css); return $rulesProcessor->convertArrayToObjects($rules, $existingRules); } /** * Get the CSS from the style-tags in the given HTML-string * * @param string $html * * @return string */ public function getCssFromStyleTags($html) { $css = ''; $matches = array(); $htmlNoComments = preg_replace('|<!--.*?-->|s', '', $html); preg_match_all('|<style(?:\s.*)?>(.*)</style>|isU', $htmlNoComments, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $match) { $css .= trim($match) . "\n"; } } return $css; } /** * @param string $css * * @return string */ private function doCleanup($css) { // remove charset $css = preg_replace('/@charset "[^"]++";/', '', $css); // remove media queries $css = preg_replace('/@media [^{]*+{([^{}]++|{[^{}]*+})*+}/', '', $css); $css = str_replace(array("\r", "\n"), '', $css); $css = str_replace(array("\t"), ' ', $css); $css = str_replace('"', '\'', $css); $css = preg_replace('|/\*.*?\*/|', '', $css); $css = preg_replace('/\s\s++/', ' ', $css); $css = trim($css); return $css; } } css-to-inline-styles/src/CssToInlineStyles.php 0000644 00000016267 15021223360 0015455 0 ustar 00 <?php namespace TijsVerkoyen\CssToInlineStyles; use Symfony\Component\CssSelector\CssSelector; use Symfony\Component\CssSelector\CssSelectorConverter; use Symfony\Component\CssSelector\Exception\ExceptionInterface; use TijsVerkoyen\CssToInlineStyles\Css\Processor; use TijsVerkoyen\CssToInlineStyles\Css\Property\Processor as PropertyProcessor; use TijsVerkoyen\CssToInlineStyles\Css\Rule\Processor as RuleProcessor; class CssToInlineStyles { private $cssConverter; public function __construct() { if (class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) { $this->cssConverter = new CssSelectorConverter(); } } /** * Will inline the $css into the given $html * * Remark: if the html contains <style>-tags those will be used, the rules * in $css will be appended. * * @param string $html * @param string $css * * @return string */ public function convert($html, $css = null) { $document = $this->createDomDocumentFromHtml($html); $processor = new Processor(); // get all styles from the style-tags $rules = $processor->getRules( $processor->getCssFromStyleTags($html) ); if ($css !== null) { $rules = $processor->getRules($css, $rules); } $document = $this->inline($document, $rules); return $this->getHtmlFromDocument($document); } /** * Inline the given properties on an given DOMElement * * @param \DOMElement $element * @param Css\Property\Property[] $properties * * @return \DOMElement */ public function inlineCssOnElement(\DOMElement $element, array $properties) { if (empty($properties)) { return $element; } $cssProperties = array(); $inlineProperties = array(); foreach ($this->getInlineStyles($element) as $property) { $inlineProperties[$property->getName()] = $property; } foreach ($properties as $property) { if (!isset($inlineProperties[$property->getName()])) { $cssProperties[$property->getName()] = $property; } } $rules = array(); foreach (array_merge($cssProperties, $inlineProperties) as $property) { $rules[] = $property->toString(); } $element->setAttribute('style', implode(' ', $rules)); return $element; } /** * Get the current inline styles for a given DOMElement * * @param \DOMElement $element * * @return Css\Property\Property[] */ public function getInlineStyles(\DOMElement $element) { $processor = new PropertyProcessor(); return $processor->convertArrayToObjects( $processor->splitIntoSeparateProperties( $element->getAttribute('style') ) ); } /** * @param string $html * * @return \DOMDocument */ protected function createDomDocumentFromHtml($html) { $document = new \DOMDocument('1.0', 'UTF-8'); $internalErrors = libxml_use_internal_errors(true); $document->loadHTML(mb_encode_numericentity($html, [0x80, 0x10FFFF, 0, 0x1FFFFF], 'UTF-8')); libxml_use_internal_errors($internalErrors); $document->formatOutput = true; return $document; } /** * @param \DOMDocument $document * * @return string */ protected function getHtmlFromDocument(\DOMDocument $document) { // retrieve the document element // we do it this way to preserve the utf-8 encoding $htmlElement = $document->documentElement; $html = $document->saveHTML($htmlElement); $html = trim($html); // retrieve the doctype $document->removeChild($htmlElement); $doctype = $document->saveHTML(); $doctype = trim($doctype); // if it is the html5 doctype convert it to lowercase if ($doctype === '<!DOCTYPE html>') { $doctype = strtolower($doctype); } return $doctype."\n".$html; } /** * @param \DOMDocument $document * @param Css\Rule\Rule[] $rules * * @return \DOMDocument */ protected function inline(\DOMDocument $document, array $rules) { if (empty($rules)) { return $document; } $propertyStorage = new \SplObjectStorage(); $xPath = new \DOMXPath($document); usort($rules, array(RuleProcessor::class, 'sortOnSpecificity')); foreach ($rules as $rule) { try { if (null !== $this->cssConverter) { $expression = $this->cssConverter->toXPath($rule->getSelector()); } else { // Compatibility layer for Symfony 2.7 and older $expression = CssSelector::toXPath($rule->getSelector()); } } catch (ExceptionInterface $e) { continue; } $elements = $xPath->query($expression); if ($elements === false) { continue; } foreach ($elements as $element) { $propertyStorage[$element] = $this->calculatePropertiesToBeApplied( $rule->getProperties(), $propertyStorage->contains($element) ? $propertyStorage[$element] : array() ); } } foreach ($propertyStorage as $element) { $this->inlineCssOnElement($element, $propertyStorage[$element]); } return $document; } /** * Merge the CSS rules to determine the applied properties. * * @param Css\Property\Property[] $properties * @param Css\Property\Property[] $cssProperties existing applied properties indexed by name * * @return Css\Property\Property[] updated properties, indexed by name */ private function calculatePropertiesToBeApplied(array $properties, array $cssProperties) { if (empty($properties)) { return $cssProperties; } foreach ($properties as $property) { if (isset($cssProperties[$property->getName()])) { $existingProperty = $cssProperties[$property->getName()]; //skip check to overrule if existing property is important and current is not if ($existingProperty->isImportant() && !$property->isImportant()) { continue; } //overrule if current property is important and existing is not, else check specificity $overrule = !$existingProperty->isImportant() && $property->isImportant(); if (!$overrule) { $overrule = $existingProperty->getOriginalSpecificity()->compareTo($property->getOriginalSpecificity()) <= 0; } if ($overrule) { unset($cssProperties[$property->getName()]); $cssProperties[$property->getName()] = $property; } } else { $cssProperties[$property->getName()] = $property; } } return $cssProperties; } }
| ver. 1.4 |
Github
|
.
| PHP 8.1.29 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка