package xm::css::sheet; use xm::o; # subroutines for handling of css infos/files # convert a css fieldhash into its text # representation. Assumes fieldhash container # as returned by mkfield. does not output # fields starting with x-. see asfieldx. # inv: mkfield for the inverse operation # use: in assheet subs to generate inverse of mksheet sub asfield { my $x = shift; my $T = " "; if (exists $$x{_class}) { $T .= $$x{_markup} if exists $$x{_markup}; $T .= " " x (7 - length $T) if length $T < 10; $T .= ".".$$x{_class}; } elsif (exists $$x{_name}) { $T .= $$x{_name}; }else{ # print STDERR "<no markup name>"; return ""; } # print STDERR "[",$T,"] "; if (length $T < 20) { $T .= " " x (20 - length $T); } $T .= " { "; my $k; for $k (keys %$x) { if ($k !~ /^_/ and $$x{$k} !~ /^x-/) { if ((length $T) % 80 > 60) { $T .= "\n "; } $T .= $k." : ".$$x{$k}." ; "; } } $T .= "}\n"; return $T; } # convert a css fieldhash into its text # representation. Assumes fieldhash container # as returned by mkfield. # inv: mkfield for the inverse operation # use: in assheet subs to generate inverse of mksheet sub asfieldx { my $x = shift; my $T = " "; if (exists $$x{_name}) { $T .= $$x{_name}; }elsif (exists $$x{_class}) { my $markup = ""; $markup = $$x{_markup} if exists $$x{_markup}; $T .= $markup.".".$$x{_class}; }else{ # print STDERR "<no markup name>"; return ""; } if (length $T < 20) { $T .= " " x (20 - length $T); } $T .= " { "; my $k; for $k (keys %$x) { if ($k !~ /^_/) { if ((length $T) % 80 > 60) { $T .= "\n "; } $T .= $k." : ".$$x{$k}." ; "; } } $T .= "}\n"; return $T; } # reading a text containing css field information. # this reader is only useful in conjunction with # the xm system as it expects all css tags to # be in a simple format - just one leader # and one subclass. The leader may be empty, but # the dot must be always there (and just one dot). # # example: # .myclass { color: #F0F0F0 ; } # pre .class2 { color: #D0D0D0 ; } # h2 { font-size: 6 ; } # # return: hash. # css-info -> fields # with some automatic fields named with # a leading underscore, especially _name # _class and _markup. # results are: # _name has everything before the opening brace # e.g. ".myclass" "pre .class" "h2" # _markup has everything before the first special char # e.g. "" "pre" "h2" # _class has everything after the last dot (that marks a class="ref") # e.g. "myclass" "class2" "/h2" # -> note that a nonclassed css-field gets its markup as classifcation # the fields class_prefix contains the # corresponding rest that was left over by the split operation # inv: asfield for the inverse operation # use: mksheet for generating a hash of these. sub mkfield { local $_ = shift; my $x = { }; my $v = ""; my $choke = sub { my $v = shift; $v =~ s/^\s*//; $v =~ s/\s*$//; return $v; }; s{ (^|\}|<style>) ([^\{\}]*) \{ } { $$x{_name} = &$choke($2); $1 }sex; while ( s{ (^|\}|<style>) \s* ([\w-]+) \s* : ([^\;]*) \; } { $$x{$2} = &$choke($3); $1 }gsex ) {}; if ($$x{_name} =~ m{ ^ (.*) \. ([\s\w\-]*) $ }sx) { $$x{_markup} = $1; $$x{_class} = $2; $$x{_markup} =~ s{\s+}{}gs; $$x{_class} =~ s{\s+}{}gs; }else{ $$x{_markup} = $$x{_name}; $$x{_markup} =~ s{\s+}{}gs; } return $x; } # reading a filetext containing css information. # this reader is only useful in conjunction with # the xm system as it expects all css tags to # be in a simple format - just one leader # and one subclass. The leader my be empty to # match as a subclass to any other leader, but # the dot must be always there (and just one dot). # and, to speak it aloud EVERY SUBCLASS MUST BE # UNIQUE. The leader is only used for formatting # in html documents (if no leader is given, a # <span> will be generated). # # example: # # pre .class2 { color: #D0D0D0 ; } # # return: a hash of hash. # subclass -> css-info # css-info -> fields # # use: if exists sheet{class} where class is an xm-markup # inv: sub assheet is the inverse operation # sub mksheet { local $_ = shift; my $sheet = { }; while( s{ (^|\}|<style>|\*\/\s) (\s*[\w\-\:]*\s*[\.]\s*) ([\w\-]+) (\s*\{ [^\{\}]* \}) } { $$sheet{$3} = mkfield($2.$3.$4); # print STDERR "<",$3,">\n"; $1 }gsex ) {}; while( s{ (^|\}|<style>|\*\/\s) (\s*) ([\w\-\:]+) (\s*\{ [^\{\}]* \}) } { $$sheet{"/".$3} = mkfield($2.$3.$4); # print STDERR "</",$3,">\n"; $1 }gsex ) {}; return $sheet; } # convert a css sheethash into its text # representation. Assumes sheethash container # as returned by mksheet # inv: mksheet is the inverse operation sub assheet { my $x = shift; my $T = ""; my $k; for $k (sort keys %$x) { if ($k !~ /^_/ and $$x{$k} !~ /^x-/) { $T .= asfield($$x{$k}); } } return $T; } # convert a css sheethash into its text # representation. Assumes sheethash container # as returned by mksheet. Outputs also x- # defines in the fields. # see: assheet for the normal usage # inv: mksheet for the inverse operation sub assheetx { my $x = shift; my $T = ""; my $k; for $k (sort keys %$x) { if ($k !~ /^_/ and $$x{$k} !~ /^x-/) { $T .= asfield($$x{$k}); } } return $T; } # convert a css sheethash into its text # representation. Assumes sheethash container # as returned by mksheet. Outputs ONLY those # classes which are present in the 2nd arg hash. # use: for embedding css-style information into some # output text - the output text's header has only # those css-tags that are used inside the text. # inv: mksheet to generate a css-sheet. sub assheetuse { my $x = shift; my $a = shift; my $T = ""; my $k; for $k (sort keys %$x) { if ($k !~ /^_/ and exists $$a{$k}) { $T .= asfield($$x{$k}); } } return $T; } sub DESC {" read the css-style input, convert it to its internal form, and print the recogized information as css-style output. "} sub DO { my $css = xm::css::sheet::mksheet($_[0]); print "<style length=\"",scalar %$css,"\">\n"; print xm::css::sheet::assheet($css); print "</style>\n"; } sub ARGS { return xm::o::args_stdin(@_,DESC); } sub main { return DO(xm::o::args_stdin(@_,DESC)); } 1;