2009-08-13 7 views
8

Wielu klientów poczty e-mail nie lubi łączonych arkuszy stylów CSS, a nawet osadzonego tagu <style>, ale raczej chce, aby CSS pojawiał się jako atrybuty stylu we wszystkich znacznikach.Jak scalić definicje CSS w plikach z atrybutami stylu śródliniowego, używając Perla?

  • BAD: <link rel=stylesheet type="text/css" href="/style.css">
  • Źle: <style type="text/css">...</style>
  • działa: <h1 style="margin: 0">...</h1>

Jednak ten atrybut style inline podejście jest prawo ból zarządzać.

Znalazłem narzędzia dla Ruby i PHP, które pobierają plik CSS i kilka oddzielnych znaczników jako dane wejściowe i zwracają wynik scalony - pojedynczy plik znaczników ze wszystkimi CSS przekonwertowanymi na atrybuty stylu.

Szukam rozwiązania Perla dla tego problemu, ale nie znalazłem go na CPAN lub przez przeszukanie Google. Jakieś wskazówki? Ewentualnie, czy istnieją moduły CPAN, które można połączyć, aby osiągnąć ten sam rezultat?

+0

@mintywalker Kod Zamieściłem pracował na kilka plików miałem, produkowane ważne HTML z prawidłowego HTML i pozornie prawidłowy CSS z poprawnego CSS. Próbowałeś tego? Byłoby wspaniale mieć opinie. –

+0

@Sinan Ünür: tak - to na pewno działa i jest bardzo blisko, ale zauważyłem, że coś nie jest w porządku, komentując twoją odpowiedź - to problem CSS :: DOM, a nie twój. A brak podglądu komentarzy sugeruje, że komentarz został zmanipulowany, ale myślę, że powinieneś być w stanie zrozumieć sedno sprawy. Dziękuję bardzo za pomoc, mam zamiar zagrać z CSS :: DOM, ale obawiam się, że złożoność może być poza mną. – mintywalker

+0

Może być łatwiejsze do 'HTML :: TreeBuilder' i' CSS'. Trochę eksperymentuję. –

Odpowiedz

10

Nie znam kompletnego, paczkowanego rozwiązania.

CSS::DOM 's compute_style podlega tym samym zastrzeżeniom, co powyżej, emogrifier. Ten moduł w połączeniu z HTML::TokeParser powinien być przydatny do gotowania czegoś.

Aktualizacja: Oto buggy miszmasz rzeczy:

#!/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

Dziękuję - to jest niesamowite, chociaż myślę, że istnieje błąd/todo z CSS :: Dom (który wygląda na trochę kruchy!), Który skuppers rzeczy trochę #foo {border-width: 2px} div {border: 1px przerywana green} z html < div id = foo > ... </div > powinien dostać style = "border: 1px przerywana zielona; border-width: 2px; ' , ale obecnie otrzymuje style = 'border-width: 2px; border: 1px przerywana na zielono " – mintywalker

+0

@mintywalker To jest problem. Spojrzałem na źródło "compute_style" i nie jestem pewien, czy mogę to teraz naprawić. Poprawka kludgy polega na zmianie kolejności w pliku CSS: div {border: 1px dashed green} #foo {border-width: 8px} , ale w ogólnym przypadku jest to niepraktyczne. –

+0

Mam zamiar zagrać z CSS :: DOM - dla moich celów, wykrywanie i wyrzucanie wyjątku byłoby lepsze niż wysyłanie czegoś, co było nie tak, więc zastanawiam się, czy mógłbym ulepszyć compute_style w tym kierunku przynajmniej. Zgłosimy się tutaj, jeśli dostanę się gdziekolwiek (co nie jest w ogóle gwarantowane!) Jeszcze raz - wielkie dzięki, to bardzo pomocny początek. – mintywalker

4

Można użyć CSS::Inlinerhttp://search.cpan.org/dist/CSS-Inliner/

+0

Niedawno również napotkam ten problem. CSS :: Inliner wygląda dokładnie tak samo dla mnie. Chcę zachować szablony przy użyciu reguł CSS, ale wstawiać style tuż przed wysłaniem wiadomości e-mail. Dzięki za link! –

Powiązane problemy