<commit_before>'use strict';

module.exports = function(grunt) {
    var _ = grunt.util._;
    var path = require('path');

    grunt.registerTask("phantomizer-html-jitbuild", "Builds html inlined request", function ( target, request ) {

        var build_assets = true;

        var task_options = grunt.config("phantomizer-html-jitbuild");

        var options = {}
        grunt.util._.merge(options, task_options);

        if( !options[target] )
            options[target] = {
                options:{}
            }

        options[target]["options"]["request"] = request;
        options[target]["options"]["build_assets"] = build_assets;

        grunt.config.set("phantomizer-html-builder", options);
        grunt.task.run("phantomizer-html-builder:" + target);

    });

    grunt.registerMultiTask("phantomizer-html-builder", "Builds html request", function () {

        var _ = grunt.util._;
        var path = require('path');

        var ph_libutil = require("phantomizer-libutil");
        var meta_factory = ph_libutil.meta;

        var wd = process.cwd();

        var options = this.options({
            out_path:'',
            meta_dir:'',
            htmlcompressor:false,
            build_assets:false,
            in_request:''
        });

        grunt.verbose.writeflags(options,"options");
        var out_path = options.out_path;
        var meta_dir = options.meta_dir;

        var build_assets = options.build_assets;
        var htmlcompressor = options.htmlcompressor;
        var in_request = options.in_request;

        var meta_manager = new meta_factory( wd, meta_dir )
        var current_target = this.target;

        var in_request_tgt = in_request+"-"+current_target;
        var meta_file = meta_dir+"/"+in_request_tgt;
        var out_file = out_path+"/"+in_request_tgt;

        var sub_tasks = [];

        if( meta_manager.is_fresh(meta_file) == false ){

            // -
            queue_strykejs_builder( sub_tasks, current_target, in_request, in_request_tgt+".stryke", out_file+".stryke" );
            grunt.log.ok("Stryke task pushed ");

            // -
            if( build_assets ){
                queue_html_assets( sub_tasks, current_target, in_request, out_file+".stryke", in_request_tgt+".assets", out_file+".assets", out_path, meta_dir,true,true );
                grunt.log.ok("assets build task pushed ");
            }

            // -
            if( htmlcompressor == true ){
                if( build_assets ){
                    queue_html_min(  sub_tasks, current_target, out_file+".min", meta_dir, in_request_tgt+".min", out_file+".assets", in_request );
                }else{
                    queue_html_min(  sub_tasks, current_target, out_file+".min", meta_dir, in_request_tgt+".min", out_file+".stryke", in_request );
                }
                grunt.log.ok("HTMLcompressor task pushed ");
            }

            // -
            queue_finalizer_builder( sub_tasks, in_request_tgt, out_file, build_assets, htmlcompressor, meta_dir );
            grunt.log.ok("Finalizer task pushed ");

            // -
            grunt.task.run( sub_tasks );

            grunt.log.ok("Done ");
        }else{
            console.log("Build is fresh ! -> " + in_request)
        }

        // -- task queue-er
        function queue_strykejs_builder( sub_tasks, current_target, in_request, meta_file, out_file ){
            var current_sub_task_name = "phantomizer-strykejs-builder";
            var sub_task_name = in_request;
            var opts = grunt.config(current_sub_task_name) || {};
            if( opts[current_target] ) opts[sub_task_name] = _.clone(opts[current_target], true)
            if( !opts[sub_task_name] ) opts[sub_task_name] = {};
            if( !opts[sub_task_name].options ) opts[sub_task_name].options = {};
            opts[sub_task_name].options.in_request = in_request;
            opts[sub_task_name].options.out = out_file;
            opts[sub_task_name].options.meta = meta_file;

            grunt.config.set(current_sub_task_name, opts);
            sub_tasks.push( current_sub_task_name+":"+sub_task_name+":"+current_target );
        }

        function queue_finalizer_builder( sub_tasks, in_request, out_file, build_assets, htmlcompressor, meta_dir ){

            var task_name = "phantomizer-finalizer";
            var opts = grunt.config(task_name) || {};
            var sub_task_name = "some-task"+"-"+sub_tasks.length;

            if( !opts[sub_task_name] )
                opts[sub_task_name] = {
                    options:{
                        copy:{}
                        ,meta_dir:meta_dir
                        ,meta_merge:{}
                    }
                };

            opts[sub_task_name].options.copy[out_file] = out_file+".stryke";
            opts[sub_task_name].options.meta_merge[in_request] = [in_request+".stryke"];
            if(build_assets){
                opts[sub_task_name].options.copy[out_file] = out_file+".assets";
                opts[sub_task_name].options.meta_merge[in_request].push(in_request+".assets");
            }
            if(htmlcompressor){
                opts[sub_task_name].options.copy[out_file] = out_file+".min";
                opts[sub_task_name].options.meta_merge[in_request].push(in_request+".min");
            }

            grunt.config.set(task_name, opts);
            sub_tasks.push( task_name+":"+sub_task_name );
        }
    });

    // Builds a phantomizer project
    // ----------
    grunt.registerMultiTask("phantomizer-html-project-builder",
        "Builds an entire project with best performance", function () {

        // this task is async
        var done = this.async();

        var ph_libutil = require("phantomizer-libutil");
        var meta_factory = ph_libutil.meta;

        var sub_tasks = [];

        // init default options
        var options = this.options({
            // the path were all build assets results
            out_path:'',
            // the path holding all build assets meta
            meta_dir:'',
            // the path to record temporarly url collection
            run_dir:'',
            // the path used for webserver
            paths:[],
            // enable extras support scripts injection (dashbaord loader, test loader)
            inject_extras:false,
            // enable js,css,img build
            build_assets:false
        });
        grunt.verbose.writeflags(options,"options");

        var current_target = this.target;

        var meta_manager = new meta_factory( process.cwd(), options.meta_dir );

        // initialize the router given the grunt config.routing key
        // router provides the catalog of urls to build
        var config = grunt.config.get();
        var router_factory = ph_libutil.router;
        var router = new router_factory(config.routing);
        // load urls eventually from a remote service
        router.load(function(){

            // fetch urls to build
            var raw_urls = router.collect_urls();
            grunt.log.ok("URL Count "+raw_urls.length);

            var in_request;
            var in_request_tgt;
            var urls = [];
            for( var n in raw_urls ){
                in_request = raw_urls[n];

                in_request_tgt = in_request+"-"+current_target;
                var meta_file = in_request_tgt;
                var out_file = options.out_path+"/"+in_request;

                out_file = path.normalize(out_file);
                meta_file = path.normalize(meta_file);

                if( meta_manager.is_fresh(meta_file) == false ){
                    urls.push({in_request:in_request,out_file:out_file,meta_file:meta_file})
                }
            }

            var urls_file = options.run_dir+"/tmp/html-builder-urls.json";
            grunt.file.mkdir( path.dirname(urls_file) );
            grunt.file.write(urls_file, JSON.stringify(urls));

            queue_strykejs_builder( sub_tasks, current_target, urls_file, options.inject_extras );

            if( options.build_assets ){
                for( var n in urls ){
                    in_request = urls[n].in_request;

                    in_request_tgt = in_request+"-"+current_target;
                    out_file = urls[n].out_file;
                    queue_html_assets( sub_tasks, current_target, in_request, out_file, in_request_tgt, out_file, options.out_path, options.meta_dir, false,false );
                }
            }
            // helps to prevent odd error such :
            // Warning: Maximum call stack size exceeded Use --force to continue.
            sub_tasks.push( "throttle:20" );

            if( options.inject_extras == true ){
                queue_html_inject_extras_dir(  sub_tasks, current_target, options.out_path );
            }

            if( options.build_assets ){
                queue_gm_merge(sub_tasks, current_target, options.paths, options.out_path);
            }
            queue_img_opt_dir(sub_tasks, current_target, options.paths, options.out_path);

            if( options.build_assets ){
                queue_css_img_merge_dir(sub_tasks, current_target, options.meta_dir, options.out_path, options.out_path);
            }
            // -
            grunt.task.run( sub_tasks );
            grunt.log.ok();

            done();
        });

        function queue_strykejs_builder( sub_tasks, sub_task_name, urls_file, inject_extras ){

            var task_name = "phantomizer-strykejs-project-builder";
            var opts = grunt.config(task_name) || {};

            opts = clone_subtasks_options(opts, sub_task_name, current_target);
            opts[sub_task_name].options.urls_file = urls_file;
            opts[sub_task_name].options.inject_extras = inject_extras;

            grunt.config.set(task_name, opts);
            sub_tasks.push( task_name+":"+sub_task_name );
        }
    });

    function queue_html_assets( sub_tasks, current_target, in_request, in_file, meta_file, out_file, out_path, meta_dir, imgcompressor, image_merge ){

        var task_name = "phantomizer-html-assets";
        var opts = grunt.config(task_name) || {};
        var sub_task_name = in_request+"-"+current_target;

        opts = clone_subtasks_options(opts, sub_task_name, current_target);
        opts[sub_task_name].options.in_file = in_file;
        opts[sub_task_name].options.as_of_target = current_target;
        opts[sub_task_name].options.out = out_file;
        opts[sub_task_name].options.meta_file = meta_file;
        opts[sub_task_name].options.out_path = out_path;
        opts[sub_task_name].options.meta_dir = meta_dir;
        opts[sub_task_name].options.in_request = in_request;
        opts[sub_task_name].options.imgcompressor = imgcompressor;
        opts[sub_task_name].options.image_merge = image_merge;

        grunt.config.set(task_name, opts)
        sub_tasks.push( task_name+":"+sub_task_name )
    }
    function queue_html_min( sub_tasks, current_target, out_file, meta_dir, meta_file, in_file, in_request ){

        var task_name = "phantomizer-htmlcompressor";
        var opts = grunt.config(task_name) || {};
        var sub_task_name = current_target+"-"+in_request;

        opts = clone_subtasks_options(opts, sub_task_name, current_target);
        opts[sub_task_name].options.in_file = in_file;
        opts[sub_task_name].options.out = out_file;
        opts[sub_task_name].options.meta_file = meta_file;
        opts[sub_task_name].options.meta_dir = meta_dir;

        grunt.config.set(task_name, opts);
        sub_tasks.push( task_name+":"+sub_task_name );
    }
    function queue_html_inject_extras_dir( sub_tasks, current_target, in_dir ){

        var task_name = "phantomizer-dir-inject-html-extras";
        var opts = grunt.config(task_name) || {};
        var sub_task_name = current_target+"-"+sub_tasks.length;

        opts = clone_subtasks_options(opts, sub_task_name, current_target);
        opts[sub_task_name].options.in_dir = in_dir+"/";

        grunt.config.set(task_name, opts);
        sub_tasks.push( task_name+":"+sub_task_name );
    }

    function queue_img_opt_dir( sub_tasks, build_target, paths, out_path ){

        var jit_target = ""+build_target;
        var task_name = "phantomizer-dir-imgopt";
        var task_options = grunt.config(task_name) || {};

        task_options = clone_subtasks_options(task_options, jit_target, build_target);
        if(!task_options[jit_target].options) task_options[jit_target].options = {};
        task_options[jit_target].options.paths = paths;
        task_options[jit_target].options.out_path = out_path;

        sub_tasks.push( task_name+":"+jit_target );

        grunt.config.set(task_name, task_options);
    }
    function queue_css_img_merge_dir( sub_tasks, build_target, meta_dir, in_dir, out_dir ){

        var merge_options = grunt.config("phantomizer-gm-merge") || {};
        var map = merge_options.options.in_files;

        var jit_target = ""+build_target;
        var task_name = "phantomizer-dir-css-imgmerge";
        var task_options = grunt.config(task_name) || {};

        task_options = clone_subtasks_options(task_options, jit_target, build_target);
        task_options[jit_target].options.paths = in_dir;
        task_options[jit_target].options.out_dir = out_dir;
        task_options[jit_target].options.meta_dir = meta_dir;
        task_options[jit_target].options.map = map;

        sub_tasks.push( task_name+":"+jit_target );

        grunt.config.set(task_name, task_options);
    }
    function queue_gm_merge( sub_tasks, build_target, paths, out_dir ){

        var jit_target = ""+build_target;
        var task_name = "phantomizer-gm-merge";
        var task_options = grunt.config(task_name) || {};

        task_options = clone_subtasks_options(task_options, jit_target, build_target);

        if( !task_options[jit_target].options )
            task_options[jit_target].options = {};
        task_options[jit_target].options.paths = paths;
        task_options[jit_target].options.out_dir = out_dir;

        sub_tasks.push( task_name+":"+jit_target );

        grunt.config.set(task_name, task_options);
    }

    function clone_subtasks_options(task_options, task_name, current_target){
        var _ = grunt.util._;
        if( task_options[current_target] ) task_options[task_name] = _.clone(task_options[current_target], true);
        if( !task_options[task_name] ) task_options[task_name] = {};
        if( !task_options[task_name].options ) task_options[task_name].options = {};
        return task_options;
    }
};<commit_msg>Code style<commit_after>'use strict';

module.exports = function(grunt) {
  var _ = grunt.util._;
  var path = require('path');

  grunt.registerTask("phantomizer-html-jitbuild", "Builds html inlined request", function ( target, request ) {

    var build_assets = true;

    var task_options = grunt.config("phantomizer-html-jitbuild");

    var options = {}
    grunt.util._.merge(options, task_options);

    if( !options[target] )
      options[target] = {
        options:{}
      }

    options[target]["options"]["request"] = request;
    options[target]["options"]["build_assets"] = build_assets;

    grunt.config.set("phantomizer-html-builder", options);
    grunt.task.run("phantomizer-html-builder:" + target);

  });

  grunt.registerMultiTask("phantomizer-html-builder", "Builds html request", function () {

    var _ = grunt.util._;
    var path = require('path');

    var ph_libutil = require("phantomizer-libutil");
    var meta_factory = ph_libutil.meta;

    var wd = process.cwd();

    var options = this.options({
      out_path:'',
      meta_dir:'',
      htmlcompressor:false,
      build_assets:false,
      in_request:''
    });

    grunt.verbose.writeflags(options,"options");
    var out_path = options.out_path;
    var meta_dir = options.meta_dir;

    var build_assets = options.build_assets;
    var htmlcompressor = options.htmlcompressor;
    var in_request = options.in_request;

    var meta_manager = new meta_factory( wd, meta_dir )
    var current_target = this.target;

    var in_request_tgt = in_request+"-"+current_target;
    var meta_file = meta_dir+"/"+in_request_tgt;
    var out_file = out_path+"/"+in_request_tgt;

    var sub_tasks = [];

    if( meta_manager.is_fresh(meta_file) == false ){

      // -
      queue_strykejs_builder( sub_tasks, current_target, in_request, in_request_tgt+".stryke", out_file+".stryke" );
      grunt.log.ok("Stryke task pushed ");

      // -
      if( build_assets ){
        queue_html_assets( sub_tasks, current_target, in_request, out_file+".stryke", in_request_tgt+".assets", out_file+".assets", out_path, meta_dir,true,true );
        grunt.log.ok("assets build task pushed ");
      }

      // -
      if( htmlcompressor == true ){
        if( build_assets ){
          queue_html_min(  sub_tasks, current_target, out_file+".min", meta_dir, in_request_tgt+".min", out_file+".assets", in_request );
        }else{
          queue_html_min(  sub_tasks, current_target, out_file+".min", meta_dir, in_request_tgt+".min", out_file+".stryke", in_request );
        }
        grunt.log.ok("HTMLcompressor task pushed ");
      }

      // -
      queue_finalizer_builder( sub_tasks, in_request_tgt, out_file, build_assets, htmlcompressor, meta_dir );
      grunt.log.ok("Finalizer task pushed ");

      // -
      grunt.task.run( sub_tasks );

      grunt.log.ok("Done ");
    }else{
      console.log("Build is fresh ! -> " + in_request)
    }

    // -- task queue-er
    function queue_strykejs_builder( sub_tasks, current_target, in_request, meta_file, out_file ){
      var current_sub_task_name = "phantomizer-strykejs-builder";
      var sub_task_name = in_request;
      var opts = grunt.config(current_sub_task_name) || {};
      if( opts[current_target] ) opts[sub_task_name] = _.clone(opts[current_target], true)
      if( !opts[sub_task_name] ) opts[sub_task_name] = {};
      if( !opts[sub_task_name].options ) opts[sub_task_name].options = {};
      opts[sub_task_name].options.in_request = in_request;
      opts[sub_task_name].options.out = out_file;
      opts[sub_task_name].options.meta = meta_file;

      grunt.config.set(current_sub_task_name, opts);
      sub_tasks.push( current_sub_task_name+":"+sub_task_name+":"+current_target );
    }

    function queue_finalizer_builder( sub_tasks, in_request, out_file, build_assets, htmlcompressor, meta_dir ){

      var task_name = "phantomizer-finalizer";
      var opts = grunt.config(task_name) || {};
      var sub_task_name = "some-task"+"-"+sub_tasks.length;

      if( !opts[sub_task_name] )
        opts[sub_task_name] = {
          options:{
            copy:{}
            ,meta_dir:meta_dir
            ,meta_merge:{}
          }
        };

      opts[sub_task_name].options.copy[out_file] = out_file+".stryke";
      opts[sub_task_name].options.meta_merge[in_request] = [in_request+".stryke"];
      if(build_assets){
        opts[sub_task_name].options.copy[out_file] = out_file+".assets";
        opts[sub_task_name].options.meta_merge[in_request].push(in_request+".assets");
      }
      if(htmlcompressor){
        opts[sub_task_name].options.copy[out_file] = out_file+".min";
        opts[sub_task_name].options.meta_merge[in_request].push(in_request+".min");
      }

      grunt.config.set(task_name, opts);
      sub_tasks.push( task_name+":"+sub_task_name );
    }
  });

  // Builds a phantomizer project
  // ----------
  grunt.registerMultiTask("phantomizer-html-project-builder",
    "Builds an entire project with best performance", function () {

      // this task is async
      var done = this.async();

      var ph_libutil = require("phantomizer-libutil");
      var meta_factory = ph_libutil.meta;

      var sub_tasks = [];

      // init default options
      var options = this.options({
        // the path were all build assets results
        out_path:'',
        // the path holding all build assets meta
        meta_dir:'',
        // the path to record temporarly url collection
        run_dir:'',
        // the path used for webserver
        paths:[],
        // enable extras support scripts injection (dashbaord loader, test loader)
        inject_extras:false,
        // enable js,css,img build
        build_assets:false
      });
      grunt.verbose.writeflags(options,"options");

      var current_target = this.target;

      var meta_manager = new meta_factory( process.cwd(), options.meta_dir );

      // initialize the router given the grunt config.routing key
      // router provides the catalog of urls to build
      var config = grunt.config.get();
      var router_factory = ph_libutil.router;
      var router = new router_factory(config.routing);
      // load urls eventually from a remote service
      router.load(function(){

        // fetch urls to build
        var raw_urls = router.collect_urls();
        grunt.log.ok("URL Count "+raw_urls.length);

        var in_request;
        var in_request_tgt;
        var urls = [];
        for( var n in raw_urls ){
          in_request = raw_urls[n];

          in_request_tgt = in_request+"-"+current_target;
          var meta_file = in_request_tgt;
          var out_file = options.out_path+"/"+in_request;

          out_file = path.normalize(out_file);
          meta_file = path.normalize(meta_file);

          if( meta_manager.is_fresh(meta_file) == false ){
            urls.push({in_request:in_request,out_file:out_file,meta_file:meta_file})
          }
        }

        var urls_file = options.run_dir+"/tmp/html-builder-urls.json";
        grunt.file.mkdir( path.dirname(urls_file) );
        grunt.file.write(urls_file, JSON.stringify(urls));

        queue_strykejs_builder( sub_tasks, current_target, urls_file, options.inject_extras );

        if( options.build_assets ){
          for( var n in urls ){
            in_request = urls[n].in_request;

            in_request_tgt = in_request+"-"+current_target;
            out_file = urls[n].out_file;
            queue_html_assets( sub_tasks, current_target, in_request, out_file, in_request_tgt, out_file, options.out_path, options.meta_dir, false,false );
          }
        }
        // helps to prevent odd error such :
        // Warning: Maximum call stack size exceeded Use --force to continue.
        sub_tasks.push( "throttle:20" );

        if( options.inject_extras == true ){
          queue_html_inject_extras_dir(  sub_tasks, current_target, options.out_path );
        }

        if( options.build_assets ){
          queue_gm_merge(sub_tasks, current_target, options.paths, options.out_path);
        }
        queue_img_opt_dir(sub_tasks, current_target, options.paths, options.out_path);

        if( options.build_assets ){
          queue_css_img_merge_dir(sub_tasks, current_target, options.meta_dir, options.out_path, options.out_path);
        }
        // -
        grunt.task.run( sub_tasks );
        grunt.log.ok();

        done();
      });

      function queue_strykejs_builder( sub_tasks, sub_task_name, urls_file, inject_extras ){

        var task_name = "phantomizer-strykejs-project-builder";
        var opts = grunt.config(task_name) || {};

        opts = clone_subtasks_options(opts, sub_task_name, current_target);
        opts[sub_task_name].options.urls_file = urls_file;
        opts[sub_task_name].options.inject_extras = inject_extras;

        grunt.config.set(task_name, opts);
        sub_tasks.push( task_name+":"+sub_task_name );
      }
    });

  function queue_html_assets( sub_tasks, current_target, in_request, in_file, meta_file, out_file, out_path, meta_dir, imgcompressor, image_merge ){

    var task_name = "phantomizer-html-assets";
    var opts = grunt.config(task_name) || {};
    var sub_task_name = in_request+"-"+current_target;

    opts = clone_subtasks_options(opts, sub_task_name, current_target);
    opts[sub_task_name].options.in_file = in_file;
    opts[sub_task_name].options.as_of_target = current_target;
    opts[sub_task_name].options.out = out_file;
    opts[sub_task_name].options.meta_file = meta_file;
    opts[sub_task_name].options.out_path = out_path;
    opts[sub_task_name].options.meta_dir = meta_dir;
    opts[sub_task_name].options.in_request = in_request;
    opts[sub_task_name].options.imgcompressor = imgcompressor;
    opts[sub_task_name].options.image_merge = image_merge;

    grunt.config.set(task_name, opts)
    sub_tasks.push( task_name+":"+sub_task_name )
  }
  function queue_html_min( sub_tasks, current_target, out_file, meta_dir, meta_file, in_file, in_request ){

    var task_name = "phantomizer-htmlcompressor";
    var opts = grunt.config(task_name) || {};
    var sub_task_name = current_target+"-"+in_request;

    opts = clone_subtasks_options(opts, sub_task_name, current_target);
    opts[sub_task_name].options.in_file = in_file;
    opts[sub_task_name].options.out = out_file;
    opts[sub_task_name].options.meta_file = meta_file;
    opts[sub_task_name].options.meta_dir = meta_dir;

    grunt.config.set(task_name, opts);
    sub_tasks.push( task_name+":"+sub_task_name );
  }
  function queue_html_inject_extras_dir( sub_tasks, current_target, in_dir ){

    var task_name = "phantomizer-dir-inject-html-extras";
    var opts = grunt.config(task_name) || {};
    var sub_task_name = current_target+"-"+sub_tasks.length;

    opts = clone_subtasks_options(opts, sub_task_name, current_target);
    opts[sub_task_name].options.in_dir = in_dir+"/";

    grunt.config.set(task_name, opts);
    sub_tasks.push( task_name+":"+sub_task_name );
  }

  function queue_img_opt_dir( sub_tasks, build_target, paths, out_path ){

    var jit_target = ""+build_target;
    var task_name = "phantomizer-dir-imgopt";
    var task_options = grunt.config(task_name) || {};

    task_options = clone_subtasks_options(task_options, jit_target, build_target);
    if(!task_options[jit_target].options) task_options[jit_target].options = {};
    task_options[jit_target].options.paths = paths;
    task_options[jit_target].options.out_path = out_path;

    sub_tasks.push( task_name+":"+jit_target );

    grunt.config.set(task_name, task_options);
  }
  function queue_css_img_merge_dir( sub_tasks, build_target, meta_dir, in_dir, out_dir ){

    var merge_options = grunt.config("phantomizer-gm-merge") || {};
    var map = merge_options.options.in_files;

    var jit_target = ""+build_target;
    var task_name = "phantomizer-dir-css-imgmerge";
    var task_options = grunt.config(task_name) || {};

    task_options = clone_subtasks_options(task_options, jit_target, build_target);
    task_options[jit_target].options.paths = in_dir;
    task_options[jit_target].options.out_dir = out_dir;
    task_options[jit_target].options.meta_dir = meta_dir;
    task_options[jit_target].options.map = map;

    sub_tasks.push( task_name+":"+jit_target );

    grunt.config.set(task_name, task_options);
  }
  function queue_gm_merge( sub_tasks, build_target, paths, out_dir ){

    var jit_target = ""+build_target;
    var task_name = "phantomizer-gm-merge";
    var task_options = grunt.config(task_name) || {};

    task_options = clone_subtasks_options(task_options, jit_target, build_target);

    if( !task_options[jit_target].options )
      task_options[jit_target].options = {};
    task_options[jit_target].options.paths = paths;
    task_options[jit_target].options.out_dir = out_dir;

    sub_tasks.push( task_name+":"+jit_target );

    grunt.config.set(task_name, task_options);
  }

  function clone_subtasks_options(task_options, task_name, current_target){
    var _ = grunt.util._;
    if( task_options[current_target] ) task_options[task_name] = _.clone(task_options[current_target], true);
    if( !task_options[task_name] ) task_options[task_name] = {};
    if( !task_options[task_name].options ) task_options[task_name].options = {};
    return task_options;
  }
};<|endoftext|>


<commit_before>/*jslint nomen: true*/
/*global _, jQuery, MAPJS, Kinetic, observable */
MAPJS.pngExport = function (idea) {
	'use strict';
	var deferred = jQuery.Deferred(),
		layout = MAPJS.calculateLayout(idea, MAPJS.KineticMediator.dimensionProvider),
		frame = MAPJS.calculateFrame(layout.nodes, 10),
		hiddencontainer = jQuery('

').css('visibility', 'hidden')
			.appendTo('body').width(frame.width).height(frame.height).attr('id', 'hiddencontainer'),
		hiddenstage = new Kinetic.Stage({ container: 'hiddencontainer' }),
		layer = new Kinetic.Layer(),
		backgroundLayer = new Kinetic.Layer(),
		nodeByIdeaId = {},
		bg = new Kinetic.Rect({
			fill: '#ffffff',
			x: frame.left,
			y: frame.top,
			width: frame.width,
			height: frame.height
		});
	hiddenstage.add(backgroundLayer);
	backgroundLayer.add(bg);
	hiddenstage.add(layer);
	hiddenstage.setWidth(frame.width);
	hiddenstage.setHeight(frame.height);
	hiddenstage.attrs.x = -1 * frame.left;
	hiddenstage.attrs.y = -1 * frame.top;
	_.each(layout.nodes, function (n) {
		var node = new Kinetic.Idea({
			level: n.level,
			x: n.x,
			y: n.y,
			text: n.title,
			mmAttr: n.attr
		});
		nodeByIdeaId[n.id] = node;
		layer.add(node);
	});
	_.each(layout.connectors, function (n) {
		var connector = new Kinetic.Connector({
			shapeFrom: nodeByIdeaId[n.from],
			shapeTo: nodeByIdeaId[n.to],
			stroke: '#888',
			strokeWidth: 1
		});
		layer.add(connector);
		connector.moveToBottom();
	});
	hiddenstage.draw();
	hiddenstage.toDataURL({
		callback: function (url) {
			deferred.resolve(url);
			hiddencontainer.remove();
		}
	});
	return deferred.promise();
};
<commit_msg>links are now exported to png<commit_after>/*jslint nomen: true*/
/*global _, jQuery, MAPJS, Kinetic */
MAPJS.pngExport = function (idea) {
	'use strict';
	var deferred = jQuery.Deferred(),
		layout = MAPJS.calculateLayout(idea, MAPJS.KineticMediator.dimensionProvider),
		frame = MAPJS.calculateFrame(layout.nodes, 10),
		hiddencontainer = jQuery('

').css('visibility', 'hidden')
			.appendTo('body').width(frame.width).height(frame.height).attr('id', 'hiddencontainer'),
		hiddenstage = new Kinetic.Stage({ container: 'hiddencontainer' }),
		layer = new Kinetic.Layer(),
		backgroundLayer = new Kinetic.Layer(),
		nodeByIdeaId = {},
		bg = new Kinetic.Rect({
			fill: '#ffffff',
			x: frame.left,
			y: frame.top,
			width: frame.width,
			height: frame.height
		});
	hiddenstage.add(backgroundLayer);
	backgroundLayer.add(bg);
	hiddenstage.add(layer);
	hiddenstage.setWidth(frame.width);
	hiddenstage.setHeight(frame.height);
	hiddenstage.attrs.x = -1 * frame.left;
	hiddenstage.attrs.y = -1 * frame.top;
	_.each(layout.nodes, function (n) {
		var node = new Kinetic.Idea({
			level: n.level,
			x: n.x,
			y: n.y,
			text: n.title,
			mmAttr: n.attr
		});
		nodeByIdeaId[n.id] = node;
		layer.add(node);
	});
	_.each(layout.connectors, function (n) {
		var connector = new Kinetic.Connector({
			shapeFrom: nodeByIdeaId[n.from],
			shapeTo: nodeByIdeaId[n.to],
			stroke: '#888',
			strokeWidth: 1
		});
		layer.add(connector);
		connector.moveToBottom();
	});
	_.each(layout.links, function (l) {
		var link = new Kinetic.Link({
			shapeFrom: nodeByIdeaId[l.ideaIdFrom],
			shapeTo: nodeByIdeaId[l.ideaIdTo],
			dashArray: [8, 8],
			stroke: '#800',
			strokeWidth: 1.5
		});
		layer.add(link);
		link.moveToBottom();
		link.setMMAttr(l.attr);
	});
	hiddenstage.draw();
	hiddenstage.toDataURL({
		callback: function (url) {
			deferred.resolve(url);
			hiddencontainer.remove();
		}
	});
	return deferred.promise();
};
<|endoftext|>


<commit_before>var async = require('async');
var should = require('should');
var client = require('fakeredis').createClient(null, null, {fast: true});
var rhom = require('../index.js');

function TestModel() {}
TestModel.properties = ['foo', 'bar'];
rhom(TestModel, TestModel.properties, client);

describe("Model utility functions", function() {
  it("generates seqential identifiers", function() {
    var seq1 = rhom.model.sequence();
    seq1().should.be.exactly("0");
    seq1().should.be.exactly("1");

    var seq2 = rhom.model.sequence();
    seq2().should.be.exactly("0");
    seq2().should.be.exactly("1");
    seq1().should.be.exactly("2");
  });

  it("generate UUIDs by default", function() {
    (typeof TestModel._mdl.idgen()).should.be.exactly("string");
    TestModel._mdl.idgen().should.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);
  });
});

describe("Model class", function(done) {
  beforeEach(function(done) {
    TestModel.purge(done);
  });

  it("has expected static methods", function() {
    (typeof TestModel.get).should.be.exactly("function");
    (typeof TestModel._mdl.idgen).should.be.exactly("function");
    (typeof TestModel.getKey).should.be.exactly("function");
  });

  it("has expected instance methods", function() {
    var test = new TestModel();
    (typeof test.save).should.be.exactly("function");
    (typeof test.toObject).should.be.exactly("function");
  });

  it("(C)reates objects as redis hashes", function(done) {
    var test = new TestModel();
    test.foo = "test one";
    test.bar = 234;
    test.save(function(err, res) {
      if (err) done(err);

      res.should.be.true;

      client.hgetall(TestModel.getKey(test.id), function(err, res) {
        if (err) done(err);

        res.foo.should.be.exactly(test.foo);
        res.bar.should.be.exactly(String(test.bar));
        res.should.not.be.eql(test);
        done();
      });
    }).then(function(result) {
      // Don't need to re-test the result, just that the callback and promise return the same thing.
      result.should.be.true;
    }, function(error) {
      done(error);
    });
  });

  it("(R)etrieves saved objects", function(done) {
    var test = new TestModel();
    test.foo = "test one two three";
    test.bar = 23456;
    test.save(function(err) {
      if (err) done(err);

      TestModel.get(test.id, function(err, res) {
        if (err) done(err);
        res.id.should.be.exactly(test.id);
        res.foo.should.be.exactly(test.foo);
        res.bar.should.be.exactly(String(test.bar));
        done();
      }).then(function(res) {
        res.id.should.be.exactly(test.id);
        res.foo.should.be.exactly(test.foo);
        res.bar.should.be.exactly(String(test.bar));
      }, function(error) {
        done(error);
      });
    });
  });

  it("(U)pdates objects", function(done) {
    var test = new TestModel();
    test.foo = "First save";
    test.save(function(err) {
      if (err) done(err);

      test.foo = "Updated value";
      test.save(function(err) {
        if (err) done(err);

        TestModel.get(test.id, function(err, res) {
          if (err) done(err);
          res.id.should.be.exactly(test.id);
          res.foo.should.be.exactly(test.foo);
          done();
        });
      });
    });
  });

  it("(D)eletes objects", function(done) {
    test = new TestModel();
    test.save(function(err) {
      if (err) done(err);

      test.delete(function(err) {
        if (err) done(err);
        var m = client.multi();
        var k = TestModel.getKey(test.id);
        m.hgetall(k);
        m.sismember(TestModel.getKey('all'), k);

        m.exec(function(err, res) {
          if (err) done(err);
          should(res[0]).be.exactly(null);
          res[1].should.be.exactly(0);
          done();
        });
      });
    });
  });

  it("Can retrieve several objects at once", function(done) {
    var times = 5;
    async.times(times, function(n, next) {
      var mdl = new TestModel();
      mdl.save(function(err, res) {
        if (err) done(err);

        next(err, mdl.id);
      });
    }, function(err, ids) {
      TestModel.get(ids, function(err, res) {
        if (err) done(err);

        res.length.should.be.exactly(times);
        for (var i = 0; i < ids.length; i++) {
          res[i].id.should.be.exactly(ids[i]);
        }
        done();
      });
    });
  });

  it("Can enumerate keys", function(done) {
    var times = 5;
    async.times(times, function(n, next) {
      var mdl = new TestModel();
      mdl.save(function(err, res) {
        if (err) done(err);
        next(err, mdl.id);
      });
    }, function(err, ids) {
      TestModel.all(function(err, res) {
        if (err) done(err);

        res.length.should.be.exactly(times);
        for (var i = 0 ; i < ids.length; i++) {
          res.indexOf(ids[i]).should.not.eql(-1);
        }

        done();
      });
    });
  });

  it("Catches missing argument to getter", function(done) {
    TestModel.get(undefined, function(err, res) {
      err.should.not.be.null;
    }).then(function(result) {
      done("Result not expected")
    }, function(error) {
      done();
    });
  });
});
<commit_msg>Add a regression test against the expected structure.<commit_after>var async = require('async');
var should = require('should');
var client = require('fakeredis').createClient(null, null, {fast: true});
var rhom = require('../index.js');

function TestModel() {}
TestModel.properties = ['foo', 'bar'];
rhom(TestModel, TestModel.properties, client);

describe("Model utility functions", function() {
  it("generates seqential identifiers", function() {
    var seq1 = rhom.model.sequence();
    seq1().should.be.exactly("0");
    seq1().should.be.exactly("1");

    var seq2 = rhom.model.sequence();
    seq2().should.be.exactly("0");
    seq2().should.be.exactly("1");
    seq1().should.be.exactly("2");
  });

  it("generate UUIDs by default", function() {
    (typeof TestModel._mdl.idgen()).should.be.exactly("string");
    TestModel._mdl.idgen().should.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);
  });
});

describe("Model class", function(done) {
  beforeEach(function(done) {
    TestModel.purge(done);
  });

  it("has expected static methods", function() {
    (typeof TestModel.get).should.be.exactly("function");
    (typeof TestModel._mdl.idgen).should.be.exactly("function");
    (typeof TestModel.getKey).should.be.exactly("function");
  });

  it("has expected instance methods", function() {
    var test = new TestModel();
    (typeof test.save).should.be.exactly("function");
    (typeof test.toObject).should.be.exactly("function");
  });

  it("(C)reates objects as redis hashes", function(done) {
    var test = new TestModel();
    test.foo = "test one";
    test.bar = 234;
    test.save(function(err, res) {
      if (err) done(err);

      res.should.be.true;

      client.hgetall(TestModel.getKey(test.id), function(err, res) {
        if (err) done(err);

        res.foo.should.be.exactly(test.foo);
        res.bar.should.be.exactly(String(test.bar));
        res.should.not.be.eql(test);
        done();
      });
    }).then(function(result) {
      // Don't need to re-test the result, just that the callback and promise return the same thing.
      result.should.be.true;
    }, function(error) {
      done(error);
    });
  });

  it("(R)etrieves saved objects", function(done) {
    var test = new TestModel();
    test.foo = "test one two three";
    test.bar = 23456;
    test.save(function(err) {
      if (err) done(err);

      TestModel.get(test.id, function(err, res) {
        if (err) done(err);
        res.id.should.be.exactly(test.id);
        res.foo.should.be.exactly(test.foo);
        res.bar.should.be.exactly(String(test.bar));
        done();
      }).then(function(res) {
        res.id.should.be.exactly(test.id);
        res.foo.should.be.exactly(test.foo);
        res.bar.should.be.exactly(String(test.bar));
      }, function(error) {
        done(error);
      });
    });
  });

  it("(U)pdates objects", function(done) {
    var test = new TestModel();
    test.foo = "First save";
    test.save(function(err) {
      if (err) done(err);

      test.foo = "Updated value";
      test.save(function(err) {
        if (err) done(err);

        TestModel.get(test.id, function(err, res) {
          if (err) done(err);
          res.id.should.be.exactly(test.id);
          res.foo.should.be.exactly(test.foo);
          done();
        });
      });
    });
  });

  it("(D)eletes objects", function(done) {
    test = new TestModel();
    test.save(function(err) {
      if (err) done(err);

      test.delete(function(err) {
        if (err) done(err);
        var m = client.multi();
        var k = TestModel.getKey(test.id);
        m.hgetall(k);
        m.sismember(TestModel.getKey('all'), k);

        m.exec(function(err, res) {
          if (err) done(err);
          should(res[0]).be.exactly(null);
          res[1].should.be.exactly(0);
          done();
        });
      });
    });
  });

  it("Can retrieve several objects at once", function(done) {
    var times = 5;
    async.times(times, function(n, next) {
      var mdl = new TestModel();
      mdl.save(function(err, res) {
        if (err) done(err);

        next(err, mdl.id);
      });
    }, function(err, ids) {
      TestModel.get(ids, function(err, res) {
        if (err) done(err);

        res.length.should.be.exactly(times);
        for (var i = 0; i < ids.length; i++) {
          res[i].id.should.be.exactly(ids[i]);
        }
        done();
      });
    });
  });

  it("Can enumerate keys", function(done) {
    var times = 5;
    async.times(times, function(n, next) {
      var mdl = new TestModel();
      mdl.save(function(err, res) {
        if (err) done(err);
        next(err, mdl.id);
      });
    }, function(err, ids) {
      TestModel.all(function(err, res) {
        if (err) done(err);

        res.length.should.be.exactly(times);
        for (var i = 0 ; i < ids.length; i++) {
          res.indexOf(ids[i]).should.not.eql(-1);
        }

        done();
      });
    });
  });

  /* Regression test */
  it("Catches missing argument to getter", function(done) {
    TestModel.get(undefined, function(err, res) {
      err.should.not.be.null;
    }).then(function(result) {
      done("Result not expected")
    }, function(error) {
      done();
    });
  });

  /* Regression test: add a bunch of objects and test the structure manually.  */
  it("Generates expected structure in redis", function(done) {
    var t1 = new TestModel();
    t1.id = "t1";
    t1.foo = "t1-foo";
    t1.bar = "t2-bar";

    var t2 = new TestModel();
    t2.id = "t2";
    t2.foo = "t2_foo";
    t2.bar = "t2_bar";

    async.parallel(
      [
        function(cb) { t1.save(cb); },
        function(cb) { t2.save(cb); }
      ],
      function(err, res) {
        client.getKeyspace({map: true}, function(err, res) {
          res.should.be.eql({
            'TestModel:all': [ 't1', 't2' ],
            'TestModel:t1': [ 'bar', 't2-bar', 'foo', 't1-foo' ],
            'TestModel:t2': [ 'bar', 't2_bar', 'foo', 't2_foo' ]
          });
          done();
        });
      }
    );
  });
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  /*
   * Include grunt configuration
   */
  var gruntConfig = require( './config/grunt.conf.js' );

  /*
   * Helpers (preparing for grunt util deprecation)
   */
  var glob = require('glob');

  /*
   * Time grunt execution
   */
  require('time-grunt')(grunt);

  /*
   * JIT Grunt will automatically load other npm tasks
   */
  require('jit-grunt')(grunt);
  grunt.loadNpmTasks('grunt-protractor-runner');

  /*
   * Configuration
   */
  var gruntTasks = {
    //////////////
    pkg: grunt.file.readJSON('package.json'),
    /*
     * Placed at the top of the compiled source files.
     */
    meta: {
      banner:
        '/*\n' +
        ' * <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
        ' * <%= pkg.repository.url %>\n' +
        ' *\n' +
        ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
        ' * Licensed <%= pkg.licenses.type %> <<%= pkg.licenses.url %>>\n' +
        ' */\n'
    },
    //////////////
    shell: {
      dev_server: {
        command: './server/build-server.sh'
      },
      prod_server: {
        command: './server/production-server.sh'
      },
      run_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager start'
      },
      update_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager update'
      }
    },
    //////////////
    copy: {
      build_app_js: {
        src: [
          findModuleFilesIn('./src/app/'),
          findModuleFilesIn('./src/common/')
        ],
        dest: '<%= build_dir %>'
      },
      build_app_data: {
        src: ['./src/app/**/*.json'],
        dest: '<%= build_dir %>/data/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_unit: {
        src: ['./src/**/*.spec.js'],
        dest: '<%= build_dir %>'
      },
      build_vendor_js: {
        src: ['<%= build.vendor_js %>'],
        dest: '<%= build_dir %>'
      },
      build_views: {
        cwd: './src',
        src: ['app/**/*.html', '!app/shared/**/*.html'],
        dest: '<%= build_dir %>/views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_shared_views: {
        cwd: './src',
        src: ['app/shared/**/*.html'],
        dest: '<%= build_dir %>/shared-views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= build_dir %>',
        expand: true,
        options: {
          process: processBuildScripts
        }
      },
      build_assets: {
        cwd: './src/assets',
        src: [
          'img/**/*',
          'fonts/**/*',
          '!**/*.less',
          '!**/*.css'
        ],
        dest: '<%= build_dir %>src/assets/',
        expand: true
      },
      build_fonts: {
        src: ['<%= common.vendor_fonts %>'],
        dest: '<%= build_dir %>src/assets/fonts/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_karma: {
        src: ['./config/karma.conf.js'],
        dest: '<%= build_dir %>',
        options: {
          process: processBuildScripts
        }
      },
      build_protractor: {
        cwd: './src',
        src: ['**/*.protractor.js', '**/*.e2e.js'],
        dest: '<%= build_dir %>src/e2e/',
        expand: true,
        flatten: true
      },
      compile_app_data: {
        cwd: '<%= build_dir %>',
        src: ['data/*.json'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_views: {
        cwd: '<%= build_dir %>',
        src: ['views/**/*.html'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= compile_dir %>',
        expand: true,
        options: {
          process: function processCompileIndex(content){
            return grunt.template.process(content);
          }
        }
      },
      compile_app_assets: {
        cwd: '<%= build_dir %>',
        src: ['src/assets/**/*', '!src/assets/**/*.md'],
        dest: '<%= compile_dir %>',
        expand: true
      }
    },
    /////////////////
    clean: {
      build_clean: ['<%= build_dir %>'],
      build_css_clean: ['<%= build_dir %>/src/assets/css/app.custom.css'],
      compile_js_clean: ['<%= compile_dir %>/src/app/modules.min.js'],
      compile_shared_views_clean: ['<%= compile_dir %>/shared-views/']
    },
    /////////////////
    less: {
      build_less: {
        src: ['./src/assets/**/*.less'],
        dest: '<%= build_dir %>/src/assets/css/app.custom.css',
        options: {
          cleancss: true,
          compress: true
        }
      }
    },
    /////////////////
    cssmin: {
      build_css: {
        src: [
          '<%= build.vendor_css %>',
          './src/assets/**/*.css',
          '<%= build_dir %>/src/assets/css/app.custom.css'
        ],
        dest: '<%= build_dir %>/src/assets/css/app.min.css'
      }
    },
    /////////////////
    uglify: {
      compile_module_js: {
        options: {
          wrap: 'moduleExports',
          mangle: {
            except: ['exceptionLoggingService']
          }
        },
        src: [
          '<%= compile.vendor_js %>',
          findModuleFilesIn('./build/src/app/'),
          findModuleFilesIn('./build/src/common/')
        ],
        dest: '<%= compile_dir %>/src/app/modules.min.js'
      },
      compile_cleanup: {
        options: {
          beautify: true,
          mangle: false
        },
        src: ['<%= compile_dir %>/src/app/app.min.js'],
        dest: '<%= compile_dir %>/src/app/app.min.js'
      }
    },
    /////////////////
    concat: {
      compile_js: {
        src: [
          '<%= compile.vendor_min_js %>',
          '<%= compile_dir %>/src/app/modules.min.js',
          '<%= compile_dir %>/shared-views/views.min.js'
        ],
        dest: '<%= compile_dir %>/src/app/app.min.js'
      }
    },
    /////////////////
    html2js: {
      options: {
        htmlmin: {
          collapseBooleanAttributes: false,
          collapseWhitespace: true,
          removeAttributeQuotes: false,
          removeComments: true,
          removeEmptyAttributes: false,
          removeRedundantAttributes: true,
          removeScriptTypeAttributes: true,
          removeStyleLinkTypeAttributes: true
        }
      },
      compile_shared_views: {
        src: ['<%= build_dir %>/shared-views/**/*.html'],
        dest: '<%= compile_dir %>/shared-views/views.min.js',
        options: {
          module: 'sharedViewsModule',
          base: './build',
          singleModule: true
        }
      }
    },
    /////////////////
    jshint: {
      options: {
        jshintrc: true
      },
      src_js: ['./src/**/*.js'],
      gruntfiles: ['./gruntfile.js', 'grunt.conf.js']
    },
    /////////////////
    karma: {
      options: {
        configFile: '<%= build_dir %>/config/karma.conf.js'
      },
      unit: {
        port: 9191,
        background: false
      },
      continuous: {
        singleRun: false,
        autoWatch: true
      }
    },
    /////////////////
    protractor: {
      options: {
        keepAlive: true, // If false, the grunt process stops when the test fails.
        noColor: false, // If true, protractor will not use colors in its output.
        args: {}
      },
      build: {
        options: {
          configFile: './config/protractor.conf.js', // Default config file
        }
      },
      ci_dev: {
        options: {
          configFile: './config/protractor-ci.conf.js'
        }
      },
      ci_prod: {
        options: {
          configFile: './config/protractor-ci-prod.conf.js'
        }
      }
    },
    /////////////////
    watch: {
      options: {
        livereload: true
      },
      src_js: {
        files: ['./src/**/*.js', './src/**/*.json'],
        tasks: ['newer:jshint:src_js', 'newer:copy:build_app_js']
      },
      src_html: {
        files: ['./src/**/*.html', '!./src/index.html'],
        tasks: ['newer:copy:build_views']
      },
      src_index: {
        files: ['./src/index.html'],
        tasks: ['copy:build_index']
      },
      src_stylesheets: {
        files: ['./src/assets/**/*.less', './src/assets/**/*.css'],
        tasks: ['newer:less:build_less', 'cssmin:build_css', 'clean:build_css_clean']
      },
      src_assets: {
        files: ['./src/assets/**/*', '!./src/assets/**/*.less', '!./src/assets/**/*.css'],
        tasks: ['newer:copy:build_assets']
      },
      gruntfiles: {
        files: ['./gruntfile.js', 'grunt.conf.js'],
        tasks: ['newer:jshint:gruntfiles'],
        options: {
          livereload: false
        }
      },
      tests: {
        files: ['src/**/*.spec.js', 'src/**/*.e2e.js', 'src/**/*.protractor.js'],
        tasks: ['newer:copy:build_karma', 'newer:copy:build_unit', 'newer:copy:build_protractor']
      }
    }
  };

  /////////////////
  grunt.initConfig(
    grunt.util._.extend(gruntTasks, gruntConfig)
  );

  /*
   * Helpers
   */
   /////////////////
  function findModuleFilesIn(modulePath){
    var output = [],
        i;

    for(i = 0; i <= gruntConfig.module_file_order.length-1; i++){
      output.push(modulePath + gruntConfig.module_file_order[i]);
    }

    return output;
  }

  //////////////
  function processBuildScripts(content){
    var buildScripts = [],
        globFiles,
        customModules = gruntConfig.build.vendor_js
                        .concat(findModuleFilesIn('./src/app/'))
                        .concat(findModuleFilesIn('./src/common/'));

    customModules.forEach(function(module){
      globFiles = glob.sync(module);

      if(globFiles.length > 0){
        buildScripts = buildScripts.concat(globFiles);
      }
    });

    return grunt.template.process(content, {
      data: {
        scripts: buildScripts
      }
    });
  }

  /*
   * Tasks
   */
  grunt.registerTask('default', ['jshint', 'build', 'karma:unit', 'watch']);
  grunt.registerTask('build', [
    'copy:build_app_js',
    'copy:build_app_data',
    'copy:build_vendor_js',
    'copy:build_views',
    'copy:build_shared_views',
    'copy:build_fonts',
    'copy:build_index',
    'copy:build_unit',
    'copy:build_protractor',
    'copy:build_karma',
    'copy:build_assets',
    'less:build_less',
    'cssmin:build_css',
    'clean:build_css_clean'
  ]);
  grunt.registerTask('compile', [
    'clean:build_clean',
    'build',
    'copy:compile_views',
    'html2js:compile_shared_views',
    'uglify:compile_module_js',
    'concat:compile_js',
    'uglify:compile_cleanup',
    'clean:compile_js_clean',
    'clean:compile_shared_views_clean',
    'copy:compile_app_data',
    'copy:compile_app_assets',
    'copy:compile_index'
  ]);
  grunt.registerTask('test', ['karma:unit', 'protractor:build']);
  grunt.registerTask('test:unit', ['karma:unit']);
  grunt.registerTask('test:ci', ['karma:unit', 'protractor:ci_dev', 'protractor:ci_prod']);
  grunt.registerTask('test:e2e', ['protractor:build']);
};<commit_msg>removed 'beautify' from grunt compile_cleanup<commit_after>module.exports = function(grunt) {
  /*
   * Include grunt configuration
   */
  var gruntConfig = require( './config/grunt.conf.js' );

  /*
   * Helpers (preparing for grunt util deprecation)
   */
  var glob = require('glob');

  /*
   * Time grunt execution
   */
  require('time-grunt')(grunt);

  /*
   * JIT Grunt will automatically load other npm tasks
   */
  require('jit-grunt')(grunt);
  grunt.loadNpmTasks('grunt-protractor-runner');

  /*
   * Configuration
   */
  var gruntTasks = {
    //////////////
    pkg: grunt.file.readJSON('package.json'),
    /*
     * Placed at the top of the compiled source files.
     */
    meta: {
      banner:
        '/*\n' +
        ' * <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
        ' * <%= pkg.repository.url %>\n' +
        ' *\n' +
        ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
        ' * Licensed <%= pkg.licenses.type %> <<%= pkg.licenses.url %>>\n' +
        ' */\n'
    },
    //////////////
    shell: {
      dev_server: {
        command: './server/build-server.sh'
      },
      prod_server: {
        command: './server/production-server.sh'
      },
      run_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager start'
      },
      update_selenium: {
        command: './node_modules/protractor/bin/webdriver-manager update'
      }
    },
    //////////////
    copy: {
      build_app_js: {
        src: [
          findModuleFilesIn('./src/app/'),
          findModuleFilesIn('./src/common/')
        ],
        dest: '<%= build_dir %>'
      },
      build_app_data: {
        src: ['./src/app/**/*.json'],
        dest: '<%= build_dir %>/data/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_unit: {
        src: ['./src/**/*.spec.js'],
        dest: '<%= build_dir %>'
      },
      build_vendor_js: {
        src: ['<%= build.vendor_js %>'],
        dest: '<%= build_dir %>'
      },
      build_views: {
        cwd: './src',
        src: ['app/**/*.html', '!app/shared/**/*.html'],
        dest: '<%= build_dir %>/views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_shared_views: {
        cwd: './src',
        src: ['app/shared/**/*.html'],
        dest: '<%= build_dir %>/shared-views/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= build_dir %>',
        expand: true,
        options: {
          process: processBuildScripts
        }
      },
      build_assets: {
        cwd: './src/assets',
        src: [
          'img/**/*',
          'fonts/**/*',
          '!**/*.less',
          '!**/*.css'
        ],
        dest: '<%= build_dir %>src/assets/',
        expand: true
      },
      build_fonts: {
        src: ['<%= common.vendor_fonts %>'],
        dest: '<%= build_dir %>src/assets/fonts/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      build_karma: {
        src: ['./config/karma.conf.js'],
        dest: '<%= build_dir %>',
        options: {
          process: processBuildScripts
        }
      },
      build_protractor: {
        cwd: './src',
        src: ['**/*.protractor.js', '**/*.e2e.js'],
        dest: '<%= build_dir %>src/e2e/',
        expand: true,
        flatten: true
      },
      compile_app_data: {
        cwd: '<%= build_dir %>',
        src: ['data/*.json'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_views: {
        cwd: '<%= build_dir %>',
        src: ['views/**/*.html'],
        dest: '<%= compile_dir %>',
        expand: true
      },
      compile_index: {
        cwd: './src',
        src: ['index.html'],
        dest: '<%= compile_dir %>',
        expand: true,
        options: {
          process: function processCompileIndex(content){
            return grunt.template.process(content);
          }
        }
      },
      compile_app_assets: {
        cwd: '<%= build_dir %>',
        src: ['src/assets/**/*', '!src/assets/**/*.md'],
        dest: '<%= compile_dir %>',
        expand: true
      }
    },
    /////////////////
    clean: {
      build_clean: ['<%= build_dir %>'],
      build_css_clean: ['<%= build_dir %>/src/assets/css/app.custom.css'],
      compile_js_clean: ['<%= compile_dir %>/src/app/modules.min.js'],
      compile_shared_views_clean: ['<%= compile_dir %>/shared-views/']
    },
    /////////////////
    less: {
      build_less: {
        src: ['./src/assets/**/*.less'],
        dest: '<%= build_dir %>/src/assets/css/app.custom.css',
        options: {
          cleancss: true,
          compress: true
        }
      }
    },
    /////////////////
    cssmin: {
      build_css: {
        src: [
          '<%= build.vendor_css %>',
          './src/assets/**/*.css',
          '<%= build_dir %>/src/assets/css/app.custom.css'
        ],
        dest: '<%= build_dir %>/src/assets/css/app.min.css'
      }
    },
    /////////////////
    uglify: {
      compile_module_js: {
        options: {
          wrap: 'moduleExports',
          mangle: {
            except: ['exceptionLoggingService']
          }
        },
        src: [
          '<%= compile.vendor_js %>',
          findModuleFilesIn('./build/src/app/'),
          findModuleFilesIn('./build/src/common/')
        ],
        dest: '<%= compile_dir %>/src/app/modules.min.js'
      },
      compile_cleanup: {
        options: {
          mangle: false
        },
        src: ['<%= compile_dir %>/src/app/app.min.js'],
        dest: '<%= compile_dir %>/src/app/app.min.js'
      }
    },
    /////////////////
    concat: {
      compile_js: {
        src: [
          '<%= compile.vendor_min_js %>',
          '<%= compile_dir %>/src/app/modules.min.js',
          '<%= compile_dir %>/shared-views/views.min.js'
        ],
        dest: '<%= compile_dir %>/src/app/app.min.js'
      }
    },
    /////////////////
    html2js: {
      options: {
        htmlmin: {
          collapseBooleanAttributes: false,
          collapseWhitespace: true,
          removeAttributeQuotes: false,
          removeComments: true,
          removeEmptyAttributes: false,
          removeRedundantAttributes: true,
          removeScriptTypeAttributes: true,
          removeStyleLinkTypeAttributes: true
        }
      },
      compile_shared_views: {
        src: ['<%= build_dir %>/shared-views/**/*.html'],
        dest: '<%= compile_dir %>/shared-views/views.min.js',
        options: {
          module: 'sharedViewsModule',
          base: './build',
          singleModule: true
        }
      }
    },
    /////////////////
    jshint: {
      options: {
        jshintrc: true
      },
      src_js: ['./src/**/*.js'],
      gruntfiles: ['./gruntfile.js', 'grunt.conf.js']
    },
    /////////////////
    karma: {
      options: {
        configFile: '<%= build_dir %>/config/karma.conf.js'
      },
      unit: {
        port: 9191,
        background: false
      },
      continuous: {
        singleRun: false,
        autoWatch: true
      }
    },
    /////////////////
    protractor: {
      options: {
        keepAlive: true, // If false, the grunt process stops when the test fails.
        noColor: false, // If true, protractor will not use colors in its output.
        args: {}
      },
      build: {
        options: {
          configFile: './config/protractor.conf.js', // Default config file
        }
      },
      ci_dev: {
        options: {
          configFile: './config/protractor-ci.conf.js'
        }
      },
      ci_prod: {
        options: {
          configFile: './config/protractor-ci-prod.conf.js'
        }
      }
    },
    /////////////////
    watch: {
      options: {
        livereload: true
      },
      src_js: {
        files: ['./src/**/*.js', './src/**/*.json'],
        tasks: ['newer:jshint:src_js', 'newer:copy:build_app_js']
      },
      src_html: {
        files: ['./src/**/*.html', '!./src/index.html'],
        tasks: ['newer:copy:build_views']
      },
      src_index: {
        files: ['./src/index.html'],
        tasks: ['copy:build_index']
      },
      src_stylesheets: {
        files: ['./src/assets/**/*.less', './src/assets/**/*.css'],
        tasks: ['newer:less:build_less', 'cssmin:build_css', 'clean:build_css_clean']
      },
      src_assets: {
        files: ['./src/assets/**/*', '!./src/assets/**/*.less', '!./src/assets/**/*.css'],
        tasks: ['newer:copy:build_assets']
      },
      gruntfiles: {
        files: ['./gruntfile.js', 'grunt.conf.js'],
        tasks: ['newer:jshint:gruntfiles'],
        options: {
          livereload: false
        }
      },
      tests: {
        files: ['src/**/*.spec.js', 'src/**/*.e2e.js', 'src/**/*.protractor.js'],
        tasks: ['newer:copy:build_karma', 'newer:copy:build_unit', 'newer:copy:build_protractor']
      }
    }
  };

  /////////////////
  grunt.initConfig(
    grunt.util._.extend(gruntTasks, gruntConfig)
  );

  /*
   * Helpers
   */
   /////////////////
  function findModuleFilesIn(modulePath){
    var output = [],
        i;

    for(i = 0; i <= gruntConfig.module_file_order.length-1; i++){
      output.push(modulePath + gruntConfig.module_file_order[i]);
    }

    return output;
  }

  //////////////
  function processBuildScripts(content){
    var buildScripts = [],
        globFiles,
        customModules = gruntConfig.build.vendor_js
                        .concat(findModuleFilesIn('./src/app/'))
                        .concat(findModuleFilesIn('./src/common/'));

    customModules.forEach(function(module){
      globFiles = glob.sync(module);

      if(globFiles.length > 0){
        buildScripts = buildScripts.concat(globFiles);
      }
    });

    return grunt.template.process(content, {
      data: {
        scripts: buildScripts
      }
    });
  }

  /*
   * Tasks
   */
  grunt.registerTask('default', ['jshint', 'build', 'karma:unit', 'watch']);
  grunt.registerTask('build', [
    'copy:build_app_js',
    'copy:build_app_data',
    'copy:build_vendor_js',
    'copy:build_views',
    'copy:build_shared_views',
    'copy:build_fonts',
    'copy:build_index',
    'copy:build_unit',
    'copy:build_protractor',
    'copy:build_karma',
    'copy:build_assets',
    'less:build_less',
    'cssmin:build_css',
    'clean:build_css_clean'
  ]);
  grunt.registerTask('compile', [
    'clean:build_clean',
    'build',
    'copy:compile_views',
    'html2js:compile_shared_views',
    'uglify:compile_module_js',
    'concat:compile_js',
    'uglify:compile_cleanup',
    'clean:compile_js_clean',
    'clean:compile_shared_views_clean',
    'copy:compile_app_data',
    'copy:compile_app_assets',
    'copy:compile_index'
  ]);
  grunt.registerTask('test', ['karma:unit', 'protractor:build']);
  grunt.registerTask('test:unit', ['karma:unit']);
  grunt.registerTask('test:ci', ['karma:unit', 'protractor:ci_dev', 'protractor:ci_prod']);
  grunt.registerTask('test:e2e', ['protractor:build']);
};<|endoftext|>


<commit_before>'use strict';

module.exports = function(grunt) {

    var path = require("path")

// Generate a config predefined AppCache file
// ---------
    grunt.registerMultiTask("phantomizer-manifest", "Builds manifest file", function () {

        var options = this.options({
            manifest_file:"",
            version:(new Date().getTime()),
            cache:[],
            network:[],
            fallback:[]
        })
        var content = generate_appcache_content(options.version,options.cache,options.network,options.fallback);
        grunt.file.write(options.manifest_file,content)
        grunt.log.ok("AppCache file wrote "+manifest_file)
    });

// Generate an AppCache file and insert it into the DOM
// ---------
    grunt.registerMultiTask("phantomizer-manifest-html",
        "Builds manifest file given an html file", function () {

        var ph_libutil = require("phantomizer-libutil");
        var _ = grunt.util._;
        var meta_factory = ph_libutil.meta;

        var options = this.options({
            in_file:'',
            out_file:'',

            meta_file:'',
            meta_dir:'<%= meta_dir %>',
            project_dir:'<%= project_dir %>',

            manifest_file:'',
            manifest_meta:'',
            manifest_url:'',
            manifest_reloader:'<%= manifest_reloader %>',

            base_url:'/',
            src_paths:'<%= paths %>',
            version:""+(new Date().getTime()),
            cache:[],
            network:[],
            fallback:[]
        });

        var in_file = options.in_file;
        var out_file = options.out_file;
        var meta_dir = options.meta_dir;
        var meta_file = options.meta_file;
        var project_dir = options.project_dir;
        var base_url = options.base_url;
        var manifest_file = options.manifest_file;
        var manifest_meta = options.manifest_meta;
        var manifest_url = options.manifest_url;
        var maninfest_reloader = options.manifest_reloader;
        var paths = options.src_paths;
        var version = options.version;
        var cache = options.cache;
        var network = options.network;
        var fallback = options.fallback;

        var meta_manager = new meta_factory( process.cwd(), meta_dir );

        var current_grunt_task  = this.nameArgs;
        var current_grunt_opt   = this.options();

        if( meta_manager.is_fresh(meta_file, current_grunt_task) == false ){

            var html_content = grunt.file.read(in_file);

            var html_entry = meta_manager.load(meta_file);
            var appcache_entry = meta_manager.create([])

// lookup for assets within html content
            var file_assets = lookup_for_assets(html_content, base_url, paths);

// dispatch assets into AppCache / HTML, cache dependencies
            for( var n in file_assets ){
                var file_path = file_assets[n];
                cache.push(file_path)
                var a_file_path = must_find_in_paths(paths, file_path)
                if( a_file_path != false ){
                    if( meta_manager.has(file_path) ){
                        var e = meta_manager.load(file_path);
                        appcache_entry.load_dependencies(e.dependences)
                        html_entry.load_dependencies(e.dependences)
                    }
                    appcache_entry.load_dependencies([a_file_path])
                    html_entry.load_dependencies([a_file_path])
                }
            }

// generate and write AppCache file
            var manifest_content = generate_appcache_content(version,cache,network,fallback);
            grunt.file.write(manifest_file,manifest_content);
            grunt.log.ok("AppCache file wrote "+manifest_file);

// include appcache and manifest reloader within html content
            var reloader = grunt.file.read(maninfest_reloader);
            html_content = html_content.replace(/<body([^>]+)?>/gi, "<body$1><script type='text/javascript'>"+reloader+"</script>")
            html_content = html_content.replace("<html", "<html manifest=\""+manifest_url+"\"")
            grunt.file.write(out_file, html_content);
            grunt.log.ok("HTML file wrote "+out_file);

// create AppCache meta
            appcache_entry.load_dependencies([
                process.cwd()+"/Gruntfile.js",
                project_dir+"/../config.json",
                __filename,
                in_file])
            appcache_entry.require_task(current_grunt_task, current_grunt_opt)
            appcache_entry.save(manifest_meta)

// create HTML meta
            html_entry.load_dependencies(appcache_entry.dependencies)
            html_entry.require_task(current_grunt_task, current_grunt_opt)
            html_entry.save(meta_file)

            grunt.log.ok("Manifest done "+manifest_url);

        }else{
            grunt.log.ok("Manifest fresh "+manifest_url);
        }

    });

// Generate an AppCache file and insert it into the DOM
// ---------
    //-
    var ph_libutil  = require("phantomizer-libutil");
    var fs          = require("fs");

    var router_factory    = ph_libutil.router;
    grunt.registerMultiTask("phantomizer-project-manifest",
        "Builds manifest files for an entire phantomizer project", function () {

            var options = this.options({
                target_path:"export/",
                appcache_extension:".appcache",
                base_url:"/",
                // one_for_all|one_for_each
                mode:"one_for_all",
                min_occurence_count:2,

                manifest_reloader:'<%= manifest_reloader %>',

                version:""+(new Date().getTime()),
                cache:[],
                network:[],
                fallback:[]
            });
            var config = grunt.config();

            var router = new router_factory(config.routing);
            router.load(function(){

                var urls = router.collect_urls();

//
                var pages = {};
                var assets = {};
                for( var n in urls ){
                    var url = urls[n];
                    var in_file = options.target_path + url;
                    if( grunt.file.exists( in_file ) ){
                        var html_content = grunt.file.read(in_file);
                        var page_assets = lookup_for_assets(html_content, options.base_url, options.target_path);
                        for(var t in page_assets ){
                            var page_asset = page_assets[t];
                            if( !assets[page_asset] ){
                                assets[page_asset] = {
                                    ocurence_count:0,
                                    ocurence_urls:[]
                                }
                            }
                            assets[page_asset].ocurence_count++;
                            assets[page_asset].ocurence_urls.push(url);
                        }

                        pages[url] = {
                            file:in_file,
                            assets:page_assets
                        };
                    }
                }

                var reloader = "";
                if( options.maninfest_reloader ){
                    if( grunt.file.exists(options.maninfest_reloader) ){
                        reloader = grunt.file.read(options.maninfest_reloader);
                    }else if( options.maninfest_reloader != "" ){
                        reloader = options.maninfest_reloader;
                    }
                }

//
                if( options.mode == "one_for_each" ){
                    for( var page_url in pages ){
                        var page_assets = pages[page_url].assets;
                        var html_file = pages[page_url].file;

//
                        var cache = [];
                        for( var n in options.cache ){
                            cache.push(options.cache[n]);
                        }
                        for( var n in page_assets ){
                            cache.push(page_assets[n]);
                        }

// generate and write AppCache file
                        var manifest_file = html_file.replace(/[.](htm|html)$/,options.appcache_extension);
                        var manifest_content = generate_appcache_content(options.version,
                            cache,options.network,options.fallback);
                        grunt.file.write(manifest_file, manifest_content);

                        var html_content = grunt.file.read(html_file);
// load appcache and manifest reloader within html content
                        var manifest_url = manifest_file.replace(options.target_path,"");
                        manifest_url = manifest_url.substr(0,1)=="/"?manifest_url:"/"+manifest_url;
                        html_content = html_content.replace("<html",
                            "<html manifest=\""+manifest_url+"\"")

// insert appcache reloader
                        if( reloader != "" ){
                            html_content = html_content.replace(/<body([^>]+)?>/gi,
                                "<body$1><script type='text/javascript'>"+reloader+"</script>");
                        }
                        grunt.file.write(html_file, html_content);
                    }
                }

//
                if( options.mode == "one_for_all" ){

                    var manifest_url = "/manifest"+options.appcache_extension;
                    var manifest_file = options.target_path+manifest_url;

                    for( var page_url in pages ){
                        var page_assets = pages[page_url].assets;
                        var html_file = pages[page_url].file;

//
                        var cache = [];
                        for( var n in options.cache ){
                            cache.push(options.cache[n]);
                        }
                        for( var n in page_assets ){
                            var page_asset = page_assets[n];
                            if( assets[page_asset].ocurence_urls.length >= options.min_occurence_count ){
                                cache.push(page_asset);
                            }
                        }

                        var html_content = grunt.file.read(html_file);
// load appcache and manifest reloader within html content
                        html_content = html_content.replace("<html",
                            "<html manifest=\""+manifest_url+"\"");

// insert appcache reloader
                        if( reloader != "" ){
                            html_content = html_content.replace(/<body([^>]+)?>/gi,
                                "<body$1><script type='text/javascript'>"+reloader+"</script>");
                        }
                        grunt.file.write(html_file, html_content);
                    }

// generate and write AppCache file
                    var manifest_content = generate_appcache_content(options.version,
                        cache,options.network,options.fallback);
                    grunt.file.write(manifest_file, manifest_content);
                }

            })
            grunt.log.ok();
        });

// helpers function
// ---------
    function generate_appcache_content(version,cache,network,fallback){
        var content = "";
        content += "CACHE MANIFEST" + "\n"
        content += "# version::" + version + "\n"
        content += "CACHE:" + "\n"
        for( var n in cache )
            content += cache[n]+ "\n"
        content += "NETWORK:" + "\n"
        for( var n in network )
            content += network[n]+ "\n"
        content += "FALLBACK:" + "\n"
        for( var n in fallback )
            content += fallback[n].ok+ " "+fallback[n].ko + "\n";

        return content;
    }
    function must_find_in_paths(paths, src){
        var retour = find_in_paths(paths, src)
        if( retour == false ){
            grunt.log.error("File not found : "+src)
        }
        return retour
    }

    function find_in_paths(paths, src){
        for( var t in paths ){
            if( grunt.file.exists(paths[t]+src) ){
                return path.resolve(paths[t]+src)
            }
        }
        return false
    }

// look up for absolute url of assets within html content
    function lookup_for_assets(html_content, base_url, paths){

        var html_utils = ph_libutil.html_utils;

        var retour = [];

// look up for <link> nodes
        var nodes = html_utils.find_link_nodes(html_content, base_url)
        for( var n in nodes ){
            if( find_in_paths(paths,nodes[n].asrc) ){
                retour.push(nodes[n].asrc)
            }
        }

// look up for css / img imports within <styles> nodes
        nodes = html_utils.find_style_nodes(html_content, base_url)
        for( var n in nodes ){
            var node = nodes[n]
            for( var k in node.imports ){
                if( find_in_paths(paths,node.imports[k].asrc) ){
                    retour.push(node.imports[k].asrc)
                }
            }
            for( var k in node.imgs ){
                if( find_in_paths(paths,node.imgs[k].asrc) ){
                    retour.push(node.imgs[k].asrc)
                }
            }
        }

// look up for <script data-main> nodes
        nodes = html_utils.find_rjs_nodes(html_content, base_url)
        for( var n in nodes ){
            if( find_in_paths(paths,nodes[n].asrc) ){
                retour.push(nodes[n].asrc)
            }s
        }

// look up for <script> nodes
        nodes = html_utils.find_scripts_nodes(html_content, base_url)
        for( var n in nodes ){
            if( find_in_paths(paths,nodes[n].asrc) ){
                retour.push(nodes[n].asrc)
            }
        }

// look up for <img> nodes
        nodes = html_utils.find_img_nodes(html_content, base_url)
        for( var n in nodes ){
            if( find_in_paths(paths,nodes[n].asrc) ){
                retour.push(nodes[n].asrc)
            }
        }
        return retour;
    }

};<commit_msg>Code style<commit_after>'use strict';

module.exports = function(grunt) {

  var path = require("path")

// Generate a config predefined AppCache file
// ---------
  grunt.registerMultiTask("phantomizer-manifest", "Builds manifest file", function () {

    var options = this.options({
      manifest_file:"",
      version:(new Date().getTime()),
      cache:[],
      network:[],
      fallback:[]
    })
    var content = generate_appcache_content(options.version,options.cache,options.network,options.fallback);
    grunt.file.write(options.manifest_file,content)
    grunt.log.ok("AppCache file wrote "+manifest_file)
  });

// Generate an AppCache file and insert it into the DOM
// ---------
  grunt.registerMultiTask("phantomizer-manifest-html",
    "Builds manifest file given an html file", function () {

      var ph_libutil = require("phantomizer-libutil");
      var _ = grunt.util._;
      var meta_factory = ph_libutil.meta;

      var options = this.options({
        in_file:'',
        out_file:'',

        meta_file:'',
        meta_dir:'<%= meta_dir %>',
        project_dir:'<%= project_dir %>',

        manifest_file:'',
        manifest_meta:'',
        manifest_url:'',
        manifest_reloader:'<%= manifest_reloader %>',

        base_url:'/',
        src_paths:'<%= paths %>',
        version:""+(new Date().getTime()),
        cache:[],
        network:[],
        fallback:[]
      });

      var in_file = options.in_file;
      var out_file = options.out_file;
      var meta_dir = options.meta_dir;
      var meta_file = options.meta_file;
      var project_dir = options.project_dir;
      var base_url = options.base_url;
      var manifest_file = options.manifest_file;
      var manifest_meta = options.manifest_meta;
      var manifest_url = options.manifest_url;
      var maninfest_reloader = options.manifest_reloader;
      var paths = options.src_paths;
      var version = options.version;
      var cache = options.cache;
      var network = options.network;
      var fallback = options.fallback;

      var meta_manager = new meta_factory( process.cwd(), meta_dir );

      var current_grunt_task  = this.nameArgs;
      var current_grunt_opt   = this.options();

      if( meta_manager.is_fresh(meta_file, current_grunt_task) == false ){

        var html_content = grunt.file.read(in_file);

        var html_entry = meta_manager.load(meta_file);
        var appcache_entry = meta_manager.create([])

// lookup for assets within html content
        var file_assets = lookup_for_assets(html_content, base_url, paths);

// dispatch assets into AppCache / HTML, cache dependencies
        for( var n in file_assets ){
          var file_path = file_assets[n];
          cache.push(file_path)
          var a_file_path = must_find_in_paths(paths, file_path)
          if( a_file_path != false ){
            if( meta_manager.has(file_path) ){
              var e = meta_manager.load(file_path);
              appcache_entry.load_dependencies(e.dependences)
              html_entry.load_dependencies(e.dependences)
            }
            appcache_entry.load_dependencies([a_file_path])
            html_entry.load_dependencies([a_file_path])
          }
        }

// generate and write AppCache file
        var manifest_content = generate_appcache_content(version,cache,network,fallback);
        grunt.file.write(manifest_file,manifest_content);
        grunt.log.ok("AppCache file wrote "+manifest_file);

// include appcache and manifest reloader within html content
        var reloader = grunt.file.read(maninfest_reloader);
        html_content = html_content.replace(/<body([^>]+)?>/gi, "<body$1><script type='text/javascript'>"+reloader+"</script>")
        html_content = html_content.replace("<html", "<html manifest=\""+manifest_url+"\"")
        grunt.file.write(out_file, html_content);
        grunt.log.ok("HTML file wrote "+out_file);

// create AppCache meta
        appcache_entry.load_dependencies([
          process.cwd()+"/Gruntfile.js",
          project_dir+"/../config.json",
          __filename,
          in_file])
        appcache_entry.require_task(current_grunt_task, current_grunt_opt)
        appcache_entry.save(manifest_meta)

// create HTML meta
        html_entry.load_dependencies(appcache_entry.dependencies)
        html_entry.require_task(current_grunt_task, current_grunt_opt)
        html_entry.save(meta_file)

        grunt.log.ok("Manifest done "+manifest_url);

      }else{
        grunt.log.ok("Manifest fresh "+manifest_url);
      }

    });

// Generate an AppCache file and insert it into the DOM
// ---------
  //-
  var ph_libutil  = require("phantomizer-libutil");
  var fs          = require("fs");

  var router_factory    = ph_libutil.router;
  grunt.registerMultiTask("phantomizer-project-manifest",
    "Builds manifest files for an entire phantomizer project", function () {

      var options = this.options({
        target_path:"export/",
        appcache_extension:".appcache",
        base_url:"/",
        // one_for_all|one_for_each
        mode:"one_for_all",
        min_occurence_count:2,

        manifest_reloader:'<%= manifest_reloader %>',

        version:""+(new Date().getTime()),
        cache:[],
        network:[],
        fallback:[]
      });
      var config = grunt.config();

      var router = new router_factory(config.routing);
      router.load(function(){

        var urls = router.collect_urls();

//
        var pages = {};
        var assets = {};
        for( var n in urls ){
          var url = urls[n];
          var in_file = options.target_path + url;
          if( grunt.file.exists( in_file ) ){
            var html_content = grunt.file.read(in_file);
            var page_assets = lookup_for_assets(html_content, options.base_url, options.target_path);
            for(var t in page_assets ){
              var page_asset = page_assets[t];
              if( !assets[page_asset] ){
                assets[page_asset] = {
                  ocurence_count:0,
                  ocurence_urls:[]
                }
              }
              assets[page_asset].ocurence_count++;
              assets[page_asset].ocurence_urls.push(url);
            }

            pages[url] = {
              file:in_file,
              assets:page_assets
            };
          }
        }

        var reloader = "";
        if( options.maninfest_reloader ){
          if( grunt.file.exists(options.maninfest_reloader) ){
            reloader = grunt.file.read(options.maninfest_reloader);
          }else if( options.maninfest_reloader != "" ){
            reloader = options.maninfest_reloader;
          }
        }

//
        if( options.mode == "one_for_each" ){
          for( var page_url in pages ){
            var page_assets = pages[page_url].assets;
            var html_file = pages[page_url].file;

//
            var cache = [];
            for( var n in options.cache ){
              cache.push(options.cache[n]);
            }
            for( var n in page_assets ){
              cache.push(page_assets[n]);
            }

// generate and write AppCache file
            var manifest_file = html_file.replace(/[.](htm|html)$/,options.appcache_extension);
            var manifest_content = generate_appcache_content(options.version,
              cache,options.network,options.fallback);
            grunt.file.write(manifest_file, manifest_content);

            var html_content = grunt.file.read(html_file);
// load appcache and manifest reloader within html content
            var manifest_url = manifest_file.replace(options.target_path,"");
            manifest_url = manifest_url.substr(0,1)=="/"?manifest_url:"/"+manifest_url;
            html_content = html_content.replace("<html",
              "<html manifest=\""+manifest_url+"\"")

// insert appcache reloader
            if( reloader != "" ){
              html_content = html_content.replace(/<body([^>]+)?>/gi,
                "<body$1><script type='text/javascript'>"+reloader+"</script>");
            }
            grunt.file.write(html_file, html_content);
          }
        }

//
        if( options.mode == "one_for_all" ){

          var manifest_url = "/manifest"+options.appcache_extension;
          var manifest_file = options.target_path+manifest_url;

          for( var page_url in pages ){
            var page_assets = pages[page_url].assets;
            var html_file = pages[page_url].file;

//
            var cache = [];
            for( var n in options.cache ){
              cache.push(options.cache[n]);
            }
            for( var n in page_assets ){
              var page_asset = page_assets[n];
              if( assets[page_asset].ocurence_urls.length >= options.min_occurence_count ){
                cache.push(page_asset);
              }
            }

            var html_content = grunt.file.read(html_file);
// load appcache and manifest reloader within html content
            html_content = html_content.replace("<html",
              "<html manifest=\""+manifest_url+"\"");

// insert appcache reloader
            if( reloader != "" ){
              html_content = html_content.replace(/<body([^>]+)?>/gi,
                "<body$1><script type='text/javascript'>"+reloader+"</script>");
            }
            grunt.file.write(html_file, html_content);
          }

// generate and write AppCache file
          var manifest_content = generate_appcache_content(options.version,
            cache,options.network,options.fallback);
          grunt.file.write(manifest_file, manifest_content);
        }

      })
      grunt.log.ok();
    });

// helpers function
// ---------
  function generate_appcache_content(version,cache,network,fallback){
    var content = "";
    content += "CACHE MANIFEST" + "\n"
    content += "# version::" + version + "\n"
    content += "CACHE:" + "\n"
    for( var n in cache )
      content += cache[n]+ "\n"
    content += "NETWORK:" + "\n"
    for( var n in network )
      content += network[n]+ "\n"
    content += "FALLBACK:" + "\n"
    for( var n in fallback )
      content += fallback[n].ok+ " "+fallback[n].ko + "\n";

    return content;
  }
  function must_find_in_paths(paths, src){
    var retour = find_in_paths(paths, src)
    if( retour == false ){
      grunt.log.error("File not found : "+src)
    }
    return retour
  }

  function find_in_paths(paths, src){
    for( var t in paths ){
      if( grunt.file.exists(paths[t]+src) ){
        return path.resolve(paths[t]+src)
      }
    }
    return false
  }

// look up for absolute url of assets within html content
  function lookup_for_assets(html_content, base_url, paths){

    var html_utils = ph_libutil.html_utils;

    var retour = [];

// look up for <link> nodes
    var nodes = html_utils.find_link_nodes(html_content, base_url)
    for( var n in nodes ){
      if( find_in_paths(paths,nodes[n].asrc) ){
        retour.push(nodes[n].asrc)
      }
    }

// look up for css / img imports within <styles> nodes
    nodes = html_utils.find_style_nodes(html_content, base_url)
    for( var n in nodes ){
      var node = nodes[n]
      for( var k in node.imports ){
        if( find_in_paths(paths,node.imports[k].asrc) ){
          retour.push(node.imports[k].asrc)
        }
      }
      for( var k in node.imgs ){
        if( find_in_paths(paths,node.imgs[k].asrc) ){
          retour.push(node.imgs[k].asrc)
        }
      }
    }

// look up for <script data-main> nodes
    nodes = html_utils.find_rjs_nodes(html_content, base_url)
    for( var n in nodes ){
      if( find_in_paths(paths,nodes[n].asrc) ){
        retour.push(nodes[n].asrc)
      }s
    }

// look up for <script> nodes
    nodes = html_utils.find_scripts_nodes(html_content, base_url)
    for( var n in nodes ){
      if( find_in_paths(paths,nodes[n].asrc) ){
        retour.push(nodes[n].asrc)
      }
    }

// look up for <img> nodes
    nodes = html_utils.find_img_nodes(html_content, base_url)
    for( var n in nodes ){
      if( find_in_paths(paths,nodes[n].asrc) ){
        retour.push(nodes[n].asrc)
      }
    }
    return retour;
  }

};<|endoftext|>