CssWork

From SoylentNews
Revision as of 09:04, 5 March 2014 by 50.45.173.141 (talk)

Jump to: navigation, search

The htaccess problem

Put a n htaccess file in the rott folder for slash, as I have done hundreds to times before...and it did not work.

Specifically, it did nothing at all.

No error, just...nothing.

Nothing in log that revealed much.

A problem with debugging this is the presence of 'Varnish' a cache ahead of the server. However, in the end I am told this is not, on this particular server, doing anything but passing the requests through.

First problem noted was that in the main apache config, the directive AllowOverride None was in place. this prevents anything in htaccess files from overriding the main config. Changed to AllowOverride All. Still not working. Checked the local apache config in the site/sslashcott.org dir and saw that had another such directive. Changed that one. Still not working. Deciuded to give up an htaccess completely, and put the directives into the main apache file. Still not working.

Noticed, however, this in the slash config file:

    # Fourth Apache phase:  access control
    PerlAccessHandler  Slash::Apache::Banlist
    PerlAccessHandler  Slash::Apache::User

The slash apache module has taken control of the Apache access control phase.

I am pretty sure this means that ONLY the perl modules now can operate in that phase, as in apache 1.3, there is just a traversal through the different phases, and whoever handles the phase causes apache to go to the nexrt phase.

Tried to check the docs to confirm this, but apache has removed 1.3 docs from their site.

Finally found an old 1.3 source on a backup, grabbed the docs out of this, and read:

-- Apache breaks down request handling into a series of steps, more or less the same way the Netscape server API does (although this API has a few more stages than NetSite does, as hooks for stuff I thought might be useful in the future). These are:

  • URI -> Filename translation
  • Auth ID checking [is the user who they say they are?]
  • Auth access checking [is the user authorized here?]
  • Access checking other than auth
  • Determining MIME type of the object requested
  • `Fixups' --- there aren't any of these yet, but the phase is intended as a hook for possible extensions like SetEnv, which don't really fit well elsewhere.
  • Actually sending a response back to the client.
  • Logging the request

These phases are handled by looking at each of a succession of modules, looking to see if each of them has a handler for the phase, and attempting invoking it if so. The handler can typically do one of three things:

  • Handle the request, and indicate that it has done so by returning the magic constant OK.
  • Decline to handle the request, by returning the magic integer constant DECLINED. In this case, the server behaves in all respects as if the handler simply hadn't been there.
  • Signal an error, by returning one of the HTTP error codes. This terminates normal handling of the request, although an ErrorDocument may be invoked to try to mop up, and it will be logged in any case.

Most phases are terminated by the first module that handles them; however, for logging, `fixups', and non-access authentication checking, all handlers always run (barring an error)

--

So in short, if perl decides to handle the 'access' phase, Apache cannot.

http://perl.apache.org/docs/1.0/index.html

21:09	stderr	Hmm... Can you use an AuthUser on a virtual host that acts like a proxy?
	NCommander		audioguy, oh wait, you're using varnish

	NCommander	You need a fucking hack in slash to make that work
	NCommander	There's a sanity check I stabbed out that causes slash to act stupid when its varnished
	audioguy	That is what I was afraid of. Wondering if there is a simple way to do the same thing in slash code.
21:10	NCommander	I think the patch is on the master branch, if not, you need to grep for "X-Forwarded-By" in slashcode

--
mechanicjay		audioguy: is it borked?

21:45	mechanicjay	Varnish is passing everything through
	audioguy	It is getting in the way of me trying to debug a problem
	audioguy	I am trying to use .htaccess files, it is not letting me see the real errors,
	audioguy	Logs shows this:
	audioguy	[Wed Mar 5 05:40:08 2014] [error] :Slash::Utility::Environment:/usr/local/lib64/perl5/Slash/Utility/Environment.pm:683:cannot getSkin for empty skid='' ;; Which was called by:Slash::Apache:/usr/local/lib64/perl5/Slash/Apache.pm:359
21:46	mechanicjay	Varnish should not be caching anything for the slashcott domain. I'll double check right now

Related pages

  • Official docs
    • InstallDoc - original INSTALL document
    • SlashGuide - this is the guide (from htdocs) you are supposed to read immediately after installing slashcode
    • SectionTopics - This is the 'new' sections and topics rewrite and is more important to read than it first appears, explains what a skin is. Sort of.
    • SlashChart Png chart of slashcode organization
    • SlashManPages Man pages available by typing man PAGENAME
    • TemplateManPages Man pages for the template library used to deliver the html
  • [[1]] git - themes

http://www.mediawiki.org/wiki/Help:Images

Unanswered Questions

  • The templates are individually output by routine slashDisplay(), but how is the order of delivery determined, and how does one insure a new template goes to the right place on the page?
  • The users home page link goes to /my/homepage. I can find no apache redirect for this nor is there a 'my' folder anywhere. I am guessing this is done in the apache perl module, through some redirects that hook into Apache innards. It is hard to be sure what script is actually being called first. I am assuming it is users. Once an edit is made, you are in /users.pl without /my/
  • Two users scripts, users,users2 Am guesssing users2 is for the d2 interface we are not using, since the forms on the page call users.pl



Got tired of scrolling through pages of perl code just to see what subs were in a module

So wrote this, now in /usr/local/sbin/listsubs.sh:

[root@slashcode Slash]# listsubs.sh Admin.pm
Admin.pm:
    addSpriteForSid, ajax_authorbox, ajax_learnword, ajax_neverdisplay, 
    ajax_perfbox, ajax_signoff, ajax_signoffbox, ajax_slashdbox, 
    ajax_storyadminbox, ajax_sub_memory, DESTROY, extractRelatedStoriesFromForm, 
    findTheTime, getAccesslogAbusersByID, getAccesslogMaxID, get_ispell_comments, 
    getRecentSubs, getRecentWebheads, getRelated, getSignoffData, 
    getStorySignoffs, getStoryThumbLargeLink, grantStoryPostingAchievements, otherLinks, 
    relatedLinks, showAdminTodo, showAuthorActivityBox, showPerformanceBox, 
    showSignoffBox, showSlashdBox, showStoryAdminBox, write_to_temp_file, 

Also will work from a list, as in

ls *.pm > list.tst
listsubs.sh < list.txt

Maybe someone else will find it useful as well.


Order css files are loaded when simple switch on user prefs page is selected viewing main page main page

  • base.css?T_2_5_0_272 The numbers are the slash verion number (from one of the docs).
  • slashcode.css?T_2_5__0_272
  • slashcode_lite.css?T_2_5__0_272
  • slashcode_lite.css?T_2_5__0_272 (appears to be loading this twice,why?)
  • print.cssT_2_5__0_272

Follow a page link from the main page to an individual article page

article.pl

The stuff of interest to us


use Slash;  -------- located in /local/lib64/perl5/slash.pm
use Slash::Display;     
use Slash::Utility;

sub main {
        my $slashdb   = getCurrentDB();
        my $constants = getCurrentStatic();
        my $user      = getCurrentUser();
        my $form      = getCurrentForm();
        my $gSkin     = getCurrentSkin();
         
        my $story;
        my $reader = getObject('Slash::DB', { db_type => 'reader' });

                # Make sure the reader is viewing this story in the
                # proper skin.
                my $cur_skid = determineCurrentSkin();
                if ($story->{primaryskid} != $cur_skid) {
                        my $cur_skin = $reader->getSkin($cur_skid);
                        my $story_skin = $reader->getSkin($story->{primaryskid});
                        if ($story_skin && $story_skin->{rootdir}
                                && $story_skin->{rootdir} ne $cur_skin->{rootdir})$
                                redirect("$story_skin->{rootdir}$ENV{REQUEST_URI}"$
                                return;

               # XXXSECTIONTOPICS this needs to be updated
                my $SECT = $reader->getSection($story->{section});
                # This should be a getData call for title
                my $title = "$constants->{sitename} | $story->{title}";
                if ($gSkin->{name} && $gSkin->{name} eq "idle") {
                        $title = "$gSkin->{hostname} | $story->{title}";
                
if (my $pollbooth_db = getObject('Slash::PollBooth')) {


slashDisplay('display', {
                        poll                    => $pollbooth,
                        section                 => $SECT,
                        section_block           => $reader->getBlock($SECT->{secti$
                        show_poll               => $pollbooth ? 1 : 0,
                        story                   => $story,
                        stories                 => \%stories,
                });


               my $called_pc = 0;
                if ($story->{discussion}) {
                        # Still not happy with this logic -Brian
                        my $discussion = $reader->getDiscussion($story->{discussio$

                        }
                        # If no comments ever have existed and commentstatus is di$
                        # just skip the display of the comment header bar -Brian

                               &&  $discussion->{commentstatus} eq 'disabled'
                        )) {
                                printComments($discussion);
                                $called_pc = 1;
                        }
                 if (!$called_pc && $form->{ssi} && $form->{ssi} eq 'yes' && $form-$
                        # This is a real hack, we're kind of skipping down
                        # two levels of code.  But the cchp printing is an
                        # important optimization;  we avoid having to do
                        # multiple expensive comment selects.  One problem
                        # is that if there's no discussion with a story,
                        # printComments() doesn't get called, which means
                        # selectComments() doesn't get called, which means
                        # the cchp file won't be written.  If article.pl
                       # is being called by slashd, and we need to write
                        # that file, then here's where we print an empty
                        # file that will satisfy slashd. - Jamie

                        Slash::Utility::Comments::_print_cchp({ stoid => "dummy" }$
                }
        } else {
                header('Error', $form->{section}) or return;
       
       my $plugins = $slashdb->getDescriptions('plugins');
        if (!$user->{is_anon} && $plugins->{Tags} && $story) {
                my $tagsdb = getObject('Slash::Tags');
                $tagsdb->markViewed($user->{uid},
                        $reader->getGlobjidCreate('stories', $story->{stoid}));
        }
                        
        footer();
        if ($story) {
                writeLog($story->{sid} || $sid);
        } else { 
                writeLog($sid);

               
createEnvironment();
main();  
1; 

(EOF)


Slash/DB/MySQL/MySQL.pm


479 sub getCSS {
480         my($self, $layout) = @_;
481         my $user = getCurrentUser();
482         my $page = $user->{currentPage};
483         my $skin = getCurrentSkin('name');
484         my $admin = $user->{is_admin};
485         my $theme = ($user->{simpledesign} || $user->{pda}) ? "light" : $user->{css_theme};
486         my $secure = apacheConnectionSSL();
487         $layout ||= '';
488         my $constants = getCurrentStatic();
489
490         my $expire_time = $constants->{css_expire} || 3600;
491         $expire_time += int(rand(60)) if $expire_time;
492         _genericCacheRefresh($self, 'css', $expire_time);
493         _genericCacheRefresh($self, 'css_pages', $expire_time);
494         _genericCacheRefresh($self, 'css_skins', $expire_time);
495         _genericCacheRefresh($self, 'css_themes', $expire_time);
496
497         my $css_ref             = $self->{_css_cache} ||= {};
498         my $css_pages_ref       = $self->{_css_pages_cache};
499         my $css_skins_ref       = $self->{_css_skins_cache};
500         my $css_themes_ref      = $self->{_css_themes_cache};
501         my $css_layouts_ref     = $self->{_css_layouts_cache};
502
503         $css_pages_ref = $self->getCSSValuesHashForCol('page') if !$css_pages_ref;
504         $css_skins_ref = $self->getCSSValuesHashForCol('skin') if !$css_skins_ref;
505         $css_themes_ref = $self->getCSSValuesHashForCol('theme') if !$css_themes_ref;
506         $css_layouts_ref = $self->getCSSValuesHashForCol('layout') if !$css_layouts_ref;
507
508         my $lowbandwidth = ($user->{lowbandwidth} || $user->{pda}) ? "yes" : "no";
509
510         $page   = '' if !$css_pages_ref->{$page};
511         $skin   = '' if !$css_skins_ref->{$skin};
512         $theme  = '' if !$css_themes_ref->{$theme};
513         $layout = '' if !$css_layouts_ref->{$layout};
514
515         return $css_ref->{$skin}{$page}{$admin}{$theme}{$lowbandwidth}{$layout}{$secure}
516                 if exists $css_ref->{$skin}{$page}{$admin}{$theme}{$lowbandwidth}{$layout}{$secure};
517
518         my @clauses;
519
520         my $page_q = $self->sqlQuote($page);
521         my $page_in = $page ? "(page = '' or page = $page_q)" : "page = ''";
522         push @clauses, $page_in;
523
524         my $skin_in = $skin ? "(skin = '' or skin = '$skin')" : "skin = ''";
525         push @clauses, $skin_in;
526
527         push @clauses, "admin='no'" if !$admin;
528
529         my $theme_q  = $self->sqlQuote($theme);
530         my $theme_in = $theme ? "(theme='' or theme=$theme_q)" : "theme=''";
531         push @clauses, $theme_in;
532
533         push @clauses, "lowbandwidth='$lowbandwidth'" if $lowbandwidth eq "no";
534
535         my $layout_q = $self->sqlQuote($layout);
536         push @clauses, "layout=$layout_q";
537
538         my $where = "css.ctid=css_type.ctid AND ";
539         $where .= join ' AND ', @clauses;
540
541         my $css = $self->sqlSelectAllHashrefArray("rel,type,media,file,title,ie_cond,skin",
542                 "css, css_type", $where, "ORDER BY css_type.ordernum, css.ordernum");
543         if ($secure) {
544                 for my $hr (@$css) { $hr->{file} =~ s/\.css/.ssl.css/ }
545         }
546         
547         $css_ref->{$skin}{$page}{$admin}{$theme}{$lowbandwidth}{$layout}{$secure} = $css;
548         return $css;
549 }
550 


Slash/Apache/User/User.pm


548 {
549 my %ops_my = (
550         inbox           => { args => 'op=list', uri => 'messages.pl' },
551         # XXX change messages to be same as /inbox, move this to /my/preferences/messages
552         messages        => { args => 'op=display_prefs', uri => 'messages.pl' },
553         comments        => { args => 'op=editcomm' },
554         homepage        => { args => 'op=edithome' },
555         password        => { args => 'op=changeprefs', uri => 'login.pl' },
556         logout          => { args => 'op=userclose', uri => 'login.pl' },
557         misc            => { args => 'op=editmiscopts' },
558         amigos          => { args => 'op=friendview', uri => 'journal.pl' },
559         bookmarks       => { args => 'op=showbookmarks' },
560         firehose        => { args => 'op=userfirehose' },
561         preferences     => { args => 'op=displayprefs', uri => 'preferences.pl' },
562         tags            => { args => 'op=showtags' },
563         journal         => { args => 'op=list', uri => 'journal.pl' },
564
565         friends         => { args => 'op=friends', uri  => 'zoo.pl' },
566         fans            => { args => 'op=fans', uri  => 'zoo.pl' },
567         freaks          => { args => 'op=freaks', uri  => 'zoo.pl' },
568         foes            => { args => 'op=foes', uri  => 'zoo.pl' },
569         zoo             => { args => 'op=all', uri  => 'zoo.pl' },
570
571         default         => { args => 'op=edituser' }
572 );

sql/mysql/defaults.sql

 134 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','base.css','','','','no','',1,0, "","no");
135 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','comments','no','',2,0, "","no");
136 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','article','no','',2,0, "","no");
137 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','print','print.css','','','','no','',5,0, "","no");
138 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','admin.css','','','','yes','',1,0, "","no");
139 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','pollBooth','no','',2,0, "","no");
140 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','slashcode_lite.css','','','','no','light',4,0, "","no");
141 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','journal','no','',2,0, "","no");
142 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','slashcode_lite.css','','','','no','light',4,0, "","no");
143 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','journal','no','',2,0, "","no");
144 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','slashcode.css','','','','no','',3,0, "","no");
145 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','metamod','no','',2,0, "","no");
146 INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond, lowbandwidth) VALUES ('stylesheet','text/css','screen, projection','slashcode_low_bw.css','','','','no','',4,99, "","yes");
147
148 #
149 # Dumping data for table 'css_type'
150 #
151 INSERT INTO css_type (ctid, name, ordernum) VALUES (1,'base',1);
152 INSERT INTO css_type (ctid, name, ordernum) VALUES (2,'page',2);
153 INSERT INTO css_type (ctid, name, ordernum) VALUES (3,'theme',3);
154 INSERT INTO css_type (ctid, name, ordernum) VALUES (4,'user_theme',5);
155 INSERT INTO css_type (ctid, name, ordernum) VALUES (5,'print',6);
156 INSERT INTO css_type (ctid, name, ordernum) VALUES (6,'skin',4);
157 INSERT INTO css_type (ctid, name, ordernum) VALUES (7,'handheld',7);
158 


plugins/FireHose/mysql_dump.sql

    INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond) VALUES ('stylesheet','text/css','screen, projection','firehose.css','','','firehose','no','',2,0, '');
==> INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond) VALUES ('stylesheet','text/css','screen, projection','firehose.css','','','users','no','',2,0, '');
    INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond) VALUES ('stylesheet','text/css','screen, projection','calendar.css','','','firehose','no','',2,0, '');
==> INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond) VALUES ('stylesheet','text/css','screen, projection','firehose.css','','','users','no','',2,0, '');
    INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond) VALUES ('stylesheet','text/css','screen, projection','comments.css','','','firehose','no','',2,0, '');
    INSERT INTO css (rel, type, media, file, title, skin, page, admin, theme, ctid, ordernum, ie_cond) VALUES ('stylesheet','text/css','screen, projection','firehose.css','','','index2','no','',2,0, ''); 

I believe that we are not using FireHose but it was needed to make the site work. As can be seen in the db dump above, it adds the firehose.css file to any of the user pages. Need to verify and then see if we can get the db purged of these values.

Good work. The question in my mind is why the heck css for one module has any effect *at all* on any other module. Talk about lack of localization...-AG

I think there was some firehose slashboxes that showed up in the users pages. They needed to be wider than the default, so they patched those pages with the firehose.css. Next step is to get a current dump of the two css tables. The important part is I know what files are for what parts of the code. Slashcode.css is the theme css file slashcode-lite.css is the style file that is called by a user pref. This means I need to fix comments.css to remove the theme elements I inserted and put them in the theme file. I still need to make sure that the changes that benefited the Simplified theme stay intact. -EP

fonts

This is what I usually start with:
   font-family: Helvetica,Geneva,Arial,Verdana,sans-serif;

Too many can lead to a LOT of testing being required. As can the wrong order. ;-)

Others I have used in the past:
font-family: Geneva,Arial,Verdana,Helvetica,Chicago,sans-serif;
font-family: Helvetica,Arial,Geneva,Chicago,Verdana,sans-serif;
font-family: Helvetica,Geneva,Arial,Verdana,sans-serif;
-AG

I have used:
font-family: Verdana, Geneva, "Bitstream Vera Sans", "DejaVu Sans", sans-serif;

Note this has Linux fonts as well to help with these users.
-EP

User Menu

INSERT INTO menus (menu, label, sel_label, value, seclev, showanon, menuorder) VALUES ('users','Logout','logout','/my/logout',1,0,10);
124 INSERT INTO menus (menu, label, sel_label, value, seclev, showanon, menuorder) VALUES ('users','Preferences','preferences','/users.pl?op=edituser',1,0,20);
125 INSERT INTO menus (menu, label, sel_label, value, seclev, showanon, menuorder) VALUES ('users','Password','password','[% constants.real_rootdir %]/my/password',1,0,40);
126 INSERT INTO menus (menu, label, sel_label, value, seclev, showanon, menuorder) VALUES ('users','~[% user.nickname | strip_literal %] ([% user.uid %])','me','/~[% user.nickname | fixparam %]',1,0,50);

This code sets up the upper menu on http://slashcott.org/users.pl which is linked from your userid on the home page. The Preferences is wrong, as it needs to be all three links: Info, Homepage, Comments. This will allow users with low-bandwidth option set to easily get to the setting to unset low-bandwidth. -EP

Refernces to css in the man pages in /usr/local/share/man/man3

grep -i css *

HTML::CalendarMonth.3pm:.IP "enable_css" 4
HTML::CalendarMonth.3pm:.IX Item "enable_css"
HTML::CalendarMonth.3pm:Set some handy \s-1CSS\s0 class attributes on elements, enabled by default.
HTML::CalendarMonth.3pm:.IP "semantic_css" 4
HTML::CalendarMonth.3pm:.IX Item "semantic_css"
HTML::CalendarMonth.3pm:Sets some additional \s-1CSS\s0 class attributes on elements, disabled by
HTML::CalendarMonth.3pm:.IP "\fIdefault_css()\fR" 4
HTML::CalendarMonth.3pm:.IX Item "default_css()"
HTML::CalendarMonth.3pm:document in conjunction with the classes assigned to elements when css
HTML::ElementSuper.3pm:might be when you'd like to assign multiple \s-1CSS\s0 classes to a single
HTML::PopupTreeSelect.3pm:.IP "include_css (optional)" 4
HTML::PopupTreeSelect.3pm:.IX Item "include_css (optional)"
HTML::PopupTreeSelect.3pm:Set this to 0 and the default \s-1CSS\s0 will not be included in the widget
HTML::PopupTreeSelect.3pm:output.  This allows you to include your own \s-1CSS\s0 which will be used by
HTML::PopupTreeSelect.3pm:your widget.  Modifying the \s-1CSS\s0 will allow you to control the fonts,
HTML::PopupTreeSelect.3pm:If you run the widget with include_css set to 1 then you can use that
HTML::Tree::Scanning.3pm:tagging, such is as useful in \s-1CSS\s0 \*(-- note the
Module::Build::API.3pm:.IP "\fIhtml_css()\fR" 4
Module::Build::API.3pm:.IX Item "html_css()"
TAP::Parser::YAMLish::Reader.3pm:YAML::Tiny, \s-1YAML\s0, YAML::Syck, Config::Tiny, CSS::Tiny,
TAP::Parser::YAMLish::Writer.3pm:YAML::Tiny, \s-1YAML\s0, YAML::Syck, Config::Tiny, CSS::Tiny,
Template::Iterator.3pm:You can then style the \f(CW\*(C`tr.odd\*(C'\fR and \f(CW\*(C`tr.even\*(C'\fR elements using \s-1CSS:\s0
Template::Toolkit.3pm:kind of text documents: \s-1HTML\s0, \s-1XML\s0, \s-1CSS\s0, Javascript, Perl code, plain text,
Template::Tutorial::Web.3pm:kind of content they contain.  So you can use \s-1TT\s0 to generate \s-1HTML\s0, \s-1XML\s0, \s-1CSS\s0,


CSS commit for Feb 23

Changes to most of the css files to set all sizes to em (some were in px and broke flow). Changed the font-family to a more friendly chain for all platforms, and remove all other font-faimily calls from the code. Changed font sizes from % to ems and adjusted size for some of the main elements. Fix a issue with the middle column size caused by firehose.css. Many small fixes to spacing over many places.

Moved all of the slashcode theme items into the slashcode.cssraw file. Some were in comments.cssraw due to some previous work I did.

On article body and comment body, made the font size a bit smaller. Also on comments body set the margins to be smaller.

-EP