Merge branch 'master' into newmc
authorMarius Gavrilescu <marius@ieval.ro>
Sat, 18 Apr 2015 09:12:03 +0000 (12:12 +0300)
committerMarius Gavrilescu <marius@ieval.ro>
Sat, 18 Apr 2015 09:12:03 +0000 (12:12 +0300)
Conflicts:
Makefile.PL
css/custom.css
js/90-mobilenav.js
js/90-nav.js
js/90-themes.js
make_static.PL
tmpl/skel.en

1  2 
Makefile.PL
css/custom.css
js/90-mobilenav.js
js/90-move-sponsors.js
js/90-nav.js
js/90-themes.js
js/90-webchat-link.js
lib/Plack/App/Gruntmaster/HTML.pm
make_static.PL
tmpl/pb_entry.en
tmpl/skel.en

diff --combined Makefile.PL
index 6f86eb4000552f0305115281d414563a5332706a,2bf04acdec3d5716f8d3ad3295299548f7f3a0b8..8404b7787e9cc0f6f0dfa3002cbff4a484d655e8
@@@ -10,13 -10,11 +10,12 @@@ WriteMakefile
        LICENSE           => 'AGPL_3',
        SIGN              => 1,
        clean             => {
-               FILES => 'static/css/ static/js.js static/js.js.gz css/logos.css static/logos.png static/js.map static/js/'
 -              FILES => 'static/css/ static/js/'
++              FILES => 'static/css/ static/js/ css/logos.css static/logos.png'
        },
        BUILD_REQUIRES    => {
                qw/CSS::Minifier::XS          0
 +                 CSS::SpriteMaker           0
                   File::Slurp                0
-                  JavaScript::Minifier::XS   0
                   Test::MockTime             0
                   Test::More                 0
                   Test::WWW::Mechanize::PSGI 0/,
diff --combined css/custom.css
index 4085ff4c0dc336f6b32e9171ffbe91f97e01b358,0188fd4dd470f40d26984c1133989e7d0fccafe4..2d5060b837b3ca1412180d371d690f4a422b7730
@@@ -68,10 -68,14 +68,14 @@@ ul.inline li:last-child:after 
        display: none !important;
  }
  
 -td.user, td.owner {
 +td.user, td.owner, .break-all {
        word-break: break-all;
  }
  
- ul.list-inline {
-       display: inline-block;
+ #themes {
+       margin-left: 0;
+ }
+ #themes:before {
+       content: " Themes: ";
 -}
 +}
diff --combined js/90-mobilenav.js
index abba03e4fd3be93830be82d3d9b081513680f5f2,fb575d9288a34f375e1118418be5181a87fdfeed..f8c9628ca824677e698c6599116fa71f16da4881
@@@ -1,13 -1,7 +1,7 @@@
- (function(){
-       'use strict';
-       $( document ).ready(function(){
-               if(window.innerWidth >= 768)
-                       return;
-               $('#title').before('<div class="text-center">Tap title to toggle menu</div>');
-               $('nav').addClass('hidden');
-               $('#title,#logo').on('click', function () {
-                       $('nav').toggleClass('hidden');
-               });
-       });
- })();
+ $(function(){
+       if(window.innerWidth >= 768)
+               return;
+       $('#title')[0].insertAdjacentHTML('beforebegin', '<div class="text-center">Tap title to toggle menu</div>');
+       $('nav')[0].classList.add('hidden');
 -      $('#title').on('click', () => $('nav')[0].classList.toggle('hidden'));
++      $('#title,#logo').on('click', () => $('nav')[0].classList.toggle('hidden'));
+ });
diff --combined js/90-move-sponsors.js
index e9bcbfaef29bf638d7781d5bd48d6b2121447384,0000000000000000000000000000000000000000..8ea621e47c7e8eee687c84eb821089a4709b7ad5
mode 100644,000000..100644
--- /dev/null
@@@ -1,7 -1,0 +1,1 @@@
- (function(){
-       'use strict';
-       $( document ).ready(function(){
-               $('#sponsors').detach().appendTo($('#sidebar'));
-       });
- })();
++$(() => $('#sidebar')[0].appendChild($('#sponsors')[0]));
diff --combined js/90-nav.js
index 7f96eeb320c2aa6f22f3a1d8d1c9810d79e29489,03dcb8257931dff52d9775d8aea71e2bd23a8db5..4412e3a89ff038d92b1ae9f916fd20639dbc9e5d
@@@ -1,23 -1,16 +1,17 @@@
- (function(){
-       'use strict';
+ const NAVS = {
+       home: /^\/$/,
+       pb: /^\/(?:pb|sol)\//,
+       ct: /^\/(?:ct|st|ed)\//,
+       log: /^\/log\//,
+       us: /^\/us\//,
+       account: /^\/account$/,
+       contribute: /^\/contribute$/,
++      about: /^\/about$/,
+ };
  
-       var NAVS = {
-               'home': /^\/$/,
-               'pb': /^\/(?:pb|sol)\//,
-               'ct': /^\/(?:ct|st|ed)\//,
-               'log': /^\/log\//,
-               'us': /^\/us\//,
-               'account': /^\/account$/,
-               'contribute': /^\/contribute$/,
-               'about': /^\/about$/,
-       };
-       $( document ).ready(function(){
-               var path = location.pathname;
-               for (var nav in NAVS)
-                       if(path.match(NAVS[nav])) {
-                               $('#nav-' + nav).addClass('active');
-                               break;
-                       }
-       });
- })();
+ $(function(){
+       let path = location.pathname;
+       for (let nav in NAVS)
+               if(path.match(NAVS[nav]))
+                       $('#nav-' + nav)[0].classList.add('active');
+ });
diff --combined js/90-themes.js
index 0b043b8e393adc21146c4a698286f441ea499f98,0e481761002282633ab60569d9a6ba27f195b9e0..9de6b1b87b510dd0e85a63d38d5e9f38bbdfe9dc
@@@ -1,36 -1,22 +1,28 @@@
- (function(){
-       'use strict';
-       function set_style(name){
-               $('link[rel~="stylesheet"]').prop('disabled', true);
-               $('link[title="' + name + '"]').prop('disabled', false);
-               localStorage.setItem("theme", name);
-               $(document).ready(function() {
-                       if(name == 'slate' || name == 'cyborg')
-                               $('.logo').removeClass('logo-light');
-                       else
-                               $('.logo').addClass('logo-light');
-               });
-       }
-       var selector;
-       function add_themelink(theme, text) {
-               var link = $('<a role="button">' + text + '</a>');
-               link.appendTo(selector.find('ul')).wrap('<li>').on('click', function () { set_style(theme) });
-       }
-       $( document ).ready(function() {
-               selector = $('<div>Themes: <ul class="list-inline"></ul></div>');
-               add_themelink('cyborg', 'Black');
-               add_themelink('slate', 'Grey');
-               add_themelink('readable', 'White');
-               $('#sidebar').prepend(selector);
+ function set_style(name){
+       $('link[rel~="stylesheet"]').each(e => e.disabled = true);
+       $('link[title="' + name + '"]')[0].disabled = false;
+       localStorage.setItem("theme", name);
++      $(function() {
++              if(name == 'slate' || name == 'cyborg')
++                      $('.logo').each(e => e.classList.remove('logo-light'));
++              else
++                      $('.logo').each(e => e.classList.add('logo-light'));
 +      });
+ }
+ $(function() {
+       var theme_ul = '<ul class="list-inline" id="themes">' +
+               '<li><a role="button" data-theme="cyborg">Black</a>' +
+               '<li><a role="button" data-theme="slate">Grey</a>' +
+               '<li><a role="button" data-theme="readable">White</a></ul>';
+       var sidebar = $('#sidebar')[0];
+       sidebar.insertBefore(m(theme_ul), sidebar.firstChild);
+       $('#themes a').on('click', e => set_style(e.target.dataset.theme));
+ });
  
-       var theme = localStorage.getItem("theme");
-       if(theme) {
-               if(theme == "cerulean" || theme == "cosmo")
-                       theme = "readable";
-               set_style(theme);
-       }
- })();
+ let theme = localStorage.getItem("theme");
+ if(theme) {
+       if(theme == "cerulean" || theme == "cosmo")
+               theme = "readable";
+       set_style(theme);
+ }
diff --combined js/90-webchat-link.js
index 77d8fb4720782d8cc803020f3551f99a875ac155,0000000000000000000000000000000000000000..fe3831ad1bc58dffe824099946ca317bb23c7ce3
mode 100644,000000..100644
--- /dev/null
@@@ -1,7 -1,0 +1,1 @@@
- (function(){
-       'use strict';
-       $( document ).ready(function() {
-               $('#webchat').prependTo('#sidebar');
-       });
- })();
++$(() => $('#sidebar')[0].insertBefore($('#webchat')[0], $('#sidebar')[0].firstChild));
index daf739baf65aa85e025b60d01dede6492219ac66,7df9ef3c5f422fc47b388120bcfdd37b86841f1d..7863f4f425a43cba20579d9e422af4cc7a6d6b3f
@@@ -89,13 -89,8 +89,13 @@@ sub _render 
        $tree->as_HTML(undef, undef, $optional_end_tags);
  }
  
 +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(HTML::Element::Library::super_literal $logo);
        $tree->content_handler(
                title   =>         $args{title},
                content => literal $args{meat});
@@@ -181,13 -176,16 +181,13 @@@ sub process_pb_entry 
        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('solution_modal')->replace_content(literal $args{solution});
        }
        if ($args{cansubmit}) {
                $tree->fid('nosubmit')->detach;
diff --combined make_static.PL
index 4857bf0ccd37e2a367a75d1b037070df167023fa,0d8d10b873a5dee5f6db1ae50cb885fe9829fb3b..44f56fa6012f89f1d0093eb3ab101e0781b5613e
@@@ -3,40 -3,15 +3,41 @@@ use v5.14
  use warnings;
  
  use CSS::Minifier::XS qw//;
- use JavaScript::Minifier::XS qw//;
 +use CSS::SpriteMaker;
  
+ use Digest::SHA qw/sha256_base64/;
  use IO::Compress::Gzip qw/gzip/;
- use File::Slurp qw/read_file write_file/;
+ use File::Slurp qw/read_file write_file edit_file_lines/;
  
  mkdir 'static';
  mkdir 'static/css';
+ mkdir 'static/js';
  
 +sub make_sprite {
 +      my $maker = Local::CSS::SpriteMaker->new(
 +              css_class_prefix => 'logo-',
 +              rc_override_classname => sub {
 +                      my ($name) = @_;
 +                      $name =~ s/-light/.logo-light/r;
 +              }
 +      );
 +
 +      $maker->make_sprite(
 +              source_images     => ['logos/'],
 +              target_file       => 'static/logos.png',
 +              add_extra_padding => 10,
 +      );
 +
 +      $maker->print_css(
 +              filename        => 'css/logos.css',
 +              sprite_filename => '/static/logos.png',
 +      );
 +
 +      system 'pngnq-s9', '-s1', 'static/logos.png';
 +      system 'optipng', '-o7', '-zm1-9', 'static/logos-nq8.png';
 +      rename 'static/logos-nq8.png', 'static/logos.png';
 +}
 +
  sub gzip_file {
        my ($file) = @_;
        gzip $file => "$file.gz", -Level => 9, Minimal => 1;
@@@ -55,27 -30,13 +56,21 @@@ sub make_css 
  }
  
  sub make_js {
-       if (-f 'compiler.jar') {
-               system java => -jar => 'compiler.jar', qw,-O SIMPLE --create_source_map static/js.map --js_output_file static/js.js --language_in ECMASCRIPT5_STRICT --source_map_location_mapping js/|/static/js/,, <js/*>;
-               my $js = read_file 'static/js.js';
-               write_file 'static/js.js', '//# sourceMappingURL=/static/js.map', "\n", $js;
-               system 'cp', '-rp', 'js', 'static/';
-       } else {
-               my $js;
-               $js .= read_file $_ for <js/*.js>;
-               write_file 'static/js.js', JavaScript::Minifier::XS::minify $js;
-       }
-       gzip_file 'static/js.js';
+       system java => -jar => 'compiler.jar', qw,-O SIMPLE --create_source_map static/js/js.map --js_output_file static/js/all.js --language_in ECMASCRIPT6_STRICT --language_out ECMASCRIPT5_STRICT --source_map_location_mapping js/|/static/js/,, <js/*>;
+       my $js = read_file 'static/js/all.js';
+       write_file 'static/js/all.js', '//# sourceMappingURL=/static/js/js.map', "\n", $js;
+       system 'cp', '-rp', 'js', 'static/';
+       gzip_file 'static/js/all.js';
  }
  
 +my $sprite_mtime = -M 'static/logos.png' // 0;
 +for (<logos/*>) {
 +      if (!$sprite_mtime || $sprite_mtime > -M) {
 +              make_sprite;
 +              last
 +      }
 +}
 +
  my $css_mtime = -M 'static/css/slate.css' // 0;
  for (<css/*>, <css/themes/*>) {
        if (!$css_mtime || $css_mtime > -M) {
@@@ -92,23 -53,9 +87,30 @@@ for (<js/*>) 
        }
  }
  
 -} 'tmpl/skel.en'
+ edit_file_lines {
+       my ($file) = m,(static.*\.(?:css|js)),;
+       return unless $file;
+       my $hash = sha256_base64 scalar read_file $file;
+       s/integrity=".*"/integrity="sha256-$hash="/;
++} 'tmpl/skel.en';
++
 +package
 +  Local::CSS::SpriteMaker;
 +
 +use parent qw/CSS::SpriteMaker/;
 +
 +sub _get_stylesheet_string {
 +      my $self = shift;
 +      my @ret = split "\n", $self->SUPER::_get_stylesheet_string(@_);
 +      shift @ret;
 +      @ret = sort @ret;
 +      unshift @ret, <<EOF;
 +a.logo {
 +      background-image: url("/static/logos.png");
 +      background-repeat: no-repeat;
 +      display: inline-block;
 +      vertical-align: middle;
 +}
 +EOF
 +      join "\n", @ret;
 +}
diff --combined tmpl/pb_entry.en
index a12633d82b5456d8d218fdfbade5db9c5f10dd89,9f0cecb8051a3ac4a106aa19b381c609406006f3..dd03ea93abad24b37f80fe1cca32df58fb5a5d0b
@@@ -9,12 -9,12 +9,12 @@@
  <dt>Owner</dt> <dd id="owner">owner</dd>
  <dt>Level</dt> <dd id="level">Easy</dd>
  <dt>Time limit (seconds)</dt> <dd smap="timeout">1</dd>
 -<dt class="rc reqjs">Score</dt> <dd id="score" class="timer reqjs rc" data-start="..." data-stop="..." data-value="100">50</dd>
 +<dt class="rc reqjs">Score</dt> <dd id="score" class="rc">50</dd>
  <dt class="rc reqjs">Contest ends in</dt> <dd id="countdown" class="timer reqjs rc" data-stop="...">01:30</dd>
  </dl>
  
  <a href="/log/?problem=problem_id" id="job_log">Job log</a><br>
- <a href="/sol/problem_id" id="solution" data-toggle="modal" data-target="#solution_modal">Solution</a>
+ <a href="/sol/problem_id" id="solution">Solution</a>
  
  <h1 static="no">Submit solution</h1>
  
@@@ -31,18 -31,18 +31,18 @@@ To submit solutions to this problem, pl
  <div class="form-group"><label for="prog">File:</label><input id="prog" name="prog" type="file"></div>
  <div class="form-group"><label for="source_code">Source code:</label> <textarea class="form-control" id="source_code" name="source_code"></textarea></div>
  <div class="form-group"><label for="prog_format">File format:</label><select id="prog_format" name="prog_format" class="form-control" required>
 -<option value="C">C (gcc)</option>
 -<option value="CPP" selected>C++ (g++)</option>
 -<option value="GCCGO">Go (gccgo)</option>
 -<option value="GOLANG">Go (gc)</option>
 +<option value="C">C11 (gcc 4.7.2)</option>
 +<option value="CPP" selected>C++11 (g++ 4.7.2)</option>
 +<option value="GCCGO">Go (gccgo 4.7.2)</option>
 +<option value="GOLANG">Go (gc 1.0.2)</option>
  <option value="GOLFSCRIPT">Golfscript (golfscript.rb)</option>
 -<option value="HASKELL">Haskell (ghc)</option>
 -<option value="JAVA">Java (javac)</option>
 -<option value="PASCAL">Pascal (fpc)</option>
 -<option value="PERL">Perl (perl)</option>
 -<option value="PYTHON">Python (python)</option>
 -<option value="RUBY">Ruby (ruby)</option>
 -<option value="SBCL">Common Lisp (sbcl)</option>
 +<option value="HASKELL">Haskell (ghc 7.4.1)</option>
 +<option value="JAVA">Java (openjdk 7u75)</option>
 +<option value="PASCAL">Pascal (fpc 2.6.0)</option>
 +<option value="PERL">Perl (perl 5.14.2)</option>
 +<option value="PYTHON">Python (python 2.7.3)</option>
 +<option value="RUBY">Ruby (ruby 2.2.1)</option>
 +<option value="SBCL">Common Lisp (sbcl 1.0.57)</option>
  </select></div>
  
  <input type="submit" value="Submit job" class="btn btn-primary">
  </div>
  </div>
  
- <div class="modal fade" id="solution_modal" role="dialog" aria-hidden="true" tabindex="-1">
- <div class="modal-dialog modal-lg">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
- <h4 class="modal-title">Solution</h4>
- </div>
- <div class="modal-body"></div>
- </div>
- </div>
- </div>
+ <div class="backdrop"></div>
+ <div id="solution_modal" class="hidden modal"></div>
diff --combined tmpl/skel.en
index a207abc408e32635a8d132639d74786f8adad2a4,b28726c11fc377bcd0755972c6466bc7798594c2..0555da9de45a207268cfeae0c52eea2d504e5739
@@@ -3,66 -3,35 +3,66 @@@
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
 -<link href="/static/css/cyborg.css" title="cyborg" rel="stylesheet" integrity="x">
 -<link href="/static/css/slate.css" title="slate" rel="alternate stylesheet" integrity="x">
 +<link href="/static/favicon.png" rel="shortcut icon">
- <link href="/static/css/cyborg.css" title="cyborg" rel="alternate  stylesheet">
- <link href="/static/css/slate.css" title="slate" rel="stylesheet">
- <link href="/static/css/readable.css" title="readable" rel="alternate stylesheet">
- <script src="/static/js.js" type="text/javascript" async defer></script>
++<link href="/static/css/cyborg.css" title="cyborg" rel="alternate stylesheet" integrity="x">
++<link href="/static/css/slate.css" title="slate" rel="stylesheet" integrity="x">
+ <link href="/static/css/readable.css" title="readable" rel="alternate stylesheet" integrity="x">
+ <script src="/static/js/all.js" type="text/javascript" async defer integrity="x"></script>
  
  <body>
  <div class="container-fluid">
  <nav role="navigation">
  <ul class="nav nav-pills nav-justified">
 -<li id="nav-home"><a href="/">Gruntmaster 6000</a>
 +<li id="nav-home"><a href="/">Home</a>
  <li id="nav-pb"><a href="/pb/">Problems</a>
  <li id="nav-ct"><a href="/ct/">Contests</a>
  <li id="nav-log"><a href="/log/">Job log</a>
  <li id="nav-us"><a href="/us/">Users</a>
  <li id="nav-account" static="no"><a href="/account">Account</a>
 +<li id="nav-about"><a href="/about">About / Help</a>
  <li id="nav-contribute"><a href="/contribute">Contribute!</a>
  
  </ul>
  </nav>
  
 +<div id="logo"></div>
  <h1 id="title">TITLE</h1>
 -<div id="static" class="alert alert-info" static="yes">This is a static version of Gruntmaster 6000.</div>
 +<div id="static" class="alert alert-info" static="yes">This is a static version of MindCoding, useful when the <a class="alert-link" href="https://mindcoding.ro/">regular version</a> is overloaded.</div>
  
  <div id="result"></div>
  
  <main id="content">Content goes here</main>
  
 +<div id="webchat"><a href="http://webchat.oftc.net/?channels=%23mindcoding" target="_blank">Webchat</a></div>
 +
 +<div id="sponsors">
 +<h3>Official sponsors</h3>
 +<a class="logo logo-emag" href="http://www.fundatiaemag.ro/"></a>
 +<a class="logo logo-easyhost" href="http://ro.easyhost.com/"></a>
 +<a class="logo logo-takeofflabs" href="http://www.takeofflabs.com/"></a>
 +<a class="logo logo-bigstep" href="http://www.bigstep.com/"></a>
 +<a class="logo logo-yardi" href="https://www.facebook.com/YardiRomania"></a>
 +<a class="logo logo-bosch" href="http://www.bosch.com.ro/"></a>
 +<a class="logo logo-endava" href="http://www.endava.com/"></a>
 +</div>
 +
  <footer>
 -Dilmom: Why don't you call your product the Gruntmaster 6000?<br>
 -Dilbert: What kind of product do you see when you imagine a Gruntmaster 6000?<br>
 -Dilmom: Well, it's a stripped-down version of the Gruntmaster 9000, of course. But it's software-upgradeable.
 +<div class="row">
 +<div class="col-md-6 column text-center">
 +<a class="logo logo-hermes" href="http://www.societatea-hermes.ro"></a>
 +</div>
 +
 +<div class="col-md-6 column text-center">
 +<a class="logo logo-facebook" href="http://www.facebook.com/mindcodingcluj"></a>
 +</div>
 +</div>
 +
 +<h3>Partners</h3>
 +<a href="https://www.facebook.com/spyhce?fref=ts" class="logo logo-spyhce"></a>
 +<a href="https://www.facebook.com/telenav?fref=ts" class="logo logo-telenav"></a>
 +<h3>Media Partners</h3>
 +<a href="http://cs.ubbcluj.ro" class="logo logo-csf"></a>
 +<a href="http://www.uniunea.ro" class="logo logo-usr"></a>
 +<a href="http://www.coscj.ro" class="logo logo-cos"></a>
 +<a href="http://www.cluj2015.ro/romana" class="logo logo-eyc"></a>
  </footer>
This page took 0.024953 seconds and 4 git commands to generate.