Changeset 54539 in spip-zone


Ignore:
Timestamp:
Nov 17, 2011, 11:09:04 AM (8 years ago)
Author:
arnaud@…
Message:

Ajout de la class inlineStyle (https://github.com/christiaan/InlineStyle) et intégration de celle-ci.
Cela remplace la trop vieille méthode $Facteur->ConvertirStylesEnligne?() qui intégrait les CSS en ligne mais de manière trop approximative.

Désolé monsieur Eric Dols, merci pour ses années de services de votre fonction.

Location:
_plugins_/facteur/branches/v1
Files:
12 added
1 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/facteur/branches/v1/classes/facteur.php

    r52840 r54539  
    271271
    272272        function ConvertirStylesEnligne() {
    273                 /*
    274 
    275                 Written by Eric Dols - edols@auditavenue.com
    276 
    277                 You may freely use or modify this, provided
    278                 you leave credits to the original coder.
    279                 Feedback about (un)successfull uses, bugs and improvements done
    280                 are much appreciated, but don't expect actual support.
    281 
    282                 PURPOSE OF THIS FUNCTION
    283                         It is designed to process html emails relying
    284                         on a css stylesheet placed in the <head> for layout in
    285                         order to enhance compatibility with email clients,
    286                         including webmail services.
    287                         Provided you use minimal css, you can keep styling separate
    288                         from the content in your email template, and let this function
    289                         "inject" those styles inline in your email html tags on-the-fly,
    290                         just before sending.
    291                         Technically, it grabs the style declarations found in the
    292                         <head> section and inserts each declaration inline,
    293                         inside the corresponding html tags in the email message.
    294 
    295                         Supports both HTML and XHTML markup seamlessly. Thus
    296                         tolerant to email message writers using non-xhtml tag,
    297                         even when template is xhtml compliant (e.g. they would
    298                         add <img ...> instead of a xhtml compliant <img ... />).
    299 
    300                 NEW 10 dec. 2003:
    301                         - code revised, including a few regexp bugs fixed.
    302                         - multiple class for a tag are now allowed <p class="firstclass secondclass">
    303                         - all unsupported css styles are now moved to the body section (not just a:hover etc...)
    304 
    305                 USE
    306                         Add this function to a function library include, like "inline.inc"
    307                         and include it near the beginning of your php page:
    308                         require ("inline.inc");
    309 
    310                         load the html source of message into a variable
    311                         like $html_source and process it using:
    312                         $html_source = sheet2inline($html_source)
    313 
    314 
    315                 STYLE DEFINITIONS SUPPORTED
    316                         TAG { ... }
    317                         TAG1, TAG2, ... { ... }
    318                         TAG.class { ... }
    319                         .class { ...)
    320                         TAG:pseudo { ... }
    321 
    322 
    323                         CSS definitions may be freely formatted (spaces, tabs, linefeeds...),
    324                         they are converted to oneliners before inserting them inline in the html tags.
    325 
    326                         .class definitions are processed AFTER tag definitions,
    327                         thus appended inline after any existing tag styling to
    328                         preserve the normal css priority behavior.
    329 
    330                         Existing style="..." attributes in tags are NOT stripped. However they MUST
    331                         be with double quotes. If not, an addtional style="..." attribute will be added
    332 
    333 
    334                 KNOWN LIMITATIONS
    335                         - style info should be placed in <head> section. I believe
    336                                 it shouldnt be too hard to modify to point to an external
    337                                 stylesheet instead.
    338                         - no support (yet?):
    339                                 * chains like P UL LI { .... } or P UL LI.class { .... }
    340                                 * #divname p { ... } and <tag id="...">
    341                                 * a:hover, a:visited {...} multiple class:pseudo
    342                                 They require a significantly more complicated processing likely
    343                                 based on stylesheet and document trees parsing.
    344                                 Many email clients don't handle more than what is supported
    345                                 by this script anyway.
    346                         - pseudo-classes like a:hover {...} can't be inserted inline
    347                                 in the html tags: they are moved to a <style> declaration in
    348                                 the <body> instead. This is a limitation from html, not this script.
    349                         - It is still up to you to check if target email clients render
    350                                 your css styled templates correctly, especially webmail services
    351                                 like Hotmail, in which the email becomes a sub-part of an html page,
    352                                 with styles already in place.
    353                 */
    354 
    355                 // variables to be accessed in the callback sub-function too
    356                 global $styledefinition, $styletag, $styleclass;
    357 
    358                 // Let's first load the stylesheet information in a $styles array using a regexp
    359                 preg_match_all ( "/^[ \t]*([.]?)([\w, #]+)([.:])?(\S*)\s+{([^}]+)}/mi", $this->Body , $styles);
    360                 /*
    361                         $styles[1] = . or ''  => .class or tag (empty)
    362                         $styles[2] = name of class or tag(s)
    363                         $styles[3] = : . or '' => followed by pseudo-element, class separator or nothing (empty)
    364                         $styles[4] = name of pseudo-element after a tag, if any
    365                         $styles[5] = the style definition itself, i.e. what's between the { }
    366                 */
    367 
    368                 // Now loop through the styles found and act accordingly;
    369 
    370                 // process TAG {...} & TAG1, TAG2,... {...} definitions only first by order of appearance
    371                 foreach ($styles[1] as $i => $type) {
    372                         if ($type=="" && $styles[3][$i]=="") {
    373                                 $styledefinition = trim($styles[5][$i]);
    374                                 $styletag = preg_replace("/ *, */", "|", trim($styles[2][$i])); //echo $styletag."<br />";
    375                                 $styleclass = "";
    376                                 // process TAG {...} and TAG1, TAG2 {...} but not TAG1 TAG2 {...} or #divname styles
    377                                 if (!preg_match("/ /", $styletag) && !preg_match("/#/", $styletag)) {
    378                                         $pattern = "!<(".$styletag.")([^>]*(?= /)|[^>]*)( /)?>!mi";
    379                                         $this->Body = preg_replace_callback ($pattern, 'facteur_addstyle' , $this->Body);
    380                                         $styles[6][$i]=1; // mark as injected inline
    381                                 }
    382                         }
    383                 }
    384 
    385                 // append additional .CLASS {...} and TAG.CLASS {...} styling by order of appearance
    386                 // important to do so after TAG {...} definitions, so that class attributes override TAG styles when needed
    387                 foreach ($styles[1] as $i => $type) {
    388                         if ($type!="." && $styles[3][$i]=="." ) {       // class definition for a specific tag
    389                                 $styledefinition = trim($styles[5][$i]);
    390                                 $styletag = trim($styles[2][$i]);
    391                                 $styleclass = trim($styles[4][$i]);
    392                                 $pattern = "!<(".$styletag.")([^>]* class\=['\"][^'\"]*".$styleclass."[^'\"]*['\"][^>]*(?= /)|[^>]* class\=['\"][^'\"]*".$styleclass."[^'\"]*['\"][^>]*)( />)?>!mi";
    393                                 $this->Body = preg_replace_callback ($pattern, 'facteur_addstyle' , $this->Body);
    394                                 $styles[6][$i]=1; // mark as injected inline
    395 
    396                         }
    397                         elseif ($type=="." && $styles[3][$i]=="" ) {    // general class definition for any tag
    398                                 $styledefinition = trim($styles[5][$i]);
    399                                 $styletag = "";
    400                                 $styleclass = trim($styles[2][$i]);
    401                                 $pattern = "!<(\w+)([^>]* class\=['\"]".$styleclass."['\"][^>]*(?= /)|[^>]* class\=['\"]".$styleclass."['\"][^>]*)( />)?>!mi";
    402                                 $this->Body = preg_replace_callback ($pattern, 'facteur_addstyle' , $this->Body);
    403                                 $styles[6][$i]=1; // mark as injected inline
    404                         }
    405                 }
    406 
    407 
    408                 /* move all style declarations that weren't injected from <head> to a <body> <style> section,
    409                          including but not limited to:
    410                          - pseudo-classes like a:hover {...} as they can't be set inline
    411                          - declaration chains like UL LI {...}
    412                          - #divname {...}. These are not supported by email clients like Mac/Entourage anyway, it seems. */
    413                 foreach ($styles[1] as $i => $type) {
    414                         if ($styles[6][$i]=="") {
    415                                 // add a <style type="text/css"> section after <body> if there's isn't one yet
    416                                 if (preg_match ("!<body[^>]*>\s*<style!mi", $this->Body)==0) {
    417                                         $this->Body = preg_replace ("/(<body[^>]*>)/i", "\n\$1\n".'<style type="text/css">'."\n<!--\n-->\n</style>\n", $this->Body);
    418                                 }
    419                                 // append a copy of the pseudo-element declaration to that body style section
    420                                 $styledefinition = trim($styles[5][$i]);
    421                                 $styledefinition = preg_replace ("!\s+!mi", " ", $styledefinition ); // convert style definition to a one-liner (optional)
    422                                 $declaration = $styles[1][$i].trim($styles[2][$i]).$styles[3][$i].trim($styles[4][$i])." { ".$styledefinition." }";
    423                                 $this->Body = preg_replace ("!(<body[^>]*>\s*<style[^>]*>\s*<\!\-\-[^>]*)"."(\s*\-\->\s*</style>)!si", "\$1".$declaration."\n\$2", $this->Body);
    424                                 $styles[6][$i]= 2; // mark as moved to <style> section in <body>
    425                         }
    426                 }
    427 
    428                 // remove stylesheet declaration(s) from <head> section (comment following line out if not wanted)
    429                 //$this->Body = preg_replace ("!(<head>.*)<style type.*</style>(.*</head>)!si", "\$1\$2" , $this->Body);
    430 
    431                 // check what styles have been injected
    432 #                       print_r($styles);
    433 
     273                include_spip('inline-style/InlineStyle');
     274                include_spip('inline-style/CSSQuery');
     275                $bodyStyleenLigne = new InlineStyle(charset2unicode($this->Body,'utf-8')); // inlineStyle préfère l'unicode
     276                $bodyStyleenLigne->applyStylesheet($bodyStyleenLigne->extractStylesheets());
     277                $this->Body = $bodyStyleenLigne->getHTML();
    434278        }
    435279
Note: See TracChangeset for help on using the changeset viewer.