<commit_before><?php
/*
UPDATES

    2008-08-10  Fixed CSS comment stripping regex to add PCRE_DOTALL (changed from '/\/\*.*\*\//U' to '/\/\*.*\*\//sU')
    2008-08-18  Added lines instructing DOMDocument to attempt to normalize HTML before processing
    2008-10-20  Fixed bug with bad variable name... Thanks Thomas!
    2008-03-02  Added licensing terms under the MIT License
                Only remove unprocessable HTML tags if they exist in the array
    2009-06-03  Normalize existing CSS (style) attributes in the HTML before we process the CSS.
                Made it so that the display:none stripper doesn't require a trailing semi-colon.
    2009-08-13  Added support for subset class values (e.g. "p.class1.class2").
                Added better protection for bad css attributes.
                Fixed support for HTML entities.
    2009-08-17  Fixed CSS selector processing so that selectors are processed by precedence/specificity, and not just in order.
    2009-10-29  Fixed so that selectors appearing later in the CSS will have precedence over identical selectors appearing earlier.
    2009-11-04  Explicitly declared static functions static to get rid of E_STRICT notices.
    2010-05-18  Fixed bug where full url filenames with protocols wouldn't get split improperly when we explode on ':'... Thanks Mark!
                Added two new attribute selectors
    2010-06-16  Added static caching for less processing overhead in situations where multiple emogrification takes place
    2010-07-26  Fixed bug where '0' values were getting discarded because of php's empty() function... Thanks Scott!
    2010-09-03  Added checks to invisible node removal to ensure that we don't try to remove non-existent child nodes of parents that have already been deleted
    2011-04-08  Fixed errors in CSS->XPath conversion for adjacent sibling selectors and id/class combinations... Thanks <NAME>.!
    2011-06-08  Fixed an error where CSS @media types weren't being parsed correctly... Thanks <NAME>.!
    2011-08-03  Fixed an error where an empty selector at the beginning of the CSS would cause a parse error on the next selector... Thanks <NAME>.!
    2011-10-13  Fully fixed a bug introduced in 2011-06-08 where selectors at the beginning of the CSS would be parsed incorrectly... Thanks Thomas A.!
    2011-10-26  Added an option to allow you to output emogrified code without extended characters being turned into HTML entities.
                Moved static references to class attributes so they can be manipulated.
                Added the ability to clear out the (formerly) static cache when CSS is reloaded.
    2011-12-22  Fixed a bug that was overwriting existing inline styles from the original HTML... Thanks Sagi L.!
    2012-01-31  Fixed a bug that was introduced with the 2011-12-22 revision... Thanks <NAME>. and <NAME>!
                Added extraction of <style> blocks within the HTML due to popular demand.
                Added several new pseudo-selectors (first-child, last-child, nth-child, and nth-of-type).
    2012-02-07  Fixed some recent code introductions to use class constants rather than global constants.
                Fixed some recent code introductions to make it cleaner to read.
    2012-05-01  Made removal of invisible nodes operate in a case-insensitive manner... Thanks Juha P.!
*/

define('CACHE_CSS', 0);
define('CACHE_SELECTOR', 1);
define('CACHE_XPATH', 2);

class Emogrifier {
    /**
     * for calculating nth-of-type and nth-child selectors
     *
     * @var integer
     */
    const INDEX = 0;

    /**
     * for calculating nth-of-type and nth-child selectors
     *
     * @var integer
     */
    const MULTIPLIER = 1;

    /**
     * @var string
     */
    private $html = '';

    /**
     * @var string
     */
    private $css = '';

    /**
     * @var array<string>
     */
    private $unprocessableHTMLTags = array('wbr');

    /**
     * @var array<array>
     */
    private $caches = array();

    /**
     * This attribute applies to the case where you want to preserve your original text encoding.
     *
     * By default, emogrifier translates your text into HTML entities for two reasons:
     *
     * 1. Because of client incompatibilities, it is better practice to send out HTML entities rather than unicode over email.
     *
     * 2. It translates any illegal XML characters that DOMDocument cannot work with.
     *
     * If you would like to preserve your original encoding, set this attribute to true.
     *
     * @var boolean
     */
    public $preserveEncoding = FALSE;

    /**
     * @param string $html
     * @param string $css
     */
    public function __construct($html = '', $css = '') {
        $this->html = $html;
        $this->css  = $css;
        $this->clearCache();
    }

    /**
     * @param string $html
     *
     * @return void
     */
    public function setHTML($html = '') { $this->html = $html; }

    /**
     * @param string $css
     *
     * @return void
     */
    public function setCSS($css = '') {
        $this->css = $css;
        $this->clearCache(CACHE_CSS);
    }

    /**
     * @param integer|null $key
     *
     * @return void
     */
    public function clearCache($key = null) {
        if (!is_null($key)) {
            if (isset($this->caches[$key])) {
                $this->caches[$key] = array();
            }
        } else {
            $this->caches = array(
                CACHE_CSS       => array(),
                CACHE_SELECTOR  => array(),
                CACHE_XPATH     => array(),
            );
        }
    }

    /**
     * There are some HTML tags that DOMDocument cannot process, and it will throw an error if it encounters them.
     * In particular, DOMDocument will complain if you try to use HTML5 tags in an XHTML document.
     *
     * This method allows you to add them if necessary.
     *
     * It only strips them from the code (i.e., it does not actually remove any nodes).
     *<commit_msg>[CLEANUP] Always make the TRUE, FALSE and NULL constants uppercase.<commit_after><?php
/*
UPDATES

    2008-08-10  Fixed CSS comment stripping regex to add PCRE_DOTALL (changed from '/\/\*.*\*\//U' to '/\/\*.*\*\//sU')
    2008-08-18  Added lines instructing DOMDocument to attempt to normalize HTML before processing
    2008-10-20  Fixed bug with bad variable name... Thanks Thomas!
    2008-03-02  Added licensing terms under the MIT License
                Only remove unprocessable HTML tags if they exist in the array
    2009-06-03  Normalize existing CSS (style) attributes in the HTML before we process the CSS.
                Made it so that the display:none stripper doesn't require a trailing semi-colon.
    2009-08-13  Added support for subset class values (e.g. "p.class1.class2").
                Added better protection for bad css attributes.
                Fixed support for HTML entities.
    2009-08-17  Fixed CSS selector processing so that selectors are processed by precedence/specificity, and not just in order.
    2009-10-29  Fixed so that selectors appearing later in the CSS will have precedence over identical selectors appearing earlier.
    2009-11-04  Explicitly declared static functions static to get rid of E_STRICT notices.
    2010-05-18  Fixed bug where full url filenames with protocols wouldn't get split improperly when we explode on ':'... Thanks Mark!
                Added two new attribute selectors
    2010-06-16  Added static caching for less processing overhead in situations where multiple emogrification takes place
    2010-07-26  Fixed bug where '0' values were getting discarded because of php's empty() function... Thanks Scott!
    2010-09-03  Added checks to invisible node removal to ensure that we don't try to remove non-existent child nodes of parents that have already been deleted
    2011-04-08  Fixed errors in CSS->XPath conversion for adjacent sibling selectors and id/class combinations... Thanks <NAME>.!
    2011-06-08  Fixed an error where CSS @media types weren't being parsed correctly... Thanks <NAME>.!
    2011-08-03  Fixed an error where an empty selector at the beginning of the CSS would cause a parse error on the next selector... Thanks <NAME>.!
    2011-10-13  Fully fixed a bug introduced in 2011-06-08 where selectors at the beginning of the CSS would be parsed incorrectly... Thanks <NAME>.!
    2011-10-26  Added an option to allow you to output emogrified code without extended characters being turned into HTML entities.
                Moved static references to class attributes so they can be manipulated.
                Added the ability to clear out the (formerly) static cache when CSS is reloaded.
    2011-12-22  Fixed a bug that was overwriting existing inline styles from the original HTML... Thanks <NAME>.!
    2012-01-31  Fixed a bug that was introduced with the 2011-12-22 revision... Thanks <NAME>. and <NAME>!
                Added extraction of <style> blocks within the HTML due to popular demand.
                Added several new pseudo-selectors (first-child, last-child, nth-child, and nth-of-type).
    2012-02-07  Fixed some recent code introductions to use class constants rather than global constants.
                Fixed some recent code introductions to make it cleaner to read.
    2012-05-01  Made removal of invisible nodes operate in a case-insensitive manner... Thanks <NAME>.!
*/

define('CACHE_CSS', 0);
define('CACHE_SELECTOR', 1);
define('CACHE_XPATH', 2);

class Emogrifier {
    /**
     * for calculating nth-of-type and nth-child selectors
     *
     * @var integer
     */
    const INDEX = 0;

    /**
     * for calculating nth-of-type and nth-child selectors
     *
     * @var integer
     */
    const MULTIPLIER = 1;

    /**
     * @var string
     */
    private $html = '';

    /**
     * @var string
     */
    private $css = '';

    /**
     * @var array<string>
     */
    private $unprocessableHTMLTags = array('wbr');

    /**
     * @var array<array>
     */
    private $caches = array();

    /**
     * This attribute applies to the case where you want to preserve your original text encoding.
     *
     * By default, emogrifier translates your text into HTML entities for two reasons:
     *
     * 1. Because of client incompatibilities, it is better practice to send out HTML entities rather than unicode over email.
     *
     * 2. It translates any illegal XML characters that DOMDocument cannot work with.
     *
     * If you would like to preserve your original encoding, set this attribute to TRUE.
     *
     * @var boolean
     */
    public $preserveEncoding = FALSE;

    /**
     * @param string $html
     * @param string $css
     */
    public function __construct($html = '', $css = '') {
        $this->html = $html;
        $this->css  = $css;
        $this->clearCache();
    }

    /**
     * @param string $html
     *
     * @return void
     */
    public function setHTML($html = '') { $this->html = $html; }

    /**
     * @param string $css
     *
     * @return void
     */
    public function setCSS($css = '') {
        $this->css = $css;
        $this->clearCache(CACHE_CSS);
    }

    /**
     * @param integer|NULL $key
     *
     * @return void
     */
    public function clearCache($key = NULL) {
        if (!is_null($key)) {
            if (isset($this->caches[$key])) {
                $this->caches[$key] = array();
            }
        } else {
            $this->caches = array(
                CACHE_CSS       => array(),
                CACHE_SELECTOR  => array(),
                CACHE_XPATH     => array(),
            );
        }
    }

    /**
     * There are some HTML tags that DOMDocument cannot process, and it will throw an error if it encounters them.
     * In particular, DOMDocument will complain if you try to use HTML5 tags in an XHTML document.
     *
     * This method allows you to add them if necessary.
     *
     * It only strips them from the code (i.e., it does not actually remove any nodes).
     *
{'fraction_non_alphanumeric': 0.08862653807781842, 'fraction_numerical': 0.0337545726637845, 'mean_word_length': 2.32292817679558, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5646141', 'n_tokens_mistral': 3566, 'n_tokens_neox': 3134, 'n_words': 1384}