<commit_before>"use strict";

(function(){

const iconTypes = {
	'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/core/1457712810/f/pdf-24': 'PDF',
	'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/core/1457712810/f/document-24': 'Word',
	'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/core/1457712810/f/powerpoint-24': 'PPT',
	'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/core/1457712810/f/spreadsheet-24': 'Excel',
	'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/core/1457712810/f/calc-24': 'Calc',
};

const acceptedTags = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
const rejectedTags = [];
const criticalFontSize = 16;

function getFontSize (el) {
	return parseFloat(getComputedStyle(el).fontSize);
}

function getLevelByEl (el, accepted = false) {
	if (!el.childElementCount) {
		let fontSize = getFontSize(el);
		if ((acceptedTags.includes(el.tagName) || accepted || fontSize >= criticalFontSize) && el.textContent.trim()) {
			return fontSize;
		} else {
			return -1;
		}
	} else {
		return Math.max.apply(null,
			Array.from(el.childNodes)
			.filter(node => node.nodeType === 3 || !rejectedTags.includes(node.nodeName))
			.map(node => {
				if (node.nodeType === 3) {
					let fontSize = getFontSize(el);
					if ((accepted || fontSize >= criticalFontSize) && node.textContent.trim()) {
						return fontSize;
					} else {
						return -1;
					}
				} else if (acceptedTags.includes(el.tagName)) {
					return getLevelByEl(node, true);
				} else {
					return getLevelByEl(node, accepted);
				}
			})
		);
	}
}

function createDirObj (name, level) {
	return {
		type: 'dir',
		name,
		icon: 'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/folder/1457712810/icon',
		files: [],
		level,
	}
}

function createFileObj (id, name, icon) {
	return {
		type: 'file',
		fileType: iconTypes[icon] || 'unknown',
		id,
		name,
		icon,
	};
}

function createFolderObj (id, name, icon) {
	return {
		type: 'folder',
		id,
		name,
		icon: icon || 'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/folder/1457712810/icon',
	}
}

function getIdByActivity (activity) {
	return activity.id.split('-')[1];
}

function getIconByActivity (activity) {
	return activity.querySelector('.activityinstance>a>.activityicon').src;
}

function getTitleByElementAndLevel (el, level) {
	if (!el.childElementCount) {
		if (getFontSize(el) === level) {
			return el.textContent.trim();
		} else {
			return '';
		}
	} else {
		return Array.from(el.childNodes)
			.filter(node => node.nodeType === 3 || !rejectedTags.includes(node.tagName))
			.map(node => {
				if (node.nodeType === 3) {
					return getFontSize(el) === level ? node.textContent.trim() : '';
				} else {
					return getTitleByElementAndLevel(node, level);
				}
			})
			.join('');
	}
}

function getTitlByEl (el, level) {
	if (level === undefined) {
		level = getLevelByEl(el);
	}
	if (level === -1) {
		return null;
	} else {
		return getTitleByElementAndLevel(el, level);
	}
}

function getNameByActivity (activity) {
	let name = '';
	let instancename = activity.querySelector('.activityinstance>a>.instancename').childNodes;
	return Array.from(instancename)
		.filter(node => node.nodeType === 3)
		.map(node => node.textContent.trim())
		.join('')
		.trim();
}

function cleanData (data) {
	delete data.level;
	delete data.parent;
	if (data.files) {
		for (let file of data.files) {
			cleanData(file);
		}
	}
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
	if (request === 'requestData') {

		let module = document.getElementById('course-header').textContent.trim();
		let data = {
			type: 'module',
			name: module,
			files: [],
		};
		let sections = document.querySelectorAll('.section.main:not(.hidden)');
		for (let section of sections) {
			let content = section.getElementsByClassName('content')[0];
			let name = content.getElementsByClassName('sectionname')[0].textContent.trim();
			let summary = getTitlByEl(content.getElementsByClassName('summary')[0]);
			if (summary && summary.length > 1 && summary.length < 50) {
				name = summary;
			}
			let dir = createDirObj(name, Infinity);
			let currentDir = dir;
			let activities = content.getElementsByClassName('activity');
			for (let activity of activities) {
				let id = getIdByActivity(activity);
				if (activity.classList.contains('modtype_label')) {
					let level = getLevelByEl(activity);
					if (level === -1) {
						// not a catagory label
						continue;
					}
					let name = getTitlByEl(activity);
					let newDir = createDirObj(name, level);
					while (currentDir.level <= newDir.level && currentDir !== dir) {
						currentDir = currentDir.parent;
					}
					newDir.parent = currentDir;
					currentDir.files.push(newDir);
					currentDir = newDir;
				} else {
					if (!activity.querySelector('.activityinstance>a')) {
						// link unavailable
						continue;
					}
					let icon = getIconByActivity(activity);
					let name = getNameByActivity(activity);
					if (activity.classList.contains('modtype_resource')) {
						let file = createFileObj(id, name, icon);
						currentDir.files.push(file);
					} else if (activity.classList.contains('modtype_folder')) {
						let folder = createFolderObj(id, name, icon);
						currentDir.files.push(folder);
					}
				}
				/*
					modtype_feedback
					modtype_url
					modtype_page
					modtype_quiz
					modtype_book
				*/
			}
			data.files.push(dir);
		}
		cleanData(data);
		sendResponse(data);
	}
});

})();

<commit_msg>fix filetype misrecognition<commit_after>"use strict";

(function(){

const iconTypes = new Map([
	[/1457712810\/f\/pdf-24$/, 'PDF'],
	[/1457712810\/f\/document-24$/, 'Word'],
	[/1457712810\/f\/powerpoint-24$/, 'PPT'],
	[/1457712810\/f\/spreadsheet-24$/, 'Excel'],
	[/1457712810\/f\/calc-24$/, 'Calc'],
]);

const acceptedTags = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
const rejectedTags = [];
const criticalFontSize = 16;

function getFiletypeByIcon (icon) {
	for (let [iconPattern, filetype] of iconTypes) {
		if (iconPattern.test(icon)) {
			return filetype;
		}
	}
	return 'unknown';
}

function getFontSize (el) {
	return parseFloat(getComputedStyle(el).fontSize);
}

function getLevelByEl (el, accepted = false) {
	if (!el.childElementCount) {
		let fontSize = getFontSize(el);
		if ((acceptedTags.includes(el.tagName) || accepted || fontSize >= criticalFontSize) && el.textContent.trim()) {
			return fontSize;
		} else {
			return -1;
		}
	} else {
		return Math.max.apply(null,
			Array.from(el.childNodes)
			.filter(node => node.nodeType === 3 || !rejectedTags.includes(node.nodeName))
			.map(node => {
				if (node.nodeType === 3) {
					let fontSize = getFontSize(el);
					if ((accepted || fontSize >= criticalFontSize) && node.textContent.trim()) {
						return fontSize;
					} else {
						return -1;
					}
				} else if (acceptedTags.includes(el.tagName)) {
					return getLevelByEl(node, true);
				} else {
					return getLevelByEl(node, accepted);
				}
			})
		);
	}
}

function createDirObj (name, level) {
	return {
		type: 'dir',
		name,
		icon: 'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/folder/1457712810/icon',
		files: [],
		level,
	}
}

function createFileObj (id, name, icon) {
	return {
		type: 'file',
		fileType: getFiletypeByIcon(icon),
		id,
		name,
		icon,
	};
}

function createFolderObj (id, name, icon) {
	return {
		type: 'folder',
		id,
		name,
		icon: icon || 'http://moodle.nottingham.ac.uk/theme/image.php/nottingham_arts/folder/1457712810/icon',
	}
}

function getIdByActivity (activity) {
	return activity.id.split('-')[1];
}

function getIconByActivity (activity) {
	return activity.querySelector('.activityinstance>a>.activityicon').src;
}

function getTitleByElementAndLevel (el, level) {
	if (!el.childElementCount) {
		if (getFontSize(el) === level) {
			return el.textContent.trim();
		} else {
			return '';
		}
	} else {
		return Array.from(el.childNodes)
			.filter(node => node.nodeType === 3 || !rejectedTags.includes(node.tagName))
			.map(node => {
				if (node.nodeType === 3) {
					return getFontSize(el) === level ? node.textContent.trim() : '';
				} else {
					return getTitleByElementAndLevel(node, level);
				}
			})
			.join('');
	}
}

function getTitlByEl (el, level) {
	if (level === undefined) {
		level = getLevelByEl(el);
	}
	if (level === -1) {
		return null;
	} else {
		return getTitleByElementAndLevel(el, level);
	}
}

function getNameByActivity (activity) {
	let name = '';
	let instancename = activity.querySelector('.activityinstance>a>.instancename').childNodes;
	return Array.from(instancename)
		.filter(node => node.nodeType === 3)
		.map(node => node.textContent.trim())
		.join('')
		.trim();
}

function cleanData (data) {
	delete data.level;
	delete data.parent;
	if (data.files) {
		for (let file of data.files) {
			cleanData(file);
		}
	}
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
	if (request === 'requestData') {

		let module = document.getElementById('course-header').textContent.trim();
		let data = {
			type: 'module',
			name: module,
			files: [],
		};
		let sections = document.querySelectorAll('.section.main:not(.hidden)');
		for (let section of sections) {
			let content = section.getElementsByClassName('content')[0];
			let name = content.getElementsByClassName('sectionname')[0].textContent.trim();
			let summary = getTitlByEl(content.getElementsByClassName('summary')[0]);
			if (summary && summary.length > 1 && summary.length < 50) {
				name = summary;
			}
			let dir = createDirObj(name, Infinity);
			let currentDir = dir;
			let activities = content.getElementsByClassName('activity');
			for (let activity of activities) {
				let id = getIdByActivity(activity);
				if (activity.classList.contains('modtype_label')) {
					let level = getLevelByEl(activity);
					if (level === -1) {
						// not a catagory label
						continue;
					}
					let name = getTitlByEl(activity);
					let newDir = createDirObj(name, level);
					while (currentDir.level <= newDir.level && currentDir !== dir) {
						currentDir = currentDir.parent;
					}
					newDir.parent = currentDir;
					currentDir.files.push(newDir);
					currentDir = newDir;
				} else {
					if (!activity.querySelector('.activityinstance>a')) {
						// link unavailable
						continue;
					}
					let icon = getIconByActivity(activity);
					let name = getNameByActivity(activity);
					if (activity.classList.contains('modtype_resource')) {
						let file = createFileObj(id, name, icon);
						currentDir.files.push(file);
					} else if (activity.classList.contains('modtype_folder')) {
						let folder = createFolderObj(id, name, icon);
						currentDir.files.push(folder);
					}
				}
				/*
					modtype_feedback
					modtype_url
					modtype_page
					modtype_quiz
					modtype_book
				*/
			}
			data.files.push(dir);
		}
		cleanData(data);
		sendResponse(data);
	}
});

})();

<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var spaw = require('child_process').spaw;
var chalk = require('chalk');
var globule = require('globule');
var shelljs = require('shelljs');
var yeoman = require('yeoman-generator');
var bundle = false;
var errr = chalk.bold.red;

var MilagroGenerator = module.exports = function MilagroGenerator(args, options, config) {

  var dependenciesInstalled = ['bundle', 'ruby'].every(function (depend) {
    return shelljs.which(depend);
  });

  if (!dependenciesInstalled) {
    console.log(errr('Erro!') + ' Certifique-se de ter instalado: ' + chalk.white('Ruby') + ' e ' +chalk.white('Bundler (gem)') + '.');
    shelljs.exit(1);
  }

  yeoman.generators.Base.apply(this, arguments);

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
  this.appname = path.basename(process.cwd());
  this.gitInfo = {
    name: this.user.git.username,
    email: this.user.git.email,
  };

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });

    if (bundle === false) {
      console.log(errr('Erro! Bundle install failed! ') + 'Execute o comando manualmente, \'gem install bundle\'');
    }
  });
};

util.inherits(MilagroGenerator, yeoman.generators.Base);

// Questions!
MilagroGenerator.prototype.askForProject = function askForProject() {
  var cb = this.async();
  var prompts = [{
    name: 'project',
    message: 'Nome do projeto: '
  },
  {
    name: 'client',
    message: 'Nome do cliente'
  }];

  this.prompt(prompts, function (props) {

    this.project = props.project;
    this.client = props.client;

    cb();
  }.bind(this));
};

MilagroGenerator.prototype.askForTools = function askForTools() {
  var cb = this.async();
  var prompts = [{
    name: 'cssPre',
    type: 'list',
    message: 'Pré-processadores CSS?',
    choices: ['Compass', 'Sass', 'None']
  },
  {
    name: 'autoPre',
    type: 'confirm',
    message: 'CSS Autoprefixer?'
  }];

  console.log(chalk.blue('Ferramentas e pré-processadores: '));

  this.prompt(prompts, function (props) {

    this.cssPre = props.cssPre;
    this.autoPre = props.autoPre;

    cb();
  }.bind(this));
}

// MilagroGenerator.prototype.askFor = function askFor() {
//   var cb = this.async();

//   // have Yeoman greet the user.
//   console.log(this.yeoman);

//   var prompts = [{
//     type: 'confirm',
//     name: 'someOption',
//     message: 'Would you like to enable this option?',
//     default: true
//   }];

//   this.prompt(prompts, function (props) {
//     this.someOption = props.someOption;

//     cb();
//   }.bind(this));
// };

// MilagroGenerator.prototype.app = function app() {
//   this.mkdir('app');
//   this.mkdir('app/templates');

//   this.copy('_package.json', 'package.json');
//   this.copy('_bower.json', 'bower.json');
// };

// MilagroGenerator.prototype.projectfiles = function projectfiles() {
//   this.copy('editorconfig', '.editorconfig');
//   this.copy('jshintrc', '.jshintrc');
// };
<commit_msg>askForDirs on index.js<commit_after>'use strict';
var util = require('util');
var path = require('path');
var spaw = require('child_process').spaw;
var chalk = require('chalk');
var globule = require('globule');
var shelljs = require('shelljs');
var yeoman = require('yeoman-generator');
var bundle = false;
var errr = chalk.bold.red;

var MilagroGenerator = module.exports = function MilagroGenerator(args, options, config) {

  var dependenciesInstalled = ['bundle', 'ruby'].every(function (depend) {
    return shelljs.which(depend);
  });

  if (!dependenciesInstalled) {
    console.log(errr('Erro!') + ' Certifique-se de ter instalado: ' + chalk.white('Ruby') + ' e ' +chalk.white('Bundler (gem)') + '.');
    shelljs.exit(1);
  }

  yeoman.generators.Base.apply(this, arguments);

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
  this.appname = path.basename(process.cwd());
  this.gitInfo = {
    name: this.user.git.username,
    email: this.user.git.email,
  };

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });

    if (bundle === false) {
      console.log(errr('Erro! Bundle install failed! ') + 'Execute o comando manualmente, \'gem install bundle\'');
    }
  });
};

util.inherits(MilagroGenerator, yeoman.generators.Base);

// Questions!
MilagroGenerator.prototype.askForProject = function askForProject() {
  var cb = this.async();
  var prompts = [{
    name: 'project',
    message: 'Nome do projeto: '
  },
  {
    name: 'client',
    message: 'Nome do cliente: '
  }];

  this.prompt(prompts, function (props) {

    this.project = props.project;
    this.client = props.client;

    cb();
  }.bind(this));
};

MilagroGenerator.prototype.askForTools = function askForTools() {
  var cb = this.async();
  var prompts = [{
    name: 'cssPre',
    type: 'list',
    message: 'Pré-processadores CSS?',
    choices: ['Compass', 'Sass', 'None']
  },
  {
    name: 'autoPre',
    type: 'confirm',
    message: 'CSS Autoprefixer?'
  }];

  console.log(chalk.blue('Ferramentas e pré-processadores: '));

  this.prompt(prompts, function (props) {

    this.cssPre = props.cssPre;
    this.autoPre = props.autoPre;

    cb();
  }.bind(this));
}

MilagroGenerator.prototype.askForDirs = function askForDirs() {
  var cb = this.async();
  var prompts = [{
    name: 'cssDir',
    default: 'css',
    message: 'Diretório CSS?'
  }];

  this.prompt(prompts, function (props) {

    this.cssDir = props.cssDir;

    cb();
  }.bind(this));
}

// MilagroGenerator.prototype.askFor = function askFor() {
//   var cb = this.async();

//   // have Yeoman greet the user.
//   console.log(this.yeoman);

//   var prompts = [{
//     type: 'confirm',
//     name: 'someOption',
//     message: 'Would you like to enable this option?',
//     default: true
//   }];

//   this.prompt(prompts, function (props) {
//     this.someOption = props.someOption;

//     cb();
//   }.bind(this));
// };

// MilagroGenerator.prototype.app = function app() {
//   this.mkdir('app');
//   this.mkdir('app/templates');

//   this.copy('_package.json', 'package.json');
//   this.copy('_bower.json', 'bower.json');
// };

// MilagroGenerator.prototype.projectfiles = function projectfiles() {
//   this.copy('editorconfig', '.editorconfig');
//   this.copy('jshintrc', '.jshintrc');
// };
<|endoftext|>


<commit_before>// === Search helper utilities ===

function getScrollPositionByOffset(offset) {
  var documentRange = document.createRange();
  var parentPre = extractTargetElement();
  // The parent pre element contains multiple child text nodes
  var childNodeStartOffset = 0;
  var containingChildNode = null;
  for (var i = 0; i < parentPre.childNodes.length; i++) {
    var childTextNode = parentPre.childNodes[i];
    if (offset >= childNodeStartOffset && offset <= childNodeStartOffset + childTextNode.length) {
      containingChildNode = childTextNode;
      break;
    }
    childNodeStartOffset += childTextNode.length;
  }
  if (!containingChildNode) {
    return null;
  }

  documentRange.setStart(containingChildNode, offset - childNodeStartOffset);
  documentRange.setEnd(containingChildNode, offset - childNodeStartOffset);
  var boundingRect = documentRange.getBoundingClientRect();
  // We need to compute based on current Y, since the rects are relative
  return window.scrollY + boundingRect.top;
}

function findAllMatches(sourceText, regexStr) {
  var re = new RegExp(regexStr,'gi');

  var results = new Array();//this is the results you want
  while (re.exec(sourceText)){
    results.push(re.lastIndex);
  }
  return results;
}

// Return timestamp
var LINE_CHAR_LIMIT = 500;
function extractTimestamp(text, offset, timestampRegex) {
  // Walk forward until we hit a newline or beginning of text, up to a limit
  var match = text.substring(Math.max(0, offset - LINE_CHAR_LIMIT), offset).match(timestampRegex);
  // Return error string if no matches
  if (!match || match.length == 0) return "__:__:__";
  return match[match.length - 1]; // get last match
}

// Return [[ruleIndex, shortDescription, offset, timestamp], ...]
function searchAndComputeIndex(text, regexStrings, regexDescriptions, timestampRegex) {
  var allMatches = [];
  for (var i = 0; i < regexStrings.length; i++) {
    var regexStr = regexStrings[i];
    var textOffsets = findAllMatches(text, regexStr);
    for (var u = 0; u < textOffsets.length; u++) {
      var scrollOffset = getScrollPositionByOffset(textOffsets[u]);
      var timestampString = extractTimestamp(text, textOffsets[u], timestampRegex);
      allMatches.push([i, regexDescriptions[i], scrollOffset, timestampString]);
    }
  }

  allMatches.sort(function(a, b) {
    return a[2] - b[2];
  });
  return allMatches;
}

// === UI Helper Utilities ===

// http://stackoverflow.com/questions/28860602/pleasing-palette-random-color-generation
function randomColor(){
  var golden_ratio_conjugate = 0.618033988749895,
      h = (Math.random() + golden_ratio_conjugate) % 1 *360,
      rgb = hsvToRgb(h, 80, 50);
  return "rgb("+rgb[0]+","+rgb[1]+","+rgb[2]+")";
}

/**
 * Converts an HSV color value to RGB. Conversion formula
 * adapted from http://en.wikipedia.org/wiki/HSL_and_HSV.
 * Assumes h is contained in the set [0, 360] and
 * s and l are contained in the set [0, 100] and
 * returns r, g, and b in the set [0, 255].
 *
 * @param   Number  h       The hue
 * @param   Number  s       The saturation
 * @param   Number  v       The value
 * @return  Array           The RGB representation
 */
function hsvToRgb(h, s, v){
  var chroma = s * v / 10000,
      min = v / 100 - chroma,
      hdash = h / 60,
      x = chroma * (1 - Math.abs(hdash % 2 - 1)),
      r = 0, g = 0, b = 0;

  switch(true){
    case hdash < 1:
      r = chroma;
      g = x;
      break;
    case hdash < 2:
      r = x;
      g = chroma;
      break;
    case hdash < 3:
      g = chroma;
      b = x;
      break;
    case hdash < 4:
      g = x;
      b = chroma;
      break;
    case hdash < 5:
      r = x;
      b = chroma;
      break;
    case hdash <= 6:
      r = chroma;
      b = x;
      break;
  }

  r += min;
  g += min;
  b += min;

  return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

function generateColorList(length) {
  var colors = []
  for (var i = 0; i < length; i++) {
    colors.push(randomColor());
  }
  return colors;
}

function scrollGenerator(offset) {
  return function() {
    window.scroll(0, offset);
  }
}

function onMouseOver() {
  this.style.fontWeight = 'bold';
}

function onLeave() {
  this.style.fontWeight = 'normal';
}

function generateTableOfContents(listHighlights, colorList) {
  var tableOfContents = document.createElement( 'ul' );
  tableOfContents.id = 'highlights-list';
  tableOfContents.style.listStyleType = "none";
  tableOfContents.style.paddingLeft = "8px";

  for (var i = 0; i < listHighlights.length ; i++) {
    var highlight = listHighlights[i];
    var listElement = document.createElement( 'li' );
    listElement.style.marginBottom = '5px';
    listElement.innerHTML = highlight[3] + " " + highlight[1];
    listElement.onclick = scrollGenerator(highlight[2]);
    listElement.onmouseover = onMouseOver;
    listElement.onmouseleave = onLeave;
    listElement.style.color = colorList[highlight[0]];
    tableOfContents.appendChild(listElement);
  }
  return tableOfContents;
}

function filterFunction() {
  var filterRegex = new RegExp(this.value, "gi");
  var highlightsList = document.getElementById('highlights-list');
  var highlights = highlightsList.childNodes;
  for (var i = 0; i < highlights.length; i++) {
    var highlight = highlights[i];
    if (highlight.innerHTML.match(filterRegex)) {
      highlight.hidden = false;
    } else {
      highlight.hidden = true;
    }
  }
}

function embedDiv(tableOfContents) {
  var currentDiv = document.getElementById("tableOfContentsDiv");
  var oldSearchBarDiv = document.getElementById("loghaus-search-bar");
  if (currentDiv) {
    currentDiv.remove();
  }
  if (oldSearchBarDiv) {
    oldSearchBarDiv.remove();
  }

  var div = document.createElement('div');

  // constants
  searchBarHeight = 26;
  searchBarPadding = 4;
  overlayWidth = 23;
  leftOverlayOffset = 100 - overlayWidth;

  //append all elements
  document.body.appendChild( div );
  div.appendChild(tableOfContents);
  //set attributes for div
  div.id = 'tableOfContentsDiv';
  div.style.position = 'fixed';
  div.style.top = (searchBarHeight + 2 * searchBarPadding) + 'px';
  div.style.left = leftOverlayOffset + '%';
  div.style.width = overlayWidth + '%';
  div.style.height = '99%';
  div.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
  div.style.overflow = 'scroll';

  var searchBarDiv = document.createElement('div');
  searchBarDiv.id = 'loghaus-search-bar';
  searchBarDiv.style.position = 'fixed';
  searchBarDiv.style.marginTop = searchBarPadding + 'px';
  searchBarDiv.style.top = '0%';
  searchBarDiv.style.height = searchBarHeight + 'px';
  searchBarDiv.style.width = overlayWidth + '%';
  searchBarDiv.style.left = leftOverlayOffset + '%';
  searchBarDiv.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
  searchBarDiv.style.textAlign = 'center';

  var searchBarInput = document.createElement('input');
  searchBarInput.type = 'search';
  searchBarInput.placeholder = 'Filter regex ...';
  searchBarInput.style.width = '96%';
  searchBarInput.style.height = searchBarHeight + 'px';
  searchBarInput.style.borderRadius = '5px';
  // Add keyup search function
  searchBarInput.oninput = filterFunction;

  searchBarDiv.appendChild(searchBarInput);

  document.body.appendChild(searchBarDiv);
}

// This works for log files where the body contains a pre with text
// NOTE: customize this!
function extractTargetElement() {
  return document.body.children[0];
}

// --- Full Generation ---

function fullGeneration() {
  chrome.storage.sync.get({
    timestampRegexString: "",
    rulesJsonString: ""
  }, function(items) {
    var rules = JSON.parse(items.rulesJsonString);
    var regexStrings = [];
    var regexDescriptions = [];
    for (var i = 0; i < rules.length; i++) {
      regexDescriptions.push(rules[i][0]);
      regexStrings.push(rules[i][1]);
    }
    var colorList = generateColorList(regexStrings.length);
    var targetText = extractTargetElement();
    if (items.timestampRegexString.length == 0) {
      // Default timestamp regex
      items.timestampRegexString = "\\d{1,2}:\\d{2}:\\d{2}\\.\\d{0,3}";
    }
    var res = searchAndComputeIndex(targetText.textContent,
      regexStrings,
      regexDescriptions,
      new RegExp(items.timestampRegexString, 'gi')
    );
    var tableOfContents = generateTableOfContents(res, colorList);
    embedDiv(tableOfContents);
  });
}

// Listen for messages
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
    // If the received message has the expected format...
    if (msg.text === 'clicked') {
        fullGeneration();
        // Set recompute on resize
        document.body.onresize = fullGeneration
    }
});
<commit_msg>remove transparency if there are no matches<commit_after>// === Search helper utilities ===

function getScrollPositionByOffset(offset) {
  var documentRange = document.createRange();
  var parentPre = extractTargetElement();
  // The parent pre element contains multiple child text nodes
  var childNodeStartOffset = 0;
  var containingChildNode = null;
  for (var i = 0; i < parentPre.childNodes.length; i++) {
    var childTextNode = parentPre.childNodes[i];
    if (offset >= childNodeStartOffset && offset <= childNodeStartOffset + childTextNode.length) {
      containingChildNode = childTextNode;
      break;
    }
    childNodeStartOffset += childTextNode.length;
  }
  if (!containingChildNode) {
    return null;
  }

  documentRange.setStart(containingChildNode, offset - childNodeStartOffset);
  documentRange.setEnd(containingChildNode, offset - childNodeStartOffset);
  var boundingRect = documentRange.getBoundingClientRect();
  // We need to compute based on current Y, since the rects are relative
  return window.scrollY + boundingRect.top;
}

function findAllMatches(sourceText, regexStr) {
  var re = new RegExp(regexStr,'gi');

  var results = new Array();//this is the results you want
  while (re.exec(sourceText)){
    results.push(re.lastIndex);
  }
  return results;
}

// Return timestamp
var LINE_CHAR_LIMIT = 500;
function extractTimestamp(text, offset, timestampRegex) {
  // Walk forward until we hit a newline or beginning of text, up to a limit
  var match = text.substring(Math.max(0, offset - LINE_CHAR_LIMIT), offset).match(timestampRegex);
  // Return error string if no matches
  if (!match || match.length == 0) return "__:__:__";
  return match[match.length - 1]; // get last match
}

// Return [[ruleIndex, shortDescription, offset, timestamp], ...]
function searchAndComputeIndex(text, regexStrings, regexDescriptions, timestampRegex) {
  var allMatches = [];
  for (var i = 0; i < regexStrings.length; i++) {
    var regexStr = regexStrings[i];
    var textOffsets = findAllMatches(text, regexStr);
    for (var u = 0; u < textOffsets.length; u++) {
      var scrollOffset = getScrollPositionByOffset(textOffsets[u]);
      var timestampString = extractTimestamp(text, textOffsets[u], timestampRegex);
      allMatches.push([i, regexDescriptions[i], scrollOffset, timestampString]);
    }
  }

  allMatches.sort(function(a, b) {
    return a[2] - b[2];
  });
  return allMatches;
}

// === UI Helper Utilities ===

// http://stackoverflow.com/questions/28860602/pleasing-palette-random-color-generation
function randomColor(){
  var golden_ratio_conjugate = 0.618033988749895,
      h = (Math.random() + golden_ratio_conjugate) % 1 *360,
      rgb = hsvToRgb(h, 80, 50);
  return "rgb("+rgb[0]+","+rgb[1]+","+rgb[2]+")";
}

/**
 * Converts an HSV color value to RGB. Conversion formula
 * adapted from http://en.wikipedia.org/wiki/HSL_and_HSV.
 * Assumes h is contained in the set [0, 360] and
 * s and l are contained in the set [0, 100] and
 * returns r, g, and b in the set [0, 255].
 *
 * @param   Number  h       The hue
 * @param   Number  s       The saturation
 * @param   Number  v       The value
 * @return  Array           The RGB representation
 */
function hsvToRgb(h, s, v){
  var chroma = s * v / 10000,
      min = v / 100 - chroma,
      hdash = h / 60,
      x = chroma * (1 - Math.abs(hdash % 2 - 1)),
      r = 0, g = 0, b = 0;

  switch(true){
    case hdash < 1:
      r = chroma;
      g = x;
      break;
    case hdash < 2:
      r = x;
      g = chroma;
      break;
    case hdash < 3:
      g = chroma;
      b = x;
      break;
    case hdash < 4:
      g = x;
      b = chroma;
      break;
    case hdash < 5:
      r = x;
      b = chroma;
      break;
    case hdash <= 6:
      r = chroma;
      b = x;
      break;
  }

  r += min;
  g += min;
  b += min;

  return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

function generateColorList(length) {
  var colors = []
  for (var i = 0; i < length; i++) {
    colors.push(randomColor());
  }
  return colors;
}

function scrollGenerator(offset) {
  return function() {
    window.scroll(0, offset);
  }
}

function onMouseOver() {
  this.style.fontWeight = 'bold';
}

function onLeave() {
  this.style.fontWeight = 'normal';
}

function generateTableOfContents(listHighlights, colorList) {
  var tableOfContents = document.createElement( 'ul' );
  tableOfContents.id = 'highlights-list';
  tableOfContents.style.listStyleType = "none";
  tableOfContents.style.paddingLeft = "8px";

  for (var i = 0; i < listHighlights.length ; i++) {
    var highlight = listHighlights[i];
    var listElement = document.createElement( 'li' );
    listElement.style.marginBottom = '5px';
    listElement.innerHTML = highlight[3] + " " + highlight[1];
    listElement.onclick = scrollGenerator(highlight[2]);
    listElement.onmouseover = onMouseOver;
    listElement.onmouseleave = onLeave;
    listElement.style.color = colorList[highlight[0]];
    tableOfContents.appendChild(listElement);
  }
  return tableOfContents;
}

function filterFunction() {
  var filterRegex = new RegExp(this.value, "gi");
  var highlightsList = document.getElementById('highlights-list');
  var highlights = highlightsList.childNodes;
  var numResults = 0;
  for (var i = 0; i < highlights.length; i++) {
    var highlight = highlights[i];
    if (highlight.innerHTML.match(filterRegex)) {
      highlight.hidden = false;
      numResults++;
    } else {
      highlight.hidden = true;
    }
  }
  if (numResults == 0) {
    document.getElementById("tableOfContentsDiv")
      .style.backgroundColor = 'rgba(255, 255, 255, 0.0)';
  } else {
    document.getElementById("tableOfContentsDiv")
      .style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
  }
}

function embedDiv(tableOfContents) {
  var currentDiv = document.getElementById("tableOfContentsDiv");
  var oldSearchBarDiv = document.getElementById("loghaus-search-bar");
  if (currentDiv) {
    currentDiv.remove();
  }
  if (oldSearchBarDiv) {
    oldSearchBarDiv.remove();
  }

  var div = document.createElement('div');

  // constants
  searchBarHeight = 26;
  searchBarPadding = 4;
  overlayWidth = 23;
  leftOverlayOffset = 100 - overlayWidth;

  //append all elements
  document.body.appendChild( div );
  div.appendChild(tableOfContents);
  //set attributes for div
  div.id = 'tableOfContentsDiv';
  div.style.position = 'fixed';
  div.style.top = (searchBarHeight + 2 * searchBarPadding) + 'px';
  div.style.left = leftOverlayOffset + '%';
  div.style.width = overlayWidth + '%';
  div.style.height = '99%';
  div.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
  div.style.overflow = 'scroll';

  var searchBarDiv = document.createElement('div');
  searchBarDiv.id = 'loghaus-search-bar';
  searchBarDiv.style.position = 'fixed';
  searchBarDiv.style.marginTop = searchBarPadding + 'px';
  searchBarDiv.style.top = '0%';
  searchBarDiv.style.height = searchBarHeight + 'px';
  searchBarDiv.style.width = overlayWidth + '%';
  searchBarDiv.style.left = leftOverlayOffset + '%';
  searchBarDiv.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
  searchBarDiv.style.textAlign = 'center';

  var searchBarInput = document.createElement('input');
  searchBarInput.type = 'search';
  searchBarInput.placeholder = 'Filter regex ...';
  searchBarInput.style.width = '96%';
  searchBarInput.style.height = searchBarHeight + 'px';
  searchBarInput.style.borderRadius = '5px';
  // Add keyup search function
  searchBarInput.oninput = filterFunction;

  searchBarDiv.appendChild(searchBarInput);

  document.body.appendChild(searchBarDiv);
}

// This works for log files where the body contains a pre with text
// NOTE: customize this!
function extractTargetElement() {
  return document.body.children[0];
}

// --- Full Generation ---

function fullGeneration() {
  chrome.storage.sync.get({
    timestampRegexString: "",
    rulesJsonString: ""
  }, function(items) {
    var rules = JSON.parse(items.rulesJsonString);
    var regexStrings = [];
    var regexDescriptions = [];
    for (var i = 0; i < rules.length; i++) {
      regexDescriptions.push(rules[i][0]);
      regexStrings.push(rules[i][1]);
    }
    var colorList = generateColorList(regexStrings.length);
    var targetText = extractTargetElement();
    if (items.timestampRegexString.length == 0) {
      // Default timestamp regex
      items.timestampRegexString = "\\d{1,2}:\\d{2}:\\d{2}\\.\\d{0,3}";
    }
    var res = searchAndComputeIndex(targetText.textContent,
      regexStrings,
      regexDescriptions,
      new RegExp(items.timestampRegexString, 'gi')
    );
    var tableOfContents = generateTableOfContents(res, colorList);
    embedDiv(tableOfContents);
  });
}

// Listen for messages
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
    // If the received message has the expected format...
    if (msg.text === 'clicked') {
        fullGeneration();
        // Set recompute on resize
        document.body.onresize = fullGeneration
    }
});
<|endoftext|>


<commit_before>#!/usr/bin/env electron

/*jshint globalstrict:true, node:true*/

"use strict";

var app = require("app"); // Module to control application life
var BrowserWindow = require("browser-window"); // Module to create native browser window
var path = require("path"); // Node path module

// Report crashes to electron server
// TODO: doesn't work
// require("crash-reporter").start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
var win = null;

// Quit when all windows are closed.
app.on("window-all-closed", function () {
    app.quit();
});

// This method will be called when Electron has done everything
// initialization and ready for creating browser windows.
app.on("ready", function () {

    // create the browser window
    win = new BrowserWindow({
        width: 800,
        height: 600
    });

    // compose path to brackets' index file
    var indexPath = "file://" + path.resolve(__dirname, "..", "src", "index.html");

    // load the index.html of the app
    win.loadUrl(indexPath);

    // emitted when the window is closed
    win.on("closed", function () {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        win = null;
    });

});
<commit_msg>fixes https://github.com/zaggino/brackets-electron/issues/5<commit_after>#!/usr/bin/env electron

/*jshint globalstrict:true, node:true*/

"use strict";

var _ = require("lodash");
var app = require("app"); // Module to control application life
var BrowserWindow = require("browser-window"); // Module to create native browser window
var path = require("path"); // Node path module

// Report crashes to electron server
// TODO: doesn't work
// require("crash-reporter").start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
var win = null;

// Quit when all windows are closed.
app.on("window-all-closed", function () {
    app.quit();
});

// This method will be called when Electron has done everything
// initialization and ready for creating browser windows.
app.on("ready", function () {

    // create the browser window
    win = new BrowserWindow({
        width: 800,
        height: 600
    });

    // build a query for brackets' window
    var queryParams = {
        hasNativeMenus: true
    };
    var query = "?" + _.map(queryParams, function (value, key) {
        return key + "=" + encodeURIComponent(value);
    }).join("&");

    // compose path to brackets' index file
    var indexPath = "file://" + path.resolve(__dirname, "..", "src", "index.html") + query;

    // load the index.html of the app
    win.loadUrl(indexPath);

    // emitted when the window is closed
    win.on("closed", function () {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        win = null;
    });

});
<|endoftext|>


<commit_before>var Q = require('q');
var async = require('async');
var url = require('url');
var cheerio = require('cheerio');
var fs = require('fs');

module.exports = {
    /*
     * Iterates through a set of HTML resources, to check for matches of given
     * CSS selectors.
     *
     * @param {Array} html Html to search through. This can be either an array
     *         of Strings (containing html code), an array of URIs to visit, or
     *         an array of paths to html files.
     * @param {String} cookie Cookie to use for login, on the form
     *         "sessionid=foo". Each uri in the html parameter will
     *         be visited both with and without the cookie.
     * @param {String} whitelist List of selectors to ignore.
     * @param {Array} selectors Array of CSS selectors
     * @param {Object} result Object on the form { used: { ".foo": 1 },
     *                                             duplicates: { ".bar": 0 } }
     */
    matchSelectors: function(pages, cookie, selectors, whitelist) {
        var result = { used: {}, ignored: {} };
        var deferred = Q.defer();
        var processed = [];
        var i, l;

        // Handle excludes by adding them to processed, so they won't be visited
        var excludedSubdomains = [];
        if (pages.exclude) {
            for (i=0, l=pages.exclude.length; i<l; i++) {
                var current = pages.exclude[i];
                if (current.indexOf("*") !== -1) {
                    var subdomain = current.substring(0, current.length - 1);
                    if (subdomain.indexOf("http") === 0) {
                        subdomain = url.parse(subdomain).pathname;
                    }
                    excludedSubdomains.push(subdomain);
                    continue;
                }

                processed.push(current.split("?")[0]);
            }
        }

        var self = this;
        var queue = async.queue(function(item, queueCallback) {
            // If in processed, skip (may have been in excluded list)
            if (-1 !== processed.indexOf(item.page.split("?")[0])) {
                queueCallback();
                return;
            }

            var page = item.page;
            var uri, host;
            if (0 === page.indexOf("http")) {
                console.log("Visiting URL: ", item.page.split("?")[0]);
                uri = page;
                host = url.parse(uri).host || "";
            }

            var visits = [];
            visits.push(self._getHtmlAsString(item, null)); // regular visit
            if (cookie) {
                visits.push(self._getHtmlAsString(item, cookie)); // logged in visit
            }
            processed.push(page.split("?")[0]);

            Q.all(visits)
            .spread(function(regularResult, loggedInResult) {
                var context = {
                    selectors: selectors,
                    whitelist: whitelist,
                    excludedSubdomains: excludedSubdomains,
                    result: result
                };

                var regularItem = {
                    page: regularResult,
                    followLinks: item.followLinks,
                    uri: uri
                };
                self._processHtmlString(regularItem, context, queue);

                if (loggedInResult) {
                    var loggedInItem = {
                        page: loggedInResult,
                        followLinks: item.followLinks,
                        uri: uri
                    };
                    self._processHtmlString(loggedInItem, context, queue);
                }
            }).fail(function(error) {
                console.log(error);
            }).done(queueCallback); // Passing queue callback, in case it needs to abort
        }, 8);

        queue.drain = function(err) { // TODO: Handle err
            if (err) {
                deferred.reject(new Error(err));
            } else {
                deferred.resolve(result);
            }
        };

        // Crawl to find all HTML links
        if (pages.crawl) {
            for (i=0, l=pages.crawl.length; i<l; i++) {
                queue.push({page: pages.crawl[i], followLinks: true});
            }
        }

        if (pages.include) {
            for (i=0, l=pages.include.length; i<l; i++) {
                queue.push({page: pages.include[i], followLinks: false});
            }
        }

        return deferred.promise;
    },

    // TODO: Rename. Add docstring. Clean up parameters.
    _processHtmlString: function(item, context, queue) {
        var html = item.page;
        var followLinks = item.followLinks;
        var uri = item.uri;

        var selectors = context.selectors;
        var whitelist = context.whitelist;
        var result = context.result;
        var excludedSubdomains = context.excludedSubdomains;

        var document = cheerio.load(html);

        if (followLinks) { // look for links in document, add to queue
            var links = document("a");
            for (var i=0, l=links.length; i<l; i++) {
                var handleThis = true;

                var href = links[i].attribs.href.split("#")[0];
                if (!href || href.indexOf("?") === 0) {
                    continue;
                }

                // If under excluded domain, skip
                for (var j=0; j<excludedSubdomains.length; j++) {
                    var excluded = excludedSubdomains[j];
                    if (href.indexOf(excluded) === 0 ||
                        url.parse(href).pathname.indexOf(excluded) === 0) {

                        handleThis = false;
                        break;
                    }
                }

                if (handleThis) {
                    this._handleLink(links[i].attribs.href, uri, followLinks, queue);
                }
            }
        }

        // Process current document
        return this._matchSelectorsInString(document, selectors, whitelist, result);
    },

    _handleLink: function(link, parentUri, followLinks, queue) {

        var host = url.parse(parentUri).host;
        if (0 === link.indexOf("http")) {
            if (url.parse(link).host === host) {
                queue.push({page: link, followLinks: followLinks});
            } else {
                // Skip, another domain
            }
        } else {
            if (parentUri) {
                link = url.resolve(parentUri, link);
                queue.push({page: link, followLinks: followLinks});
            } else {
                console.log("Could not resolve " + link);
            }
        }
    },

    // TODO: Rename. Add docstring. Clean up parameters.
    _matchSelectorsInString: function(htmlString, selectors, whitelist, result) {
        // Loop through selectors
        for (var k=0, l=selectors.length; k<l; k++) {
            var selector = selectors[k];

            // If current selector is whitelisted, skip.
            if (whitelist && -1 < whitelist.indexOf(selector)) {
                continue;
            }
            if (-1 < selector.indexOf("@")) {
                result.ignored[selector] = 1;
                continue;
            }

            if (selector) {
                var oSelector = selector;

                // Add selector to index, if not already added
                if (undefined === result.used[oSelector]) {
                    result.used[oSelector] = 0;
                }

                // Remove pseudo part of selector
                selector = selector.split(":")[0];

                // Check if selector is used
                try {
                    if (htmlString(selector).length > 0) {
                        result.used[oSelector] =
                            result.used[oSelector]
                            + htmlString(selector).length;
                    }
                } catch (e) {
                    console.log("Problem with selector: "
                                + oSelector);
                }
            }
        }
        return;
    },

    // TODO: Add docstring. Clean up parameters.
    _getHtmlAsString: function(item, cookie) {
        var deferred = Q.defer();
        var page = item.page;
        var data;

        // Get page as raw html
        // If URI is given, fetch HTML
        //
        // Note: _handleLink will add domain to relative URLs when crawling,
        // so they won't be mistaken for strings.
        if (0 === page.indexOf("http")) { // From URI
            var uri = page;

            var headers = {};
            if (cookie) {
                headers = {
                    "Cookie": cookie,
                    "Referer": uri
                };
            }

            var options = { uri: uri,
                            headers: headers };

            require('request').get(options, function(error, res, data) {
                                       // TODO: Error checking, response status code, etc.
                                       deferred.resolve(data);
                                   });
        } else if (-1 === page.indexOf("<html>")) { // From file
            try {
                data = fs.readFileSync(page).toString();
            } catch (e) {
                console.log(e.message);
            }
            deferred.resolve(data);
        } else { // From string
            deferred.resolve(page);
        }

        return deferred.promise;
    }
};
<commit_msg>Rename function, add docstring, add comments.<commit_after>var Q = require('q');
var async = require('async');
var url = require('url');
var cheerio = require('cheerio');
var fs = require('fs');

module.exports = {
    /*
     * Iterates through a set of HTML resources, to check for matches of given
     * CSS selectors.
     *
     * @param {Array} html Html to search through. This can be either an array
     *         of Strings (containing html code), an array of URIs to visit, or
     *         an array of paths to html files.
     * @param {String} cookie Cookie to use for login, on the form
     *         "sessionid=foo". Each uri in the html parameter will
     *         be visited both with and without the cookie.
     * @param {String} whitelist List of selectors to ignore.
     * @param {Array} selectors Array of CSS selectors
     * @param {Object} result Object on the form { used: { ".foo": 1 },
     *                                             duplicates: { ".bar": 0 } }
     */
    matchSelectors: function(pages, cookie, selectors, whitelist) {
        var result = { used: {}, ignored: {} };
        var deferred = Q.defer();
        var processed = [];
        var i, l;

        // Handle excludes by adding them to processed, so they won't be visited
        var excludedSubdomains = [];
        if (pages.exclude) {
            for (i=0, l=pages.exclude.length; i<l; i++) {
                var current = pages.exclude[i];
                if (current.indexOf("*") !== -1) {
                    var subdomain = current.substring(0, current.length - 1);
                    if (subdomain.indexOf("http") === 0) {
                        subdomain = url.parse(subdomain).pathname;
                    }
                    excludedSubdomains.push(subdomain);
                    continue;
                }

                processed.push(current.split("?")[0]);
            }
        }

        var self = this;
        var queue = async.queue(function(item, queueCallback) {
            // If in processed, skip (may have been in excluded list)
            if (-1 !== processed.indexOf(item.page.split("?")[0])) {
                queueCallback();
                return;
            }

            var page = item.page;
            var uri, host;
            if (0 === page.indexOf("http")) {
                console.log("Visiting URL: ", item.page.split("?")[0]);
                uri = page;
                host = url.parse(uri).host || "";
            }

            var visits = [];
            visits.push(self._getHtmlAsString(item, null)); // regular visit
            if (cookie) {
                visits.push(self._getHtmlAsString(item, cookie)); // logged in visit
            }
            processed.push(page.split("?")[0]);

            Q.all(visits)
            .spread(function(regularResult, loggedInResult) {
                var context = {
                    selectors: selectors,
                    whitelist: whitelist,
                    excludedSubdomains: excludedSubdomains,
                    result: result
                };

                var regularItem = {
                    page: regularResult,
                    followLinks: item.followLinks,
                    uri: uri
                };
                self._processHtmlString(regularItem, context, queue);

                if (loggedInResult) {
                    var loggedInItem = {
                        page: loggedInResult,
                        followLinks: item.followLinks,
                        uri: uri
                    };
                    self._processHtmlString(loggedInItem, context, queue);
                }
            }).fail(function(error) {
                console.log(error);
            }).done(queueCallback); // Passing queue callback, in case it needs to abort
        }, 8);

        queue.drain = function(err) { // TODO: Handle err
            if (err) {
                deferred.reject(new Error(err));
            } else {
                deferred.resolve(result);
            }
        };

        // Crawl to find all HTML links
        if (pages.crawl) {
            for (i=0, l=pages.crawl.length; i<l; i++) {
                queue.push({page: pages.crawl[i], followLinks: true});
            }
        }

        if (pages.include) {
            for (i=0, l=pages.include.length; i<l; i++) {
                queue.push({page: pages.include[i], followLinks: false});
            }
        }

        return deferred.promise;
    },

    // TODO: Rename. Add docstring. Clean up parameters.
    _processHtmlString: function(item, context, queue) {
        var html = item.page;
        var followLinks = item.followLinks;
        var uri = item.uri;

        var selectors = context.selectors;
        var whitelist = context.whitelist;
        var result = context.result;
        var excludedSubdomains = context.excludedSubdomains;

        var document = cheerio.load(html);

        if (followLinks) { // look for links in document, add to queue
            var links = document("a");
            for (var i=0, l=links.length; i<l; i++) {
                var handleThis = true;

                var href = links[i].attribs.href.split("#")[0];
                if (!href || href.indexOf("?") === 0) {
                    continue;
                }

                // If under excluded domain, skip
                for (var j=0; j<excludedSubdomains.length; j++) {
                    var excluded = excludedSubdomains[j];
                    if (href.indexOf(excluded) === 0 ||
                        url.parse(href).pathname.indexOf(excluded) === 0) {

                        handleThis = false;
                        break;
                    }
                }

                if (handleThis) {
                    this._addLinkToQueue(links[i].attribs.href, queue, uri, followLinks);
                }
            }
        }

        // Process current document
        return this._matchSelectorsInString(document, selectors, whitelist, result);
    },

    /**
     * Add link to queue, given it's on the current domain.
     *
     * @param {String} link Link to handle.
     * @param {Object} queue Queue object, as returned from the Async library.
     * @param {String} parentUri URL to document that contained link.
     * @param {Boolean} followLinks Follow links contained in the document
     *                 link refers to.
     */
    _addLinkToQueue: function(link, queue, parentUri, followLinks) {
        var host = url.parse(parentUri).host;
        if (0 === link.indexOf("http")) { // Absolute url
            if (url.parse(link).host === host) {
                queue.push({page: link, followLinks: followLinks});
            } else {
                // Skip, another domain
            }
        } else { // Relative url?
            if (parentUri) { // Yes
                link = url.resolve(parentUri, link);
                queue.push({page: link, followLinks: followLinks});
            } else { // What Is This Thing Called Link?
                console.log("Could not resolve " + link);
            }
        }
    },

    // TODO: Rename. Add docstring. Clean up parameters.
    _matchSelectorsInString: function(htmlString, selectors, whitelist, result) {
        // Loop through selectors
        for (var k=0, l=selectors.length; k<l; k++) {
            var selector = selectors[k];

            // If current selector is whitelisted, skip.
            if (whitelist && -1 < whitelist.indexOf(selector)) {
                continue;
            }
            if (-1 < selector.indexOf("@")) {
                result.ignored[selector] = 1;
                continue;
            }

            if (selector) {
                var oSelector = selector;

                // Add selector to index, if not already added
                if (undefined === result.used[oSelector]) {
                    result.used[oSelector] = 0;
                }

                // Remove pseudo part of selector
                selector = selector.split(":")[0];

                // Check if selector is used
                try {
                    if (htmlString(selector).length > 0) {
                        result.used[oSelector] =
                            result.used[oSelector]
                            + htmlString(selector).length;
                    }
                } catch (e) {
                    console.log("Problem with selector: "
                                + oSelector);
                }
            }
        }
        return;
    },

    // TODO: Add docstring. Clean up parameters.
    _getHtmlAsString: function(item, cookie) {
        var deferred = Q.defer();
        var page = item.page;
        var data;

        // Get page as raw html
        // If URI is given, fetch HTML
        //
        // Note: _addLinkToQueue adds host etc. to relative URLs when crawling.
        if (0 === page.indexOf("http")) { // From URI
            var uri = page;

            var headers = {};
            if (cookie) {
                headers = {
                    "Cookie": cookie,
                    "Referer": uri
                };
            }

            var options = { uri: uri,
                            headers: headers };

            require('request').get(options, function(error, res, data) {
                                       // TODO: Error checking, response status code, etc.
                                       deferred.resolve(data);
                                   });
        } else if (-1 === page.indexOf("<html>")) { // From file
            try {
                data = fs.readFileSync(page).toString();
            } catch (e) {
                console.log(e.message);
            }
            deferred.resolve(data);
        } else { // From string
            deferred.resolve(page);
        }

        return deferred.promise;
    }
};
<|endoftext|>


<commit_before>
module.exports = bugs

bugs.usage = "npm bugs <pkgname>"

var npm = require("./npm.js")
  , registry = npm.registry
  , log = require("npmlog")
  , opener = require("opener")
  , path = require("path")
  , readJson = require("read-package-json")
  , fs = require("fs")

bugs.completion = function (opts, cb) {
  if (opts.conf.argv.remain.length > 2) return cb()
  registry.get("/-/short", 60000, function (er, list) {
    return cb(null, list || [])
  })
}

function bugs (args, cb) {
  var n = args.length && args[0].split("@").shift() || '.'
  fs.stat(n, function (er, s) {
    if (er && er.code === "ENOENT") return callRegistry(n, cb)
    else if (er) return cb (er)
    if (!s.isDirectory()) return callRegistry(n, cb)
    readJson(path.resolve(n, "package.json"), function(er, d) {
      if (er) return cb(err)
      getUrlAndOpen(d, cb)
    })
  })
}

function getUrlAndOpen (d, cb) {
  var bugs = d.bugs
    , repo = d.repository || d.repositories
    , url
  if (bugs) {
    url = (typeof url === "string") ? bugs : bugs.url
  } else if (repo) {
    if (Array.isArray(repo)) repo = repo.shift()
    if (repo.hasOwnProperty("url")) repo = repo.url
    log.verbose("repository", repo)
    if (bugs && bugs.match(/^(https?:\/\/|git(:\/\/|@))github.com/)) {
      url = bugs.replace(/^git(@|:\/\/)/, "https://")
                .replace(/^https?:\/\/github.com:/, "https://github.com/")
                .replace(/\.git$/, '')+"/issues"
    }
  }
  if (!url) {
    url = "https://npmjs.org/package/" + d.name
  }
  opener(url, { command: npm.config.get("browser") }, cb)
}

function callRegistry (n, cb) {
  registry.get(n + "/latest", 3600, function (er, d) {
    if (er) return cb(er)
    getUrlAndOpen (d, cb)
  })
}
<commit_msg>Typo, "err" variable name should be "er".<commit_after>
module.exports = bugs

bugs.usage = "npm bugs <pkgname>"

var npm = require("./npm.js")
  , registry = npm.registry
  , log = require("npmlog")
  , opener = require("opener")
  , path = require("path")
  , readJson = require("read-package-json")
  , fs = require("fs")

bugs.completion = function (opts, cb) {
  if (opts.conf.argv.remain.length > 2) return cb()
  registry.get("/-/short", 60000, function (er, list) {
    return cb(null, list || [])
  })
}

function bugs (args, cb) {
  var n = args.length && args[0].split("@").shift() || '.'
  fs.stat(n, function (er, s) {
    if (er && er.code === "ENOENT") return callRegistry(n, cb)
    else if (er) return cb (er)
    if (!s.isDirectory()) return callRegistry(n, cb)
    readJson(path.resolve(n, "package.json"), function(er, d) {
      if (er) return cb(er)
      getUrlAndOpen(d, cb)
    })
  })
}

function getUrlAndOpen (d, cb) {
  var bugs = d.bugs
    , repo = d.repository || d.repositories
    , url
  if (bugs) {
    url = (typeof url === "string") ? bugs : bugs.url
  } else if (repo) {
    if (Array.isArray(repo)) repo = repo.shift()
    if (repo.hasOwnProperty("url")) repo = repo.url
    log.verbose("repository", repo)
    if (bugs && bugs.match(/^(https?:\/\/|git(:\/\/|@))github.com/)) {
      url = bugs.replace(/^git(@|:\/\/)/, "https://")
                .replace(/^https?:\/\/github.com:/, "https://github.com/")
                .replace(/\.git$/, '')+"/issues"
    }
  }
  if (!url) {
    url = "https://npmjs.org/package/" + d.name
  }
  opener(url, { command: npm.config.get("browser") }, cb)
}

function callRegistry (n, cb) {
  registry.get(n + "/latest", 3600, function (er, d) {
    if (er) return cb(er)
    getUrlAndOpen (d, cb)
  })
}
<|endoftext|>


<commit_before>const bannedWords = {
  "countries": [
    "Iraq",
    "Syria",
    "Iran",
    "Libya",
    "Somalia",
    "Sudan",
    "Yemen"
  ],
  "demonyms": [
    "Iraqi",
    "Iraqis",
    "Syrian",
    "Syrians",
    "Iranian",
    "Iranians",
    "Libyan",
    "Libyans",
    "Somali",
    "Somalis",
    "Somalian",
    "Somalians",
    "Sudanese",
    "Yemeni",
    "Yemenis"
  ]
}

String.prototype.replaceAll = function(search, replacement) {

    function genereateRegExpStr(search) {
      return `\\b${search}\\b`;
    }

    var target = this;
    return target.replace(
      new RegExp(genereateRegExpStr(search), 'gi'), replacement
    );
};

function textNodesUnder(el){
  let n,
      allNodes = [],
      acceptNodeObj = {
        acceptNode: function(node) {
          // Ignore text nodes that just contain white space
          if ( ! /^\s*$/.test(node.data) ) {
            return NodeFilter.FILTER_ACCEPT;
          }
        }
      },
      walk = document.createTreeWalker(
        el, NodeFilter.SHOW_TEXT, acceptNodeObj, false
      );
  while (n = walk.nextNode()) allNodes.push(n);
  return allNodes;
}

function redactedWord(word) {
  let mouseOut = `this.innerHTML='${word}';this.className='bannedword strikethrough';`,
      mouseOver = `this.innerHTML='#MuslimBan';this.className='bannedword';`;

  return `${word}`;

}

function replaceAllBannedWords(text) {
  let newText = text;
  for (let word of allBannedWords) {
    newText = newText.replaceAll(word, redactedWord(word));
  }
  return newText;
}

function handleTextNode(node) {
  let newText = replaceAllBannedWords(node.textContent);
  if (newText !== node.textContent) {
    let sp = document.createElement("span");
    sp.innerHTML = newText;
    if (node.parentNode !== null) {
      node.parentNode.insertBefore(sp, node);
      node.parentNode.removeChild(node);
    }
  }
}

function checkAndReplaceAllTextNodes() {
  let textNodes = textNodesUnder(document.querySelector('body'));
  textNodes.map(handleTextNode);
}

function initializeMutationObserver() {
  let target = document.querySelector('body');
  let observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        Array.prototype.slice.call(mutation.addedNodes).forEach(function(node) {
          if (node.nodeType === 3) {
            handleTextNode(node);
          }
        });
      });
    });

  let config = {childList: true, subtree: true};

  observer.observe(target, config);
}

let allBannedWords = [].concat(bannedWords["countries"])
                       .concat(bannedWords["demonyms"]);

checkAndReplaceAllTextNodes();
initializeMutationObserver();
<commit_msg>change hover text to stop the #muslimban<commit_after>const bannedWords = {
  "countries": [
    "Iraq",
    "Syria",
    "Iran",
    "Libya",
    "Somalia",
    "Sudan",
    "Yemen"
  ],
  "demonyms": [
    "Iraqi",
    "Iraqis",
    "Syrian",
    "Syrians",
    "Iranian",
    "Iranians",
    "Libyan",
    "Libyans",
    "Somali",
    "Somalis",
    "Somalian",
    "Somalians",
    "Sudanese",
    "Yemeni",
    "Yemenis"
  ]
}

String.prototype.replaceAll = function(search, replacement) {

    function genereateRegExpStr(search) {
      return `\\b${search}\\b`;
    }

    var target = this;
    return target.replace(
      new RegExp(genereateRegExpStr(search), 'gi'), replacement
    );
};

function textNodesUnder(el){
  let n,
      allNodes = [],
      acceptNodeObj = {
        acceptNode: function(node) {
          // Ignore text nodes that just contain white space
          if ( ! /^\s*$/.test(node.data) ) {
            return NodeFilter.FILTER_ACCEPT;
          }
        }
      },
      walk = document.createTreeWalker(
        el, NodeFilter.SHOW_TEXT, acceptNodeObj, false
      );
  while (n = walk.nextNode()) allNodes.push(n);
  return allNodes;
}

function redactedWord(word) {
  let mouseOut = `this.innerHTML='${word}';this.className='bannedword strikethrough';`,
      mouseOver = `this.innerHTML='Stop the #MuslimBan';this.className='bannedword';`;

  return `${word}`;

}

function replaceAllBannedWords(text) {
  let newText = text;
  for (let word of allBannedWords) {
    newText = newText.replaceAll(word, redactedWord(word));
  }
  return newText;
}

function handleTextNode(node) {
  let newText = replaceAllBannedWords(node.textContent);
  if (newText !== node.textContent) {
    let sp = document.createElement("span");
    sp.innerHTML = newText;
    if (node.parentNode !== null) {
      node.parentNode.insertBefore(sp, node);
      node.parentNode.removeChild(node);
    }
  }
}

function checkAndReplaceAllTextNodes() {
  let textNodes = textNodesUnder(document.querySelector('body'));
  textNodes.map(handleTextNode);
}

function initializeMutationObserver() {
  let target = document.querySelector('body');
  let observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        Array.prototype.slice.call(mutation.addedNodes).forEach(function(node) {
          if (node.nodeType === 3) {
            handleTextNode(node);
          }
        });
      });
    });

  let config = {childList: true, subtree: true};

  observer.observe(target, config);
}

let allBannedWords = [].concat(bannedWords["countries"])
                       .concat(bannedWords["demonyms"]);

checkAndReplaceAllTextNodes();
initializeMutationObserver();
<|endoftext|>


<commit_before>"use strict";

const ProjectBase = require("../base");
const EnvConfigurator = require("../../environment/environment_configurator");
const Command = require("../../system/system_command");

/**
 * @id drupal
 */
class DrupalProject extends ProjectBase {

  static getEnvConfigurator() {
    return new EnvConfigurator({
      group: {
        required: ["web", "database"],
        single: ["web", "database"]
      },
      service: {
        required: ["php"],
        restricted: ["mongodb"]
      }
    });
  }

  static isInDirectory(dir) {

  }

  static getInstallationMethods() {
    return {
      standard: "Install new project with composer.",
      issue: "Clone drupal dev to work on issues.",
    };
  }

  static download(method, dir) {
    let cmd;

    switch (method) {
      case "standard":
        cmd = new Command("composer", [
          ["create-project", "drupal-composer/drupal-project:8.x-dev"],
          [dir, "--no-interaction"],
          ["--stability", "dev"],
       ]);
        break;
      default:
        throw new Error("Unhandled installation method: " + method);
    }

    return cmd.execute();
  }

  static postInstall(data) {
    console.log("post install");
  }

}

module.exports = DrupalProject;
<commit_msg>Adds handling for composer path max length exceed on windows.<commit_after>"use strict";

const os = require("os");

const ProjectBase = require("../base");
const EnvConfigurator = require("../../environment/environment_configurator");
const Command = require("../../system/system_command");

/**
 * @id drupal
 */
class DrupalProject extends ProjectBase {

  static getEnvConfigurator() {
    return new EnvConfigurator({
      group: {
        required: ["web", "database"],
        single: ["web", "database"]
      },
      service: {
        required: ["php"],
        restricted: ["mongodb"]
      }
    });
  }

  static isInDirectory(dir) {

  }

  static getInstallationMethods() {
    return {
      standard: "Install new project with composer.",
      issue: "Clone drupal dev to work on issues.",
    };
  }

  static download(method, dir) {
    let cmd;

    switch (method) {
      case "standard":
        let params = [
          ["create-project", "drupal-composer/drupal-project:8.x-dev"],
          [dir, "--no-interaction"],
          ["--stability", "dev"],
        ];

        // In case of windows max path length will be reached and composer
        // create will fail. Prefer source so that this doesn't happen.
        if (os.platform() == "win32") {
          params.push("--prefer-source");
        }

        cmd = new Command("composer", params);
        break;
      default:
        throw new Error("Unhandled installation method: " + method);
    }

    return cmd.execute();
  }

  static postInstall(data) {
    console.log("post install");
  }

}

module.exports = DrupalProject;
<|endoftext|>


<commit_before>'use strict';

var generators = require('yeoman-generator');
var chalk = require('chalk');
var mkdirp = require('mkdirp');
var _s = require('underscore.string');
var _ = require('underscore');

module.exports = generators.Base.extend({
  constructor: function () {

    generators.Base.apply(this, arguments);

    this.option('skip_welcome_message', {
      desc: 'Skips the welcome message',
      type: Boolean
    });

    this.option('projectName', {
      desc: 'Sets the project name',
      type: String
    });

    this.fs.delete('demo');
    mkdirp('demo');
    this.destinationRoot('demo');

  },

  initializing: function () {
    this.pkg = require('../package.json');
  },

  prompting: function () {
    var done = this.async();

    if (!this.options['skip-welcome-message']) {
      this.log(chalk.white.bgRed.bold('Welcome to Pixel2HTML Boilerplate Generator'));
    }

     var prompts = [
      {
        type    : 'input',
        name    : 'projectName',
        message : 'Your project name',
        required: true
      },
      {
        type: 'list',
        name: 'cssPreprocessor',
        message: 'What preprocessor would you like to use? Pick one',
        choices: [
          {
            name: 'Sass',
            value: 'sass',
          }, {
            name: 'Less',
            value: 'less',
          }, {
            name: 'Stylus',
            value: 'stylus',
          }
        ]
      },
      {
        type: 'list',
        name: 'cssFramework',
        message: 'What CSS Framework do you like to include?',
        choices: [{
            name: 'BassCss',
            value: 'basscss',
          }, {
            name: 'Bootstrap',
            value: 'bootstrap',
          }, {
            name: 'Foundation',
            value: 'foundation',
          }
        ]
      },
      {
        type: 'confirm',
        name: 'jquery',
        message: 'Would you like to include jQuery?',
        default: true,
       },
       {
        type: 'confirm',
        name: 'parsley',
        message: 'Do you have forms to validate? Include Parsley!',
       },
       {
        type: 'confirm',
        name: 'modernizer',
        message: 'Do you want to add Modernizr?',
       }
    ];

    this.prompt(prompts, function (answers) {

      this.projectName     = answers.projectName;
      this.cssPreprocessor = answers.cssPreprocessor;
      this.cssFramework    = answers.cssFramework;
      this.jquery           = answers.jquery;
      this.parsley          = answers.parsley;
      this.modernizr        = answers.modernizr;

      done();
    }.bind(this));
  },

  paths: function() {
    this.paths = {
      srcFonts:    'assets/src/fonts',
      srcIcons:    'assets/src/icons',
      srcImages:   'assets/src/images',
      srcVendors:  'assets/src/vendor',
      srcJs:       'assets/src/js',
      srcCssPreprocessor: 'assets/src/'+this.cssPreprocessor
    };
  },

  writing: {

    createFolders: function() {
      console.log(chalk.yellow('Creating directories.'));

      mkdirp('assets');

      _.each(this.paths, function(path){
        mkdirp(path);
      });
    },

    gulpfile: function () {
      console.log(chalk.yellow('Copying gulpfile.'));
      this.fs.copyTpl(
        this.templatePath('gulp/_gulpfile.js'),
        this.destinationPath('gulpfile.js')
      );

    },

    packageJSON: function () {
      console.log(chalk.yellow('Copying package.json file and adding dependencies.'));
      this.fs.copyTpl(
        this.templatePath('base/_package.json'),
        this.destinationPath('package.json'),
        {
          projectName    : this.projectName,
          cssPreprocessor: this.cssPreprocessor
        }
      );
    },

    jshint: function () {
      console.log(chalk.yellow('Copying jshintrc file.'));
      this.fs.copy(
        this.templatePath('base/jshintrc'),
        this.destinationPath('.jshintrc')
      );
    },

    git: function () {
      console.log(chalk.yellow('Copying git files.'));
      this.fs.copy(
        this.templatePath('git/gitignore'),
        this.destinationPath('.gitignore'));

      this.fs.copy(
        this.templatePath('git/gitattributes'),
        this.destinationPath('.gitattributes'));
    },

    bower: function () {
      console.log(chalk.yellow('Adding some bower magic.'));

      var bowerJson = {
        projectName: 'pixel2html-'+_s.slugify(this.projectName),
        private: true,
        dependencies: {}
      };

      switch(this.cssFramework) {
        case 'bootstrap':
          switch(this.cssPreprocessor){
            case 'sass':
              bowerJson.dependencies['bootstrap-sass'] = '~3.3.*';
            break; //sass
            case 'less':
              bowerJson.dependencies['bootstrap'] = '~3.3.*';
            break; //less
            case 'stylus':
              bowerJson.dependencies['bootstrap-stylus'] = '~4.0.*';
            break; //stylus
          }
        break; //bootstrap

        case 'basscss':
          switch(this.cssPreprocessor){
            case 'sass':
              bowerJson.dependencies['basscss-sass'] = '~3.0.*';
            break; //sass

            default:
            case 'less':
            case 'stylus':
              bowerJson.dependencies['basscss'] = '~7.0.*';
            break; //less

          }
        break;

        case 'foundation':
          switch(this.cssPreprocessor){
            case 'sass':
              bowerJson.dependencies['foundation'] = '~5.5.*';
            break; //sass
            case 'less':
              bowerJson.dependencies['foundation'] = '~5.5.*';
            break; //less
            case 'stylus':
              bowerJson.dependencies['foundation'] = '~5.5.*';
            break; //stylus
          }
        break;

      }
      if (this.jquery) {
        bowerJson.dependencies['jquery'] = '~2.1.*';
      }
      if (this.parsley) {
        bowerJson.dependencies['parsleyjs'] = '~2.1.*';
      }
      if (this.modernizer) {
        bowerJson.dependencies['modernizr'] = '~2.8.*';
      }

      this.fs.writeJSON('bower.json', bowerJson);
      this.fs.copy(
        this.templatePath('bower/bowerrc'),
        this.destinationPath('.bowerrc')
      );
    },

    editorConfig: function () {
      console.log(chalk.yellow('Copying editorconfig file.'));
      this.fs.copy(
        this.templatePath('base/editorconfig'),
        this.destinationPath('.editorconfig')
      );
    },

    misc: function () {
      console.log(chalk.yellow('Copying misc files.'));
      // this.fs.copy(
      //   this.templatePath('misc/favicon.ico'),
      //   this.destinationPath('assets/src/icons/favicon.ico')
      // );

      // this.fs.copy(
      //   this.templatePath('misc/apple-touch-icon.png'),
      //   this.destinationPath('assets/src/icons/apple-touch-icon.png')
      // );

      this.fs.copy(
        this.templatePath('misc/robots.txt'),
        this.destinationPath('robots.txt'));
    },

    styles: function () {
      var cssFile = 'main';
      switch(this.cssPreprocessor){
        case 'sass':
          cssFile += '.scss';
        break; //sass
        case 'less':
          cssFile += '.less';
        break; //less
        case 'stylus':
          cssFile += '.styl';
        break; //stylus
      }

      this.fs.copyTpl(
        this.templatePath('styles/'+cssFile),
        this.destinationPath(this.paths.srcCssPreprocessor + '/' +cssFile)
      );
    },

    scripts: function () {
      this.fs.copy(
        this.templatePath('scripts/main.js'),
        this.destinationPath(this.paths.srcJs+'/main.js')
      );
    },

    html: function () {

      this.fs.copyTpl(
        this.templatePath('layouts/index.html'),
        this.destinationPath('index.html'),
        {
          projectName: this.projectName,
          modernizr: this.modernizr,
          cssPreprocessor: this.cssPreprocessor,
          cssFramework: this.cssFramework,
          jquery: this.jquery
        }
      );

    }
  },

  install: function () {
    this.installDependencies({
      skipMessage: this.options['skip-install-message'],
      skipInstall: this.options['skip-install']
    });
  },

  end: function () {

    var howToInstall =
      '\nAfter running ' +
      chalk.yellow.bold('npm install & bower install') + '\n' +
      '\n\n Happy coding :)';

    if (this.options['skip-install']) {
      this.log(howToInstall);
      return;
    }

  }
});
<commit_msg>splitting prompts to add conditionals<commit_after>'use strict';

var generators = require('yeoman-generator');
var chalk = require('chalk');
var mkdirp = require('mkdirp');
var _s = require('underscore.string');
var _ = require('underscore');

module.exports = generators.Base.extend({
  constructor: function () {

    generators.Base.apply(this, arguments);

    this.option('skip_welcome_message', {
      desc: 'Skips the welcome message',
      type: Boolean
    });

    this.option('projectName', {
      desc: 'Sets the project name',
      type: String
    });

    this.fs.delete('demo');
    mkdirp('demo');
    this.destinationRoot('demo');

  },

  initializing: function () {
    this.pkg = require('../package.json');
  },

  prompting: function () {
    var done = this.async();

    if (!this.options['skip-welcome-message']) {
      this.log(chalk.white.bgRed.bold('Welcome to Pixel2HTML Boilerplate Generator'));
    }

     var prompts = [
      {
        type    : 'input',
        name    : 'projectName',
        message : 'Your project name',
        required: true
      }];
    //   ,
    //   {
    //     type: 'list',
    //     name: 'cssPreprocessor',
    //     message: 'What preprocessor would you like to use? Pick one',
    //     choices: [
    //       {
    //         name: 'Sass',
    //         value: 'sass',
    //       }, {
    //         name: 'Less',
    //         value: 'less',
    //       }, {
    //         name: 'Stylus',
    //         value: 'stylus',
    //       }
    //     ]
    //   },
    //   {
    //     type: 'list',
    //     name: 'cssFramework',
    //     message: 'What CSS Framework do you like to include?',
    //     choices: [{
    //         name: 'BassCss',
    //         value: 'basscss',
    //       }, {
    //         name: 'Bootstrap',
    //         value: 'bootstrap',
    //       }, {
    //         name: 'Foundation',
    //         value: 'foundation',
    //       }
    //     ]
    //   },
    //   {
    //     type: 'confirm',
    //     name: 'jquery',
    //     message: 'Would you like to include jQuery?',
    //     default: true,
    //    },
    //    {
    //     type: 'confirm',
    //     name: 'parsley',
    //     message: 'Do you have forms to validate? Include Parsley!',
    //    },
    //    {
    //     type: 'confirm',
    //     name: 'modernizer',
    //     message: 'Do you want to add Modernizr?',
    //    }
    // ];

    console.log(prompts);

    this.prompt(prompts, function (answers) {

      this.projectName     = answers.projectName;
      this.cssPreprocessor = answers.cssPreprocessor;
      this.cssFramework    = answers.cssFramework;
      this.jquery           = answers.jquery;
      this.parsley          = answers.parsley;
      this.modernizr        = answers.modernizr;

      done();
    }.bind(this));
  },

  paths: function() {
    this.paths = {
      srcFonts:    'assets/src/fonts',
      srcIcons:    'assets/src/icons',
      srcImages:   'assets/src/images',
      srcVendors:  'assets/src/vendor',
      srcJs:       'assets/src/js',
      srcCssPreprocessor: 'assets/src/'+this.cssPreprocessor
    };
  },

  writing: {

    createFolders: function() {
      console.log(chalk.yellow('Creating directories.'));

      mkdirp('assets');

      _.each(this.paths, function(path){
        mkdirp(path);
      });
    },

    gulpfile: function () {
      console.log(chalk.yellow('Copying gulpfile.'));
      this.fs.copyTpl(
        this.templatePath('gulp/_gulpfile.js'),
        this.destinationPath('gulpfile.js')
      );

    },

    packageJSON: function () {
      console.log(chalk.yellow('Copying package.json file and adding dependencies.'));
      this.fs.copyTpl(
        this.templatePath('base/_package.json'),
        this.destinationPath('package.json'),
        {
          projectName    : this.projectName,
          cssPreprocessor: this.cssPreprocessor
        }
      );
    },

    jshint: function () {
      console.log(chalk.yellow('Copying jshintrc file.'));
      this.fs.copy(
        this.templatePath('base/jshintrc'),
        this.destinationPath('.jshintrc')
      );
    },

    git: function () {
      console.log(chalk.yellow('Copying git files.'));
      this.fs.copy(
        this.templatePath('git/gitignore'),
        this.destinationPath('.gitignore'));

      this.fs.copy(
        this.templatePath('git/gitattributes'),
        this.destinationPath('.gitattributes'));
    },

    bower: function () {
      console.log(chalk.yellow('Adding some bower magic.'));

      var bowerJson = {
        projectName: 'pixel2html-'+_s.slugify(this.projectName),
        private: true,
        dependencies: {}
      };

      switch(this.cssFramework) {
        case 'bootstrap':
          switch(this.cssPreprocessor){
            case 'sass':
              bowerJson.dependencies['bootstrap-sass'] = '~3.3.*';
            break; //sass
            case 'less':
              bowerJson.dependencies['bootstrap'] = '~3.3.*';
            break; //less
            case 'stylus':
              bowerJson.dependencies['bootstrap-stylus'] = '~4.0.*';
            break; //stylus
          }
        break; //bootstrap

        case 'basscss':
          switch(this.cssPreprocessor){
            case 'sass':
              bowerJson.dependencies['basscss-sass'] = '~3.0.*';
            break; //sass

            default:
            case 'less':
            case 'stylus':
              bowerJson.dependencies['basscss'] = '~7.0.*';
            break; //less

          }
        break;

        case 'foundation':
          switch(this.cssPreprocessor){
            case 'sass':
              bowerJson.dependencies['foundation'] = '~5.5.*';
            break; //sass
            case 'less':
              bowerJson.dependencies['foundation'] = '~5.5.*';
            break; //less
            case 'stylus':
              bowerJson.dependencies['foundation'] = '~5.5.*';
            break; //stylus
          }
        break;

      }
      if (this.jquery) {
        bowerJson.dependencies['jquery'] = '~2.1.*';
      }
      if (this.parsley) {
        bowerJson.dependencies['parsleyjs'] = '~2.1.*';
      }
      if (this.modernizer) {
        bowerJson.dependencies['modernizr'] = '~2.8.*';
      }

      this.fs.writeJSON('bower.json', bowerJson);
      this.fs.copy(
        this.templatePath('bower/bowerrc'),
        this.destinationPath('.bowerrc')
      );
    },

    editorConfig: function () {
      console.log(chalk.yellow('Copying editorconfig file.'));
      this.fs.copy(
        this.templatePath('base/editorconfig'),
        this.destinationPath('.editorconfig')
      );
    },

    misc: function () {
      console.log(chalk.yellow('Copying misc files.'));
      // this.fs.copy(
      //   this.templatePath('misc/favicon.ico'),
      //   this.destinationPath('assets/src/icons/favicon.ico')
      // );

      // this.fs.copy(
      //   this.templatePath('misc/apple-touch-icon.png'),
      //   this.destinationPath('assets/src/icons/apple-touch-icon.png')
      // );

      this.fs.copy(
        this.templatePath('misc/robots.txt'),
        this.destinationPath('robots.txt'));
    },

    styles: function () {
      var cssFile = 'main';
      switch(this.cssPreprocessor){
        case 'sass':
          cssFile += '.scss';
        break; //sass
        case 'less':
          cssFile += '.less';
        break; //less
        case 'stylus':
          cssFile += '.styl';
        break; //stylus
      }

      this.fs.copyTpl(
        this.templatePath('styles/'+cssFile),
        this.destinationPath(this.paths.srcCssPreprocessor + '/' +cssFile)
      );
    },

    scripts: function () {
      this.fs.copy(
        this.templatePath('scripts/main.js'),
        this.destinationPath(this.paths.srcJs+'/main.js')
      );
    },

    html: function () {

      this.fs.copyTpl(
        this.templatePath('layouts/index.html'),
        this.destinationPath('index.html'),
        {
          projectName: this.projectName,
          modernizr: this.modernizr,
          cssPreprocessor: this.cssPreprocessor,
          cssFramework: this.cssFramework,
          jquery: this.jquery
        }
      );

    }
  },

  install: function () {
    this.installDependencies({
      skipMessage: this.options['skip-install-message'],
      skipInstall: this.options['skip-install']
    });
  },

  end: function () {

    var howToInstall =
      '\nAfter running ' +
      chalk.yellow.bold('npm install & bower install') + '\n' +
      '\n\n Happy coding :)';

    if (this.options['skip-install']) {
      this.log(howToInstall);
      return;
    }

  }
});
<|endoftext|>