2009-08-13 4 views
8

De nombreux clients de messagerie n'aiment pas les feuilles de style CSS liées, ni même la balise <style> intégrée, mais souhaitent que le CSS apparaisse en ligne en tant qu'attributs de style sur tous vos balisages.Comment fusionner des définitions CSS dans des fichiers en attributs de style en ligne, en utilisant Perl?

  • BAD: <link rel=stylesheet type="text/css" href="/style.css">
  • BAD: <style type="text/css">...</style>
  • TRAVAUX: <h1 style="margin: 0">...</h1>

Cependant, cette approche d'attribut de style en ligne est une douleur droit de gérer.

J'ai trouvé des outils pour Ruby et PHP qui vont prendre un fichier CSS et un balisage séparé en entrée et vous renvoyer le résultat fusionné - un seul fichier de balisage avec toutes les CSS converties en attributs de style.

Je suis à la recherche d'une solution Perl à ce problème, mais je n'en ai pas trouvé sur le CPAN ni sur Google. Des pointeurs? Sinon, y a-t-il des modules CPAN que l'on pourrait combiner pour obtenir le même résultat?

+0

@mintywalker Le code que j'ai posté travaillé sur un tas de fichiers que j'avais, produit valide HTML de HTML valide et CSS valide de CSS valide. L'as tu essayé? Ce serait génial d'avoir des commentaires. –

+0

@Sinan Ünür: oui - il fonctionne certainement et se rapproche assez, mais j'ai noté quelque chose qu'il ne va pas tout à fait droit en commentant sur votre réponse - c'est le problème CSS :: DOM, pas votre tho. Et le manque de prévisualisation sur les commentaires signifie que le commentaire a été brisé, mais je pense que vous devriez être en mesure de comprendre le crux. Merci beaucoup pour votre aide, je vais avoir un jeu avec CSS :: DOM mais je crains que la complexité ne me dépasse ici. – mintywalker

+0

Il pourrait être plus facile de 'HTML :: TreeBuilder' et' CSS'. J'expérimente un peu. –

Répondre

10

Je ne connais pas de solution complète et préemballée.

CSS::DOM « s compute_style est sujet à peu près les mêmes mises en garde que emogrifier ci-dessus. Ce module, en conjonction avec HTML::TokeParser devrait être utilisable pour cuire quelque chose.

Mise à jour: Voici un méli-mélo buggy de choses:

#!/usr/bin/perl 

use strict; 
use warnings; 

use CSS::DOM; 
use File::Slurp; 
use HTML::DOM; 
use HTML::TokeParser; 

die "convert html_file css_file" unless @ARGV == 2; 
my ($html_file, $css_file) = @ARGV; 

my $html_parser = HTML::TokeParser->new($html_file) 
    or die "Cannot open '$html_file': $!"; 

my $sheet = CSS::DOM::parse(scalar read_file $css_file); 

while (my $token = $html_parser->get_token) { 
    my $type = $token->[0]; 
    my $text = $type eq 'T' ? $token->[1] : $token->[-1]; 
    if ($type eq 'S') { 
     unless (skip($token->[1])) { 
      $text = insert_computed_style($sheet, $token); 
     } 
    } 
    print $text; 
} 

sub insert_computed_style { 
    my ($sheet, $token) = @_; 
    my ($tag, $attr, $attrseq) = @$token[1 .. 3]; 
    my $doc = HTML::DOM->new; 

    my $element = $doc->createElement($tag); 

    for my $attr_name (@$attrseq) { 
     $element->setAttribute($attr_name, $attr->{$attr_name}); 
    } 

    my $style = CSS::DOM::compute_style(
     element => $element, user_sheet => $sheet 
    ); 

    my @attrseq = (style => grep { lc $_ ne 'style' } @$attrseq); 
    $attr->{style} = $style->cssText; 

    my $text .= join(" ", 
     "<$tag", 
     map{ qq/$_='$attr->{$_}'/ } @attrseq); 
    $text .= '>'; 

    return $text; 
} 

sub skip { 
    my ($tag) = @_; 
    $tag = lc $tag; 
    return 1 if $tag =~ /^(?:h(?:ead|tml)|link|meta|script|title)$/; 
} 
+0

Merci - c'est assez incroyable, même si je pense qu'il y a un bug/todo avec CSS :: Dom (qui semble un peu fragile encore!) Qui saute un peu les choses #foo {border-width: 2px} div {border: 1px pointillés vert} avec le code html < div id = toto > ... </div > doit obtenir style = 'border: 1px pointillés vert; border-width: 2px; ' mais obtient actuellement style = 'border-width: 2px; frontière: 1px en pointillés vert ' – mintywalker

+0

@mintywalker C'est un problème. J'ai regardé la source de 'compute_style' et je ne suis pas sûr de pouvoir le réparer maintenant. Une correction kludgy consiste à changer l'ordre dans le fichier CSS: div {border: 1px en pointillé vert} #foo {border-width: 8px} mais ce n'est pas pratique dans le cas général. –

+0

Je vais avoir un jeu avec CSS :: DOM - pour mes fins, repérer et lancer une exception serait mieux que d'émettre quelque chose qui ne va pas, donc je me demande si je pourrais être en mesure de tordre compute_style dans cette direction au moins. Je rapporterai ici si j'arrive quelque part (ce qui n'est pas garanti du tout!) Encore une fois - merci beaucoup, c'est un début très utile. – mintywalker

4

Vous pouvez utiliser CSS::Inlinerhttp://search.cpan.org/dist/CSS-Inliner/

+0

J'ai récemment rencontré ce problème aussi. CSS :: Inliner ressemble exactement à l'outil pour moi. Je souhaite conserver mes modèles en utilisant les règles CSS, mais j'ajoute les styles avant d'envoyer l'e-mail. Merci pour le lien! –

Questions connexes