<commit_before>var path = require('path');
var spawn = require('child_process').spawn;
var redirect = require('../lib/redirect.js');
var defaults = models.Config.defaults;
var command = commands['start'];

command.options['server'] = {
    'title': 'server=1|0',
    'description': 'Run TileMill in windowless mode.',
    'default': defaults.server
};

command.options['port'] = { 'default': defaults.port };
command.options['coreUrl'] = { 'default': defaults.coreUrl };

// Retrieve args to pass to child process here
// prior to Bones filtering out options.
var args = _(require('optimist').argv).chain()
    .map(function(val, key) {
        if (key === '$0') return;
        if (key === '_') return;
        return '--' + key + '=' + val;
    })
    .compact()
    .value();

command.prototype.initialize = function(plugin, callback) {
    // Process args.
    plugin.config.server = Boolean(plugin.config.server);

    // Default out the coreUrl, needed to point the client
    // window at the right URL.
    plugin.config.coreUrl = plugin.config.coreUrl ||
        'localhost:' + plugin.config.port;

    Bones.plugin.command = this;
    Bones.plugin.children = {};
    process.title = 'tilemill';
    // Kill child processes on exit.
    process.on('exit', function(code, signal) {
        console.warn('Exiting [' + process.title + ']');
        _(Bones.plugin.children).each(function(child) {
            console.warn('closing child process: ' + child.pid );
            child.kill();
        });
    });
    // Handle SIGUSR2 for dev integration with nodemon.
    process.once('SIGUSR2', function() {
        _(Bones.plugin.children).each(function(child) { child.kill('SIGUSR2'); });
        process.kill(process.pid, 'SIGUSR2');
    });
    this.child('core');
    this.child('tile');

    if (!plugin.config.server) plugin.children['core'].stderr.on('data', function(d) {
        if (!d.toString().match(/Started \[Server Core:\d+\]./)) return;
        var client = require('topcube')({
            url: 'http://' + plugin.config.coreUrl,
            name: 'TileMill',
            width: 800,
            height: 600,
            minwidth: 800,
            minheight: 400,
            // win32-only options.
            ico: path.resolve(path.join(__dirname + '/../tilemill.ico')),
            'cache-path': path.join(process.env.HOME, '.tilemill/cache-cefclient'),
            'log-file': path.join(process.env.HOME, '.tilemill/cefclient.log')

        });
        if (client) {
            console.warn('Client window created.');
            plugin.children['client'] = client;
        }
    });

    callback && callback();
};

command.prototype.child = function(name) {
    Bones.plugin.children[name] = spawn(process.execPath, [
        path.resolve(path.join(__dirname + '/../index.js')),
        name
    ].concat(args));

    redirect.onData(Bones.plugin.children[name]);
    Bones.plugin.children[name].once('exit', function(code, signal) {
        if (code === 0) {
            // restart server if exit was clean
            console.warn('Restarting child process: "' + name + '"');
            this.child(name);
        } else {
            if (signal) {
                console.warn('Error: child process: "' + name + '" failed with signal "' + signal + '" and code "' + code + '"')
                _(Bones.plugin.children).each(function(child) { child.kill(signal); });
                process.kill(process.pid,signal);
            } else {
                // Note: it would be great, in many cases, to auto-restart here
                // but we cannot because we will trigger recursion like in cases
                // of failed startup due to EADDRINUSE
                console.warn('Error: child process: "' + name + '" failed with code "' + code + '"')
                _(Bones.plugin.children).each(function(child) { child.kill(); });
            }
        }
    }.bind(this));
};

<commit_msg>detect c-land crashes in servers/Tile.bones and report them in logs - refs #698<commit_after>var path = require('path');
var spawn = require('child_process').spawn;
var redirect = require('../lib/redirect.js');
var defaults = models.Config.defaults;
var command = commands['start'];
var crashutil = require('../lib/crashutil');

command.options['server'] = {
    'title': 'server=1|0',
    'description': 'Run TileMill in windowless mode.',
    'default': defaults.server
};

command.options['port'] = { 'default': defaults.port };
command.options['coreUrl'] = { 'default': defaults.coreUrl };

// Retrieve args to pass to child process here
// prior to Bones filtering out options.
var args = _(require('optimist').argv).chain()
    .map(function(val, key) {
        if (key === '$0') return;
        if (key === '_') return;
        return '--' + key + '=' + val;
    })
    .compact()
    .value();

command.prototype.initialize = function(plugin, callback) {
    // Process args.
    plugin.config.server = Boolean(plugin.config.server);

    // Default out the coreUrl, needed to point the client
    // window at the right URL.
    plugin.config.coreUrl = plugin.config.coreUrl ||
        'localhost:' + plugin.config.port;

    Bones.plugin.command = this;
    Bones.plugin.children = {};
    process.title = 'tilemill';
    // Kill child processes on exit.
    process.on('exit', function(code, signal) {
        _(Bones.plugin.children).each(function(child, key) {
            console.warn('[tilemill] Closing child process: ' + key  + " (pid:" + child.pid + ")");
            child.kill();
        });
        crashutil.display_crash_log(function(err,logname) {
            if (err) {
                console.warn(err.stack || err.toString());
            }
            if (logname) {
                console.warn("[tilemill] Please post this crash log: '" + logname + "' to https://github.com/mapbox/tilemill/issues");
            }
        });
        console.warn('Exiting [' + process.title + ']');
    });
    // Handle SIGUSR2 for dev integration with nodemon.
    process.once('SIGUSR2', function() {
        _(Bones.plugin.children).each(function(child) { child.kill('SIGUSR2'); });
        process.kill(process.pid, 'SIGUSR2');
    });
    this.child('core');
    this.child('tile');

    if (!plugin.config.server) plugin.children['core'].stderr.on('data', function(d) {
        if (!d.toString().match(/Started \[Server Core:\d+\]./)) return;
        var client = require('topcube')({
            url: 'http://' + plugin.config.coreUrl,
            name: 'TileMill',
            width: 800,
            height: 600,
            minwidth: 800,
            minheight: 400,
            // win32-only options.
            ico: path.resolve(path.join(__dirname + '/../tilemill.ico')),
            'cache-path': path.join(process.env.HOME, '.tilemill/cache-cefclient'),
            'log-file': path.join(process.env.HOME, '.tilemill/cefclient.log')

        });
        if (client) {
            console.warn('[tilemill] Client window created (pass --server=true to disable this)');
            plugin.children['client'] = client;
        }
    });

    callback && callback();
};

command.prototype.child = function(name) {
    Bones.plugin.children[name] = spawn(process.execPath, [
        path.resolve(path.join(__dirname + '/../index.js')),
        name
    ].concat(args));

    redirect.onData(Bones.plugin.children[name]);
    Bones.plugin.children[name].once('exit', function(code, signal) {
        if (code === 0) {
            // restart server if exit was clean
            console.warn('[tilemill] Restarting child process: "' + name + '"');
            this.child(name);
        } else {
            if (signal) {
                var msg = '[tilemill] Error: child process: "' + name + '" failed with signal "' + signal + '"';
                if (code != undefined)
                    msg += " and code '" + code + "'";
                console.warn(msg);
                _(Bones.plugin.children).each(function(child) { child.kill(signal); });
                process.exit(1);
            } else {
                // Note: it would be great, in many cases, to auto-restart here
                // but we cannot because we will trigger recursion like in cases
                // of failed startup due to EADDRINUSE
                console.warn('[tilemill] Error: child process: "' + name + '" failed with code "' + code + '"')
                _(Bones.plugin.children).each(function(child) { child.kill(); });
            }
        }
    }.bind(this));
};

<|endoftext|>


<commit_before>var Network = (function ()
{
    var kinases = null
    var kinase_groups = null
    var protein = null

    var edges = []

    function fitTextIntoCircle(d, context)
    {
        var radius = d.r
        return Math.min(2 * radius, (2 * radius - 8) / context.getComputedTextLength() * 24) + 'px';
    }

    function calculateRadius(mutations_count, is_group)
    {
        is_group = is_group ? 1 : 0

        var r = config.minimalRadius
        // the groups are shown as two times bigger
        r *= (is_group + 1)
        // more mutations = bigger circle
        r += 6 * Math.log10(mutations_count + 1)

        return r
    }

    function createProteinNode()
    {
        var radius = calculateRadius(protein.mutations_count)

        return {
            name: protein.name,
            r: radius,
            x: (config.width - radius) / 2,
            y: (config.height - radius) / 2,
            color: 'blue'
        }
    }

    var config = {
        width: 600,
        height: null,
        minimalRadius: 6,   // of a single node
        ratio: 1,   // the aspect ratio of the network
        nodeURL: (function(node) {
            return window.location.href + '#' + node.name
        })
    }

    function configure(new_config)
    {
        // Automatical configuration update:
        for(var key in new_config)
        {
            if(new_config.hasOwnProperty(key))
            {
                config[key] = new_config[key]
            }
        }
        // Manual configuration patching:
        config.height = config.height || config.width * config.ratio
    }

    function getKinasesByName(names)
    {
        matching_kinases = []

        for(var i = 0; i < kinases.length; i++)
        {
            for(var j = 0; j < names.length; j++)
            {
                if(kinases[i].name === names[j])
                {
                    matching_kinases.push(kinases[i])
                }
            }
        }
        return matching_kinases
    }

    function getKinaseByName(name)
    {
        return getKinasesByName([name])[0]
    }

    function getKinasesInGroups()
    {
        var names = []
        for(var i = 0; i < kinase_groups.length; i++)
        {
            group = kinase_groups[i]
            Array.prototype.push.apply(names, group.kinases)
        }
        return names
    }

    function addEdge(source, target, weight)
    {
        weight = weight || 1
        edges.push(
            {
                source: source,
                target: target,
                weight: weight
            }
        )
    }

    function prepareKinases()
    {
        kinases_in_groups = getKinasesInGroups()
        for(var i = 0; i < kinases.length; i++)
        {
            var kinase = kinases[i]
            kinase.x = Math.random() * config.width
            kinase.y = Math.random() * config.height
            kinase.r = calculateRadius(
                kinase.protein ? kinase.protein.mutations_count : 0
            )
            kinase.node_id = i + 1

            // make links to the central protein's node from those
            // kinases that do not belong to any of groups
            if(kinases_in_groups.indexOf(kinase.name) === -1)
            {
                addEdge(kinase.node_id, 0)
            }
        }
    }

    function prepareKinaseGroups(index_shift)
    {
        for(var i = 0; i < kinase_groups.length; i++)
        {
            var group = kinase_groups[i]

            group.x = Math.random() * config.width
            group.y = Math.random() * config.height

            var group_kinases = getKinasesByName(group.kinases)
            var group_index = index_shift + i

            var mutations_in_kinases = 0
            for(var j = 0; j < group_kinases.length; j++)
            {
                var kinase = group_kinases[j]
                mutations_in_kinases += kinase.protein ? kinase.protein.mutations_count : 0

                addEdge(group_index, kinase.node_id)
            }

            group.r = calculateRadius(
                mutations_in_kinases / group_kinases.length || 0,
                true
            )
            group.color = 'red'
            // 0 is (by convention) the index of the central protein
            addEdge(group_index, 0)
        }
    }

    var publicSpace = {
        init: function(user_config)
        {
            configure(user_config)

            var force = d3.layout.force()
                .gravity(0.05)
                .distance(100)
                .charge(-100)
                .size([config.width, config.height])

            var vis = d3.select(config.element).append('svg')
                .attr('preserveAspectRatio', 'xMinYMin meet')
                .attr('viewBox', '0 0 ' + config.width + ' ' + config.height)
                .classed('svg-content-responsive', true)

            var data = config.data

            kinase_groups = data.kinase_groups
            kinases = data.kinases
            protein = data.protein

            var protein_node = createProteinNode()
            var nodes_data = [protein_node]

            prepareKinases()
            Array.prototype.push.apply(nodes_data, kinases)

            prepareKinaseGroups(nodes_data.length)
            Array.prototype.push.apply(nodes_data, kinase_groups)

            force
                .nodes(nodes_data)
                .links(edges)
                .start()

            var link = vis.selectAll(".link")
                .data(edges)
                .enter().append("line")
                .attr("class", "link")
                .style("stroke-width", function(d) { return Math.sqrt(d.weight); });

            var nodes = vis.selectAll('.node')
                .data(nodes_data)
                .enter().append('g')
                .attr('transform', function(d){return 'translate(' + [d.x, d.y] + ')'})
                .attr('class', 'node')
                .call(force.drag)
                .on('click', function(node) {
                    if(d3.event.defaultPrevented === false)
                    {
                        window.location.href = config.nodeURL(node)
                    }
                })

            nodes.append('circle')
                .attr('class', 'nodes')
                .attr('r', function(node){ return node.r })
                .attr('stroke', function(node) {
                    var default_color = '#905590'
                    return node.color || default_color
                })

            nodes.append('text')
                .text(function(d){return d.name})
                .style('font-size', function(d) { return fitTextIntoCircle(d, this) })
                .attr('dy', '.35em')

            force.on('tick', function() {
                link.attr("x1", function(d) { return d.source.x })
                    .attr("y1", function(d) { return d.source.y })
                    .attr("x2", function(d) { return d.target.x })
                    .attr("y2", function(d) { return d.target.y })
                    nodes.attr('transform', function(d){return 'translate(' + [d.x, d.y] + ')'})
                })

        }
    }

    return publicSpace
})()
<commit_msg>Change scale factor for groups to 1.5 #7<commit_after>var Network = (function ()
{
    var kinases = null
    var kinase_groups = null
    var protein = null

    var edges = []

    function fitTextIntoCircle(d, context)
    {
        var radius = d.r
        return Math.min(2 * radius, (2 * radius - 8) / context.getComputedTextLength() * 24) + 'px';
    }

    function calculateRadius(mutations_count, is_group)
    {
        var r = config.minimalRadius
        // the groups are shown as 1.5 times bigger
        r *= is_group ? 1.5 : 1
        // more mutations = bigger circle
        r += 6 * Math.log10(mutations_count + 1)

        return r
    }

    function createProteinNode()
    {
        var radius = calculateRadius(protein.mutations_count)

        return {
            name: protein.name,
            r: radius,
            x: (config.width - radius) / 2,
            y: (config.height - radius) / 2,
            color: 'blue'
        }
    }

    var config = {
        width: 600,
        height: null,
        minimalRadius: 6,   // of a single node
        ratio: 1,   // the aspect ratio of the network
        nodeURL: (function(node) {
            return window.location.href + '#' + node.name
        })
    }

    function configure(new_config)
    {
        // Automatical configuration update:
        for(var key in new_config)
        {
            if(new_config.hasOwnProperty(key))
            {
                config[key] = new_config[key]
            }
        }
        // Manual configuration patching:
        config.height = config.height || config.width * config.ratio
    }

    function getKinasesByName(names)
    {
        matching_kinases = []

        for(var i = 0; i < kinases.length; i++)
        {
            for(var j = 0; j < names.length; j++)
            {
                if(kinases[i].name === names[j])
                {
                    matching_kinases.push(kinases[i])
                }
            }
        }
        return matching_kinases
    }

    function getKinaseByName(name)
    {
        return getKinasesByName([name])[0]
    }

    function getKinasesInGroups()
    {
        var names = []
        for(var i = 0; i < kinase_groups.length; i++)
        {
            group = kinase_groups[i]
            Array.prototype.push.apply(names, group.kinases)
        }
        return names
    }

    function addEdge(source, target, weight)
    {
        weight = weight || 1
        edges.push(
            {
                source: source,
                target: target,
                weight: weight
            }
        )
    }

    function prepareKinases()
    {
        kinases_in_groups = getKinasesInGroups()
        for(var i = 0; i < kinases.length; i++)
        {
            var kinase = kinases[i]
            kinase.x = Math.random() * config.width
            kinase.y = Math.random() * config.height
            kinase.r = calculateRadius(
                kinase.protein ? kinase.protein.mutations_count : 0
            )
            kinase.node_id = i + 1

            // make links to the central protein's node from those
            // kinases that do not belong to any of groups
            if(kinases_in_groups.indexOf(kinase.name) === -1)
            {
                addEdge(kinase.node_id, 0)
            }
        }
    }

    function prepareKinaseGroups(index_shift)
    {
        for(var i = 0; i < kinase_groups.length; i++)
        {
            var group = kinase_groups[i]

            group.x = Math.random() * config.width
            group.y = Math.random() * config.height

            var group_kinases = getKinasesByName(group.kinases)
            var group_index = index_shift + i

            var mutations_in_kinases = 0
            for(var j = 0; j < group_kinases.length; j++)
            {
                var kinase = group_kinases[j]
                mutations_in_kinases += kinase.protein ? kinase.protein.mutations_count : 0

                addEdge(group_index, kinase.node_id)
            }

            group.r = calculateRadius(
                mutations_in_kinases / group_kinases.length || 0,
                true
            )
            group.color = 'red'
            // 0 is (by convention) the index of the central protein
            addEdge(group_index, 0)
        }
    }

    var publicSpace = {
        init: function(user_config)
        {
            configure(user_config)

            var force = d3.layout.force()
                .gravity(0.05)
                .distance(100)
                .charge(-100)
                .size([config.width, config.height])

            var vis = d3.select(config.element).append('svg')
                .attr('preserveAspectRatio', 'xMinYMin meet')
                .attr('viewBox', '0 0 ' + config.width + ' ' + config.height)
                .classed('svg-content-responsive', true)

            var data = config.data

            kinase_groups = data.kinase_groups
            kinases = data.kinases
            protein = data.protein

            var protein_node = createProteinNode()
            var nodes_data = [protein_node]

            prepareKinases()
            Array.prototype.push.apply(nodes_data, kinases)

            prepareKinaseGroups(nodes_data.length)
            Array.prototype.push.apply(nodes_data, kinase_groups)

            force
                .nodes(nodes_data)
                .links(edges)
                .start()

            var link = vis.selectAll(".link")
                .data(edges)
                .enter().append("line")
                .attr("class", "link")
                .style("stroke-width", function(d) { return Math.sqrt(d.weight); });

            var nodes = vis.selectAll('.node')
                .data(nodes_data)
                .enter().append('g')
                .attr('transform', function(d){return 'translate(' + [d.x, d.y] + ')'})
                .attr('class', 'node')
                .call(force.drag)
                .on('click', function(node) {
                    if(d3.event.defaultPrevented === false)
                    {
                        window.location.href = config.nodeURL(node)
                    }
                })

            nodes.append('circle')
                .attr('class', 'nodes')
                .attr('r', function(node){ return node.r })
                .attr('stroke', function(node) {
                    var default_color = '#905590'
                    return node.color || default_color
                })

            nodes.append('text')
                .text(function(d){return d.name})
                .style('font-size', function(d) { return fitTextIntoCircle(d, this) })
                .attr('dy', '.35em')

            force.on('tick', function() {
                link.attr("x1", function(d) { return d.source.x })
                    .attr("y1", function(d) { return d.source.y })
                    .attr("x2", function(d) { return d.target.x })
                    .attr("y2", function(d) { return d.target.y })
                    nodes.attr('transform', function(d){return 'translate(' + [d.x, d.y] + ')'})
                })

        }
    }

    return publicSpace
})()
<|endoftext|>


<commit_before>
var jsMerge = {
	splits : [
		//base splits
		'isConstant',
		'isLegacy',
		'isModern',

		//extra splits
		'isHome',
	],
	components : [
		{
			folder: 'plugins--3rdParty-JS',
			//isSplit : true //(default)
		}, {
			folder: '00-variables-global-JS',
		}, {
			folder: '01-functions-global-JS',
		}, {
			folder: 'plugins--1stParty-JS',
		}, {
			file: 'doc.ready-open.js',
			//usedIn : 'all', //(default)// other option is an array eg. ['isHome', 'isModern']
		}, {
			folder : 'modules-JS',
		}, {
			file: 'doc.ready-close.js',
		}
	]
};

//configure grunt concat options here
var JS_mergeConfig = {
	options: {
		banner: '/* This is a generated file. Do not edit */'
	}
};

var JS_merge_files = {};

//generates an array of files delegated to each split
for (var x = 0; x < jsMerge.splits.length; x++){

	var root = 'website/assets/js/';
	var split = jsMerge.splits[x];

	JS_merge_files[split] = [];

	for (var i = 0; i < jsMerge.components.length; i++){

		var component = jsMerge.components[i];

		//if it's a file
		if (typeof component.file !== 'undefined'){
			//default "usedIn" to "all"
			component.usedIn = component.usedIn || 'all';
			//if file is used in all, or current split is in the "usedIn" array
			if (component.usedIn == 'all' || component.usedIn.indexOf(split) > -1){
				JS_merge_files[split].push(root + component.file);
			}

		//else it's a folder
		} else {
			//default "isSplit" to "true"
			component.isSplit = component.isSplit || true;
			//if componenet is not split, only load it in the 'isConstant' set
			if (component.isSplit || split == 'isConstant'){

				var currentSplit = component.isSplit ? '/' + split : '';

				JS_merge_files[split].push(root + component.folder + currentSplit + '/**/*.js');
			}
		}
	};

	//formats the data into a form that grunt concat understands
	JS_mergeConfig[split] = {
		src : JS_merge_files[split],
		dest : root + 'ZZ-merged-JS/' + split + '.js'
	}

}

//use this to test the grunt concat code
//console.log(JS_mergeConfig);
//console.log(JS_merge_files);

//generates the grunt uglify syntax
var JS_minified_files = {};
for (var key in JS_merge_files) {
  if (JS_merge_files.hasOwnProperty(key)) {

  	JS_minified_files['website/assets/js/ZZ-merged-JS/'+key+'.min.js'] = ['website/assets/js/ZZ-merged-JS/'+key+'.js'];
  }
}
//test grunt uglify syntax
//console.log(JS_minified_files);

//var autoprefixer = require('autoprefixer-core');

//needed for the sync function
var server_root;

//Use this to discover what platform your computer uses
//console.log(process.platform);
switch (process.platform) {
// Windows
	case 'win32':
		server_root =  '//CAN1DEV012/webs/folderName/';
		break;

// Mac OSX
	case 'darwin' :
		server_root =  '/Volumes/webs/folderName/';
		break;
}

module.exports = function (grunt) {

	//Avoids the need for the grunt.loadNpmTasks('xxx') commands
	//https://www.npmjs.org/package/jit-grunt
	require("jit-grunt")(grunt, {
		//for any grunt plugins that aren't working without grunt.loadNpmTasks("grunt_plugin_name");, list them here:
		// task_name: "grunt_plugin_name",
		watch: "grunt-contrib-watch",
		sprite: "grunt-spritesmith",
	});

	grunt.initConfig({
		pkg: grunt.file.readJSON("package.json"),

		//Merges JS files together
		concat: JS_mergeConfig,

		//Minimises the JS
		uglify: {
			my_target: {
				options: {
					sourceMap: false,
					preserveComments: 'some'
				},
				files: JS_minified_files
			}
		},

		//This shrinks the HD sprite to normal size
// In order for it to work, you need to install imageMagic on your computer:
//	1.	Go here to download it http://www.imagemagick.org/script/binary-releases.php
//	2.	Follow the instructions while cd is the default, NOT the project directory (make sure to tick "add to system path" when the option comes up)
//	3.	Once installed “npm install im”
//	4.	When cd is the project folder “npm install grunt-image-resize”
//	5.	You’re done, it should be working now :)
		image_resize: {
			resize: {
				options: {
					width: '50%',
					height: '50%',
				},
				files: {
					//destination
					'assets/images/auto-sprite/LD-retina-autosprite.png':
					//source
					'assets/images/auto-sprite/HD-retina-autosprite.png'
				}
			}
		},

		//auto-spriting without compass
		sprite:{
			//Generates the double sized version of the retina sprite
	        retina: {
	            src: 'website/assets/images/auto-sprite/HD-retina-sourcefiles/*.png',
	            dest: 'website/assets/images/auto-sprite/HD-retina-autosprite.png',
	            destCss: 'website/assets/sass/00-config/sprite-sheets/HD-retina-sprites.scss',
	            cssFormat: 'scss_maps',
	            imgPath: '../images/auto-sprite/HD-retina-autosprite.png',
	            padding: 4,
				cssSpritesheetName: 'spritesheet-retina',
	            cssOpts: {
	                functions: false,
	            },
	        },
			//Generates a normal sized sprite that is used on both retina and non retina screens
			//If you do not have a double sized version for an image, use this.
			nonRetina: {
	            src: 'website/assets/images/auto-sprite/LD-nonRetina-sourceFiles/*.png',
	            dest: 'website/assets/images/auto-sprite/LD-nonRetina-autosprite.png',
	            destCss: 'website/assets/sass/00-config/sprite-sheets/LD-nonRetina-sprites.scss',
	            cssFormat: 'scss_maps',
	            imgPath: '../images/auto-sprite/LD-nonRetina-autosprite.png',
	            padding: 2,
				cssSpritesheetName: 'spritesheet-nonRetina',
	            cssOpts: {
	                functions: false,
	            },
			}
	    },

		//allows sass to import a whole directory at a time
		sass_globbing: {
			all: {
				files: {
					'website/assets/sass/import-maps/map-functions.scss': 'website/assets/sass/00-functions-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-config.scss': 'website/assets/sass/01-config-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-mixins.scss': 'website/assets/sass/02-mixins-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-plugins.scss': 'website/assets/sass/03-plugins-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-base.scss': 'website/assets/sass/04-base-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-modules.scss': 'website/assets/sass/05-modules-SASS/**/*.scss',
				}
			}
		},

		//compiles the SASS
		sass: {
			options: {
				style: "compact",
				//sourcemap: true, //deprecated in latest SASS version
				compass: false
			},
			modern: {//only compile the modern style sheet
				files: {
					//Modern style sheet
					"website/assets/css/modern.css": "website/assets/sass/output-files/modern.scss",
				}
			},
			ie9 : {
				files : {
					//IE9 style sheet
					"website/assets/css/ie9.css": "website/assets/sass/output-files/ie9.scss",
				}
			},
			ie8 : {
				files : {
					//IE8 style sheet
					"website/assets/css/ie8.css": "website/assets/sass/output-files/ie8.scss",
				}
			}
		},

		//Merge similar media queries into single MQ's
		//It isn't capable of generating css maps, so this is only used in the CSS minification process
		cmq: {
			your_target: {
				files: {
					'website/assets/css/media-merge/': [
						'website/assets/css/modern.css',
						'website/assets/css/ie9.css',
						'website/assets/css/ie8.css',
					]
				}
			}
		},

		//css optimiser (minification) better than standard minification
		//http://bem.info/tools/optimizers/csso/description/
		csso: {
		  minify: {
		    options: {
		      banner: '/* Simmilar mediaqueries have been merged and CSS has been Minified in this file (Not to be loaded into the browser during site development) */'
		    },
			//takes the current css files in the "media-merge" folder, minifies them, adds '.min.css' to the end of the file, and copies them back into the main css folder
		      expand: true,
		      cwd: 'website/assets/css/media-merge/',
		      src: ['modern.css','ie9.css','ie8.css'],
		      dest: 'website/assets/css/',
		      ext: '.min.css'
		  }
		},

		postcss: {
		    options: {
		      map: {
		          inline: false, // save all sourcemaps as separate files...
		      },

		      processors: [
		        require('autoprefixer')({browsers: 'last 2 versions'}), // add vendor prefixes
				require("css-mqpacker")()
		      ]
		    },
		    prefixMQ: {
		      src: 'website/assets/css/*.css'
		    }
		},
		// Keep files on server in sync with local copy
		// Extreamly useful at build stage
		sync: {
			js: {
				files: [
					// includes files within path
					{
						cwd: 'website/assets/js/',
						src: ['ZZ-merged-JS/*.js'],
						dest: server_root + 'website/assets/js/',
					}
				],
				//pretend: true, // Don't do any IO. Before you run the task with `updateAndDelete` PLEASE MAKE SURE it doesn't remove too much.
				verbose: true // Display log messages when copying files
			},
			images: {
				files: [
					{
						src: 'website/assets/images/**',
						dest: server_root
					}
				],
				//pretend: true,
				verbose: true
			},
			css: {
				files: [
					{
						cwd: 'website/assets/css/',
						src: ['*.css', '*.map'],
						dest: server_root + 'website/assets/css/'
					}
				],
				//pretend: true,
				verbose: true
			},
			html: {
				files: [
					{
						src: '**/*.php',
						dest: server_root
					}
				],
				//pretend: true,
				verbose: true
			},
			fonts: {
				files: [
					{
						cwd: 'website/assets/fonts/',
						src: ['**/**'],
						dest: server_root + 'website/assets/fonts/'
					}
				],
				//pretend: true,
				verbose: true
			}
		},

		ftpush: {
			uat: {
				auth: {
					host: 'domain.uat.aws1.readingroom.com.au',
					port: '',
					authKey: 'uat'
				},
				dest: 'web/',
				src: '',
				exclusions: [
					'.git/**/*',
					'**/.DS_Store',
					'**/Thumbs.db',
					'**/tmp',
					'.sass-cache/**/*',
					'node_modules/**/*',
					'grunt-start-up.txt',
					'grunt-first-time.txt',
					'Gruntfile.js',
					'package.json',
					'.ftppass',
					//'downloads/**/*',//optional

					//UAT only
				],
				keep: [
					'.htaccess',
					'.htpasswd',
					'error/**/*',
					'stats/**/*',
				]
			}
		},

		watch: {
			options: {
				livereload: true
			},
			scripts: {
				files: ["website/assets/js/**/*.js", "!website/assets/js/ZZ-merged-JS/*.js"],
				tasks: [
					"concat", //merges constant js files into one file
					//"uglify", //minify JS
					//"sync:js" //copy js to server
				],
				options: { spawn: false }
			},
			images: {
				files: ['website/assets/images/**'],
				tasks: [
					'image_resize',
					'sprite',
					//"sync:images" //copy js to server
				],
				options: { spawn: false }
			},
			scss: {
				files: ["website/assets/sass/**/*.scss"],
				tasks: [
					"sass_globbing",//generates import maps for SASS modules
					"sass:modern", //compile the modern SASS (modern only by default for speed)
					//"sass:ie8", //compile the IE8 SASS
					//"sass:ie9", //compile the IE9 SASS
					"postcss"//merge media queries and add auto prefixing
					//"cmq", //merge media queries
					//"csso", //minify css
					//"sync:css" //copy css to server
				],
				options: { spawn: false }
			},
			html: {
				options: {
					livereload: true
				},
				//The other file types that will trigger a browser refresh on save
				tasks: [
					//"sync:html",
				],
				files: [
					"**/*.html",
					"**/*.htm",
					"**/*.php",
					"**/*.cshtml"
				]
			},
			fonts: {
				options: {
					livereload: true
				},
				//The other file types that will trigger a browser refresh on save
				tasks: [
					//"sync:fonts",
				],
				files: [
					"website/assets/fonts/**/**"
				]
			}
		}

	});

	//don't bother with the grunt.loadNpmTasks('xxx'); commands. They are generated automatically

	//list the tasks in the order you want them done in
	grunt.registerTask("default", [
		'image_resize',
		'sprite',

		"concat",//merge JS files
		"uglify",//minify JS
		"sass_globbing", //merge SASS files
		"sass",//compile CSS files for all browsers when running the grunt command
		"postcss",//merge media queries and add auto prefixing
		//"cmq",//combine media queries
		"csso",//minify css (css optimiser)
		//"sync",//copy files to another location
		"watch"
	]);

};<commit_msg>updates to Grunt ftpush default settings<commit_after>
var jsMerge = {
	splits : [
		//base splits
		'isConstant',
		'isLegacy',
		'isModern',

		//extra splits
		'isHome',
	],
	components : [
		{
			folder: 'plugins--3rdParty-JS',
			//isSplit : true //(default)
		}, {
			folder: '00-variables-global-JS',
		}, {
			folder: '01-functions-global-JS',
		}, {
			folder: 'plugins--1stParty-JS',
		}, {
			file: 'doc.ready-open.js',
			//usedIn : 'all', //(default)// other option is an array eg. ['isHome', 'isModern']
		}, {
			folder : 'modules-JS',
		}, {
			file: 'doc.ready-close.js',
		}
	]
};

//configure grunt concat options here
var JS_mergeConfig = {
	options: {
		banner: '/* This is a generated file. Do not edit */'
	}
};

var JS_merge_files = {};

//generates an array of files delegated to each split
for (var x = 0; x < jsMerge.splits.length; x++){

	var root = 'website/assets/js/';
	var split = jsMerge.splits[x];

	JS_merge_files[split] = [];

	for (var i = 0; i < jsMerge.components.length; i++){

		var component = jsMerge.components[i];

		//if it's a file
		if (typeof component.file !== 'undefined'){
			//default "usedIn" to "all"
			component.usedIn = component.usedIn || 'all';
			//if file is used in all, or current split is in the "usedIn" array
			if (component.usedIn == 'all' || component.usedIn.indexOf(split) > -1){
				JS_merge_files[split].push(root + component.file);
			}

		//else it's a folder
		} else {
			//default "isSplit" to "true"
			component.isSplit = component.isSplit || true;
			//if componenet is not split, only load it in the 'isConstant' set
			if (component.isSplit || split == 'isConstant'){

				var currentSplit = component.isSplit ? '/' + split : '';

				JS_merge_files[split].push(root + component.folder + currentSplit + '/**/*.js');
			}
		}
	};

	//formats the data into a form that grunt concat understands
	JS_mergeConfig[split] = {
		src : JS_merge_files[split],
		dest : root + 'ZZ-merged-JS/' + split + '.js'
	}

}

//use this to test the grunt concat code
//console.log(JS_mergeConfig);
//console.log(JS_merge_files);

//generates the grunt uglify syntax
var JS_minified_files = {};
for (var key in JS_merge_files) {
  if (JS_merge_files.hasOwnProperty(key)) {

  	JS_minified_files['website/assets/js/ZZ-merged-JS/'+key+'.min.js'] = ['website/assets/js/ZZ-merged-JS/'+key+'.js'];
  }
}
//test grunt uglify syntax
//console.log(JS_minified_files);

//var autoprefixer = require('autoprefixer-core');

//needed for the sync function
var server_root;

//Use this to discover what platform your computer uses
//console.log(process.platform);
switch (process.platform) {
// Windows
	case 'win32':
		server_root =  '//CAN1DEV012/webs/folderName/';
		break;

// Mac OSX
	case 'darwin' :
		server_root =  '/Volumes/webs/folderName/';
		break;
}

module.exports = function (grunt) {

	//Avoids the need for the grunt.loadNpmTasks('xxx') commands
	//https://www.npmjs.org/package/jit-grunt
	require("jit-grunt")(grunt, {
		//for any grunt plugins that aren't working without grunt.loadNpmTasks("grunt_plugin_name");, list them here:
		// task_name: "grunt_plugin_name",
		watch: "grunt-contrib-watch",
		sprite: "grunt-spritesmith",
	});

	grunt.initConfig({
		pkg: grunt.file.readJSON("package.json"),

		//Merges JS files together
		concat: JS_mergeConfig,

		//Minimises the JS
		uglify: {
			my_target: {
				options: {
					sourceMap: false,
					preserveComments: 'some'
				},
				files: JS_minified_files
			}
		},

		//This shrinks the HD sprite to normal size
// In order for it to work, you need to install imageMagic on your computer:
//	1.	Go here to download it http://www.imagemagick.org/script/binary-releases.php
//	2.	Follow the instructions while cd is the default, NOT the project directory (make sure to tick "add to system path" when the option comes up)
//	3.	Once installed “npm install im”
//	4.	When cd is the project folder “npm install grunt-image-resize”
//	5.	You’re done, it should be working now :)
		image_resize: {
			resize: {
				options: {
					width: '50%',
					height: '50%',
				},
				files: {
					//destination
					'assets/images/auto-sprite/LD-retina-autosprite.png':
					//source
					'assets/images/auto-sprite/HD-retina-autosprite.png'
				}
			}
		},

		//auto-spriting without compass
		sprite:{
			//Generates the double sized version of the retina sprite
	        retina: {
	            src: 'website/assets/images/auto-sprite/HD-retina-sourcefiles/*.png',
	            dest: 'website/assets/images/auto-sprite/HD-retina-autosprite.png',
	            destCss: 'website/assets/sass/00-config/sprite-sheets/HD-retina-sprites.scss',
	            cssFormat: 'scss_maps',
	            imgPath: '../images/auto-sprite/HD-retina-autosprite.png',
	            padding: 4,
				cssSpritesheetName: 'spritesheet-retina',
	            cssOpts: {
	                functions: false,
	            },
	        },
			//Generates a normal sized sprite that is used on both retina and non retina screens
			//If you do not have a double sized version for an image, use this.
			nonRetina: {
	            src: 'website/assets/images/auto-sprite/LD-nonRetina-sourceFiles/*.png',
	            dest: 'website/assets/images/auto-sprite/LD-nonRetina-autosprite.png',
	            destCss: 'website/assets/sass/00-config/sprite-sheets/LD-nonRetina-sprites.scss',
	            cssFormat: 'scss_maps',
	            imgPath: '../images/auto-sprite/LD-nonRetina-autosprite.png',
	            padding: 2,
				cssSpritesheetName: 'spritesheet-nonRetina',
	            cssOpts: {
	                functions: false,
	            },
			}
	    },

		//allows sass to import a whole directory at a time
		sass_globbing: {
			all: {
				files: {
					'website/assets/sass/import-maps/map-functions.scss': 'website/assets/sass/00-functions-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-config.scss': 'website/assets/sass/01-config-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-mixins.scss': 'website/assets/sass/02-mixins-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-plugins.scss': 'website/assets/sass/03-plugins-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-base.scss': 'website/assets/sass/04-base-SASS/**/*.scss',
					'website/assets/sass/import-maps/map-modules.scss': 'website/assets/sass/05-modules-SASS/**/*.scss',
				}
			}
		},

		//compiles the SASS
		sass: {
			options: {
				style: "compact",
				//sourcemap: true, //deprecated in latest SASS version
				compass: false
			},
			modern: {//only compile the modern style sheet
				files: {
					//Modern style sheet
					"website/assets/css/modern.css": "website/assets/sass/output-files/modern.scss",
				}
			},
			ie9 : {
				files : {
					//IE9 style sheet
					"website/assets/css/ie9.css": "website/assets/sass/output-files/ie9.scss",
				}
			},
			ie8 : {
				files : {
					//IE8 style sheet
					"website/assets/css/ie8.css": "website/assets/sass/output-files/ie8.scss",
				}
			}
		},

		//Merge similar media queries into single MQ's
		//It isn't capable of generating css maps, so this is only used in the CSS minification process
		cmq: {
			your_target: {
				files: {
					'website/assets/css/media-merge/': [
						'website/assets/css/modern.css',
						'website/assets/css/ie9.css',
						'website/assets/css/ie8.css',
					]
				}
			}
		},

		//css optimiser (minification) better than standard minification
		//http://bem.info/tools/optimizers/csso/description/
		csso: {
		  minify: {
		    options: {
		      banner: '/* Simmilar mediaqueries have been merged and CSS has been Minified in this file (Not to be loaded into the browser during site development) */'
		    },
			//takes the current css files in the "media-merge" folder, minifies them, adds '.min.css' to the end of the file, and copies them back into the main css folder
		      expand: true,
		      cwd: 'website/assets/css/media-merge/',
		      src: ['modern.css','ie9.css','ie8.css'],
		      dest: 'website/assets/css/',
		      ext: '.min.css'
		  }
		},

		postcss: {
		    options: {
		      map: {
		          inline: false, // save all sourcemaps as separate files...
		      },

		      processors: [
		        require('autoprefixer')({browsers: 'last 2 versions'}), // add vendor prefixes
				require("css-mqpacker")()
		      ]
		    },
		    prefixMQ: {
		      src: 'website/assets/css/*.css'
		    }
		},
		// Keep files on server in sync with local copy
		// Extreamly useful at build stage
		sync: {
			js: {
				files: [
					// includes files within path
					{
						cwd: 'website/assets/js/',
						src: ['ZZ-merged-JS/*.js'],
						dest: server_root + 'website/assets/js/',
					}
				],
				//pretend: true, // Don't do any IO. Before you run the task with `updateAndDelete` PLEASE MAKE SURE it doesn't remove too much.
				verbose: true // Display log messages when copying files
			},
			images: {
				files: [
					{
						src: 'website/assets/images/**',
						dest: server_root
					}
				],
				//pretend: true,
				verbose: true
			},
			css: {
				files: [
					{
						cwd: 'website/assets/css/',
						src: ['*.css', '*.map'],
						dest: server_root + 'website/assets/css/'
					}
				],
				//pretend: true,
				verbose: true
			},
			html: {
				files: [
					{
						src: '**/*.php',
						dest: server_root
					}
				],
				//pretend: true,
				verbose: true
			},
			fonts: {
				files: [
					{
						cwd: 'website/assets/fonts/',
						src: ['**/**'],
						dest: server_root + 'website/assets/fonts/'
					}
				],
				//pretend: true,
				verbose: true
			}
		},

		ftpush: {
			uat: {
				auth: {
					host: 'prototype.projectName.aws1.adelphi.digital',
					port: '',
					authKey: 'uat'
				},
				dest: 'web/',
				src: 'website/',
				exclusions: [
					'.git/**/*',
					'**/.DS_Store',
					'**/Thumbs.db',
					'**/tmp',
					'.sass-cache/**/*',
					'node_modules/**/*',
					'grunt-start-up.txt',
					'grunt-first-time.txt',
					'Gruntfile.js',
					'package.json',
					'.ftppass',
					'**/**/*.js',
					'!website/assets/js/ZZ-merged-JS/*.js',
					'**/**/*.scss'//optional

					//UAT only
				],
				keep: [
					'.htaccess',
					'.htpasswd',
					'error/**/*',
					'stats/**/*',
				]
			}
		},

		watch: {
			options: {
				livereload: true
			},
			scripts: {
				files: ["website/assets/js/**/*.js", "!website/assets/js/ZZ-merged-JS/*.js"],
				tasks: [
					"concat", //merges constant js files into one file
					//"uglify", //minify JS
					//"sync:js" //copy js to server
				],
				options: { spawn: false }
			},
			images: {
				files: ['website/assets/images/**'],
				tasks: [
					'image_resize',
					'sprite',
					//"sync:images" //copy js to server
				],
				options: { spawn: false }
			},
			scss: {
				files: ["website/assets/sass/**/*.scss"],
				tasks: [
					"sass_globbing",//generates import maps for SASS modules
					"sass:modern", //compile the modern SASS (modern only by default for speed)
					//"sass:ie8", //compile the IE8 SASS
					//"sass:ie9", //compile the IE9 SASS
					"postcss"//merge media queries and add auto prefixing
					//"cmq", //merge media queries
					//"csso", //minify css
					//"sync:css" //copy css to server
				],
				options: { spawn: false }
			},
			html: {
				options: {
					livereload: true
				},
				//The other file types that will trigger a browser refresh on save
				tasks: [
					//"sync:html",
				],
				files: [
					"**/*.html",
					"**/*.htm",
					"**/*.php",
					"**/*.cshtml"
				]
			},
			fonts: {
				options: {
					livereload: true
				},
				//The other file types that will trigger a browser refresh on save
				tasks: [
					//"sync:fonts",
				],
				files: [
					"website/assets/fonts/**/**"
				]
			}
		}

	});

	//don't bother with the grunt.loadNpmTasks('xxx'); commands. They are generated automatically

	//list the tasks in the order you want them done in
	grunt.registerTask("default", [
		'image_resize',
		'sprite',

		"concat",//merge JS files
		"uglify",//minify JS
		"sass_globbing", //merge SASS files
		"sass",//compile CSS files for all browsers when running the grunt command
		"postcss",//merge media queries and add auto prefixing
		//"cmq",//combine media queries
		"csso",//minify css (css optimiser)
		//"sync",//copy files to another location
		"watch"
	]);

};<|endoftext|>


<commit_before>module.exports = function (grunt) {
    require('./grunt/tasks/config')(grunt);
    require('./grunt/tasks/build-tasks')(grunt);
    require('./grunt/tasks/js-tasks')(grunt);
    require('./grunt/tasks/css-tasks')(grunt);
    require('./grunt/tasks/qa-tasks')(grunt);

    /**
     * 'default' formerly known as 'grunt serve'
     */
    grunt.registerTask('default', [
        'build-develop',
        'connect:build',
        'watch'
    ]);

    grunt.registerTask('test', [
        'build-develop',
        'test-js',
        'test-css',
        'test-e2e'
    ]);

    grunt.registerTask('fulltest', [
        'build-develop',
        'test-js-full',
        'test-css'
    ]);
};
<commit_msg>Even dit bekijken in Jenkins...<commit_after>module.exports = function (grunt) {
    console.log(process.env);

    require('./grunt/tasks/config')(grunt);
    require('./grunt/tasks/build-tasks')(grunt);
    require('./grunt/tasks/js-tasks')(grunt);
    require('./grunt/tasks/css-tasks')(grunt);
    require('./grunt/tasks/qa-tasks')(grunt);

    /**
     * 'default' formerly known as 'grunt serve'
     */
    grunt.registerTask('default', [
        'build-develop',
        'connect:build',
        'watch'
    ]);

    grunt.registerTask('test', [
        'build-develop',
        'test-js',
        'test-css',
        'test-e2e'
    ]);

    grunt.registerTask('fulltest', [
        'build-develop',
        'test-js-full',
        'test-css'
    ]);
};
<|endoftext|>


<commit_before>/**
 * Titanium SDK Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var ti = require('./titanium'),
	appc = require('node-appc'),
	i18n = appc.i18n(__dirname),
	__ = i18n.__,
	__n = i18n.__n,
	afs = appc.fs,
	fs = require('fs'),
	path = require('path');

function stripQuotes(s) {
	return (''+s).replace(/^(['"])(.+)(['"])$/, '$2');
}

exports.load = function (dir, deviceFamilies, logger, callback) {
	var entries = {};

	afs.visitFiles(dir, function (file, full) {
		if (/.+\.jss$/.test(file)) {
			var base = file.substring(0, file.length - 4).split('.'),
				density = base.pop(),
				platform = base.pop();
				entry = {
					base: null,
					platform: null,
					density: {}
				};

			if (deviceFamilies.indexOf(platform) == -1) {
				platform && base.push(platform);
				// maybe the density is our platform?
				if (deviceFamilies.indexOf(density)) {
					density && base.push(density);
					platform = null;
				} else {
					platform = density;
				}
				density = null;
			}

			base = base.join('.');
			entries[base] && (entry = entries[base]);

			if (density) {
				entry.density[density] = full;
			} else if (platform) {
				entry.platform = full;
			} else {
				entry.base = full;
			}

			entries[base] = entry;
		}
	}, function () {
		var results = {},
			parse = require('css-parse'),
			propMap = {
				'background-image': 'backgroundImage',
				'background-url': 'backgroundImage',
				'text-align': 'textAlign',
				'border-radius': 'borderRadius',
				'border-color': 'borderColor',
				'border-width': 'borderWidth',
				'background-color': 'backgroundColor'
			},
			parseFile = function (file, name, density) {
				logger.debug(__('Parsing JSS file: %s', file.cyan));
				var rules = parse(fs.readFileSync(file).toString()).stylesheet.rules;
				rules.forEach(function (rule) {
					if (rule['import']) {
						var importFilename = stripQuotes(rule['import']),
							importFile = path.join(path.dirname(file), importFilename);
						if (!afs.exists(importFile)) {
							logger.error(__('Error parsing JSS file.') + '\n');
							logger.log(__("Couldn't find import file %s referenced from %s", importFilename.cyan, file.cyan) + '\n');
							process.exit(1);
						} else {
							parseFile(importFile, name, density);
						}
					} else if (rule.selectors) {
						rule.selectors.forEach(function (selector) {
							var c = selector.charAt(0),
								dest = c == '#' ? 'ids' : c == '.' ? 'classes' : 'tags';

							dest != 'tags' && (selector = selector.substring(1));
							density && (dest += '_density');

							rule.declarations.forEach(function (decl) {
								var prop = propMap[decl.property] || decl.property;
								results.hasOwnProperty(dest) || (results[dest] = {});
								results[dest].hasOwnProperty(name) || (results[dest][name] = {});
								if (density) {
									results[dest][name].hasOwnProperty('density') || (results[dest][name][density] = {});
									results[dest][name][density].hasOwnProperty(selector) || (results[dest][name][density][selector] = {});
									results[dest][name][density][selector][prop] = stripQuotes(decl.value);
								} else {
									results[dest][name].hasOwnProperty(selector) || (results[dest][name][selector] = {});
									results[dest][name][selector][prop] = stripQuotes(decl.value);
								}
							});
						});
					}
				});
			};

		if (Object.keys(entries).length) {
			logger.info(__('Loading and parsing JSS files'));

			Object.keys(entries).forEach(function(name) {
				var entry = entries[name];
				entry.base && parseFile(entry.base, name);
				entry.platform && parseFile(entry.platform, name);
				Object.keys(entry.density).forEach(function (d) {
					parseFile(entry.density[d], name, d);
				});
			});
		}

		callback(results);
	});
};
<commit_msg>[TIMOB-12264] Fixed font support in jss files.<commit_after>/**
 * Titanium SDK Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var appc = require('node-appc'),
	i18n = appc.i18n(__dirname),
	__ = i18n.__,
	afs = appc.fs,
	fs = require('fs'),
	path = require('path');

function stripQuotes(s) {
	return (''+s).replace(/^(['"])(.+)(['"])$/, '$2');
}

exports.load = function (dir, deviceFamilies, logger, callback) {
	var entries = {};

	afs.visitFiles(dir, function (file, full) {
		if (/.+\.jss$/.test(file)) {
			var base = file.substring(0, file.length - 4).split('.'),
				density = base.pop(),
				platform = base.pop();
				entry = {
					base: null,
					platform: null,
					density: {}
				};

			if (deviceFamilies.indexOf(platform) == -1) {
				platform && base.push(platform);
				// maybe the density is our platform?
				if (deviceFamilies.indexOf(density)) {
					density && base.push(density);
					platform = null;
				} else {
					platform = density;
				}
				density = null;
			}

			base = base.join('.');
			entries[base] && (entry = entries[base]);

			if (density) {
				entry.density[density] = full;
			} else if (platform) {
				entry.platform = full;
			} else {
				entry.base = full;
			}

			entries[base] = entry;
		}
	}, function () {
		var results = {},
			parse = require('css-parse'),
			propMap = {
				'background-image': 'backgroundImage',
				'background-url': 'backgroundImage',
				'text-align': 'textAlign',
				'border-radius': 'borderRadius',
				'border-color': 'borderColor',
				'border-width': 'borderWidth',
				'background-color': 'backgroundColor'
			},
			parseFile = function (file, name, density) {
				logger.debug(__('Parsing JSS file: %s', file.cyan));
				var rules = parse(fs.readFileSync(file).toString()).stylesheet.rules;
				rules.forEach(function (rule) {
					if (rule['import']) {
						var importFilename = stripQuotes(rule['import']),
							importFile = path.join(path.dirname(file), importFilename);
						if (!afs.exists(importFile)) {
							logger.error(__('Error parsing JSS file.') + '\n');
							logger.log(__("Couldn't find import file %s referenced from %s", importFilename.cyan, file.cyan) + '\n');
							process.exit(1);
						} else {
							parseFile(importFile, name, density);
						}
					} else if (rule.selectors) {
						rule.selectors.forEach(function (selector) {
							var c = selector.charAt(0),
								dest = c == '#' ? 'ids' : c == '.' ? 'classes' : 'tags';

							dest != 'tags' && (selector = selector.substring(1));
							density && (dest += '_density');

							rule.declarations.forEach(function (decl) {
								var prop = propMap[decl.property] || decl.property,
									tmp;

								results.hasOwnProperty(dest) || (results[dest] = {});
								results[dest].hasOwnProperty(name) || (results[dest][name] = {});

								if (density) {
									results[dest][name].hasOwnProperty('density') || (results[dest][name][density] = {});
									results[dest][name][density].hasOwnProperty(selector) || (results[dest][name][density][selector] = {});
									tmp = results[dest][name][density][selector];
								} else {
									results[dest][name].hasOwnProperty(selector) || (results[dest][name][selector] = {});
									tmp = results[dest][name][selector];
								}

								if (/^font-.+/.test(prop)) {
									// font-size, font-family, font-weight, and friends are special and need to go in special font object
									tmp = tmp.font || (tmp.font = {});
									prop = 'font' + prop.split('-').map(function (p) { return p.substring(0, 1).toUpperCase() + p.substring(1); }).join('').substring(4);
								}

								tmp[prop] = stripQuotes(decl.value)
							});
						});
					}
				});
			};

		if (Object.keys(entries).length) {
			logger.info(__('Loading and parsing JSS files'));

			Object.keys(entries).forEach(function (name) {
				var entry = entries[name];
				entry.base && parseFile(entry.base, name);
				entry.platform && parseFile(entry.platform, name);
				Object.keys(entry.density).forEach(function (d) {
					parseFile(entry.density[d], name, d);
				});
			});
		}

		callback(results);
	});
};
<|endoftext|>


<commit_before>(function(){
  var root = this,
      self, workersSocket, workflowsSocket, workflows;

  var Gush = {

    initialize: function(){
      self = this;
      workflows = [];
      console.log("Hello from gush");
      this.registerSockets();
      this.displayCurrentWorkflows();
      this.displayJobsOverview();
    },

    getWorkflows: function(){
      return workflows;
    },

    registerSockets: function(){
      this.registerWorkersSocket();
      this.registerWorkflowsSocket();
    },

    displayCurrentWorkflows: function(){
      $("table.workflows tbody").empty();
      $.each(($("table.workflows").data("workflows") || []), function(){
        self.addWorkflow(this);
      });
    },

    displayJobsOverview: function(){
      if(typeof nodes != "undefined"){
        var node;
        $.each(nodes, function(){
          node = new Node(this);
          console.log(node.render());
          $("table.nodes tbody").append(node.render());
        });
      }
    },

    registerWorkersSocket: function(){
      workersSocket = new EventSource("/subscribe/workers.status");

      workersSocket.onopen    = this.onOpen;
      workersSocket.onerror   = this.onError;
      workersSocket.onmessage = this.onStatus;
      workersSocket.onclose   = this.onClose;
    },

    registerWorkflowsSocket: function(){
      workflowsSocket = new EventSource("/subscribe/workflows.status");

      workflowsSocket.onopen    = this.onOpen;
      workflowsSocket.onerror   = this.onError;
      workflowsSocket.onmessage = this.onWorkflowStatusChange;
      workflowsSocket.onclose   = this.onClose;
    },

    onOpen: function(){
      $("#modalBox").foundation("reveal", "close");
    },

    onError: function(error){
      $("#modalBox .data").html("
Lost connection with server.

Reconnecting…
");
      $("#modalBox").foundation("reveal", "open");
      console.error(error);
    },

    onClose: function(){
      console.log("Connection closed");
    },

    onStatus: function(message){
      message = JSON.parse(message.data);

      switch(message.status){
        case "started":
          self.onJobStart(message);
          break;
        case "finished":
          self.onJobSuccess(message);
          break;
        case "heartbeat":
          self.onJobHeartbeat(message);
          break;
        case "failed":
          self.onJobFail(message);
          break;
        default:
          console.error("Unkown job status:", message.status, "data: ", message);
      }
    },

    onWorkflowStatusChange: function(message){
      message = JSON.parse(message.data);

      workflows[message.workflow_id].changeStatus(message.status);
    },

    onJobStart: function(message){
      this.markGraphNode(message.workflow_id, message.job, 'status-running');
      console.log("Job started:", message.job);
    },

    onJobSuccess: function(message){
      this.markGraphNode(message.workflow_id, message.job, 'status-finished');

      var workflow = workflows[message.workflow_id];
      if (workflow) {
        workflow.updateProgress();
        $("table.workflows").find("#" + message.workflow_id).replaceWith(workflow.render());
      }
    },

    onJobHeartbeat: function(message){
    },

    onJobFail: function(message){
      this.markGraphNode(message.workflow_id, message.job, 'status-finished status-failed');

      var workflow = workflows[message.workflow_id];
      workflow.markAsFailed();
      $("table.workflows").find("#" + message.workflow_id).replaceWith(workflow.render());
    },

    startWorkflow: function(workflow, el){
      $.ajax({
        url: "/start/" + workflow,
        type: "POST",
        error: function(response){
          console.log(response);
        }
      });

      if(el){
        el.removeClass("success")
          .addClass("alert")
          .data("action", "stop")
          .text("Stop Workflow")
      }
    },

    stopWorkflow: function(workflow, el){
      if(el){
        el.addClass("success")
          .removeClass("alert")
          .data("action", "start")
          .text("Start Workflow")
      }
    },

    createWorkflow: function(workflow){
      $.ajax({
        url: "/create/" + workflow,
        type: "POST",
        error: function(response){
          console.log(response);
        },
        success: function(response){
          self.addWorkflow(response);
        }
      });
    },

    markGraphNode: function(workflow_id, name, class_names) {
      name = name.replace(/::/g, '_').toLowerCase();
      $('svg[data-workflow-id=' + workflow_id +'] .node.' + name)
        .attr('class', 'node ' + name + ' ' + class_names);

      var total = $('svg[data-workflow-id=' + workflow_id +'] .node').length;
      var finished = $('svg[data-workflow-id=' + workflow_id +'] .node.status-finished').length;

      if (finished == total) {
        $('.button.start-workflow')
          .addClass('success')
          .removeClass('alert')
          .text("Start workflow");
      }
    },

    addWorkflow: function(data){
      data.progress = 0;
      var workflow = new Workflow(data);
      workflows[data.id] = workflow;

      $("table.workflows").append(workflow.render());
    }
  };

  var Workflow = function(data){
    this.data = data;
    this.template = $("#workflow-template").html();
    this.render = function(){
      return this.view.render();
    };
    this.updateProgress = function(){
      this.data.finished += 1;
      this.view.updateProgress(this.calculateProgress());
      return true;
    },
    this.changeStatus = function(status){
      this.data.status = status;
      if(this.view){
        this.view.updateStatus(status);
      }
    },
    this.markAsCompleted = function(){
      this.changeStatus("Finished");
    },
    this.markAsFailed = function(){
      this.changeStatus("Failed");
    },
    this.calculateProgress = function(){
      var progress = (this.data.finished*100)/this.data.total;
      if(progress == 100){
        this.markAsCompleted();
      }
      return progress;
    },
    this.view = new View(this.template, data, {progress: this.calculateProgress(), status: data.status});
  };

  var Templates = {
    status: function(status){
      var labelClass = {"Failed": "alert", "Running": "", "Finished": "success", "Pending": "secondary"};
      var template = $("#status-template").html();
      return Mustache.render(template, {status: status, class: labelClass[status]});
    },

    progress: function(progress){
      var template = $("#progress-template").html();
      return Mustache.render(template, {progress: parseInt(progress)});
    }
  };

  var View = function(template, params, partialsData){
    this.template = template;
    this.params = params;
    this.partialsData = partialsData;
    this.updateStatus = function(status){
      this.partialsData.status = status;
    },
    this.updateProgress = function(progress){
      this.partialsData.progress = progress;
    },
    this.incrementProgress = function(){
      this.partialsData.progress += 1;
    },
    this.partials = function(){
      return {progress: Templates.progress(this.partialsData.progress), status: Templates.status(this.partialsData.status)};
    },
    this.render = function(){
      return Mustache.render(template, params, this.partials());
    };
  };

  var Node = function(data){
    this.data = data;
    this.template = $("#node-template");

    this.isFinished = function(){
      return this.data.finished === true;
    },
    this.isFailed = function(){
      return this.data.failed == true
    },
    this.isRunning = function(){
      return this.data.running == true;
    },
    this.isWaiting = function(){
      return !this.isRunning() && !this.isFailed();
    },
    this.status = function(){
      if(this.isFinished()){
        return "Finished";
      }
      else if(this.isFailed()){
        return "Failed";
      }
      else if(this.isRunning()){
        return "Running"
      }
      else{
        return "Waiting";
      }
    },
    this.isValid = function(){
      return this.data.hasOwnProperty("finished");
    },
    this.render = function(){
      if(this.isValid()){
        return Mustache.render(this.template.html(), {name: this.data.name, status: this.status()} );
      }
    }
  }
  root.Gush = Gush;
})();

$(document).ready(function(){
  Gush.initialize();

  $(this).on("click", ".button.start-workflow", function(){
    if($(this).data("action") === "start"){
      Gush.startWorkflow($(this).data("workflow-id"), $(this));
    }
    else{
      Gush.stopWorkflow($(this).data("workflow-id"), $(this));
    }
  });

  $(this).on("click", ".create-workflow", function () {
    Gush.createWorkflow($(this).data("workflow-class"));
  })
});
<commit_msg>remove another unneede log<commit_after>(function(){
  var root = this,
      self, workersSocket, workflowsSocket, workflows;

  var Gush = {

    initialize: function(){
      self = this;
      workflows = [];
      console.log("Hello from gush");
      this.registerSockets();
      this.displayCurrentWorkflows();
      this.displayJobsOverview();
    },

    getWorkflows: function(){
      return workflows;
    },

    registerSockets: function(){
      this.registerWorkersSocket();
      this.registerWorkflowsSocket();
    },

    displayCurrentWorkflows: function(){
      $("table.workflows tbody").empty();
      $.each(($("table.workflows").data("workflows") || []), function(){
        self.addWorkflow(this);
      });
    },

    displayJobsOverview: function(){
      if(typeof nodes != "undefined"){
        var node;
        $.each(nodes, function(){
          node = new Node(this);
          console.log(node.render());
          $("table.nodes tbody").append(node.render());
        });
      }
    },

    registerWorkersSocket: function(){
      workersSocket = new EventSource("/subscribe/workers.status");

      workersSocket.onopen    = this.onOpen;
      workersSocket.onerror   = this.onError;
      workersSocket.onmessage = this.onStatus;
      workersSocket.onclose   = this.onClose;
    },

    registerWorkflowsSocket: function(){
      workflowsSocket = new EventSource("/subscribe/workflows.status");

      workflowsSocket.onopen    = this.onOpen;
      workflowsSocket.onerror   = this.onError;
      workflowsSocket.onmessage = this.onWorkflowStatusChange;
      workflowsSocket.onclose   = this.onClose;
    },

    onOpen: function(){
      $("#modalBox").foundation("reveal", "close");
    },

    onError: function(error){
      $("#modalBox .data").html("
Lost connection with server.

Reconnecting…
");
      $("#modalBox").foundation("reveal", "open");
      console.error(error);
    },

    onClose: function(){
      console.log("Connection closed");
    },

    onStatus: function(message){
      message = JSON.parse(message.data);

      switch(message.status){
        case "started":
          self.onJobStart(message);
          break;
        case "finished":
          self.onJobSuccess(message);
          break;
        case "heartbeat":
          self.onJobHeartbeat(message);
          break;
        case "failed":
          self.onJobFail(message);
          break;
        default:
          console.error("Unkown job status:", message.status, "data: ", message);
      }
    },

    onWorkflowStatusChange: function(message){
      message = JSON.parse(message.data);

      workflows[message.workflow_id].changeStatus(message.status);
    },

    onJobStart: function(message){
      this.markGraphNode(message.workflow_id, message.job, 'status-running');
    },

    onJobSuccess: function(message){
      this.markGraphNode(message.workflow_id, message.job, 'status-finished');

      var workflow = workflows[message.workflow_id];
      if (workflow) {
        workflow.updateProgress();
        $("table.workflows").find("#" + message.workflow_id).replaceWith(workflow.render());
      }
    },

    onJobHeartbeat: function(message){
    },

    onJobFail: function(message){
      this.markGraphNode(message.workflow_id, message.job, 'status-finished status-failed');

      var workflow = workflows[message.workflow_id];
      workflow.markAsFailed();
      $("table.workflows").find("#" + message.workflow_id).replaceWith(workflow.render());
    },

    startWorkflow: function(workflow, el){
      $.ajax({
        url: "/start/" + workflow,
        type: "POST",
        error: function(response){
          console.log(response);
        }
      });

      if(el){
        el.removeClass("success")
          .addClass("alert")
          .data("action", "stop")
          .text("Stop Workflow")
      }
    },

    stopWorkflow: function(workflow, el){
      if(el){
        el.addClass("success")
          .removeClass("alert")
          .data("action", "start")
          .text("Start Workflow")
      }
    },

    createWorkflow: function(workflow){
      $.ajax({
        url: "/create/" + workflow,
        type: "POST",
        error: function(response){
          console.log(response);
        },
        success: function(response){
          self.addWorkflow(response);
        }
      });
    },

    markGraphNode: function(workflow_id, name, class_names) {
      name = name.replace(/::/g, '_').toLowerCase();
      $('svg[data-workflow-id=' + workflow_id +'] .node.' + name)
        .attr('class', 'node ' + name + ' ' + class_names);

      var total = $('svg[data-workflow-id=' + workflow_id +'] .node').length;
      var finished = $('svg[data-workflow-id=' + workflow_id +'] .node.status-finished').length;

      if (finished == total) {
        $('.button.start-workflow')
          .addClass('success')
          .removeClass('alert')
          .text("Start workflow");
      }
    },

    addWorkflow: function(data){
      data.progress = 0;
      var workflow = new Workflow(data);
      workflows[data.id] = workflow;

      $("table.workflows").append(workflow.render());
    }
  };

  var Workflow = function(data){
    this.data = data;
    this.template = $("#workflow-template").html();
    this.render = function(){
      return this.view.render();
    };
    this.updateProgress = function(){
      this.data.finished += 1;
      this.view.updateProgress(this.calculateProgress());
      return true;
    },
    this.changeStatus = function(status){
      this.data.status = status;
      if(this.view){
        this.view.updateStatus(status);
      }
    },
    this.markAsCompleted = function(){
      this.changeStatus("Finished");
    },
    this.markAsFailed = function(){
      this.changeStatus("Failed");
    },
    this.calculateProgress = function(){
      var progress = (this.data.finished*100)/this.data.total;
      if(progress == 100){
        this.markAsCompleted();
      }
      return progress;
    },
    this.view = new View(this.template, data, {progress: this.calculateProgress(), status: data.status});
  };

  var Templates = {
    status: function(status){
      var labelClass = {"Failed": "alert", "Running": "", "Finished": "success", "Pending": "secondary"};
      var template = $("#status-template").html();
      return Mustache.render(template, {status: status, class: labelClass[status]});
    },

    progress: function(progress){
      var template = $("#progress-template").html();
      return Mustache.render(template, {progress: parseInt(progress)});
    }
  };

  var View = function(template, params, partialsData){
    this.template = template;
    this.params = params;
    this.partialsData = partialsData;
    this.updateStatus = function(status){
      this.partialsData.status = status;
    },
    this.updateProgress = function(progress){
      this.partialsData.progress = progress;
    },
    this.incrementProgress = function(){
      this.partialsData.progress += 1;
    },
    this.partials = function(){
      return {progress: Templates.progress(this.partialsData.progress), status: Templates.status(this.partialsData.status)};
    },
    this.render = function(){
      return Mustache.render(template, params, this.partials());
    };
  };

  var Node = function(data){
    this.data = data;
    this.template = $("#node-template");

    this.isFinished = function(){
      return this.data.finished === true;
    },
    this.isFailed = function(){
      return this.data.failed == true
    },
    this.isRunning = function(){
      return this.data.running == true;
    },
    this.isWaiting = function(){
      return !this.isRunning() && !this.isFailed();
    },
    this.status = function(){
      if(this.isFinished()){
        return "Finished";
      }
      else if(this.isFailed()){
        return "Failed";
      }
      else if(this.isRunning()){
        return "Running"
      }
      else{
        return "Waiting";
      }
    },
    this.isValid = function(){
      return this.data.hasOwnProperty("finished");
    },
    this.render = function(){
      if(this.isValid()){
        return Mustache.render(this.template.html(), {name: this.data.name, status: this.status()} );
      }
    }
  }
  root.Gush = Gush;
})();

$(document).ready(function(){
  Gush.initialize();

  $(this).on("click", ".button.start-workflow", function(){
    if($(this).data("action") === "start"){
      Gush.startWorkflow($(this).data("workflow-id"), $(this));
    }
    else{
      Gush.stopWorkflow($(this).data("workflow-id"), $(this));
    }
  });

  $(this).on("click", ".create-workflow", function () {
    Gush.createWorkflow($(this).data("workflow-class"));
  })
});
<|endoftext|>


<commit_before>/* ==========================================================================
   Yes We Work WordPress + Vagrant development kit
   ========================================================================== */

var gulp = require('gulp'),
	autoprefixer = require('autoprefixer'),
	browserSync = require('browser-sync').create(),
	del = require('del'),
	beml = require('gulp-beml'),
	concat = require('gulp-concat'),
	changed = require('gulp-changed'),
	csslint = require('gulp-csslint'),
	cssnano = require('gulp-cssnano'),
	gulpFilter = require('gulp-filter'),
	flatten = require('gulp-flatten'),
	imagemin = require('gulp-imagemin'),
	jshint = require('gulp-jshint'),
	postcss = require('gulp-postcss'),
	rename = require('gulp-rename'),
	sourcemaps = require('gulp-sourcemaps'),
	tap = require('gulp-tap'),
	fs = require('fs'),
	uglify = require('gulp-uglify'),
	lost = require('lost'),
	mainBowerFiles = require('main-bower-files'),
	postcssFontpath = require('postcss-fontpath'),
	postcssNested = require('postcss-nested'),
	postcssNestedProps = require('postcss-nested-props'),
	postcssSimpleVars = require('postcss-simple-vars'),
	shell = require('shelljs'),
	ftp = require('vinyl-ftp'),
	YAML = require('yamljs');

// Default project settings
var projectSlug = 'yww-project';
var projectUrl = 'yeswework.dev';
var projectName = 'YWW Project';
var projectAuthor = 'Yes We Work - http://yeswework.com/';

// Overwrite with defaults from Vagrant's YML file in the parent folder, if available
var projectSettings = YAML.load('site.yml');
if(typeof projectSettings.slug != 'undefined' && projectSettings.slug != '') {
	var projectSlug = projectSettings.slug;
}
if(typeof projectSettings.hostname != 'undefined' && projectSettings.hostname != '') {
	var projectUrl = projectSettings.hostname;
}
if(typeof projectSettings.title != 'undefined' && projectSettings.title != '') {
	var projectName = projectSettings.title;
}

// Paths for remapping
var base = {
	src: './dev/src/',
	build: './dev/build/',
	theme: './www/wordpress/wp-content/themes/' + projectSlug + '/'
};

// Globs for each file type
var glob = {
	acfTheme: base.theme + 'acf-json/*.json',
	acf: base.src + 'acf-json/*.json',
	bower: base.src + 'bower_components/**/*.php',
	includes: [base.src + 'includes/**/*.php', base.src + 'includes/.env'],
	controllers: base.src + 'templates/controllers/**/*.php',
	views: base.src + 'templates/**/*.twig',
	styles: base.src + 'assets/css/**/*.{css,pcss}',
	scripts: base.src + 'assets/js/**/*.js',
	images: base.src + 'assets/img/**/*',
	fonts: base.src + 'assets/fonts/**/*'
};

// Build folder slugs
var dest = {
	acf: 'acf-json',
	includes: 'inc',
	controllers: '', // need to go in the root theme folder
	views: 'views',
	styles: 'css',
	scripts: 'js',
	images: 'img',
	fonts: 'fonts'
};

// Plugin options
var options = {
	uglify: {mangle: false},
	imagemin: {optimizationLevel: 7, progressive: true, interlaced: true, multipass: true},
	postcss: [
		postcssSimpleVars,
		postcssNestedProps,
		postcssNested,
		postcssFontpath,
		lost,
		autoprefixer({browsers: ['last 3 versions']})
	],
	beml: {
		elemPrefix: '__',
		modPrefix: '--',
		modDlmtr: '-'
	}
};

// Before cleaning, retrieve latest ACF JSON from live theme
// This is the only task which modifies the src folder
gulp.task('acfPull', function() {
	del(base.src + dest.acf);
	return gulp.src(glob.acfTheme)
		.pipe(gulp.dest(base.src + dest.acf));
});

// Erase build and theme folders before each compile
gulp.task('clean', function(cb) {
	del(base.build);
	del(base.theme, {force: true});
	cb(); // indicate completion
});

// Bower: concatenate "main files" into library script and stylesheet and copy
gulp.task('bower', function() {
	var jsFilter = gulpFilter('**/*.js', {restore: true});
	var cssFilter = gulpFilter('**/*.css', {restore: true});
	return gulp.src(mainBowerFiles({paths: base.src}))
		.pipe(jsFilter)
		.pipe(concat('lib.js'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream())
		.pipe(uglify(options.uglify))
		.pipe(rename('lib.min.js'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream())
		.pipe(jsFilter.restore)
		.pipe(cssFilter)
		.pipe(concat('lib.css'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}))
		.pipe(cssnano())
		.pipe(rename('lib.min.css'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}));
});

// style.css: auto-create our theme's style.css using project info we already have
gulp.task('style.css', function(cb) {
	var data = '/*\r\n'
		+ 'Theme Name: ' + projectName + '\r\n'
		+ 'Theme URI: http://' + projectUrl + '\r\n'
		+ 'Author: ' + projectAuthor + '\r\n' + '*/';
	fs.writeFileSync(base.build + 'style.css', data);
	fs.writeFileSync(base.theme + 'style.css', data);
	cb(); // indicate completion
});

// Put ACF JSON back (previously saved with acfPull task)
gulp.task('acf', function() {
	fs.mkdir(base.theme + dest.acf); // Create this folder under any circumstances, so ACF saves to it
	return gulp.src(glob.acf)
		.pipe(gulp.dest(base.build + dest.acf))
		.pipe(gulp.dest(base.theme + dest.acf));
});

// Includes: copy internal PHP dependencies to an inc folder and auto-create functions.php with includes
gulp.task('includes', function() {
	fs.writeFileSync(base.build + 'functions.php', '<?php\r\n'); // create a blank functions.php
	fs.writeFileSync(base.theme + 'functions.php', '<?php\r\n');
	var nonVendorFilter = gulpFilter('*.php', {restore: true}); // only require top-level files in functions.php
	return gulp.src(glob.includes)
		.pipe(nonVendorFilter)
		.pipe(tap(function(file, t) {// write an include for this file to our functions.php automatically
			fs.appendFileSync(base.build + 'functions.php', "require_once(get_stylesheet_directory() . '/" + dest.includes + "/" + file.path.replace(file.base, '') + "');\r\n");
			fs.appendFileSync(base.theme + 'functions.php', "require_once(get_stylesheet_directory() . '/" + dest.includes + "/" + file.path.replace(file.base, '') + "');\r\n");
		}))
		.pipe(nonVendorFilter.restore)
		.pipe(changed(base.build + dest.includes))
		.pipe(gulp.dest(base.build + dest.includes))
		.pipe(gulp.dest(base.theme + dest.includes))
		.pipe(browserSync.stream());
});

// Controllers: copy PHP files, flattening tree
gulp.task('controllers', function() {
	return gulp.src(glob.controllers)
		.pipe(flatten())
		.pipe(changed(base.build + dest.controllers))
		.pipe(gulp.dest(base.build + dest.controllers))
		.pipe(gulp.dest(base.theme + dest.controllers))
		.pipe(browserSync.stream());
});

// Views: copy Twig files, flattening tree
gulp.task('views', function() {
	return gulp.src(glob.views)
		.pipe(flatten())
		.pipe(changed(base.build + dest.views))
		/* .pipe(beml(options.beml)) */
		.pipe(gulp.dest(base.build + dest.views))
		.pipe(gulp.dest(base.theme + dest.views))
		.pipe(browserSync.stream());
});

// Styles (CSS): lint, concatenate into one file, write source map, postcss, save full and minified versions, then copy
gulp.task('styles', function() {
	var lintFilter = gulpFilter(['**/*', '!defaults.css', '!helpers.css'], {restore: true});
	return gulp.src(glob.styles)
		.pipe(postcss(options.postcss))
		.pipe(lintFilter) // don't lint certain files which we use on all projects
		.pipe(csslint({'font-sizes': false, 'box-model': false, 'compatible-vendor-prefixes': false}))
		.pipe(csslint.reporter())
		.pipe(lintFilter.restore) // restore all files after linting
		.pipe(concat('main.css'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}))
		.pipe(cssnano())
		.pipe(rename('main.min.css'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}));
});

// Scripts (JS): lint, concatenate into one file, save full and minified versions, then copy
gulp.task('scripts', function() {
	return gulp.src(glob.scripts)
		.pipe(jshint())
		.pipe(jshint.reporter())
		.pipe(concat('main.js'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream())
		.pipe(uglify(options.uglify))
		.pipe(rename('main.min.js'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream());
});

// Images: optimise and copy, maintaining tree
gulp.task('images', function() {
	return gulp.src(glob.images)
		.pipe(changed(base.build + dest.images))
		.pipe(imagemin(options.imagemin))
		.pipe(gulp.dest(base.build + dest.images))
		.pipe(gulp.dest(base.theme + dest.images))
		.pipe(browserSync.stream());
});

// Fonts: just copy, maintaining tree
gulp.task('fonts', function() {
	return gulp.src(glob.fonts)
		.pipe(changed(base.build + dest.fonts))
		.pipe(gulp.dest(base.build + dest.fonts))
		.pipe(gulp.dest(base.theme + dest.fonts))
		.pipe(browserSync.stream());
});

// Build: sequences all the other tasks
gulp.task('build', gulp.series('acfPull', 'clean', 'bower', gulp.parallel('style.css', 'acf', 'includes', 'controllers', 'views', 'styles', 'scripts', 'images', 'fonts')));

// Install: tell Vagrant to activate the built theme
gulp.task('install', gulp.series('build', activate));
function activate(cb) {
	shell.exec('vagrant ssh -c "wp theme activate ' + projectSlug + '"');
	cb(); // indicate completion
}

// Watch: fire build, then watch for changes
gulp.task('default', gulp.series('build', watch));
function watch() {
	browserSync.init({
		proxy: projectUrl,
		open: false
	});
	gulp.watch(glob.styles, gulp.series('styles'));
	gulp.watch(glob.bower, gulp.series('bower'));
	gulp.watch(glob.includes, gulp.series('includes'));
	gulp.watch(glob.controllers, gulp.series('controllers'));
	gulp.watch(glob.views, gulp.series('views'));
	gulp.watch(glob.scripts, gulp.series('scripts'));
	gulp.watch(glob.images, gulp.series('images'));
	gulp.watch(glob.fonts, gulp.series('fonts'));
}
<commit_msg>suppressed annoying CSS lint rule<commit_after>/* ==========================================================================
   Yes We Work WordPress + Vagrant development kit
   ========================================================================== */

var gulp = require('gulp'),
	autoprefixer = require('autoprefixer'),
	browserSync = require('browser-sync').create(),
	del = require('del'),
	beml = require('gulp-beml'),
	concat = require('gulp-concat'),
	changed = require('gulp-changed'),
	csslint = require('gulp-csslint'),
	cssnano = require('gulp-cssnano'),
	gulpFilter = require('gulp-filter'),
	flatten = require('gulp-flatten'),
	imagemin = require('gulp-imagemin'),
	jshint = require('gulp-jshint'),
	postcss = require('gulp-postcss'),
	rename = require('gulp-rename'),
	sourcemaps = require('gulp-sourcemaps'),
	tap = require('gulp-tap'),
	fs = require('fs'),
	uglify = require('gulp-uglify'),
	lost = require('lost'),
	mainBowerFiles = require('main-bower-files'),
	postcssFontpath = require('postcss-fontpath'),
	postcssNested = require('postcss-nested'),
	postcssNestedProps = require('postcss-nested-props'),
	postcssSimpleVars = require('postcss-simple-vars'),
	shell = require('shelljs'),
	ftp = require('vinyl-ftp'),
	YAML = require('yamljs');

// Default project settings
var projectSlug = 'yww-project';
var projectUrl = 'yeswework.dev';
var projectName = 'YWW Project';
var projectAuthor = 'Yes We Work - http://yeswework.com/';

// Overwrite with defaults from Vagrant's YML file in the parent folder, if available
var projectSettings = YAML.load('site.yml');
if(typeof projectSettings.slug != 'undefined' && projectSettings.slug != '') {
	var projectSlug = projectSettings.slug;
}
if(typeof projectSettings.hostname != 'undefined' && projectSettings.hostname != '') {
	var projectUrl = projectSettings.hostname;
}
if(typeof projectSettings.title != 'undefined' && projectSettings.title != '') {
	var projectName = projectSettings.title;
}

// Paths for remapping
var base = {
	src: './dev/src/',
	build: './dev/build/',
	theme: './www/wordpress/wp-content/themes/' + projectSlug + '/'
};

// Globs for each file type
var glob = {
	acfTheme: base.theme + 'acf-json/*.json',
	acf: base.src + 'acf-json/*.json',
	bower: base.src + 'bower_components/**/*.php',
	includes: [base.src + 'includes/**/*.php', base.src + 'includes/.env'],
	controllers: base.src + 'templates/controllers/**/*.php',
	views: base.src + 'templates/**/*.twig',
	styles: base.src + 'assets/css/**/*.{css,pcss}',
	scripts: base.src + 'assets/js/**/*.js',
	images: base.src + 'assets/img/**/*',
	fonts: base.src + 'assets/fonts/**/*'
};

// Build folder slugs
var dest = {
	acf: 'acf-json',
	includes: 'inc',
	controllers: '', // need to go in the root theme folder
	views: 'views',
	styles: 'css',
	scripts: 'js',
	images: 'img',
	fonts: 'fonts'
};

// Plugin options
var options = {
	uglify: {mangle: false},
	imagemin: {optimizationLevel: 7, progressive: true, interlaced: true, multipass: true},
	postcss: [
		postcssSimpleVars,
		postcssNestedProps,
		postcssNested,
		postcssFontpath,
		lost,
		autoprefixer({browsers: ['last 3 versions']})
	],
	beml: {
		elemPrefix: '__',
		modPrefix: '--',
		modDlmtr: '-'
	}
};

// Before cleaning, retrieve latest ACF JSON from live theme
// This is the only task which modifies the src folder
gulp.task('acfPull', function() {
	del(base.src + dest.acf);
	return gulp.src(glob.acfTheme)
		.pipe(gulp.dest(base.src + dest.acf));
});

// Erase build and theme folders before each compile
gulp.task('clean', function(cb) {
	del(base.build);
	del(base.theme, {force: true});
	cb(); // indicate completion
});

// Bower: concatenate "main files" into library script and stylesheet and copy
gulp.task('bower', function() {
	var jsFilter = gulpFilter('**/*.js', {restore: true});
	var cssFilter = gulpFilter('**/*.css', {restore: true});
	return gulp.src(mainBowerFiles({paths: base.src}))
		.pipe(jsFilter)
		.pipe(concat('lib.js'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream())
		.pipe(uglify(options.uglify))
		.pipe(rename('lib.min.js'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream())
		.pipe(jsFilter.restore)
		.pipe(cssFilter)
		.pipe(concat('lib.css'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}))
		.pipe(cssnano())
		.pipe(rename('lib.min.css'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}));
});

// style.css: auto-create our theme's style.css using project info we already have
gulp.task('style.css', function(cb) {
	var data = '/*\r\n'
		+ 'Theme Name: ' + projectName + '\r\n'
		+ 'Theme URI: http://' + projectUrl + '\r\n'
		+ 'Author: ' + projectAuthor + '\r\n' + '*/';
	fs.writeFileSync(base.build + 'style.css', data);
	fs.writeFileSync(base.theme + 'style.css', data);
	cb(); // indicate completion
});

// Put ACF JSON back (previously saved with acfPull task)
gulp.task('acf', function() {
	fs.mkdir(base.theme + dest.acf); // Create this folder under any circumstances, so ACF saves to it
	return gulp.src(glob.acf)
		.pipe(gulp.dest(base.build + dest.acf))
		.pipe(gulp.dest(base.theme + dest.acf));
});

// Includes: copy internal PHP dependencies to an inc folder and auto-create functions.php with includes
gulp.task('includes', function() {
	fs.writeFileSync(base.build + 'functions.php', '<?php\r\n'); // create a blank functions.php
	fs.writeFileSync(base.theme + 'functions.php', '<?php\r\n');
	var nonVendorFilter = gulpFilter('*.php', {restore: true}); // only require top-level files in functions.php
	return gulp.src(glob.includes)
		.pipe(nonVendorFilter)
		.pipe(tap(function(file, t) {// write an include for this file to our functions.php automatically
			fs.appendFileSync(base.build + 'functions.php', "require_once(get_stylesheet_directory() . '/" + dest.includes + "/" + file.path.replace(file.base, '') + "');\r\n");
			fs.appendFileSync(base.theme + 'functions.php', "require_once(get_stylesheet_directory() . '/" + dest.includes + "/" + file.path.replace(file.base, '') + "');\r\n");
		}))
		.pipe(nonVendorFilter.restore)
		.pipe(changed(base.build + dest.includes))
		.pipe(gulp.dest(base.build + dest.includes))
		.pipe(gulp.dest(base.theme + dest.includes))
		.pipe(browserSync.stream());
});

// Controllers: copy PHP files, flattening tree
gulp.task('controllers', function() {
	return gulp.src(glob.controllers)
		.pipe(flatten())
		.pipe(changed(base.build + dest.controllers))
		.pipe(gulp.dest(base.build + dest.controllers))
		.pipe(gulp.dest(base.theme + dest.controllers))
		.pipe(browserSync.stream());
});

// Views: copy Twig files, flattening tree
gulp.task('views', function() {
	return gulp.src(glob.views)
		.pipe(flatten())
		.pipe(changed(base.build + dest.views))
		.pipe(beml(options.beml))
		.pipe(gulp.dest(base.build + dest.views))
		.pipe(gulp.dest(base.theme + dest.views))
		.pipe(browserSync.stream());
});

// Styles (CSS): lint, concatenate into one file, write source map, postcss, save full and minified versions, then copy
gulp.task('styles', function() {
	var lintFilter = gulpFilter(['**/*', '!defaults.css', '!helpers.css'], {restore: true});
	return gulp.src(glob.styles)
		.pipe(postcss(options.postcss))
		.pipe(lintFilter) // don't lint certain files which we use on all projects
		.pipe(csslint({'font-sizes': false, 'box-model': false, 'compatible-vendor-prefixes': false, 'font-faces': false}))
		.pipe(csslint.reporter())
		.pipe(lintFilter.restore) // restore all files after linting
		.pipe(concat('main.css'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}))
		.pipe(cssnano())
		.pipe(rename('main.min.css'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.styles))
		.pipe(gulp.dest(base.build + dest.styles))
		.pipe(gulp.dest(base.theme + dest.styles))
		.pipe(browserSync.stream({match: '**/*.css'}));
});

// Scripts (JS): lint, concatenate into one file, save full and minified versions, then copy
gulp.task('scripts', function() {
	return gulp.src(glob.scripts)
		.pipe(jshint())
		.pipe(jshint.reporter())
		.pipe(concat('main.js'))
		.pipe(sourcemaps.init())
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream())
		.pipe(uglify(options.uglify))
		.pipe(rename('main.min.js'))
		.pipe(sourcemaps.write('.'))
		.pipe(changed(base.build + dest.scripts))
		.pipe(gulp.dest(base.build + dest.scripts))
		.pipe(gulp.dest(base.theme + dest.scripts))
		.pipe(browserSync.stream());
});

// Images: optimise and copy, maintaining tree
gulp.task('images', function() {
	return gulp.src(glob.images)
		.pipe(changed(base.build + dest.images))
		.pipe(imagemin(options.imagemin))
		.pipe(gulp.dest(base.build + dest.images))
		.pipe(gulp.dest(base.theme + dest.images))
		.pipe(browserSync.stream());
});

// Fonts: just copy, maintaining tree
gulp.task('fonts', function() {
	return gulp.src(glob.fonts)
		.pipe(changed(base.build + dest.fonts))
		.pipe(gulp.dest(base.build + dest.fonts))
		.pipe(gulp.dest(base.theme + dest.fonts))
		.pipe(browserSync.stream());
});

// Build: sequences all the other tasks
gulp.task('build', gulp.series('acfPull', 'clean', 'bower', gulp.parallel('style.css', 'acf', 'includes', 'controllers', 'views', 'styles', 'scripts', 'images', 'fonts')));

// Install: tell Vagrant to activate the built theme
gulp.task('install', gulp.series('build', activate));
function activate(cb) {
	shell.exec('vagrant ssh -c "wp theme activate ' + projectSlug + '"');
	cb(); // indicate completion
}

// Watch: fire build, then watch for changes
gulp.task('default', gulp.series('build', watch));
function watch() {
	browserSync.init({
		proxy: projectUrl,
		open: false
	});
	gulp.watch(glob.styles, gulp.series('styles'));
	gulp.watch(glob.bower, gulp.series('bower'));
	gulp.watch(glob.includes, gulp.series('includes'));
	gulp.watch(glob.controllers, gulp.series('controllers'));
	gulp.watch(glob.views, gulp.series('views'));
	gulp.watch(glob.scripts, gulp.series('scripts'));
	gulp.watch(glob.images, gulp.series('images'));
	gulp.watch(glob.fonts, gulp.series('fonts'));
}
<|endoftext|>


<commit_before>/* globals $ */
window.openGitMD = function(target) {
  window.open('https://github.com/Altinn/DesignSystem/edit/master/source' +
    $(target).closest('.sg-pattern').find('.patternLink')
      .attr('href')
      .replace('DesignSystem/', '')
      .replace(/\.\.\//g, '')
      .replace('patterns', '/_patterns')
      .replace(/(?:[^/*]*)$/, '')
      .slice(0, -1)
      .replace(/-([0-9]{2})/g, '/$1') + '.md', '_blank'
  );
};
<commit_msg>link to github now works<commit_after>/* globals $ */
window.openGitMD = function(target) {
  window.open('https://github.com/Altinn/DesignSystem/edit/master/source' +
    $(target).closest('.sg-pattern').find('.patternLink')
      .attr('href')
      .replace('DesignSystem/', '')
      .replace(/\.\.\//g, '')
      .replace('patterns', '/_patterns')
      .replace(/(?:[^\\*]*)$/, '')
      .replace('\\', '.md')
      .replace(/-([0-9]{2})/g, '/$1'), '_blank'
  );
};
<|endoftext|>