<commit_before>'use strict';

function RoundManager(game, bulletManager, enemyManager, weaponManager, powerupManager)
{

var self = this;

// Variables related to managing game mechanics

self.dirty = [];
self.dirty['score'] = true;
self.dirty['playerAmount'] = true;
self.dirty['rooms'] = true;

var players = {};
var playerGroup = game.add.group();
playerGroup = game.add.physicsGroup(Phaser.Physics.ARCADE);
playerGroup.enableBody = true;

var minPlayerSpawnDistance = 10;

var scoreBoard = new  ScoreBoard(game, {x: 0, y: 0});

var roundRunning = false;

var qr = game.add.sprite(game.camera.x + game.camera.width, game.camera.y + game.camera.height, 'qr_niko_wlan_niko'); //or: 'qr_janika'
qr.scale.x = 0.5*scalingFactors.x;
qr.scale.y = 0.5*scalingFactors.y;
game.physics.enable(qr, Phaser.Physics.ARCADE);
qr.body.immovable = true;
qr.anchor.setTo(1,1);

//This group is used to manage the draw order of other groups
//The draw order is defined by the order in which groupds are added
//The last gorup is always drawn on top of others
var drawOrderGroup = game.add.group();

self.backgroundLayerGroup = game.add.group();
self.popUpGroup = game.add.group();
self.collisionGroup = game.add.group();

var fpsText = game.add.text(game.camera.x, game.camera.y + game.camera.height, '', { fontSize: '12px', fill: '#f00'});
fpsText.anchor.setTo(0, 1);
fpsText.stroke = '#000000';
fpsText.strokeThickness = 1;

// Variables related to map functioning

var currentRound;
var currentDirection;
var currentSpeed;
var rooms = [];
var roomGroup = game.add.group();
var nextRoom;

var lastPaused = 0;
var pauseTime = 500;

var defaultMinDX = 6 * game.world.width;
var defaultMinDY = 6 * game.world.height;

var currentMinDX = defaultMinDX;
var currentMinDY = defaultMinDY;

var speedDict = [];
speedDict["normal"] = 0.5;
speedDict["fast"] = 1;
speedDict["stop"] = null;

self.roundOver = false;
self.lastRoomTimeout = 600000; //600s
self.lastRoomTimer = 0;

var done = false;

var initialSpawnBorder = game.width/15;
self.loadRound = function (roundData)
	{

	// Set camera in the middle of the stage
	game.camera.x = Math.floor(game.world.width/2 - game.camera.width/2);
	game.camera.y = Math.floor(game.world.height/2 - game.camera.height/2);
	currentRound = roundData;

	rooms[0] = null;

	// Load first two rooms;
	for (var i = 0; i < Math.min(2, currentRound.rooms.length); i++)
		{
		rooms[i + 1] = new Room(game,
														currentRound.rooms[i].roomBg,
														currentRound.rooms[i].colliders,
														currentRound.rooms[i].moveDirection,
														currentRound.rooms[i].moveSpeed,
														self);
		self.dirty['rooms'] = true;
		}
	nextRoom = 2;

	// Position the two loaded rooms

	rooms[1].moveTo(game.camera.x, game.camera.y);
	if (rooms[2] != undefined)
		{
		switch (rooms[1].moveDirection)
			{
			case "north":
				rooms[2].moveTo(game.camera.x, game.camera.y, - game.camera.height);
				break;
			case "east":
				rooms[2].moveTo(game.camera.x + game.camera.width, game.camera.y);
				break;
			case "south":
				rooms[2].moveTo(game.camera.x, game.camera.y + game.camera.height);
				break;
			case "west":
				rooms[2].moveTo(game.camera.x - game.camera.width, game.camera.y);
				break;
			default:
				rooms[2] = null;
			}
		}

	roundRunning = true;
	currentDirection = rooms[1].moveDirection;
	currentSpeed = rooms[1].moveSpeed;
	establishDrawOrder();
	};

/**
* Initializes the draw order of all sprite groups in the game
* GROUPS ARE DRAWN IN THE ORDER THEY ARE DEFINED!
* New groups always go above older ones
*/
var establishDrawOrder = function()
	{
	drawOrderGroup.add(self.backgroundLayerGroup);
	drawOrderGroup.add(enemyManager.enemyGroup);
	drawOrderGroup.add(powerupManager.pUpGroup);
	drawOrderGroup.add(playerGroup);
	drawOrderGroup.add(weaponManager.weaponGroup);
	drawOrderGroup.add(self.collisionGroup);
	drawOrderGroup.add(scoreBoard.sprite);
	drawOrderGroup.add(bulletManager.playerBulletGroup);
	drawOrderGroup.add(bulletManager.enemyBulletGroup);
	drawOrderGroup.add(self.popUpGroup);
	drawOrderGroup.add(qr);
	drawOrderGroup.add(fpsText);
	};

// Client data parsing

self.setPlayerInput = function (id, input)
	{
	if (players[id] != undefined)
		{
		players[id].setInput(input);
		}
	};

self.newPlayer = function (id)
	{
	var spawnPosition = getInitialSpawnPos(game, players, minPlayerSpawnDistance, initialSpawnBorder, null);
	game.effectManager.createSpawnEffect(spawnPosition);
	players[id] = new Player(game, spawnPosition.x, spawnPosition.y, bulletManager, id, weaponManager, enemyManager);
	players[id].sprite.scale.x = scalingFactors.x;
	players[id].sprite.scale.y = scalingFactors.y;
	playerGroup.add(players[id].sprite);

	self.dirty['playerAmount'] = true;
	};

self.disconnectPlayer = function (id)
	{
	if (players[id] != undefined)
		{
		playerGroup.remove(players[id].sprite);
		players[id].kill();
		//players[id] = undefined;
		delete players[id];
		// ^ deletes also key from obj list so no key in this list points to undefined when people disconnect
		}
	};

// Functions that manage game mechanics

self.update = function ()
	{
	scoreBoard.update(players);

	qr.position.setTo(game.camera.x + game.camera.width, game.camera.y + game.camera.height);

	fpsText.text = ' FPS: ' + game.time.fps + '\n now.elapsed: ' + game.time.elapsed + 'ms\n time.elapsed: ' + game.time.elapsedMS + 'ms';
	fpsText.position.setTo(game.camera.x, game.camera.y + game.camera.height);

	if (roundRunning && lastPaused < game.time.now && !self.roundOver)
		{
		bulletManager.update();

		for (var id in players)
			{
			if (players[id] != undefined)
				{
				players[id].update();
				}
			}

		enemyManager.update(players);
		powerupManager.update(playerGroup);

		game.physics.arcade.collide(playerGroup);
		game.physics.arcade.collide(qr, playerGroup);
		game.physics.arcade.collide(qr, enemyManager.enemyGroup);
		game.physics.arcade.collide(enemyManager.enemyGroup);
		game.physics.arcade.collide(playerGroup, enemyManager.enemyGroup);
		game.physics.arcade.collide(enemyManager.enemyGroup, self.collisionGroup);
		game.physics.arcade.collide(bulletManager.playerBulletGroup, self.collisionGroup, bulletCollisionHandler);
		game.physics.arcade.collide(bulletManager.enemyBulletGroup, self.collisionGroup, bulletCollisionHandler);
		game.physics.arcade.collide(playerGroup, self.collisionGroup);

		updateRoomMovement();
		if(self.lastRoomTimer > 0)
			{
			if (self.lastRoomTimer < game.time.now)
				{
				self.roundOver = true;
				}
			}
		}

	};

var bulletCollisionHandler = function(bullet, wall)
	{
		bulletManager.killbullet(bullet);
	}

var updateRoomMovement = function ()
	{
	if (self.dirty['rooms'])
		{
		rooms.forEach(function (room, index, array) { if (room != undefined && !room.onceScaled) { room.updateScaling(); } });
		self.dirty['rooms'] = false;
		}

	if (speedDict[currentSpeed] != undefined)
		{
		// Figure out which speed to go

		var curSpeed = speedDict[currentSpeed];

		// Figure out in which direction to move rooms

		var changeInPos;
		switch (currentDirection)
			{
			case "north":
				changeInPos = {"x": 0, "y": -curSpeed};
				break;
			case "east":
				changeInPos = {"x": curSpeed, "y": 0};
				break;
			case "south":
				changeInPos = {"x": 0, "y": curSpeed};
				break;
			case "west":
				changeInPos = {"x": -curSpeed, "y": 0};
				break;
			default:
				console.log("something went awry");
			}

		for (var i = 0; i < rooms.length; i++)
			{
			game.camera.x += changeInPos.x;
			game.camera.y += changeInPos.y;
			}

		// Check if next room has passed the game.camera, if it has, align it with camera, load new room etc.
		if (rooms[2] != undefined)
			{

			var testDX = Math.abs(rooms[2].getPos().x - game.camera.x);
			var testDY = Math.abs(rooms[2].getPos().y - game.camera.y);

			if (testDX > currentMinDX || testDY > currentMinDY)
				{
				currentMinDX = defaultMinDX;
				currentMinDY = defaultMinDY;
				rooms.shift();
				delete rooms[0];

				rooms[1].moveTo(game.camera.x, game.camera.y);

				currentDirection = rooms[1].moveDirection;
				currentSpeed = rooms[1].moveSpeed;

				if (speedDict[currentSpeed] != undefined)
					{
					rooms[2] = new Room(game,
															currentRound.rooms[nextRoom].roomBg,
															currentRound.rooms[nextRoom].colliders,
															currentRound.rooms[nextRoom].moveDirection,
															currentRound.rooms[nextRoom].moveSpeed,
															self);
					self.dirty['rooms'] = true;
					switch (rooms[1].moveDirection)
    					{
    					case "north":
      					rooms[2].moveTo(game.camera.x, game.camera.y - game.camera.height);
      					break;
    					case "east":
      					rooms[2].moveTo(game.camera.x + game.camera.width, game.camera.y);
      					break;
    					case "south":
      					rooms[2].moveTo(game.camera.x, game.camera.y+ game.camera.height);
      					break;
    					case "west":
      					rooms[2].moveTo(game.camera.x - game.camera.width, game.camera.y);
      					break;
    					default:
      					rooms[2] = null;
    					}
					lastPaused = game.time.now + pauseTime;
					nextRoom++;
					} else
					{
					var lastMovedDirection = 'null';
					if(currentRound.rooms[currentRound.rooms.length-2] != undefined)
						{
						lastMovedDirection = currentRound.rooms[currentRound.rooms.length-2].moveDirection;
						}

					var bossPos = new Phaser.Point();
					switch (lastMovedDirection)
						{
						case "north":
							bossPos.x = game.camera.x + game.camera.width/2
							bossPos.y = game.camera.y + game.camera.height*1/4
							break;
						case "east":
							bossPos.x = game.camera.x + game.camera.width*3/4
							bossPos.y = game.camera.y + game.camera.height/2
							break;
						case "west":
							bossPos.x = game.camera.x + game.camera.width*1/4
							bossPos.y = game.camera.y + game.camera.height/2
							break;
						case "south":
							bossPos.x = game.camera.x + game.camera.width/2
							bossPos.y = game.camera.y + game.camera.height*3/4
							break;
						default:
							bossPos.x = game.camera.x + game.camera.width/2
							bossPos.y = game.camera.y + game.camera.height/2
						}
					//enemyManager.createBoss('tentacle', bossPos);
					enemyManager.createBoss(currentRound.boss, bossPos);
					self.lastRoomTimer = game.time.now + self.lastRoomTimeout;
					}
				} else
				{
				currentMinDX = testDX;
				currentMinDY = testDY;
				}
			}
		}
	};

self.getScoreTable = function ()
	{
	return scoreBoard.getScoreTable();
	};

}

<commit_msg>OMG I PUSH TO MASTER<commit_after>'use strict';

function RoundManager(game, bulletManager, enemyManager, weaponManager, powerupManager)
{

var self = this;

// Variables related to managing game mechanics

self.dirty = [];
self.dirty['score'] = true;
self.dirty['playerAmount'] = true;
self.dirty['rooms'] = true;

var players = {};
var playerGroup = game.add.group();
playerGroup = game.add.physicsGroup(Phaser.Physics.ARCADE);
playerGroup.enableBody = true;

var minPlayerSpawnDistance = 10;

var scoreBoard = new  ScoreBoard(game, {x: 0, y: 0});

var roundRunning = false;

var qr = game.add.sprite(game.camera.x + game.camera.width, game.camera.y + game.camera.height, 'qr_niko_wlan_niko'); //or: 'qr_janika'
qr.scale.x = 0.5*scalingFactors.x;
qr.scale.y = 0.5*scalingFactors.y;
game.physics.enable(qr, Phaser.Physics.ARCADE);
qr.body.immovable = true;
qr.anchor.setTo(1,1);

//This group is used to manage the draw order of other groups
//The draw order is defined by the order in which groupds are added
//The last gorup is always drawn on top of others
var drawOrderGroup = game.add.group();

self.backgroundLayerGroup = game.add.group();
self.popUpGroup = game.add.group();
self.collisionGroup = game.add.group();

var fpsText = game.add.text(game.camera.x, game.camera.y + game.camera.height, '', { fontSize: '12px', fill: '#f00'});
fpsText.anchor.setTo(0, 1);
fpsText.stroke = '#000000';
fpsText.strokeThickness = 1;

// Variables related to map functioning

var currentRound;
var currentDirection;
var currentSpeed;
var rooms = [];
var roomGroup = game.add.group();
var nextRoom;

var lastPaused = 0;
var pauseTime = 500;

var defaultMinDX = 6 * game.world.width;
var defaultMinDY = 6 * game.world.height;

var currentMinDX = defaultMinDX;
var currentMinDY = defaultMinDY;

var speedDict = [];
speedDict["normal"] = 0.5;
speedDict["fast"] = 1;
speedDict["stop"] = null;

self.roundOver = false;
self.lastRoomTimeout = 600000; //600s
self.lastRoomTimer = 0;

var done = false;

var initialSpawnBorder = game.width/15;
self.loadRound = function (roundData)
	{

	// Set camera in the middle of the stage
	game.camera.x = Math.floor(game.world.width/2 - game.camera.width/2);
	game.camera.y = Math.floor(game.world.height/2 - game.camera.height/2);
	currentRound = roundData;

	rooms[0] = null;

	// Load first two rooms;
	for (var i = 0; i < Math.min(2, currentRound.rooms.length); i++)
		{
		rooms[i + 1] = new Room(game,
														currentRound.rooms[i].roomBg,
														currentRound.rooms[i].colliders,
														currentRound.rooms[i].moveDirection,
														currentRound.rooms[i].moveSpeed,
														self);
		self.dirty['rooms'] = true;
		}
	nextRoom = 2;

	// Position the two loaded rooms

	rooms[1].moveTo(game.camera.x, game.camera.y);
	if (rooms[2] != undefined)
		{
		switch (rooms[1].moveDirection)
			{
			case "north":
				rooms[2].moveTo(game.camera.x, game.camera.y, - game.camera.height);
				break;
			case "east":
				rooms[2].moveTo(game.camera.x + game.camera.width, game.camera.y);
				break;
			case "south":
				rooms[2].moveTo(game.camera.x, game.camera.y + game.camera.height);
				break;
			case "west":
				rooms[2].moveTo(game.camera.x - game.camera.width, game.camera.y);
				break;
			default:
				rooms[2] = null;
			}
		}

	roundRunning = true;
	currentDirection = rooms[1].moveDirection;
	currentSpeed = rooms[1].moveSpeed;
	establishDrawOrder();
	};

/**
* Initializes the draw order of all sprite groups in the game
* GROUPS ARE DRAWN IN THE ORDER THEY ARE DEFINED!
* New groups always go above older ones
*/
var establishDrawOrder = function()
	{
	drawOrderGroup.add(self.backgroundLayerGroup);
	drawOrderGroup.add(enemyManager.enemyGroup);
	drawOrderGroup.add(powerupManager.pUpGroup);
	drawOrderGroup.add(playerGroup);
	drawOrderGroup.add(weaponManager.weaponGroup);
	drawOrderGroup.add(self.collisionGroup);
	drawOrderGroup.add(scoreBoard.sprite);
	drawOrderGroup.add(bulletManager.playerBulletGroup);
	drawOrderGroup.add(bulletManager.enemyBulletGroup);
	drawOrderGroup.add(self.popUpGroup);
	drawOrderGroup.add(qr);
	drawOrderGroup.add(fpsText);
	};

// Client data parsing

self.setPlayerInput = function (id, input)
	{
	if (players[id] != undefined)
		{
		players[id].setInput(input);
		}
	};

self.newPlayer = function (id)
	{
	var spawnPosition = getInitialSpawnPos(game, players, minPlayerSpawnDistance, initialSpawnBorder, null);
	game.effectManager.createSpawnEffect(spawnPosition);
	players[id] = new Player(game, spawnPosition.x, spawnPosition.y, bulletManager, id, weaponManager, enemyManager);
	players[id].sprite.scale.x = scalingFactors.x;
	players[id].sprite.scale.y = scalingFactors.y;
	playerGroup.add(players[id].sprite);

	self.dirty['playerAmount'] = true;
	};

self.disconnectPlayer = function (id)
	{
	if (players[id] != undefined)
		{
		playerGroup.remove(players[id].sprite);
		players[id].kill();
		//players[id] = undefined;
		delete players[id];
		// ^ deletes also key from obj list so no key in this list points to undefined when people disconnect
		}
	};

// Functions that manage game mechanics

self.update = function ()
	{
	scoreBoard.update(players);

	qr.position.setTo(game.camera.x + game.camera.width, game.camera.y + game.camera.height);

	fpsText.text = ' FPS: ' + game.time.fps + '\n now.elapsed: ' + game.time.elapsed + 'ms\n time.elapsed: ' + game.time.elapsedMS + 'ms';
	fpsText.position.setTo(game.camera.x, game.camera.y + game.camera.height);

	if (roundRunning && lastPaused < game.time.now && !self.roundOver)
		{
		bulletManager.update();

		for (var id in players)
			{
			if (players[id] != undefined)
				{
				players[id].update();
				}
			}

		enemyManager.update(players);
		powerupManager.update(playerGroup);

		game.physics.arcade.collide(playerGroup);
		game.physics.arcade.collide(qr, playerGroup);
		game.physics.arcade.collide(qr, enemyManager.enemyGroup);
		game.physics.arcade.collide(enemyManager.enemyGroup);
		game.physics.arcade.collide(playerGroup, enemyManager.enemyGroup);
		game.physics.arcade.collide(enemyManager.enemyGroup, self.collisionGroup);
		game.physics.arcade.collide(bulletManager.playerBulletGroup, self.collisionGroup, bulletCollisionHandler);
		game.physics.arcade.collide(bulletManager.enemyBulletGroup, self.collisionGroup, bulletCollisionHandler);
		game.physics.arcade.collide(playerGroup, self.collisionGroup);

		updateRoomMovement();
		if(self.lastRoomTimer > 0)
			{
			if (self.lastRoomTimer < game.time.now)
				{
				self.roundOver = true;
				}
			}
		}

	};

var bulletCollisionHandler = function(bullet, wall)
	{
		bulletManager.killBullet(bullet);
	}

var updateRoomMovement = function ()
	{
	if (self.dirty['rooms'])
		{
		rooms.forEach(function (room, index, array) { if (room != undefined && !room.onceScaled) { room.updateScaling(); } });
		self.dirty['rooms'] = false;
		}

	if (speedDict[currentSpeed] != undefined)
		{
		// Figure out which speed to go

		var curSpeed = speedDict[currentSpeed];

		// Figure out in which direction to move rooms

		var changeInPos;
		switch (currentDirection)
			{
			case "north":
				changeInPos = {"x": 0, "y": -curSpeed};
				break;
			case "east":
				changeInPos = {"x": curSpeed, "y": 0};
				break;
			case "south":
				changeInPos = {"x": 0, "y": curSpeed};
				break;
			case "west":
				changeInPos = {"x": -curSpeed, "y": 0};
				break;
			default:
				console.log("something went awry");
			}

		for (var i = 0; i < rooms.length; i++)
			{
			game.camera.x += changeInPos.x;
			game.camera.y += changeInPos.y;
			}

		// Check if next room has passed the game.camera, if it has, align it with camera, load new room etc.
		if (rooms[2] != undefined)
			{

			var testDX = Math.abs(rooms[2].getPos().x - game.camera.x);
			var testDY = Math.abs(rooms[2].getPos().y - game.camera.y);

			if (testDX > currentMinDX || testDY > currentMinDY)
				{
				currentMinDX = defaultMinDX;
				currentMinDY = defaultMinDY;
				rooms.shift();
				delete rooms[0];

				rooms[1].moveTo(game.camera.x, game.camera.y);

				currentDirection = rooms[1].moveDirection;
				currentSpeed = rooms[1].moveSpeed;

				if (speedDict[currentSpeed] != undefined)
					{
					rooms[2] = new Room(game,
															currentRound.rooms[nextRoom].roomBg,
															currentRound.rooms[nextRoom].colliders,
															currentRound.rooms[nextRoom].moveDirection,
															currentRound.rooms[nextRoom].moveSpeed,
															self);
					self.dirty['rooms'] = true;
					switch (rooms[1].moveDirection)
    					{
    					case "north":
      					rooms[2].moveTo(game.camera.x, game.camera.y - game.camera.height);
      					break;
    					case "east":
      					rooms[2].moveTo(game.camera.x + game.camera.width, game.camera.y);
      					break;
    					case "south":
      					rooms[2].moveTo(game.camera.x, game.camera.y+ game.camera.height);
      					break;
    					case "west":
      					rooms[2].moveTo(game.camera.x - game.camera.width, game.camera.y);
      					break;
    					default:
      					rooms[2] = null;
    					}
					lastPaused = game.time.now + pauseTime;
					nextRoom++;
					} else
					{
					var lastMovedDirection = 'null';
					if(currentRound.rooms[currentRound.rooms.length-2] != undefined)
						{
						lastMovedDirection = currentRound.rooms[currentRound.rooms.length-2].moveDirection;
						}

					var bossPos = new Phaser.Point();
					switch (lastMovedDirection)
						{
						case "north":
							bossPos.x = game.camera.x + game.camera.width/2
							bossPos.y = game.camera.y + game.camera.height*1/4
							break;
						case "east":
							bossPos.x = game.camera.x + game.camera.width*3/4
							bossPos.y = game.camera.y + game.camera.height/2
							break;
						case "west":
							bossPos.x = game.camera.x + game.camera.width*1/4
							bossPos.y = game.camera.y + game.camera.height/2
							break;
						case "south":
							bossPos.x = game.camera.x + game.camera.width/2
							bossPos.y = game.camera.y + game.camera.height*3/4
							break;
						default:
							bossPos.x = game.camera.x + game.camera.width/2
							bossPos.y = game.camera.y + game.camera.height/2
						}
					//enemyManager.createBoss('tentacle', bossPos);
					enemyManager.createBoss(currentRound.boss, bossPos);
					self.lastRoomTimer = game.time.now + self.lastRoomTimeout;
					}
				} else
				{
				currentMinDX = testDX;
				currentMinDY = testDY;
				}
			}
		}
	};

self.getScoreTable = function ()
	{
	return scoreBoard.getScoreTable();
	};

}

<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';
var https = require('https');
var fs = require('fs');
var url = require('url');

function getOptions(urlString) {
	var _url = url.parse(urlString);
	return {
		protocol: _url.protocol,
		host: _url.host,
		port: _url.port,
		path: _url.path,
		headers: {
			'User-Agent': 'NodeJS'
		}
	}
}

exports.toFile = function (url, dest) {
  return new Promise((c, e) => {
		var file = fs.createWriteStream(dest);
		var request = https.get(getOptions(url), function (response) {
			response.pipe(file);
			file.on('finish', function () {
				var cb = (err, result) => err ? e(err) : c(result);
				file.close(cb);
			});
		}).on('error', function (err) { // Handle errors
			fs.unlink(dest); // Delete the file async, don't check the result
			e(err.message);
		});
  });
};

exports.toString = function(url) {
  return new Promise((c, e) => {
	  var content = '';
		var request = https.get(getOptions(url), function (response) {
			response.on('data', function (data) {
				content += data.toString();
			}).on('end', function () {
				c(content);
			});
		}).on('error', function (err) {
			e(err.message);
		});
  });
}<commit_msg>remove unused build script<commit_after><|endoftext|>


<commit_before>var _ = require('underscore')
var path = require('path')
var fs = require('fs-extra')

var STOPWORDS = ['//', 'var', '||', 'return', '+', '-', '*', '/', '%', 'true', 'false', '?', ':']
var SPLIT_REGEX = /[(){}_=\/\s'",.]+/
var INDEX_FILENAME = 'invertedIndex.js'

function build (options, grunt) {
    var invertedIndex = {}
    var mapByPath = {}
    var mapById = {}
    var docPath
    var tokens
    var source
    var currentIndex
    var i = 0

    options.args.forEach(function (filepath) {
        docPath = getDocPath(filepath)
        source = grunt.file.read(filepath)
        tokens = tokenize(source)

        // create a path lookup
        if (!mapByPath[docPath]) {
            currentIndex = i
            mapByPath[docPath] = i
            mapById[i] = docPath
            i++
        }

        // make file searchable by name
        invertedIndex[filepath] = {}
        invertedIndex[filepath][currentIndex] = 1

        // make file searchable by tokens
        tokens.forEach(function (token) {
            if (!invertedIndex[token]) invertedIndex[token] = {}
            if (!invertedIndex[token][currentIndex]) invertedIndex[token][currentIndex] = 0
            invertedIndex[token][currentIndex]++
        })
    })

    return {
        invertedIndex: invertedIndex,
        mapById: mapById,
    }
}

function tokenize (code) {
    return _.chain(code.split(SPLIT_REGEX))
        .map(function (token) { return token.trim().toLowerCase() })
        .difference(STOPWORDS)
        .value()
}

function getDocPath (filepath) {
    return path.join(path.dirname(filepath), path.basename(filepath, path.extname(filepath)) + '.html')
}

module.exports = { build: build }
<commit_msg>always set current index<commit_after>var _ = require('underscore')
var path = require('path')
var fs = require('fs-extra')

var STOPWORDS = ['//', 'var', '||', 'return', '+', '-', '*', '/', '%', 'true', 'false', '?', ':']
var SPLIT_REGEX = /[(){}_=\/\s'",.]+/
var INDEX_FILENAME = 'invertedIndex.js'

function build (options, grunt) {
    var invertedIndex = {}
    var mapByPath = {}
    var mapById = {}
    var docPath
    var tokens
    var source
    var currentIndex
    var i = 0

    options.args.forEach(function (filepath) {
        docPath = getDocPath(filepath)
        source = grunt.file.read(filepath)
        tokens = tokenize(source)

        // create a path lookup
        if (!mapByPath[docPath]) {
            mapByPath[docPath] = i
            mapById[i] = docPath
            i++
        }

        currentIndex = mapByPath[docPath]

        // make file searchable by name
        invertedIndex[filepath] = {}
        invertedIndex[filepath][currentIndex] = 1

        // make file searchable by tokens
        tokens.forEach(function (token) {
            if (!invertedIndex[token]) invertedIndex[token] = {}
            if (!invertedIndex[token][currentIndex]) invertedIndex[token][currentIndex] = 0
            invertedIndex[token][currentIndex]++
        })
    })

    return {
        invertedIndex: invertedIndex,
        mapById: mapById,
    }
}

function tokenize (code) {
    return _.chain(code.split(SPLIT_REGEX))
        .map(function (token) { return token.trim().toLowerCase() })
        .difference(STOPWORDS)
        .value()
}

function getDocPath (filepath) {
    return path.join(path.dirname(filepath), path.basename(filepath, path.extname(filepath)) + '.html')
}

module.exports = { build: build }
<|endoftext|>


<commit_before>var fs = require('fs')
var url = require('url')
var http = require('http')
var https = require('https')
var level = require('level')
var asyncMap = require('slide').asyncMap
var multiLevel = require('multilevel')
var livestream = require('level-live-stream')
var browserify = require('browserify')
var engineServer = require('engine.io-stream')
var fileserver = require('node-static').Server
var newHmac = require('crypto').createHmac
var formidable = require('formidable')

var users = {}
var configFlag = process.argv[2] // specify a config file when booting

!(configFlag)
  ? boot(require('./config.json'))
  : boot(process.argv[2])

function startServer (conf, db, cb) { // just write the index... yeah...

  fs.writeFileSync('./static/index.html', '<!doctype html>'+
  ''+
  '<meta charset="utf-8">'+
  ''+
  '<title>Untitiled</title>'+
  '<link rel="stylesheet" href="/style.css">'+
  ''+
  ''+
  '
'+
  '
'+
  ''+
  ''+
  '')

  if (!conf.ssl) {
    var file = new fileserver('./static')
    var server = http.createServer(handleHttp)
  } else {
    var hsts = {'Strict-Transport-Security':'max-age=31536000'}
    var file = new fileServer('./static', hsts)
    var server = https.createServer({
      honorCipherOrder : true,
      key : fs.readFileSync(conf.ssl.key),
      cert : fs.readFileSync(conf.ssl.cert),
      cipher : 'ecdh+aesgcm:dh+aesgcm:ecdh+aes256:dh+aes256:'+
               'ecdh+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:'+
               'RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
    }, handleHttp)
  }

  function handleHttp (req, res) {
    if (req.url === '/upload' && req.method === 'post') fileUpload(req, res)
    file.serve(req, res, function noFile (e) {
      if (e) {
        var path = url.parse(req.url).pathname.slice(1)
        file.serveFile('/index.html', 200, {}, req, res)
      }
    })
  }

  var engine = engineServer(function (wss) {
    wss.pipe(multiLevel.server(db, {
      auth: function (user, cb) { // split to external fn
        getHmac({
          token:user.pass,
          user:user.user,
          secret:conf.secretKey}
          , function handleHmac (d) {
            if (users[user.user] === pass) cb(null, { name: user.user, token: d.val })
            if (users[user.user] !== pass) cb(new Error('wrong pass!'), null)
            if (e) cb(e, null)
        })
      },
      access: function (user, db, method, args) {} //split out
    })).pipe(wss)
    wss.on('error', console.error)
  }, {cookie:false})
    .attach(server, '/ws')

  server.listen(conf.port, conf.host, cb)
}

function boot (conf) {

  process.stdin.on('data', function (buf) {
    var str = buf.toString()
    if (str === 'c\n') compileModules(conf.bundle, console.log)
  })

  if (!conf || !conf.server || !conf.bricoleur || !conf.bundle) {
    throw new Error('nimoy: invalid or missing config.json')
  }

  if (!fs.existsSync('./static')) fs.mkdir('./static')

  var db = level('./' + conf.host)
  livestream.install(db)
  multiLevel.writeManifest(db, './static/manifest.json')

  conf.server.secretKey = conf.bricoleur.secretKey

  compileModules(conf.bundle, function (library) {
    db.put('library', JSON.stringify(library))
    startServer(conf.server, db, function () {
      console.log('server running')
    })
  })

  var bricoConf = conf.bricoleur
  for (user in bricoConf.users) {
    var u = bricoConf.users[user]
    if (!u.pass) return false
    getHmac({token:u.pass,user:user,secret:bricoConf.secretKey}, function (d) {
      users[d.key] = d.val
      delete u.pass
    })
  }

  delete bricoConf.secretKey

  db.put('config', JSON.stringify(bricoConf))
}

function getHmac (d, cb) {
  var hmac = newHmac('sha256', d.secret)
  hmac.setEncoding('hex')
  hmac.write(d.token)
  hmac.end()
  cb({key:'users:'+d.user, val:hmac.read().toString()})
}

function compileModules (config, cb) {
  var library  = {}
  var inBun = config.pathBundleEntry
  var outBun = config.pathBundleOut
  var b = browserify(inBun)
  var modulesFolder = fs.readdirSync(config.pathModules)

  asyncMap(modulesFolder, function (moduleFolder, next) {
    var pkgPath = config.pathModules + moduleFolder + '/package.json'
    var templatePath = config.pathModules + moduleFolder+'/'+moduleFolder+'.hogan'

    if (!fs.existsSync(pkgPath)) { next(); return null }

    var pkg = JSON.parse(fs.readFileSync(pkgPath, {encoding:'utf8'}))
    if (!pkg.nimoy) { next(); return null }

    if (fs.existsSync(templatePath))
      pkg.html = fs.readFileSync(templatePath, {encoding:'utf8'})

    var key = 'modules:'+pkg.name

    library[key] = pkg

    b.require(config.pathModules+moduleFolder+'/'+pkg.main, {
      expose: moduleFolder
    })

    next()
  }, function end () {
    var bun = fs.createWriteStream(outBun)
    b.bundle().pipe(bun)
    bun.on('finish',function () {
      console.log('compiled '+inBun+' to '+outBun)
      cb(library)
    })
  })
}

function fileUpload (req, res) {
  var form = new formidable.IncomingForm()

  form.parse(req, function(err, fields, files) {
    var filePath = './static/uploads/'+fields.file
    res.writeHead(200, {'content-type': 'text/plain'})
    res.write('received upload:\n\n')
    res.end()
    var blob = fields.blob.split(',')[1]
    fs.writeFileSync(filePath, blob, {encoding:'base64'}) // encoding !?
  })
}
<commit_msg>fix login / auth methods<commit_after>var fs = require('fs')
var url = require('url')
var http = require('http')
var https = require('https')
var level = require('level')
var asyncMap = require('slide').asyncMap
var multiLevel = require('multilevel')
var livestream = require('level-live-stream')
var browserify = require('browserify')
var engineServer = require('engine.io-stream')
var fileserver = require('node-static').Server
var newHmac = require('crypto').createHmac
var formidable = require('formidable')

var users = {}
var configFlag = process.argv[2] // specify a config file when booting

!(configFlag)
  ? boot(require('./config.json'))
  : boot(process.argv[2])

function startServer (conf, db, cb) { // just write the index... yeah...

  fs.writeFileSync('./static/index.html', '<!doctype html>'+
  ''+
  '<meta charset="utf-8">'+
  ''+
  '<title>Untitiled</title>'+
  '<link rel="stylesheet" href="/style.css">'+
  ''+
  ''+
  '
'+
  '
'+
  ''+
  ''+
  '')

  if (!conf.ssl) {
    var file = new fileserver('./static')
    var server = http.createServer(handleHttp)
  } else {
    var hsts = {'Strict-Transport-Security':'max-age=31536000'}
    var file = new fileServer('./static', hsts)
    var server = https.createServer({
      honorCipherOrder : true,
      key : fs.readFileSync(conf.ssl.key),
      cert : fs.readFileSync(conf.ssl.cert),
      cipher : 'ecdh+aesgcm:dh+aesgcm:ecdh+aes256:dh+aes256:'+
               'ecdh+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:'+
               'RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
    }, handleHttp)
  }

  function handleHttp (req, res) {
    if (req.url === '/upload' && req.method === 'post') fileUpload(req, res)
    file.serve(req, res, function noFile (e) {
      if (e) {
        var path = url.parse(req.url).pathname.slice(1)
        file.serveFile('/index.html', 200, {}, req, res)
      }
    })
  }

  var engine = engineServer(function (wss) {
    wss.pipe(multiLevel.server(db, {
      auth: function (user, cb) { // split to external fn
        getHmac({
          token:user.pass,
          user:user.user,
          secret:conf.secretKey}
          , function handleHmac (d) {
            if (users[user.user] === d.val) cb(null, { name: user.user, token: d.val })
            if (users[user.user] !== d.val) cb(new Error('wrong pass!'), null)
        })
      },
      access: function (user, db, method, args) {
        console.log(user)
        console.log(db)
        console.log(args)
        console.log(method)
      } //split out
    })).pipe(wss)
    wss.on('error', console.error)
  }, {cookie:false})
    .attach(server, '/ws')

  server.listen(conf.port, conf.host, cb)
}

function boot (conf) {

  process.stdin.on('data', function (buf) {
    var str = buf.toString()
    if (str === 'c\n') compileModules(conf.bundle, console.log)
  })

  if (!conf || !conf.server || !conf.bricoleur || !conf.bundle) {
    throw new Error('nimoy: invalid or missing config.json')
  }

  if (!fs.existsSync('./static')) fs.mkdir('./static')

  var db = level('./' + conf.host)
  livestream.install(db)
  multiLevel.writeManifest(db, './static/manifest.json')

  conf.server.secretKey = conf.bricoleur.secretKey

  compileModules(conf.bundle, function (library) {
    db.put('library', JSON.stringify(library))
    startServer(conf.server, db, function () {
      console.log('server running')
    })
  })

  var bricoConf = conf.bricoleur
  for (user in bricoConf.users) {
    var u = bricoConf.users[user]
    if (u.pass) getHmac({token:u.pass,user:user,secret:bricoConf.secretKey}, function (d) {
      users[user] = d.val
    //   delete u.pass
    })
  }

  delete bricoConf.secretKey

  db.put('config', JSON.stringify(bricoConf))
}

function getHmac (d, cb) {
  var hmac = newHmac('sha256', d.secret)
  hmac.setEncoding('hex')
  hmac.write(d.token)
  hmac.end()
  cb({key:d.user, val:hmac.read().toString()})
}

function compileModules (config, cb) {
  var library  = {}
  var inBun = config.pathBundleEntry
  var outBun = config.pathBundleOut
  var b = browserify(inBun)
  var modulesFolder = fs.readdirSync(config.pathModules)

  asyncMap(modulesFolder, function (moduleFolder, next) {
    var pkgPath = config.pathModules + moduleFolder + '/package.json'
    var templatePath = config.pathModules + moduleFolder+'/'+moduleFolder+'.hogan'

    if (!fs.existsSync(pkgPath)) { next(); return null }

    var pkg = JSON.parse(fs.readFileSync(pkgPath, {encoding:'utf8'}))
    if (!pkg.nimoy) { next(); return null }

    if (fs.existsSync(templatePath))
      pkg.html = fs.readFileSync(templatePath, {encoding:'utf8'})

    var key = 'modules:'+pkg.name

    library[key] = pkg

    b.require(config.pathModules+moduleFolder+'/'+pkg.main, {
      expose: moduleFolder
    })

    next()
  }, function end () {
    var bun = fs.createWriteStream(outBun)
    b.bundle().pipe(bun)
    bun.on('finish',function () {
      console.log('compiled '+inBun+' to '+outBun)
      cb(library)
    })
  })
}

function fileUpload (req, res) {
  var form = new formidable.IncomingForm()

  form.parse(req, function(err, fields, files) {
    var filePath = './static/uploads/'+fields.file
    res.writeHead(200, {'content-type': 'text/plain'})
    res.write('received upload:\n\n')
    res.end()
    var blob = fields.blob.split(',')[1]
    fs.writeFileSync(filePath, blob, {encoding:'base64'}) // encoding !?
  })
}
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const md = require('markdown-ast')
const { parseFrontMatter } = require('./md-loader-utils.js')

const { slugify } = require('./utils')

const levelName = 'l'

// get the menu from assets folder
const menu = require(path.resolve(__dirname, '../src/assets/menu.js'))

// where the markdown lives
const intro = '../src/pages'

let objectID = 1
const getObjectID = () => objectID++

const createFolder = (folder) => {
  const dir = path.join(__dirname, '..', folder)
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir)
  }
}

const createIndex = (data) => {
  const requiredFields = [ levelName + '0', 'url' ]
  const missingFields = requiredFields.filter(
    (requiredField) => !data[ requiredField ]
  )
  if (missingFields.length) {
    throw new Error(
      `Missing fields for indexing page ${data.url}: ${missingFields.join(
        ', '
      )}`
    )
  }
  return {
    id: getObjectID(),
    [ levelName + '0' ]: null,
    [ levelName + '1' ]: null,
    [ levelName + '2' ]: null,
    [ levelName + '3' ]: null,
    [ levelName + '4' ]: null,
    [ levelName + '5' ]: null,
    [ levelName + '6' ]: null,
    keys: null,
    content: null,
    anchor: null,
    ...data
  }
}

const cleanObject = (item) => {
  if (item.content === '') {
    item.content = null
  }
  const keys = Object.keys(item)
  for (const key in keys) {
    if (item[ keys[ key ] ] === null) {
      delete item[ keys[ key ] ]
    }
  }
  return item
}

const getNextLevel = (item, text) => {
  for (let index = 0; index < 7; ++index) {
    if (item[ levelName + index ] === void 0 || item[ levelName + index ] === text) {
      return index
    }
  }
  return 6 // highest
}

// makes sure there is content before adding to array
const addItem = (entries, item) => {
  entries.push(cleanObject(createIndex(item)))
}

// returns the contents of the associated file
const getFileContents = (mdPath) => {
  const page = path.resolve(__dirname, mdPath)
  return fs.readFileSync(page, {
    encoding: 'utf8'
  })
}

const processNode = (node, prefix = '') => {
  const text = []
  let type = 'page-content'

  if (Array.isArray(node)) {
    node.forEach(leaf => {
      const data = processNode(leaf, prefix)
      text.push(data.text)
    })
  }
  else if (node.type === 'link') {
    const data = processNode(node.block)
    text.push(data.text)
  }
  else if (node.type === 'list' ||
    node.type === 'quote') {
    const data = processNode(node.block, ' ')
    text.push(data.text)
  }
  else if (node.type === 'bold' ||
    node.type === 'italic' ||
    node.type === 'strike') {
    const data = processNode(node.block)
    text.push(data.text)
  }
  else if (node.type === 'title') {
    type = 'page-link'
    const data = processNode(node.block)
    data.type = type
    return data
  }
  else if (node.type === 'image' ||
    node.type === 'codeBlock') {
    text.push('')
  }
  else if (node.type === 'codeSpan') {
    text.push(prefix + node.code)
  }
  else if (node.type === 'text' ||
    node.type === 'break' ||
    node.type === 'codeSpan') {
    text.push(prefix + node.text)
  }
  else {
    // unknown/unprocessed node type
    console.log(node)
  }

  return { text: text.join(' ').replace(/\n/g, ''), type }
}

const processMarkdown = (syntaxTree, entries, entry) => {
  const contents = []
  let type = 'page-content'
  let parent = { ...entry }

  const handleAnchor = () => {
    const joiner = type === 'page-list' ? '' : ' '
    if (contents.length > 0) {
      const text = contents.join(joiner)
        // .replace(/\n/g, ' ')
        .replace(/<[^>]*\/>/g, '') // remove self-closing tags
        .replace(/
/g, '\n')
        .replace(/\|/g, '')
        .replace(/---/g, '')
        .replace(/::: tip/g, '')
        .replace(/::: warning/g, '')
        .replace(/::: danger/g, '')
        .replace(/:::/g, '')
        .replace(/\s\s+/g, ' ') // change multi-space to 1 space
        .trim()

      if (text === '') {
        // if text is empty, it's a link (ie: H2) with no
        // content, but it will be a parent (ie: to an H3)
        type = 'page-link'
      }
      else if (type === 'page-list') {
        // page-list is needed because lists have no breaks
        // when the text is joined, we need it done with a space
        // here, we translate back to page-content
        type = 'page-content'
      }

      // handle text from previous
      addItem(entries, { ...parent, content: text, type })

      // start a new index
      parent = { ...parent, content: '' }

      // clean up contents array
      contents.splice(0, contents.length)
    }
  }

  syntaxTree.forEach((node, index) => {
    const val = processNode(node)

    if (val.type === 'page-link') {
      handleAnchor()
      const level = getNextLevel(parent, val.text)
      const entryItem = {
        [ levelName + (level) ]: val.text,
        anchor: slugify(val.text),
        type: val.type
      }
      parent = { ...parent, ...entryItem }
    }
    else {
      contents.push(val.text)
    }

    type = val.type
  })

  // handle last bits on the page
  handleAnchor()
}

const processPage = (page, entry, entries) => {
  const contents = getFileContents(page)
  const frontMatter = parseFrontMatter(contents)
  let keys = null

  if (frontMatter.data.keys) {
    keys = frontMatter.data.keys.split(',').join(' ')
  }

  const entryItem = {
    ...entry,
    keys,
    l0: frontMatter.data.title,
    content: frontMatter.data.desc,
    type: 'page-link',
    anchor: 'introduction'
  }

  addItem(entries, entryItem)

  // get markdown ast
  const ast = md(frontMatter.content)

  // process ast
  processMarkdown(ast, entries, entryItem)
}

// process child entries from menu.js
const processChildren = (parent, entry, entries) => {
  if (parent.children) {
    parent.children.forEach(menuItem => {
      if (menuItem.external !== true) {
        let entryChild = { ...entry }
        if (menuItem.path) {
          const level = getNextLevel(entry, menuItem.name)
          entryChild = {
            ...entry,
            [ levelName + (level) ]: menuItem.name,
            url: entry.url + '/' + menuItem.path,
            anchor: slugify(menuItem.name)
          }
        }

        if (menuItem.children) {
          processChildren(menuItem, entryChild, entries)
        }
        else {
          processPage(intro + entryChild.url + '.md', entryChild, entries)
        }
      }
    })
  }
}

const processMenuItem = (menuItem, entries) => {
  let level = 0
  const entryItem = {
    [ levelName + level ]: menuItem.name,
    content: '',
    anchor: '',
    url: '/' + menuItem.path
  }

  if (menuItem.external !== true) {
    if (menuItem.children) {
      level = getNextLevel(entryItem, menuItem.name)
      const entryChild = {
        ...entryItem,
        [ levelName + level ]: menuItem.name,
        anchor: slugify(menuItem.name)
      }
      processChildren(menuItem, entryChild, entries)
    }
    else {
      processPage(intro + entryItem.url + '.md', entryItem, entries)
    }
  }
}

// -- Begin processing

const run = () => {
  const start = new Date().getTime()

  createFolder('dist')

  const fileName = path.resolve(__dirname, '../dist/indices.json')
  const entries = []

  menu.forEach(item => {
    processMenuItem(item, entries)
  })

  fs.writeFileSync(fileName, JSON.stringify(entries, null, 2), () => {})

  const end = new Date().getTime()
  const time = end - start
  console.log(`Finished ${entries.length} indices in ${time}ms`)
  console.log(`Generated ${fileName}`)
}

run()
<commit_msg>feat(docs): further tweaking to search markdown parser<commit_after>const fs = require('fs')
const path = require('path')
const md = require('markdown-ast')
const { parseFrontMatter } = require('./md-loader-utils.js')

const { slugify } = require('./utils')

const levelName = 'l'

// get the menu from assets folder
const menu = require(path.resolve(__dirname, '../src/assets/menu.js'))

// where the markdown lives
const intro = '../src/pages'

let objectID = 1
const getObjectID = () => objectID++

const createFolder = (folder) => {
  const dir = path.join(__dirname, '..', folder)
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir)
  }
}

const createIndex = (data) => {
  const requiredFields = [ levelName + '0', 'url' ]
  const missingFields = requiredFields.filter(
    (requiredField) => !data[ requiredField ]
  )
  if (missingFields.length) {
    throw new Error(
      `Missing fields for indexing page ${data.url}: ${missingFields.join(
        ', '
      )}`
    )
  }
  return {
    id: getObjectID(),
    [ levelName + '0' ]: null,
    [ levelName + '1' ]: null,
    [ levelName + '2' ]: null,
    [ levelName + '3' ]: null,
    [ levelName + '4' ]: null,
    [ levelName + '5' ]: null,
    [ levelName + '6' ]: null,
    keys: null,
    content: null,
    anchor: null,
    ...data
  }
}

const cleanObject = (item) => {
  if (item.content === '') {
    item.content = null
  }
  const keys = Object.keys(item)
  for (const key in keys) {
    if (item[ keys[ key ] ] === null) {
      delete item[ keys[ key ] ]
    }
  }
  return item
}

// deletes any levelName key higher than the passed value
const deleteHigherThan = (item, level) => {
  for (let index = level + 1; index < 7; ++index) {
    if (item[ levelName + index ] !== void 0) {
      delete item[ levelName + index ]
    }
  }
  return item
}

// makes sure there is content before adding to array
const addItem = (entries, item) => {
  entries.push(cleanObject(createIndex(item)))
}

// returns the contents of the associated file
const getFileContents = (mdPath) => {
  const page = path.resolve(__dirname, mdPath)
  return fs.readFileSync(page, {
    encoding: 'utf8'
  })
}

const processNode = (node, prefix = '') => {
  const text = []
  let type = 'page-content'

  if (Array.isArray(node)) {
    node.forEach(leaf => {
      const data = processNode(leaf, prefix)
      text.push(data.text)
    })
  }
  else if (node.type === 'link') {
    const data = processNode(node.block)
    text.push(data.text)
  }
  else if (node.type === 'list' ||
    node.type === 'quote') {
    const data = processNode(node.block, ' ')
    text.push(data.text)
  }
  else if (node.type === 'bold' ||
    node.type === 'italic' ||
    node.type === 'strike') {
    const data = processNode(node.block)
    text.push(data.text)
  }
  else if (node.type === 'title') {
    type = 'page-link'
    const data = processNode(node.block)
    data.type = type
    data.rank = node.rank
    return data
  }
  else if (node.type === 'image' ||
    node.type === 'codeBlock') {
    text.push('')
  }
  else if (node.type === 'codeSpan') {
    text.push(prefix + node.code)
  }
  else if (node.type === 'text' ||
    node.type === 'break' ||
    node.type === 'codeSpan') {
    text.push(prefix + node.text)
  }
  else {
    // unknown/unprocessed node type
    console.log(node)
  }

  return { text: text.join(' ').replace(/\n/g, ''), type }
}

const processMarkdown = (syntaxTree, entries, entry) => {
  const contents = []
  let type = 'page-content'
  let parent = { ...entry }

  const handleAnchor = () => {
    const joiner = type === 'page-list' ? '' : ' '
    if (contents.length > 0) {
      const text = contents.join(joiner)
        // .replace(/\n/g, ' ')
        .replace(/<[^>]*\/>/g, '') // remove self-closing tags
        .replace(/
/g, '\n')
        .replace(/\|/g, '')
        .replace(/---/g, '')
        .replace(/::: tip/g, '')
        .replace(/::: warning/g, '')
        .replace(/::: danger/g, '')
        .replace(/:::/g, '')
        .replace(/\s\s+/g, ' ') // change multi-space to 1 space
        .trim()

      if (text === '') {
        // if text is empty, it's a link (ie: H2) with no
        // content, but it will be a parent (ie: to an H3)
        type = 'page-link'
      }
      else if (type === 'page-list') {
        // page-list is needed because lists have no breaks
        // when the text is joined, we need it done with a space
        // here, we translate back to page-content
        type = 'page-content'
      }

      // handle text from previous
      addItem(entries, { ...parent, content: text, type })

      // start a new index
      parent = { ...parent, content: '' }

      // clean up contents array
      contents.splice(0, contents.length)
    }
  }

  syntaxTree.forEach((node, index) => {
    const val = processNode(node)

    if (val.type === 'page-link') {
      handleAnchor()
      const level = val.rank
      const entryItem = {
        [ levelName + (level) ]: val.text,
        anchor: slugify(val.text),
        type: val.type
      }
      parent = deleteHigherThan({ ...parent, ...entryItem }, level)
    }
    else {
      contents.push(val.text)
    }

    type = val.type
  })

  // handle last bits on the page
  handleAnchor()
}

const processPage = (page, entry, entries) => {
  const contents = getFileContents(page)
  const frontMatter = parseFrontMatter(contents)
  let keys = null

  if (frontMatter.data.keys) {
    keys = frontMatter.data.keys.split(',').join(' ')
  }

  const entryItem = {
    ...entry,
    keys,
    content: frontMatter.data.desc,
    type: 'page-link',
    anchor: 'introduction'
  }

  addItem(entries, entryItem)

  // get markdown ast
  const ast = md(frontMatter.content)

  // process ast
  processMarkdown(ast, entries, entryItem)
}

// process child entries from menu.js
const processChildren = (parent, entry, entries) => {
  if (parent.children) {
    parent.children.forEach(menuItem => {
      if (menuItem.external !== true) {
        let entryChild = { ...entry }
        if (menuItem.path) {
          const level = 0
          entryChild = {
            ...entry,
            [ levelName + (level) ]: menuItem.name,
            url: entry.url + '/' + menuItem.path,
            anchor: slugify(menuItem.name)
          }
        }

        if (menuItem.children) {
          processChildren(menuItem, entryChild, entries)
        }
        else {
          processPage(intro + entryChild.url + '.md', entryChild, entries)
        }
      }
    })
  }
}

const processMenuItem = (menuItem, entries) => {
  let level = 0
  const entryItem = {
    [ levelName + level ]: menuItem.name,
    content: '',
    anchor: '',
    url: '/' + menuItem.path
  }

  if (menuItem.external !== true) {
    if (menuItem.children) {
      level = 0
      const entryChild = {
        ...entryItem,
        [ levelName + level ]: menuItem.name,
        anchor: slugify(menuItem.name)
      }
      processChildren(menuItem, entryChild, entries)
    }
    else {
      processPage(intro + entryItem.url + '.md', entryItem, entries)
    }
  }
}

// -- Begin processing

const run = () => {
  const start = new Date().getTime()

  createFolder('dist')

  const fileName = path.resolve(__dirname, '../dist/indices.json')
  const entries = []

  menu.forEach(item => {
    processMenuItem(item, entries)
  })

  fs.writeFileSync(fileName, JSON.stringify(entries, null, 2), () => {})

  const end = new Date().getTime()
  const time = end - start
  console.log(`Finished ${entries.length} indices in ${time}ms`)
  console.log(`Generated ${fileName}`)
}

run()
<|endoftext|>


<commit_before>import { ViewEngine } from 'grind-view'

import './CacheManager'
import './Compiler'
import './HtmlString'
import './StoneLoop'
import './Watcher'
import './StoneRuntime'

import './Support/escape'

const path = require('path')
const fs = require('fs')

export class StoneEngine extends ViewEngine {

	cacheManager = null
	compiler = null
	watcher = null
	runtime = null
	namespaces = { }

	context = {
		escape: escape,
		HtmlString: HtmlString,
		StoneLoop: StoneLoop,
		stringify: JSON.stringify
	}

	constructor(app, view) {
		super(app, view)

		this.cacheManager = new CacheManager(app, this)
		this.compiler = new Compiler(this)
		this.runtime = new StoneRuntime(this)
	}

	async bootstrap() {
		const engine = this

		function StoneExpressView(name) {
			this.template = name
			this.name = name
			this.path = name
		}

		StoneExpressView.prototype.render = function(context, callback) {
			let template = null

			try {
				template = engine._render(this.template, context)
			} catch(err) {
				return callback(err)
			}

			callback(null, template)
		}

		this.app.express.set('view', StoneExpressView)

		if(this.app.config.get('view.watch', this.app.debug)) {
			this.watcher = new Watcher(this, this.view.viewPath)
			this.watcher.start()
		}

		const tags = this.app.config.get('view.tags')

		if(!tags.isNil) {
			for(const [ key, value ] of Object.entries(tags)) {
				if(value === '*') {
					this.tag(`${key}.*`)
					continue
				}

				this.tag(key, value)
			}
		}

		if(await this.cacheManager.exists()) {
			await this.cacheManager.load()
		}
	}

	namespace(namespace, path) {
		this.namespaces[namespace] = path
	}

	shutdown() {
		if(this.watcher.isNil) {
			return
		}

		return this.watcher.stop()
	}

	share(name, value) {
		this.context[name] = value
	}

	extend(name, extension) {
		this.compiler.directives[name] = extension
	}

	tag(name, template = null) {
		if(template.isNil) {
			if(name.endsWith('.*')) {
				const base = name.substring(0, name.length - 2)

				// eslint-disable-next-line no-sync
				const templates = fs.readdirSync(path.join(this.view.viewPath, base.replace(/\./g, '/')))

				for(const template of templates) {
					const extname = path.extname(template)
					const name = path.basename(template, extname)

					if(extname !== '.stone') {
						continue
					}

					this.tag(`${base}.${name}`)
				}

				return
			}

			template = name
			name = template.split(/\./).pop().replace(/^_/g, '')
		}

		this.compiler.tags[name] = template
	}

	render(template, context) {
		this.view.emit('render:start', template)

		return Promise.resolve(this._render(template, context)).then(result => {
			this.view.emit('render:end', template, result)

			return result
		})
	}

	_render(template, context) {
		return this._renderCompiled(this.compiler.compile(this.resolve(template)), context)
	}

	renderString(template, context) {
		return this._renderCompiled(this.compiler.compileString(template), context)
	}

	_renderCompiled(compiled, context) {
		return compiled({
			...this.context,
			...context,
			$stone: this.runtime,
			$engine: this,
			$compiler: this.compiler
		})
	}

	resolve(template, relativeTo = null) {
		if(template.substring(0, 1) === '.' && typeof relativeTo === 'string') {
			let join = ''

			template = template.replace(/^(\.+)/, (_, dots) => {
				if(dots.length !== 1) {
					join = '../'.repeat(dots.length - 1)
				}

				return ''
			})

			return path.join(path.dirname(relativeTo), join, `${template.replace(/\./g, '/')}.stone`)
		}

		const index = template.indexOf('::')
		let viewPath = null

		if(index === -1) {
			viewPath = this.view.viewPath
		} else {
			const namespace = template.substring(0, index)
			viewPath = this.namespaces[namespace]

			if(typeof viewPath !== 'string') {
				throw new Error(`Invalid namespace: ${namespace}`)
			}

			template = template.substring(index + 2)
		}

		return path.join(viewPath, `${template.replace(/\./g, '/')}.stone`)
	}

	writeCache() {
		return this.cacheManager.write()
	}

	clearCache() {
		return this.cacheManager.clear()
	}

	toHtmlString(html) {
		return new HtmlString(html)
	}

	isHtmlString(html) {
		return html instanceof HtmlString
	}

}
<commit_msg>Updated to work without grind-http<commit_after>import { ViewEngine } from 'grind-view'

import './CacheManager'
import './Compiler'
import './HtmlString'
import './StoneLoop'
import './Watcher'
import './StoneRuntime'

import './Support/escape'

const path = require('path')
const fs = require('fs')

export class StoneEngine extends ViewEngine {

	cacheManager = null
	compiler = null
	watcher = null
	runtime = null
	namespaces = { }

	context = {
		escape: escape,
		HtmlString: HtmlString,
		StoneLoop: StoneLoop,
		stringify: JSON.stringify
	}

	constructor(app, view) {
		super(app, view)

		this.cacheManager = new CacheManager(app, this)
		this.compiler = new Compiler(this)
		this.runtime = new StoneRuntime(this)
	}

	async bootstrap() {
		const engine = this

		function StoneExpressView(name) {
			this.template = name
			this.name = name
			this.path = name
		}

		StoneExpressView.prototype.render = function(context, callback) {
			let template = null

			try {
				template = engine._render(this.template, context)
			} catch(err) {
				return callback(err)
			}

			callback(null, template)
		}

		if(!this.app.express.isNil) {
			this.app.express.set('view', StoneExpressView)
		}

		if(this.app.config.get('view.watch', this.app.debug)) {
			this.watcher = new Watcher(this, this.view.viewPath)
			this.watcher.start()
		}

		const tags = this.app.config.get('view.tags')

		if(!tags.isNil) {
			for(const [ key, value ] of Object.entries(tags)) {
				if(value === '*') {
					this.tag(`${key}.*`)
					continue
				}

				this.tag(key, value)
			}
		}

		if(await this.cacheManager.exists()) {
			await this.cacheManager.load()
		}
	}

	namespace(namespace, path) {
		this.namespaces[namespace] = path
	}

	shutdown() {
		if(this.watcher.isNil) {
			return
		}

		return this.watcher.stop()
	}

	share(name, value) {
		this.context[name] = value
	}

	extend(name, extension) {
		this.compiler.directives[name] = extension
	}

	tag(name, template = null) {
		if(template.isNil) {
			if(name.endsWith('.*')) {
				const base = name.substring(0, name.length - 2)

				// eslint-disable-next-line no-sync
				const templates = fs.readdirSync(path.join(this.view.viewPath, base.replace(/\./g, '/')))

				for(const template of templates) {
					const extname = path.extname(template)
					const name = path.basename(template, extname)

					if(extname !== '.stone') {
						continue
					}

					this.tag(`${base}.${name}`)
				}

				return
			}

			template = name
			name = template.split(/\./).pop().replace(/^_/g, '')
		}

		this.compiler.tags[name] = template
	}

	render(template, context) {
		this.view.emit('render:start', template)

		return Promise.resolve(this._render(template, context)).then(result => {
			this.view.emit('render:end', template, result)

			return result
		})
	}

	_render(template, context) {
		return this._renderCompiled(this.compiler.compile(this.resolve(template)), context)
	}

	renderString(template, context) {
		return this._renderCompiled(this.compiler.compileString(template), context)
	}

	_renderCompiled(compiled, context) {
		return compiled({
			...this.context,
			...context,
			$stone: this.runtime,
			$engine: this,
			$compiler: this.compiler
		})
	}

	resolve(template, relativeTo = null) {
		if(template.substring(0, 1) === '.' && typeof relativeTo === 'string') {
			let join = ''

			template = template.replace(/^(\.+)/, (_, dots) => {
				if(dots.length !== 1) {
					join = '../'.repeat(dots.length - 1)
				}

				return ''
			})

			return path.join(path.dirname(relativeTo), join, `${template.replace(/\./g, '/')}.stone`)
		}

		const index = template.indexOf('::')
		let viewPath = null

		if(index === -1) {
			viewPath = this.view.viewPath
		} else {
			const namespace = template.substring(0, index)
			viewPath = this.namespaces[namespace]

			if(typeof viewPath !== 'string') {
				throw new Error(`Invalid namespace: ${namespace}`)
			}

			template = template.substring(index + 2)
		}

		return path.join(viewPath, `${template.replace(/\./g, '/')}.stone`)
	}

	writeCache() {
		return this.cacheManager.write()
	}

	clearCache() {
		return this.cacheManager.clear()
	}

	toHtmlString(html) {
		return new HtmlString(html)
	}

	isHtmlString(html) {
		return html instanceof HtmlString
	}

}
<|endoftext|>


<commit_before>import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { createApolloClient, restartWebsockets } from 'vue-cli-plugin-apollo/graphql-client';

// Install the vue plugin
Vue.use(VueApollo);

// Name of the localStorage item
const AUTH_TOKEN = 'apollo-token';

// Http endpoint
const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:3000/graphql';
// Files URL root
export const filesRoot = process.env.VUE_APP_FILES_ROOT || httpEndpoint.substr(0, httpEndpoint.indexOf('/graphql'));

Vue.prototype.$filesRoot = filesRoot;

// Config
const defaultOptions = {
  // You can use `https` for secure connection (recommended in production)
  httpEndpoint,
  // You can use `wss` for secure connection (recommended in production)
  // Use `null` to disable subscriptions
  wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:3000/graphql',
  // LocalStorage token
  tokenName: AUTH_TOKEN,
  // Enable Automatic Query persisting with Apollo Engine
  persisting: false,
  // Use websockets for everything (no HTTP)
  // You need to pass a `wsEndpoint` for this to work
  websocketsOnly: false,
  // Is being rendered on the server?
  ssr: false,

  // Override default apollo link
  // note: don't override httpLink here, specify httpLink options in the
  // httpLinkOptions property of defaultOptions.
  // link: myLink

  // Override default cache
  // cache: myCache

  // Override the way the Authorization header is set
  // getAuth: (tokenName) => ...

  // Additional ApolloClient options
  // apollo: { ... }

  // Client local data (see apollo-link-state)
  // clientState: { resolvers: { ... }, defaults: { ... } }
};

// Call this in the Vue app file
export function createProvider(options = {}) {
  // Create apollo client
  const { apolloClient, wsClient } = createApolloClient({
    ...defaultOptions,
    ...options,
  });
  apolloClient.wsClient = wsClient;

  // Create vue apollo provider
  const apolloProvider = new VueApollo({
    defaultClient: apolloClient,
    defaultOptions: {
      $query: {
        // fetchPolicy: 'cache-and-network',
      },
    },
    errorHandler(error) {
      // eslint-disable-next-line no-console
      console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message);
    },
  });

  return apolloProvider;
}

// Manually call this when user log in
export async function onLogin(apolloClient, token) {
  if (typeof localStorage !== 'undefined' && token) {
    localStorage.setItem(AUTH_TOKEN, token);
  }
  if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
  try {
    await apolloClient.resetStore();
  } catch (e) {
    // eslint-disable-next-line no-console
    console.log('%cError on cache reset (login)', 'color: orange;', e.message);
  }
}

// Manually call this when user log out
export async function onLogout(apolloClient) {
  if (typeof localStorage !== 'undefined') {
    localStorage.removeItem(AUTH_TOKEN);
  }
  if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
  try {
    await apolloClient.resetStore();
  } catch (e) {
    // eslint-disable-next-line no-console
    console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
  }
}
<commit_msg>Capture GraphQL exceptions with Sentry<commit_after>import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { createApolloClient, restartWebsockets } from 'vue-cli-plugin-apollo/graphql-client';

import * as Sentry from '@sentry/browser';

// Install the vue plugin
Vue.use(VueApollo);

// Name of the localStorage item
const AUTH_TOKEN = 'apollo-token';

// Http endpoint
const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:3000/graphql';
// Files URL root
export const filesRoot = process.env.VUE_APP_FILES_ROOT || httpEndpoint.substr(0, httpEndpoint.indexOf('/graphql'));

Vue.prototype.$filesRoot = filesRoot;

// Config
const defaultOptions = {
  // You can use `https` for secure connection (recommended in production)
  httpEndpoint,
  // You can use `wss` for secure connection (recommended in production)
  // Use `null` to disable subscriptions
  wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:3000/graphql',
  // LocalStorage token
  tokenName: AUTH_TOKEN,
  // Enable Automatic Query persisting with Apollo Engine
  persisting: false,
  // Use websockets for everything (no HTTP)
  // You need to pass a `wsEndpoint` for this to work
  websocketsOnly: false,
  // Is being rendered on the server?
  ssr: false,

  // Override default apollo link
  // note: don't override httpLink here, specify httpLink options in the
  // httpLinkOptions property of defaultOptions.
  // link: myLink

  // Override default cache
  // cache: myCache

  // Override the way the Authorization header is set
  // getAuth: (tokenName) => ...

  // Additional ApolloClient options
  // apollo: { ... }

  // Client local data (see apollo-link-state)
  // clientState: { resolvers: { ... }, defaults: { ... } }
};

// Call this in the Vue app file
export function createProvider(options = {}) {
  // Create apollo client
  const { apolloClient, wsClient } = createApolloClient({
    ...defaultOptions,
    ...options,
  });
  apolloClient.wsClient = wsClient;

  // Create vue apollo provider
  const apolloProvider = new VueApollo({
    defaultClient: apolloClient,
    defaultOptions: {
      $query: {
        // fetchPolicy: 'cache-and-network',
      },
    },
    errorHandler(error) {
      // eslint-disable-next-line no-console
      console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message);
      Sentry.captureException(error);
    },
  });

  return apolloProvider;
}

// Manually call this when user log in
export async function onLogin(apolloClient, token) {
  if (typeof localStorage !== 'undefined' && token) {
    localStorage.setItem(AUTH_TOKEN, token);
  }
  if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
  try {
    await apolloClient.resetStore();
  } catch (e) {
    // eslint-disable-next-line no-console
    console.log('%cError on cache reset (login)', 'color: orange;', e.message);
  }
}

// Manually call this when user log out
export async function onLogout(apolloClient) {
  if (typeof localStorage !== 'undefined') {
    localStorage.removeItem(AUTH_TOKEN);
  }
  if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
  try {
    await apolloClient.resetStore();
  } catch (e) {
    // eslint-disable-next-line no-console
    console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
'use strict';

const mockComponent = require.requireActual('./mockComponent');

require.requireActual('../Libraries/polyfills/babelHelpers.js');
require.requireActual('../Libraries/polyfills/Object.es7.js');
require.requireActual('../Libraries/polyfills/error-guard');

global.__DEV__ = true;

global.Promise = require.requireActual('promise');
global.regeneratorRuntime = require.requireActual('regenerator-runtime/runtime');

global.requestAnimationFrame = function(callback) {
  return setTimeout(callback, 0);
};
global.cancelAnimationFrame = function(id) {
  clearTimeout(id);
};

jest
  .mock('setupDevtools')
  .mock('npmlog');

// there's a __mock__ for it.
jest.setMock('ErrorUtils', require('ErrorUtils'));

jest
  .mock('InitializeCore', () => {})
  .mock('Image', () => mockComponent('Image'))
  .mock('Text', () => mockComponent('Text'))
  .mock('TextInput', () => mockComponent('TextInput'))
  .mock('Modal', () => mockComponent('Modal'))
  .mock('View', () => mockComponent('View'))
  .mock('RefreshControl', () => require.requireMock('RefreshControlMock'))
  .mock('ScrollView', () => require.requireMock('ScrollViewMock'))
  .mock(
    'ActivityIndicator',
    () => mockComponent('ActivityIndicator'),
  )
  .mock('ListView', () => require.requireMock('ListViewMock'))
  .mock('ListViewDataSource', () => {
    const DataSource = require.requireActual('ListViewDataSource');
    DataSource.prototype.toJSON = function() {
      function ListViewDataSource(dataBlob) {
        this.items = 0;
        // Ensure this doesn't throw.
        try {
          Object.keys(dataBlob).forEach(key => {
            this.items += dataBlob[key] && (
              dataBlob[key].length || dataBlob[key].size || 0
            );
          });
        } catch (e) {
          this.items = 'unknown';
        }
      }

      return new ListViewDataSource(this._dataBlob);
    };
    return DataSource;
  })
  .mock('AnimatedImplementation', () => {
    const AnimatedImplementation = require.requireActual('AnimatedImplementation');
    const oldCreate = AnimatedImplementation.createAnimatedComponent;
    AnimatedImplementation.createAnimatedComponent = function(Component) {
      const Wrapped = oldCreate(Component);
      Wrapped.__skipSetNativeProps_FOR_TESTS_ONLY = true;
      return Wrapped;
    };
    return AnimatedImplementation;
  })
  .mock('ReactNative', () => {
    const ReactNative = require.requireActual('ReactNative');
    const NativeMethodsMixin =
      ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.NativeMethodsMixin;
    [
      'measure',
      'measureInWindow',
      'measureLayout',
      'setNativeProps',
      'focus',
      'blur',
    ].forEach((key) => {
      let warned = false;
      NativeMethodsMixin[key] = function() {
        if (warned) {
          return;
        }
        warned = true;
        console.warn(
          'Calling .' + key + '() in the test renderer environment is not ' +
            'supported. Instead, mock out your components that use ' +
            'findNodeHandle with replacements that don\'t rely on the ' +
            'native environment.',
        );
      };
    });
    return ReactNative;
  })
  .mock('ensureComponentIsNative', () => () => true);

const mockEmptyObject = {};
const mockNativeModules = {
  AlertManager: {
    alertWithArgs: jest.fn(),
  },
  AppState: {
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
  },
  AsyncLocalStorage: {
    multiGet: jest.fn((keys, callback) => process.nextTick(() => callback(null, []))),
    multiSet: jest.fn((entries, callback) => process.nextTick(() => callback(null))),
    multiRemove: jest.fn((keys, callback) => process.nextTick(() => callback(null))),
    multiMerge: jest.fn((entries, callback) => process.nextTick(() => callback(null))),
    clear: jest.fn(callback => process.nextTick(() => callback(null))),
    getAllKeys: jest.fn(callback => process.nextTick(() => callback(null, []))),
  },
  BuildInfo: {
    appVersion: '0',
    buildVersion: '0',
  },
  Clipboard: {
    setString: jest.fn(),
  },
  DataManager: {
    queryData: jest.fn(),
  },
  DeviceInfo: {
    Dimensions: {
      window: {
        fontScale: 2,
        height: 1334,
        scale: 2,
        width: 750,
      },
      screen: {
        fontScale: 2,
        height: 1334,
        scale: 2,
        width: 750,
      },
    },
  },
  FacebookSDK: {
    login: jest.fn(),
    logout: jest.fn(),
    queryGraphPath: jest.fn((path, method, params, callback) => callback()),
  },
  FbRelayNativeAdapter: {
    updateCLC: jest.fn(),
  },
  GraphPhotoUpload: {
    upload: jest.fn(),
  },
  I18n: {
    translationsDictionary: JSON.stringify({
      'Good bye, {name}!|Bye message': '\u{00A1}Adi\u{00F3}s {name}!',
    }),
  },
  ImageLoader: {
    getSize: jest.fn(
      (url) => Promise.resolve({width: 320, height: 240})
    ),
    prefetchImage: jest.fn(),
  },
  ImageViewManager: {
    getSize: jest.fn(
      (uri, success) => process.nextTick(() => success(320, 240))
    ),
    prefetchImage: jest.fn(),
  },
  KeyboardObserver: {
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
  Linking: {
    openURL: jest.fn(),
    canOpenURL: jest.fn(
      () => Promise.resolve(true)
    ),
    addEventListener: jest.fn(),
    getInitialURL: jest.fn(
      () => Promise.resolve()
    ),
    removeEventListener: jest.fn(),
  },
  LocationObserver: {
    getCurrentPosition: jest.fn(),
    startObserving: jest.fn(),
    stopObserving: jest.fn(),
  },
  ModalFullscreenViewManager: {},
  NetInfo: {
    fetch: jest.fn(
      () => Promise.resolve()
    ),
    getConnectionInfo: jest.fn(
      () => Promise.resolve()
    ),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    isConnected: {
      fetch: jest.fn(
        () => Promise.resolve()
      ),
      addEventListener: jest.fn(),
      removeEventListener: jest.fn(),
    },
    isConnectionExpensive: jest.fn(
      () => Promise.resolve()
    ),
  },
  Networking: {
    sendRequest: jest.fn(),
    abortRequest: jest.fn(),
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
  PushNotificationManager: {
    presentLocalNotification: jest.fn(),
    scheduleLocalNotification: jest.fn(),
    cancelAllLocalNotifications: jest.fn(),
    removeAllDeliveredNotifications: jest.fn(),
    getDeliveredNotifications: jest.fn(callback => process.nextTick(() => [])),
    removeDeliveredNotifications: jest.fn(),
    setApplicationIconBadgeNumber: jest.fn(),
    getApplicationIconBadgeNumber: jest.fn(callback => process.nextTick(() => callback(0))),
    cancelLocalNotifications: jest.fn(),
    getScheduledLocalNotifications: jest.fn(callback => process.nextTick(() => callback())),
    requestPermissions: jest.fn(() => Promise.resolve({alert: true, badge: true, sound: true})),
    abandonPermissions: jest.fn(),
    checkPermissions: jest.fn(callback => process.nextTick(() => callback({alert: true, badge: true, sound: true}))),
    getInitialNotification: jest.fn(() => Promise.resolve(null)),
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
  SourceCode: {
    scriptURL: null,
  },
  StatusBarManager: {
    setColor: jest.fn(),
    setStyle: jest.fn(),
    setHidden: jest.fn(),
    setNetworkActivityIndicatorVisible: jest.fn(),
    setBackgroundColor: jest.fn(),
    setTranslucent: jest.fn(),
  },
  Timing: {
    createTimer: jest.fn(),
    deleteTimer: jest.fn(),
  },
  UIManager: {
    AndroidViewPager: {
      Commands: {
        setPage: jest.fn(),
        setPageWithoutAnimation: jest.fn(),
      },
    },
    blur: jest.fn(),
    createView: jest.fn(),
    dispatchViewManagerCommand: jest.fn(),
    focus: jest.fn(),
    setChildren: jest.fn(),
    manageChildren: jest.fn(),
    updateView: jest.fn(),
    removeSubviewsFromContainerWithID: jest.fn(),
    replaceExistingNonRootView: jest.fn(),
    customBubblingEventTypes: {},
    customDirectEventTypes: {},
    AndroidTextInput: {
      Commands: {},
    },
    ModalFullscreenView: {
      Constants: {},
    },
    ScrollView: {
      Constants: {},
    },
    View: {
      Constants: {},
    },
  },
  BlobModule: {
    BLOB_URI_SCHEME: 'content',
    BLOB_URI_HOST: null,
    enableBlobSupport: jest.fn(),
    disableBlobSupport: jest.fn(),
    createFromParts: jest.fn(),
    sendBlob: jest.fn(),
    release: jest.fn(),
  },
  WebSocketModule: {
    connect: jest.fn(),
    send: jest.fn(),
    sendBinary: jest.fn(),
    ping: jest.fn(),
    close: jest.fn(),
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
};

Object.keys(mockNativeModules).forEach(module => {
  try {
    jest.doMock(module, () => mockNativeModules[module]); // needed by FacebookSDK-test
  } catch (e) {
    jest.doMock(module, () => mockNativeModules[module], {virtual: true});
  }
});

jest
  .doMock('NativeModules', () => mockNativeModules)
  .doMock('ReactNativePropRegistry', () => ({
    register: id => id,
    getByID: () => mockEmptyObject,
  }));

jest.doMock('requireNativeComponent', () => {
  const React = require('react');

  return viewName => class extends React.Component {
    render() {
      return React.createElement(
        viewName,
        this.props,
        this.props.children,
      );
    }
  };
});
<commit_msg>Mock ReactNative.NativeComponent native methods in jest<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
'use strict';

const mockComponent = require.requireActual('./mockComponent');

require.requireActual('../Libraries/polyfills/babelHelpers.js');
require.requireActual('../Libraries/polyfills/Object.es7.js');
require.requireActual('../Libraries/polyfills/error-guard');

global.__DEV__ = true;

global.Promise = require.requireActual('promise');
global.regeneratorRuntime = require.requireActual('regenerator-runtime/runtime');

global.requestAnimationFrame = function(callback) {
  return setTimeout(callback, 0);
};
global.cancelAnimationFrame = function(id) {
  clearTimeout(id);
};

jest
  .mock('setupDevtools')
  .mock('npmlog');

// there's a __mock__ for it.
jest.setMock('ErrorUtils', require('ErrorUtils'));

jest
  .mock('InitializeCore', () => {})
  .mock('Image', () => mockComponent('Image'))
  .mock('Text', () => mockComponent('Text'))
  .mock('TextInput', () => mockComponent('TextInput'))
  .mock('Modal', () => mockComponent('Modal'))
  .mock('View', () => mockComponent('View'))
  .mock('RefreshControl', () => require.requireMock('RefreshControlMock'))
  .mock('ScrollView', () => require.requireMock('ScrollViewMock'))
  .mock(
    'ActivityIndicator',
    () => mockComponent('ActivityIndicator'),
  )
  .mock('ListView', () => require.requireMock('ListViewMock'))
  .mock('ListViewDataSource', () => {
    const DataSource = require.requireActual('ListViewDataSource');
    DataSource.prototype.toJSON = function() {
      function ListViewDataSource(dataBlob) {
        this.items = 0;
        // Ensure this doesn't throw.
        try {
          Object.keys(dataBlob).forEach(key => {
            this.items += dataBlob[key] && (
              dataBlob[key].length || dataBlob[key].size || 0
            );
          });
        } catch (e) {
          this.items = 'unknown';
        }
      }

      return new ListViewDataSource(this._dataBlob);
    };
    return DataSource;
  })
  .mock('AnimatedImplementation', () => {
    const AnimatedImplementation = require.requireActual('AnimatedImplementation');
    const oldCreate = AnimatedImplementation.createAnimatedComponent;
    AnimatedImplementation.createAnimatedComponent = function(Component) {
      const Wrapped = oldCreate(Component);
      Wrapped.__skipSetNativeProps_FOR_TESTS_ONLY = true;
      return Wrapped;
    };
    return AnimatedImplementation;
  })
  .mock('ReactNative', () => {
    const ReactNative = require.requireActual('ReactNative');
    const NativeMethodsMixin =
      ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.NativeMethodsMixin;

    const mockFunction = (key) => {
      let warned = false;
      return function() {
        if (warned) {
          return;
        }
        warned = true;
        console.warn(
          'Calling .' + key + '() in the test renderer environment is not ' +
            'supported. Instead, mock out your components that use ' +
            'findNodeHandle with replacements that don\'t rely on the ' +
            'native environment.',
        );
      };
    };

    [
      'measure',
      'measureInWindow',
      'measureLayout',
      'setNativeProps',
      'focus',
      'blur',
    ].forEach((key) => {
      NativeMethodsMixin[key] = mockFunction(key);
      ReactNative.NativeComponent.prototype[key] = mockFunction(key);
    });
    return ReactNative;
  })
  .mock('ensureComponentIsNative', () => () => true);

const mockEmptyObject = {};
const mockNativeModules = {
  AlertManager: {
    alertWithArgs: jest.fn(),
  },
  AppState: {
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
  },
  AsyncLocalStorage: {
    multiGet: jest.fn((keys, callback) => process.nextTick(() => callback(null, []))),
    multiSet: jest.fn((entries, callback) => process.nextTick(() => callback(null))),
    multiRemove: jest.fn((keys, callback) => process.nextTick(() => callback(null))),
    multiMerge: jest.fn((entries, callback) => process.nextTick(() => callback(null))),
    clear: jest.fn(callback => process.nextTick(() => callback(null))),
    getAllKeys: jest.fn(callback => process.nextTick(() => callback(null, []))),
  },
  BuildInfo: {
    appVersion: '0',
    buildVersion: '0',
  },
  Clipboard: {
    setString: jest.fn(),
  },
  DataManager: {
    queryData: jest.fn(),
  },
  DeviceInfo: {
    Dimensions: {
      window: {
        fontScale: 2,
        height: 1334,
        scale: 2,
        width: 750,
      },
      screen: {
        fontScale: 2,
        height: 1334,
        scale: 2,
        width: 750,
      },
    },
  },
  FacebookSDK: {
    login: jest.fn(),
    logout: jest.fn(),
    queryGraphPath: jest.fn((path, method, params, callback) => callback()),
  },
  FbRelayNativeAdapter: {
    updateCLC: jest.fn(),
  },
  GraphPhotoUpload: {
    upload: jest.fn(),
  },
  I18n: {
    translationsDictionary: JSON.stringify({
      'Good bye, {name}!|Bye message': '\u{00A1}Adi\u{00F3}s {name}!',
    }),
  },
  ImageLoader: {
    getSize: jest.fn(
      (url) => Promise.resolve({width: 320, height: 240})
    ),
    prefetchImage: jest.fn(),
  },
  ImageViewManager: {
    getSize: jest.fn(
      (uri, success) => process.nextTick(() => success(320, 240))
    ),
    prefetchImage: jest.fn(),
  },
  KeyboardObserver: {
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
  Linking: {
    openURL: jest.fn(),
    canOpenURL: jest.fn(
      () => Promise.resolve(true)
    ),
    addEventListener: jest.fn(),
    getInitialURL: jest.fn(
      () => Promise.resolve()
    ),
    removeEventListener: jest.fn(),
  },
  LocationObserver: {
    getCurrentPosition: jest.fn(),
    startObserving: jest.fn(),
    stopObserving: jest.fn(),
  },
  ModalFullscreenViewManager: {},
  NetInfo: {
    fetch: jest.fn(
      () => Promise.resolve()
    ),
    getConnectionInfo: jest.fn(
      () => Promise.resolve()
    ),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    isConnected: {
      fetch: jest.fn(
        () => Promise.resolve()
      ),
      addEventListener: jest.fn(),
      removeEventListener: jest.fn(),
    },
    isConnectionExpensive: jest.fn(
      () => Promise.resolve()
    ),
  },
  Networking: {
    sendRequest: jest.fn(),
    abortRequest: jest.fn(),
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
  PushNotificationManager: {
    presentLocalNotification: jest.fn(),
    scheduleLocalNotification: jest.fn(),
    cancelAllLocalNotifications: jest.fn(),
    removeAllDeliveredNotifications: jest.fn(),
    getDeliveredNotifications: jest.fn(callback => process.nextTick(() => [])),
    removeDeliveredNotifications: jest.fn(),
    setApplicationIconBadgeNumber: jest.fn(),
    getApplicationIconBadgeNumber: jest.fn(callback => process.nextTick(() => callback(0))),
    cancelLocalNotifications: jest.fn(),
    getScheduledLocalNotifications: jest.fn(callback => process.nextTick(() => callback())),
    requestPermissions: jest.fn(() => Promise.resolve({alert: true, badge: true, sound: true})),
    abandonPermissions: jest.fn(),
    checkPermissions: jest.fn(callback => process.nextTick(() => callback({alert: true, badge: true, sound: true}))),
    getInitialNotification: jest.fn(() => Promise.resolve(null)),
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
  SourceCode: {
    scriptURL: null,
  },
  StatusBarManager: {
    setColor: jest.fn(),
    setStyle: jest.fn(),
    setHidden: jest.fn(),
    setNetworkActivityIndicatorVisible: jest.fn(),
    setBackgroundColor: jest.fn(),
    setTranslucent: jest.fn(),
  },
  Timing: {
    createTimer: jest.fn(),
    deleteTimer: jest.fn(),
  },
  UIManager: {
    AndroidViewPager: {
      Commands: {
        setPage: jest.fn(),
        setPageWithoutAnimation: jest.fn(),
      },
    },
    blur: jest.fn(),
    createView: jest.fn(),
    dispatchViewManagerCommand: jest.fn(),
    focus: jest.fn(),
    setChildren: jest.fn(),
    manageChildren: jest.fn(),
    updateView: jest.fn(),
    removeSubviewsFromContainerWithID: jest.fn(),
    replaceExistingNonRootView: jest.fn(),
    customBubblingEventTypes: {},
    customDirectEventTypes: {},
    AndroidTextInput: {
      Commands: {},
    },
    ModalFullscreenView: {
      Constants: {},
    },
    ScrollView: {
      Constants: {},
    },
    View: {
      Constants: {},
    },
  },
  BlobModule: {
    BLOB_URI_SCHEME: 'content',
    BLOB_URI_HOST: null,
    enableBlobSupport: jest.fn(),
    disableBlobSupport: jest.fn(),
    createFromParts: jest.fn(),
    sendBlob: jest.fn(),
    release: jest.fn(),
  },
  WebSocketModule: {
    connect: jest.fn(),
    send: jest.fn(),
    sendBinary: jest.fn(),
    ping: jest.fn(),
    close: jest.fn(),
    addListener: jest.fn(),
    removeListeners: jest.fn(),
  },
};

Object.keys(mockNativeModules).forEach(module => {
  try {
    jest.doMock(module, () => mockNativeModules[module]); // needed by FacebookSDK-test
  } catch (e) {
    jest.doMock(module, () => mockNativeModules[module], {virtual: true});
  }
});

jest
  .doMock('NativeModules', () => mockNativeModules)
  .doMock('ReactNativePropRegistry', () => ({
    register: id => id,
    getByID: () => mockEmptyObject,
  }));

jest.doMock('requireNativeComponent', () => {
  const React = require('react');

  return viewName => class extends React.Component {
    render() {
      return React.createElement(
        viewName,
        this.props,
        this.props.children,
      );
    }
  };
});
<|endoftext|>


<commit_before>let assets_dir = './assets';
const path = require('path');

let Encore = require('@symfony/webpack-encore');
const WorkboxPlugin = require('workbox-webpack-plugin');

Encore
    // directory where all compiled assets will be stored
    .setOutputPath('public/build/')

    // what's the public path to this directory (relative to your project's document root dir)
    .setPublicPath(Encore.isProduction() ? '/build' : 'https://swapp.local:8874')

    // .setOutputPath()

    // empty the outputPath dir before each build
    .cleanupOutputBeforeBuild()

    .copyFiles(
        {
            from: './assets/images/icons',
            to: '../images/icons/[path][name].[ext]',
            pattern: /\.(png|jpg|jpeg)$/,
        },
    )

    .configureManifestPlugin(options => {
        // options.fileName = 'webpack-manifest.json';
        options.seed = {
            'name': 'Swapp - Die Streetworkapp',
            'short_name': 'Swapp',
            'display': 'standalone',
            'display_overrides': ['tabbed', 'fullscreen'],
            'description': 'Swapp für Fachkräfte der Streetwork/Mobilen Jugendarbeit.\nDokumentation und Reflexion für unterwegs.\nsince 2015',
            'start_url': '.',
            'lang': 'de',
            'dir': 'ltr',
            'background_color': '#fff',
            'theme_color': '#1c97b0',
            'icons': [
                {
                    'src': '/images/icons/icon-512x512.png',
                    'type': 'image/png',
                    'sizes': '512x512',
                },
                {
                    'src': '/images/icons/icon-192x192.png',
                    'type': 'image/png',
                    'sizes': '192x192',
                },
            ],
        };
    })

    // will output as web/build/app.js
    .addEntry('app', assets_dir + '/js/app.js')

    .addAliases(
        {
            'api': path.resolve(__dirname, 'assets/js/api'),
            'components': path.resolve(__dirname, 'assets/js/components'),
            'pages': path.resolve(__dirname, 'assets/js/pages'),
            'router': path.resolve(__dirname, 'assets/js/router'),
            'store': path.resolve(__dirname, 'assets/js/store'),
            'css': path.resolve(__dirname, 'assets/css'),
        },
    )

    // will require an extra script tag for runtime.js
    // but, you probably want this, unless you're building a single-page app
    .enableSingleRuntimeChunk()

    // allow sass/scss files to be processed
    .enableSassLoader()

    // allow legacy applications to use $/jQuery as a global variable
    // .autoProvidejQuery()

    .enableSourceMaps(!Encore.isProduction())

    .setManifestKeyPrefix('build/')

    // create hashed filenames (e.g. app.abc123.css)
    .enableVersioning(Encore.isProduction())

    // enable vue-load
    .enableVueLoader(() => {}, { runtimeCompilerBuild: false })

    .enablePostCssLoader()
    .enableEslintPlugin()

    .configureDevServerOptions(options => {
        options.allowedHosts = 'all';
        options.server = {
            type: 'https',
            options: {
                key: '/var/www/certs/swapp.local.key',
                cert: '/var/www/certs/swapp.local.crt',
            },
        };
        options.host = '0.0.0.0';
        options.port = '8874';
    })
;

if (Encore.isProduction()) {
    Encore.addPlugin(
        // new WorkboxPlugin.InjectManifest({
        new WorkboxPlugin.GenerateSW({
            // swSrc: "./assets/js/service-worker.js",
            swDest: 'service-worker.js',
            maximumFileSizeToCacheInBytes: 50000000,
        })
    );
}

module.exports = Encore.getWebpackConfig();
<commit_msg>Fix icon image loading #227<commit_after>let assets_dir = './assets';
const path = require('path');

let Encore = require('@symfony/webpack-encore');
const WorkboxPlugin = require('workbox-webpack-plugin');

Encore
    // directory where all compiled assets will be stored
    .setOutputPath('public/build/')

    // what's the public path to this directory (relative to your project's document root dir)
    .setPublicPath(Encore.isProduction() ? '/build' : 'https://swapp.local:8874')

    // .setOutputPath()

    // empty the outputPath dir before each build
    .cleanupOutputBeforeBuild()

    .copyFiles(
        {
            from: './assets/images/icons',
            to: 'images/icons/[path][name].[ext]',
            pattern: /\.(png|jpg|jpeg)$/,
        },
    )

    .configureManifestPlugin(options => {
        // options.fileName = 'webpack-manifest.json';
        options.seed = {
            'name': 'Swapp - Die Streetworkapp',
            'short_name': 'Swapp',
            'display': 'standalone',
            'display_overrides': ['tabbed', 'fullscreen'],
            'description': 'Swapp für Fachkräfte der Streetwork/Mobilen Jugendarbeit.\nDokumentation und Reflexion für unterwegs.\nsince 2015',
            'start_url': '.',
            'lang': 'de',
            'dir': 'ltr',
            'background_color': '#fff',
            'theme_color': '#1c97b0',
            'icons': [
                {
                    'src': '/build/images/icons/icon-512x512.png',
                    'type': 'image/png',
                    'sizes': '512x512',
                },
                {
                    'src': '/build/images/icons/icon-192x192.png',
                    'type': 'image/png',
                    'sizes': '192x192',
                },
            ],
        };
    })

    // will output as web/build/app.js
    .addEntry('app', assets_dir + '/js/app.js')

    .addAliases(
        {
            'api': path.resolve(__dirname, 'assets/js/api'),
            'components': path.resolve(__dirname, 'assets/js/components'),
            'pages': path.resolve(__dirname, 'assets/js/pages'),
            'router': path.resolve(__dirname, 'assets/js/router'),
            'store': path.resolve(__dirname, 'assets/js/store'),
            'css': path.resolve(__dirname, 'assets/css'),
        },
    )

    // will require an extra script tag for runtime.js
    // but, you probably want this, unless you're building a single-page app
    .enableSingleRuntimeChunk()

    // allow sass/scss files to be processed
    .enableSassLoader()

    // allow legacy applications to use $/jQuery as a global variable
    // .autoProvidejQuery()

    .enableSourceMaps(!Encore.isProduction())

    .setManifestKeyPrefix('build/')

    // create hashed filenames (e.g. app.abc123.css)
    .enableVersioning(Encore.isProduction())

    // enable vue-load
    .enableVueLoader(() => {}, { runtimeCompilerBuild: false })

    .enablePostCssLoader()
    .enableEslintPlugin()

    .configureDevServerOptions(options => {
        options.allowedHosts = 'all';
        options.server = {
            type: 'https',
            options: {
                key: '/var/www/certs/swapp.local.key',
                cert: '/var/www/certs/swapp.local.crt',
            },
        };
        options.host = '0.0.0.0';
        options.port = '8874';
    })
;

if (Encore.isProduction()) {
    Encore.addPlugin(
        // new WorkboxPlugin.InjectManifest({
        new WorkboxPlugin.GenerateSW({
            // swSrc: "./assets/js/service-worker.js",
            swDest: 'service-worker.js',
            maximumFileSizeToCacheInBytes: 50000000,
        })
    );
}

module.exports = Encore.getWebpackConfig();
<|endoftext|>