2009-08-13 4 views
8

Viele E-Mail-Clients mögen keine verknüpften CSS-Stylesheets oder sogar das eingebettete <style>-Tag, sondern möchten, dass das CSS inline als Stilattribute für alle Ihre Markups angezeigt wird.Wie kann ich CSS-Definitionen in Dateien mit Perl in Inline-Stilattribute zusammenführen?

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

jedoch dieser Inline-Stil-Attribut Ansatz ist ein richtigen Schmerzen zu verwalten.

Ich habe Tools für Ruby und PHP gefunden, die eine CSS-Datei und ein separates Markup als Eingabe nehmen und Ihnen das zusammengefügte Ergebnis zurückgeben - eine einzelne Markupdatei mit allen CSS-Attributen, die in Stilattribute umgewandelt wurden.

Ich bin auf der Suche nach einer Perl-Lösung für dieses Problem, aber ich habe keine gefunden auf CPAN oder Google suchen. Irgendwelche Zeiger? Oder gibt es CPAN-Module, die man kombinieren könnte, um dasselbe Ergebnis zu erzielen?

+0

@mintywalker Der Code, den ich auf eine Reihe von Dateien gearbeitet habe ich geschrieben hatte, produziert gültig HTML aus gültigem HTML und scheinbar gültiges CSS aus gültigem CSS. Hast du es versucht? Es wäre großartig, Feedback zu bekommen. –

+0

@Sinan Ünür: Ja - es läuft sicherlich und wird ziemlich nah, aber ich bemerkte etwas, dass es nicht ganz richtig kommt, indem er Ihre Antwort kommentiert - es ist CSS :: DOM Problem, nicht Ihr tho. Und der Mangel an Vorschau auf Kommentare bedeutet, dass der Kommentar verstümmelt wurde, aber ich denke, dass Sie in der Lage sein sollten, die Crux herauszufinden. Vielen Dank für Ihre Hilfe, ich werde mit CSS :: DOM spielen, aber ich fürchte, die Komplexität mag hier über mich hinausgehen. – mintywalker

+0

Es könnte einfacher sein, 'HTML :: TreeBuilder' und' CSS' zu verwenden. Ich experimentiere ein wenig. –

Antwort

10

Ich kenne keine vollständige, vorkonfektionierte Lösung.

CSS::DOM ‚s compute_style unterliegt so ziemlich die gleichen Einschränkungen wie emogrifier oben. Dieses Modul sollte in Verbindung mit HTML::TokeParser verwendbar sein, um etwas zu kochen.

Update: Hier ist ein Buggy Mischmasch der Dinge:

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

Danke - das ist ziemlich erstaunlich, obwohl ich denke, es gibt einen Bug/Todo mit CSS :: Dom (die ein wenig zerbrechlich aussieht!), Die Dinge ein wenig skuppers #foo {border-width: 2px} div {border: 1px grün gestrichelte} mit dem html < div id = foo > ... </div > sollte style = "Grenze bekommen: 1px gestrichelte grün; Rahmenbreite: 2px; ' , aber wird derzeit style = 'border-width: 2px; Grenze: 1px gestrichelt grün ' – mintywalker

+0

@mintywalker Das ist ein Problem. Ich habe mir die Quelle für 'compute_style' angesehen und bin mir nicht sicher, ob ich das jetzt beheben kann. Ein kludgy Fix ist, die Reihenfolge in der CSS-Datei zu ändern: div {border: 1px gestrichelt grün} #foo {border-width: 8px} aber das ist im allgemeinen Fall nicht praktisch. –

+0

Ich werde mit CSS :: DOM spielen - für meine Zwecke wäre es besser, etwas zu entdecken und zu werfen, als etwas zu senden, was falsch war, also frage ich mich, ob ich compute_style in diese Richtung optimieren könnte mindestens. Ich melde mich hier, wenn ich irgendwo hinkomme (was überhaupt nicht garantiert ist!) Nochmals vielen Dank, es ist ein sehr hilfreicher Start. – mintywalker

4

können Sie verwenden CSS::Inlinerhttp://search.cpan.org/dist/CSS-Inliner/

+0

Ich habe kürzlich auch auf dieses Problem gestoßen. CSS :: Inliner sieht genau wie das Werkzeug für mich aus. Ich möchte meine Vorlagen mithilfe von CSS-Regeln behalten, aber die Stile unmittelbar vor dem Senden der E-Mail einfügen. Danke für den Link! –

Verwandte Themen