$self->replace_content($name);
}
+my %page_cache;
+for (<tmpl/*>) {
+ my ($tmpl, $lang) = m,tmpl/(\w+)\.(\w+),;
+ my $builder = HTML::Seamstress->new;
+ $builder->ignore_unknown(0);
+ $page_cache{$tmpl, $lang} = $builder->parse_file($_);
+}
+
sub render {
my ($tmpl, $lang, %args) = @_;
$lang //= 'en';
}
sub render_article {
- my ($art, $lang) = @_;
+ my ($art, $lang, %args) = @_;
$lang //= 'en';
my $title = read_file "a/$art.$lang.title";
my $meat = read_file "a/$art.$lang";
- _render('skel', $lang, title => $title , meat => $meat)
+ _render('skel', $lang, title => $title , meat => $meat, %args)
}
sub _render {
my ($tmpl, $lang, %args) = @_;
- my $builder = HTML::Seamstress->new;
- $builder->ignore_unknown(0);
- my $tree = $builder->parse_file("tmpl/$tmpl.$lang");
+ my $tree = $page_cache{$tmpl, $lang}->clone or die "No such template/language combination: $tmpl/$lang\n";
$tree = $tree->guts unless $tmpl eq 'skel';
$tree->defmap(smap => \%args);
my $process = __PACKAGE__->can("process_$tmpl");
$process->($tree, %args) if $process;
+ $_->detach for $tree->look_down(static => $args{static} ? 'no' : 'yes');
+ $_->attr('static', undef) for $tree->look_down(sub {$_[0]->attr('static')});
+ $_->attr('smap', undef) for $tree->look_down(sub {$_[0]->attr('defmap')});
$tree->as_HTML;
}
+my $logo = read_file 'mclogo.svg';
+$logo =~ y/\n//d;
+$logo =~ s/(\s+)/ /g;
+
sub process_skel {
my ($tree, %args) = @_;
- $tree->fid('logo')->replace_with(literal scalar read_file "mclogo.svg");
+ $tree->fid('logo')->replace_with(literal $logo);
$tree->content_handler(
title => $args{title},
content => literal $args{meat});
$tree->fid('owner')->edit_href(sub{s/owner_id/$args{owner}/});
$tree->fid('job_log')->edit_href(sub{s/problem_id/$args{id}/});
$tree->fid('solution')->edit_href(sub{s/problem_id/$args{id}/});
- $tree->fid('job_log')->edit_href(sub{$_ .= "&private=$args{private}"}) if $args{private};
$tree->content_handler(
statement => literal $args{statement},
level => ucfirst $args{level},
author => $args{author},
owner => $args{owner_name} || $args{owner});
+ if ($args{limits}) {
+ my @limits = (@{$args{limits}}, {format => 'Other', timeout => $args{timeout} });
+ @limits = map { sprintf '%s (%s)', @{$_}{qw/timeout format/} } @limits;
+ $tree->look_down(smap => 'timeout')->replace_content(join ', ', @limits);
+ }
if ($args{contest_stop}) {
$tree->fid('solution')->detach;
$tree->fid('solution_modal')->detach;
- my $score = $tree->fid('score');
- $score->attr('data-start' => $args{open_time});
- $score->attr('data-stop' => $args{contest_stop});
- $score->attr('data-value' => $args{value});
+ $tree->fid('score')->replace_content($args{value});
$tree->fid('countdown')->attr('data-stop' => $args{contest_stop});
} else {
+ $tree->fid('job_log')->edit_href(sub{$_ .= "&private=$args{private}"}) if $args{private};
$tree->fid('solution')->detach unless $args{solution};
$_->detach for $tree->fclass('rc'); # requires contest
$tree->fid('solution_modal')->fclass('modal-body')->replace_content(literal $args{solution});
$tree->fid('nosubmit')->detach;
$tree->look_down(name => 'problem')->attr(value => $args{id});
my $contest = $tree->look_down(name => 'contest');
- $contest->attr(value => $args{contest}) if $args{contest};
- $contest->detach unless $args{contest}
+ $contest->attr(value => $args{args}{contest}) if $args{args}{contest};
+ $contest->detach unless $args{args}{contest}
} else {
$tree->fid('nosubmit')->find('a')->edit_href(sub{s/id/$args{id}/});
$tree->fid('submit')->detach
$tr->fclass('name')->namedlink($data->{id}, $data->{name});
$tr->fclass('name')->find('a')->edit_href(sub {$_ .= "?contest=$args{contest}"}) if $args{contest};
$tr->fclass('owner')->namedlink($data->{owner}, $data->{owner_name});
- $tr->find('td')->attr(class => $tr->find('td')->attr('class').' warning') if $data->{private};
+ $tr->find('td')->attr(class => $tr->find('td')->attr('class').' warning') if $data->{private} && !$args{contest};
};
my $iter = sub {
my ($data, $div) = @_;
my ($data, $tr) = @_;
$tr->fclass('id')->namedlink($data->{id});
$tr->fclass('problem')->namedlink($data->{problem}, $data->{problem_name});
- $tr->fclass('problem')->find('a')->edit_href(sub{$_ .= "?contest=$args{contest}"}) if $args{contest};
+ $tr->fclass('problem')->find('a')->edit_href(sub{$_ .= "?contest=$args{args}{contest}"}) if $args{args}{contest};
$tr->fclass('contest')->namedlink($data->{contest}, $data->{contest_name}) if $data->{contest};
$tr->fclass('contest')->replace_content('None') unless $data->{contest};
$tr->fclass('date')->replace_content(ftime $data->{date});
- $tr->fclass('format')->replace_content($data->{format});
- $tr->fclass('size')->namedlink("$data->{id}.$data->{extension}", sprintf "%.2fKB", $data->{size}/1024);
- $tr->fclass('size')->attr('data-private', '') if $data->{private};
+ $tr->fclass('source')->namedlink("$data->{id}.$data->{extension}", sprintf "%.2fKB %s", $data->{size}/1024, Plack::App::Gruntmaster::FORMAT_EXTENSION()->{$data->{format}});
$tr->fclass('owner')->namedlink($data->{owner}, $data->{owner_name});
$tr->fclass('result_text')->replace_content($data->{result_text});
$tr->fclass('result_text')->attr(class => "r$data->{result}");
$elem->find('a')->edit_href(sub{s/$/&$str/}) if $str;
}
$tree->fclass('current')->replace_content("Page $args{current_page} of $args{last_page}");
+
+ my @detach;
+ push @detach, $args{args}{$_} ? $tree->fclass($_) : () for qw/problem contest owner/;
+ $_->detach for @detach;
}
sub process_st {
$div->set_child_content(class => 'solution', literal $data->{solution});
$div->fclass('problem')->namedlink($data->{id}, $data->{name});
};
- my @pb = map { @{$args{$_}} } qw/beginner easy medium hard/;
+ my @pb = map { @{$args{$_} // []} } qw/beginner easy medium hard/;
$tree->fclass('well')->iter3(\@pb, $iter);
}
+
+1;
+__END__