<commit_before>/*-------JSHint Directives-------*/
/* global THREE, $               */
/*-------------------------------*/
'use strict';

/*********************************
 * Global Variables and Settings *
 *********************************/
var containerID = '#canvas-body';
var scene, camera, controls, renderer;

// Camera settings
var CAMERA = {
  fov : 45,
  near : 1,
  far : 2000,
  zoomX : 0,
  zoomY : 100,
  zoomZ : 120,
};

// OrbitControls settings
var CONTROLS = {
  enabled: true,
  userPan : true,
  userPanSpeed : 1,
  minDistance : 10.0,
  maxDistance : 200.0,
  maxPolarAngle : (Math.PI/180) * 80,
};

// Renderer settings
var RENDERER = {
  antialias : false,
};

/********************
 * Helper Functions *
 ********************/
function degToRad(degrees) {
  return Math.PI/180 * degrees;
}

function basicFloorGrid(lines, steps, gridColor) {
  lines = lines || 20;
  steps = steps || 2;
  gridColor = gridColor || 0xFFFFFF;
  var floorGrid = new THREE.Geometry();
  var gridLine = new THREE.LineBasicMaterial( {color: gridColor} );
  for (var i = -lines; i <= lines; i += steps) {
    floorGrid.vertices.push(new THREE.Vector3(-lines, 0, i));
    floorGrid.vertices.push(new THREE.Vector3( lines, 0, i));
    floorGrid.vertices.push(new THREE.Vector3( i, 0, -lines));
    floorGrid.vertices.push(new THREE.Vector3( i, 0, lines));
  }
  return new THREE.Line(floorGrid, gridLine, THREE.LinePieces);
}

function dippyBird() {
  // Bird parameters
  var figure = new THREE.Object3D();
  var movingFigure = new THREE.Object3D();
  var tubeHeight = 30;
  var headRadius = 4;

  // Define bird head
  var figureHead = new THREE.Object3D();
  var headMaterial = new THREE.MeshLambertMaterial({color: 0xEE1111, transparent: true, opacity: 0.85});
  var eyeMaterial = new THREE.MeshLambertMaterial({color: 0xEEEEEE});
  var irisMaterial = new THREE.MeshLambertMaterial({color: 0x111111});
  var headGeometry = new THREE.SphereGeometry(headRadius, 32, 32);
  var noseGeometry = new THREE.CylinderGeometry(1, 0.3, 5, 32);
  var eyeGeometry = new THREE.CircleGeometry(0.8, 16);
  var irisGeometry = new THREE.CircleGeometry(0.4, 16);
  var birdHead = new THREE.Mesh(headGeometry, headMaterial);
  var birdNose = new THREE.Mesh(noseGeometry, headMaterial);
  var leftEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
  var rightEye = leftEye.clone();
  var leftIris = new THREE.Mesh(irisGeometry, irisMaterial);
  var rightIris = leftIris.clone();

  // Set parameters of head
  birdNose.position.set(0, 0, 6);
  birdNose.rotation.x = degToRad(-90);
  leftEye.position.set(-1.8, 2, 3.5);
  rightEye.position.set(1.8, 2, 3.5);
  leftIris.position.set(-1.8, 2, 3.55);
  rightIris.position.set(1.8, 2, 3.55);
  figureHead.add(birdHead);
  figureHead.add(birdNose);
  figureHead.add(leftEye);
  figureHead.add(rightEye);
  figureHead.add(leftIris);
  figureHead.add(rightIris);

  // Bird hat
  var hatMaterial = new THREE.MeshPhongMaterial({color: 0x1111EE});
  var hatBaseGeometry = new THREE.CylinderGeometry(headRadius+1.5, headRadius+1.5, 0.5, 32);
  var hatTopGeometry = new THREE.CylinderGeometry(headRadius-1, headRadius-0.5, 5, 32);
  var hatBase = new THREE.Mesh(hatBaseGeometry, hatMaterial);
  var hatTop = new THREE.Mesh(hatTopGeometry, hatMaterial);
  hatBase.position.set(0, headRadius-0.5, 0);
  hatTop.position.set(0, headRadius+2, 0);
  figureHead.add(hatBase);
  figureHead.add(hatTop);
  figureHead.position.set(0, tubeHeight+headRadius-0.5, 0);

  // Tube body
  var figureBody = new THREE.Object3D();
  var tubeMaterial = new THREE.MeshLambertMaterial({color: 0x2277EE, transparent: true, opacity: 0.7});
  var tubeGeometry = new THREE.CylinderGeometry(1.1, 1.1, tubeHeight, 16);
  var figureTube = new THREE.Mesh(tubeGeometry, tubeMaterial);
  figureBody.position.set(0, tubeHeight/2, 0);
  figureBody.add(figureTube);

  // Configure figure
  movingFigure.add(figureHead);
  movingFigure.add(figureBody);

  // Bind moving and static figure
  figure.add(movingFigure);
  figure.position.set(0, 0, 0);
  return figure;
}

/***********************
 * Rendering Functions *
 ***********************/
function renderScene() {
  renderer.render( scene, camera );
}

function animateScene() {
  window.requestAnimationFrame( animateScene );
  controls.update();
}

function resizeWindow() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderScene();
}

/************************
 * Scene Initialization *
 ************************/
function initializeScene() {

  // Scene and resize listener
  scene = new THREE.Scene();
  var canvasWidth  = window.innerWidth;
  var canvasHeight = window.innerHeight;
  window.addEventListener('resize', resizeWindow, false);

  // Camera and initial view
  var aspectRatio  = canvasWidth/canvasHeight;
  camera = new THREE.PerspectiveCamera(CAMERA.fov, aspectRatio, CAMERA.near, CAMERA.far);
  camera.position.set(CAMERA.zoomX, CAMERA.zoomY, CAMERA.zoomZ);
  scene.add(camera);

  // OrbitControls with mouse
  controls = new THREE.OrbitControls(camera);
  for (var key in CONTROLS) { controls[key] = CONTROLS[key]; }
  controls.addEventListener('change', renderScene);

  // WebGL renderer
  renderer = new THREE.WebGLRenderer(RENDERER);
  renderer.setSize(canvasWidth, canvasHeight);
  $(containerID).append(renderer.domElement);

  // Light sources
  var frontLight = new THREE.DirectionalLight(0xaaaaaa);
  var sideLight = new THREE.DirectionalLight(0xaaaaaa);
  frontLight.position.set(0, 0.5, 0.5);
  sideLight.position.set(0.5, 0.8, 0);
  scene.add(frontLight);
  scene.add(sideLight);

  // Starter floor grid
  scene.add(basicFloorGrid(80, 8));

  // Dippy bird
  scene.add(dippyBird());
}

/**********************
 * Render and Animate *
 **********************/
initializeScene();
animateScene();
<commit_msg>Adding bird leg and feet<commit_after>/*-------JSHint Directives-------*/
/* global THREE, $               */
/*-------------------------------*/
'use strict';

/*********************************
 * Global Variables and Settings *
 *********************************/
var containerID = '#canvas-body';
var scene, camera, controls, renderer;

// Camera settings
var CAMERA = {
  fov : 45,
  near : 1,
  far : 2000,
  zoomX : 0,
  zoomY : 100,
  zoomZ : 120,
};

// OrbitControls settings
var CONTROLS = {
  enabled: true,
  userPan : true,
  userPanSpeed : 1,
  minDistance : 10.0,
  maxDistance : 200.0,
  maxPolarAngle : (Math.PI/180) * 80,
};

// Renderer settings
var RENDERER = {
  antialias : false,
};

/********************
 * Helper Functions *
 ********************/
function degToRad(degrees) {
  return Math.PI/180 * degrees;
}

function basicFloorGrid(lines, steps, gridColor) {
  lines = lines || 20;
  steps = steps || 2;
  gridColor = gridColor || 0xFFFFFF;
  var floorGrid = new THREE.Geometry();
  var gridLine = new THREE.LineBasicMaterial( {color: gridColor} );
  for (var i = -lines; i <= lines; i += steps) {
    floorGrid.vertices.push(new THREE.Vector3(-lines, 0, i));
    floorGrid.vertices.push(new THREE.Vector3( lines, 0, i));
    floorGrid.vertices.push(new THREE.Vector3( i, 0, -lines));
    floorGrid.vertices.push(new THREE.Vector3( i, 0, lines));
  }
  return new THREE.Line(floorGrid, gridLine, THREE.LinePieces);
}

function dippyBird() {
  // Bird parameters
  var figure = new THREE.Object3D();
  var movingFigure = new THREE.Object3D();
  var tubeHeight = 25;
  var headRadius = 4;

  // Define bird head
  var figureHead = new THREE.Object3D();
  var headMaterial = new THREE.MeshLambertMaterial({color: 0xEE1111, transparent: true, opacity: 0.85});
  var eyeMaterial = new THREE.MeshLambertMaterial({color: 0xEEEEEE});
  var irisMaterial = new THREE.MeshLambertMaterial({color: 0x111111});
  var headGeometry = new THREE.SphereGeometry(headRadius, 32, 32);
  var noseGeometry = new THREE.CylinderGeometry(1, 0.3, 5, 32);
  var eyeGeometry = new THREE.CircleGeometry(0.8, 16);
  var irisGeometry = new THREE.CircleGeometry(0.4, 16);
  var birdHead = new THREE.Mesh(headGeometry, headMaterial);
  var birdNose = new THREE.Mesh(noseGeometry, headMaterial);
  var leftEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
  var rightEye = leftEye.clone();
  var leftIris = new THREE.Mesh(irisGeometry, irisMaterial);
  var rightIris = leftIris.clone();

  // Set parameters of head
  birdNose.position.set(0, 0, 6);
  birdNose.rotation.x = degToRad(-90);
  leftEye.position.set(-1.8, 2, 3.5);
  rightEye.position.set(1.8, 2, 3.5);
  leftIris.position.set(-1.8, 2, 3.55);
  rightIris.position.set(1.8, 2, 3.55);
  figureHead.add(birdHead);
  figureHead.add(birdNose);
  figureHead.add(leftEye);
  figureHead.add(rightEye);
  figureHead.add(leftIris);
  figureHead.add(rightIris);

  // Bird hat
  var hatMaterial = new THREE.MeshPhongMaterial({color: 0x1111EE});
  var hatBaseGeometry = new THREE.CylinderGeometry(headRadius+1.5, headRadius+1.5, 0.5, 32);
  var hatTopGeometry = new THREE.CylinderGeometry(headRadius-1, headRadius-0.5, 5, 32);
  var hatBase = new THREE.Mesh(hatBaseGeometry, hatMaterial);
  var hatTop = new THREE.Mesh(hatTopGeometry, hatMaterial);
  hatBase.position.set(0, headRadius-0.5, 0);
  hatTop.position.set(0, headRadius+2, 0);
  figureHead.add(hatBase);
  figureHead.add(hatTop);
  figureHead.position.set(0, tubeHeight+headRadius-0.5, 0);

  // Tube body
  var figureBody = new THREE.Object3D();
  var tubeMaterial = new THREE.MeshLambertMaterial({color: 0x2255FE, transparent: true, opacity: 0.7});
  var tubeGeometry = new THREE.CylinderGeometry(1.1, 1.1, tubeHeight, 16);
  var bowlGeometry = new THREE.SphereGeometry(3.5, 16, 16);
  var figureTube = new THREE.Mesh(tubeGeometry, tubeMaterial);
  var figureBowl = new THREE.Mesh(bowlGeometry, tubeMaterial);
  figureBowl.scale.y = 1.3;
  figureTube.position.set(0, tubeHeight/2, 0);
  figureBody.add(figureTube);
  figureBody.add(figureBowl);

  // Configure moving figure
  movingFigure.position.set(0, 7, 0);
  movingFigure.add(figureHead);
  movingFigure.add(figureBody);

  // Static figure legs
  var staticFigure = new THREE.Object3D();
  var hingeHeight = tubeHeight/2+8;
  var hingeMaterial = new THREE.MeshLambertMaterial({color: 0xAAAAAA});
  var legMaterial = new THREE.MeshLambertMaterial({color: 0xCCCCCC});
  var feetMaterial = new THREE.MeshLambertMaterial({color: 0xBB2222});
  var hingeGeometry = new THREE.CylinderGeometry(0.6, 0.6, 15, 16);
  var legGeometry = new THREE.BoxGeometry(1, tubeHeight-5, 5);
  var feetGeometry = new THREE.BoxGeometry(1, 5, 12);
  var feetBaseGeometry = new THREE.BoxGeometry(12, 1, 12);
  var figureHinge = new THREE.Mesh(hingeGeometry, hingeMaterial);
  var leftLeg = new THREE.Mesh(legGeometry, legMaterial);
  var rightLeg = leftLeg.clone();
  var leftFoot = new THREE.Mesh(feetGeometry, feetMaterial);
  var rightFoot = leftFoot.clone();
  var feetBase = new THREE.Mesh(feetBaseGeometry, feetMaterial);

  // Configure static figure
  figureHinge.rotation.z = degToRad(90);
  figureHinge.position.set(0, hingeHeight, 0);
  leftLeg.position.set(-6, 12.5, 0);
  rightLeg.position.set(6, 12.5, 0);
  leftFoot.position.set(-6, 0, 3);
  rightFoot.position.set(6, 0, 3);
  feetBase.position.set(0, -2, 3);
  staticFigure.add(figureHinge);
  staticFigure.add(leftLeg);
  staticFigure.add(rightLeg);
  staticFigure.add(leftFoot);
  staticFigure.add(rightFoot);
  staticFigure.add(feetBase);

  // Bind moving and static figure
  figure.add(movingFigure);
  figure.add(staticFigure);
  figure.position.set(0, 2, 0);
  return figure;
}

/***********************
 * Rendering Functions *
 ***********************/
function renderScene() {
  renderer.render( scene, camera );
}

function animateScene() {
  window.requestAnimationFrame( animateScene );
  controls.update();
}

function resizeWindow() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderScene();
}

/************************
 * Scene Initialization *
 ************************/
function initializeScene() {

  // Scene and resize listener
  scene = new THREE.Scene();
  var canvasWidth  = window.innerWidth;
  var canvasHeight = window.innerHeight;
  window.addEventListener('resize', resizeWindow, false);

  // Camera and initial view
  var aspectRatio  = canvasWidth/canvasHeight;
  camera = new THREE.PerspectiveCamera(CAMERA.fov, aspectRatio, CAMERA.near, CAMERA.far);
  camera.position.set(CAMERA.zoomX, CAMERA.zoomY, CAMERA.zoomZ);
  scene.add(camera);

  // OrbitControls with mouse
  controls = new THREE.OrbitControls(camera);
  for (var key in CONTROLS) { controls[key] = CONTROLS[key]; }
  controls.addEventListener('change', renderScene);

  // WebGL renderer
  renderer = new THREE.WebGLRenderer(RENDERER);
  renderer.setSize(canvasWidth, canvasHeight);
  $(containerID).append(renderer.domElement);

  // Light sources
  var frontLight = new THREE.DirectionalLight(0xaaaaaa);
  var sideLight = new THREE.DirectionalLight(0xaaaaaa);
  frontLight.position.set(0, 0.5, 0.5);
  sideLight.position.set(0.5, 0.8, 0);
  scene.add(frontLight);
  scene.add(sideLight);

  // Starter floor grid
  scene.add(basicFloorGrid(80, 8));

  // Dippy bird
  scene.add(dippyBird());
}

/**********************
 * Render and Animate *
 **********************/
initializeScene();
animateScene();
<|endoftext|>


<commit_before>/*
 * Adds HTLM5 history support to history navigation, with the following provisos:
 * - History points must be added using the StateController.
 * - The page must not have been navigated to using NavigationMode.Server.
 */
(function (app, prm, win) {

    if (!(win.history && history.pushState)) return;

    app._onIdle = function () { };

    app._setState = function (entry, title) {
        entry = entry || '';
        if (app._enableHistory && entry !== app._currentEntry && app._historyPointIsNew) {
            history.pushState(entry, title, n1);
            fixFormAction();
            app._currentEntry = entry;
            app._historyPointIsNew = false;
            ready = true;
        }
    };

    var ready = win.history.state;
    $addHandler(win, 'popstate', function (evt) {
        if (ready) {
            fixFormAction();
            app._historyPointIsNew = false;
            if (!evt.rawEvent.state && !app._state.__s)
                app.setServerState('0')
            app._navigate(evt.rawEvent.state);
        }
        ready = true;
    });

    function fixFormAction() {
        prm._form.action = location.href.indexOf('#') == -1 ? location.href : location.href.substr(0, str.indexOf('#'));
    };

})(Sys.Application, Sys.WebForms.PageRequestManager.getInstance(), window);<commit_msg>When using cross page post back the __PREVIOUSPAGE hidden field gets populated and this causes PostBack to be set to false. This happens because a check runs in ProcessRequestMain that sets a (post back) flag to false because the previous page virtual path doesn't match the current request path - if defaults are used with routing then these won't match<commit_after>/*
 * Adds HTLM5 history support to history navigation, with the following provisos:
 * - History points must be added using the StateController.
 * - The page must not have been navigated to using NavigationMode.Server.
 * - Cross page post backs not supported for States with route parameters.
 */
(function (app, prm, win) {

    if (!(win.history && history.pushState)) return;

    app._onIdle = function () { };

    app._setState = function (entry, title) {
        entry = entry || '';
        if (app._enableHistory && entry !== app._currentEntry && app._historyPointIsNew) {
            history.pushState(entry, title, n1);
            fixFormAction();
            app._currentEntry = entry;
            app._historyPointIsNew = false;
            ready = true;
        }
    };

    var ready = win.history.state;
    $addHandler(win, 'popstate', function (evt) {
        if (ready) {
            fixFormAction();
            app._historyPointIsNew = false;
            if (!evt.rawEvent.state && !app._state.__s)
                app.setServerState('0')
            app._navigate(evt.rawEvent.state);
        }
        ready = true;
    });

    function fixFormAction() {
        prm._form.action = location.href.indexOf('#') == -1 ? location.href : location.href.substr(0, str.indexOf('#'));
    };

})(Sys.Application, Sys.WebForms.PageRequestManager.getInstance(), window);<|endoftext|>


<commit_before>import syllable from 'syllable';
import _ from 'lodash';
import wordnet from 'wordnet';
var $ = require('jquery-deferred');
import stopwords from './data/stopwords.js';
import descriptors from './data/descriptors.js';
import cusseth from './data/cusseth.js';
import nouns from './data/nouns.js';
import thesaurus from './data/thesaurus.js';

let adjectives = descriptors.map(word => [word, syllable(word)]);
let curses = cusseth.map(word => [word, syllable(word)]);

const HAIKU_LENGTH = 17;
const separator = '//';
const FOUL = false;

// Chrys' Domain
function addModifier(phrase, length, mod) {
  let tokens = phrase.split(/\W/);
  let nounList = tokens.map(word => _.contains(nouns, word));

  for (var i in nounList) {
    if (nounList[i]) {
      tokens.splice(i, 0, mod);
      return tokens.join(' ');
    }
  }

  return mod + ' ' + phrase;
}

export function addExpletive(phrase, length) {
  var curse = _.sample(curses.filter(tuple => tuple[1] === length));
  if (!curse) {
    return addExpletive(addExpletive(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, curse[0]);
}

export function addAdjective(phrase, length) {
  var adj = _.sample(adjectives.filter(tuple => tuple[1] === length));
  if (!adj) {
    return addAdjective(addAdjective(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, adj[0]);
}

export function removeWords(phrase, length) {
  length *= -1;
  let tokens = phrase.split(/\W/);
  let newTokens = [];
  tokens.forEach(function(token) {
    if (length && _.contains(stopwords, token)) {
      length -= syllable(token);
    } else {
      newTokens.push(token);
    }
  });

  return newTokens.join(' ');
}

function addWords(phrase, length) {
  if (FOUL) {
    return addExpletive(phrase, length);
  } else {
    return addAdjective(phrase, length);
  }
}

// Nicole WUZ HERE
export function shortenWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);

  adjustment = -adjustment;

  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)) {
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);

    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    }

    else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables > adjustment) && (synonym[1] < currentWordSyllables)).sort(function(a, b) {return a[1]-b[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }

}

function possibleSynonymArray(word) {
  if (thesaurus[word]) {
    return thesaurus[word];
  }
}

function possibleSynonymArrayAsync(word) {
  var promise = $.Deferred();

  var possibleNewWords = [];
  wordnet.lookup(word, function(err, definitions) {
    if (definitions) {
      definitions.forEach(function(definition) {
        var words = definition.meta.words;
        words.forEach(function(word) {
          if (!_.includes(possibleNewWords, word.word)) {
            possibleNewWords.push(word.word);
          }
        });
      });
    }
    promise.resolve(possibleNewWords);
  });
  return promise;
}

export function expandWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);
  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)){
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);
    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    } else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables < adjustment) && (synonym[1] > currentWordSyllables)).sort(function(a, b) {return b[1]-a[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }
}

let countSyllables = function(phrase) {
  let tokens = phrase.split(/\W/);
  return _.sum(tokens.map(syllable));
};

function adjustWord(word, adjustment) {
  if (adjustment > 0) {
    return expandWord(word, adjustment);
  } else if (adjustment < 0) {
    return shortenWord(word, adjustment);
  } else {
    return word;
  }
}

export function adjustPhrase(phrase, adjustment) {
  if (adjustment > 0) {
    return addWords(phrase, adjustment);
  } else if (adjustment < 0) {
    return removeWords(phrase, adjustment);
  } else {
    return phrase;
  }
}

function adjustSyllables(lines, adjustment) {
  let line = 0;
  let idx = 0;
  let token = lines[line][idx];

  // First loop to make small adjustments to existing words' lengths.
  while (adjustment !== 0 && line < 3) {
    let newWord = adjustWord(token, adjustment);

    if (newWord) {
      lines[line][idx] = newWord;
      adjustment -= (syllable(newWord) - syllable(token));
    }

    idx++;
    token = lines[line][idx];
    if (!token) {
      line++;
      idx = 0;
      if (line > 2) {
        break;
      }
      token = lines[line][idx];

    }
  }

  var joined = lines.map(line => line.join(' '));
  line = 0;

  // Second while loop to add / remove extraneous words
  while (adjustment !== 0 && line < 3) {
    let oldPhrase = joined[line];
    let lineCount = countSyllables(oldPhrase);

    if ((line === 1 && lineCount === 7) || lineCount === 5) {
      line++;
    } else {
      var newPhrase;
      var maxLineAdjustment = (line === 1) ? 7 : 5;
      var lineAdjustment;

      if (adjustment < 0) {
        maxLineAdjustment *= -1;
        lineAdjustment = adjustment < maxLineAdjustment ?  maxLineAdjustment : adjustment;
        // lineAdjustment += lineCount;
      } else if (adjustment > 0) {

        let maxPossibleAdjustment = (maxLineAdjustment - lineCount);
        lineAdjustment = adjustment > maxPossibleAdjustment ? maxPossibleAdjustment : adjustment;

      }

      newPhrase = adjustPhrase(oldPhrase, lineAdjustment);

      joined[line] = newPhrase;
      adjustment -= (countSyllables(newPhrase) - countSyllables(oldPhrase));
      line++;
    }

  }

  return joined.join(' ' + separator + ' ');
}

export function isHaiku(msg) {
  return countSyllables(msg, separator) === HAIKU_LENGTH;
}

export function breakIntoHaiku(msg) {
  var tokens = msg.trim().split(/\W/);
  var rows = [[], [], []];
  var rowSyllables = 0;
  var line = 0;
  while (tokens.length) {
    let token = tokens.shift();
    let tokenLength = syllable(token);

    if (line === 0) {
      var diff = (rowSyllables + tokenLength) - 5;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    } else if (line === 1) {

      var diff = (rowSyllables + tokenLength) - 7;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    }

    rowSyllables += tokenLength;
    rows[line].push(token);

  }

  return rows;
}

/**
 * steps to check if it is a haiku
 * 1. check syllable length of commit
 * 2. if longer - > check for haikus in commit..
 *  a) if haiku -> print done !
 *  b) if not -> get most of haiku and continue? choose key words and continue?
 * 3. if shorter -> check syllable counts?
 * for what is missing -> fill in rhyme etc. to make up length ?? nonsensical ??
 */
 export function makeHaiku(msg) {
  let syllables = countSyllables(msg);
  let difference = HAIKU_LENGTH - syllables;

  msg = breakIntoHaiku(msg);
  return adjustSyllables(msg, difference);
}<commit_msg>this commit message // is already a haiku // refrigerator  is a haiku<commit_after>import syllable from 'syllable';
import _ from 'lodash';
import wordnet from 'wordnet';
var $ = require('jquery-deferred');
import stopwords from './data/stopwords.js';
import descriptors from './data/descriptors.js';
import cusseth from './data/cusseth.js';
import nouns from './data/nouns.js';
import thesaurus from './data/thesaurus.js';

let adjectives = descriptors.map(word => [word, syllable(word)]);
let curses = cusseth.map(word => [word, syllable(word)]);

const HAIKU_LENGTH = 17;
const separator = '//';
const FOUL = false;

// Chrys' Domain
function addModifier(phrase, length, mod) {
  let tokens = phrase.split(/\W/);
  let nounList = tokens.map(word => _.contains(nouns, word));

  for (var i in nounList) {
    if (nounList[i]) {
      tokens.splice(i, 0, mod);
      return tokens.join(' ');
    }
  }

  return mod + ' ' + phrase;
}

export function addExpletive(phrase, length) {
  var curse = _.sample(curses.filter(tuple => tuple[1] === length));
  if (!curse) {
    return addExpletive(addExpletive(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, curse[0]);
}

export function addAdjective(phrase, length) {
  var adj = _.sample(adjectives.filter(tuple => tuple[1] === length));
  if (!adj) {
    return addAdjective(addAdjective(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, adj[0]);
}

export function removeWords(phrase, length) {
  length *= -1;
  let tokens = phrase.split(/\W/);
  let newTokens = [];
  tokens.forEach(function(token) {
    if (length && _.contains(stopwords, token)) {
      length -= syllable(token);
    } else {
      newTokens.push(token);
    }
  });

  return newTokens.join(' ');
}

function addWords(phrase, length) {
  if (FOUL) {
    return addExpletive(phrase, length);
  } else {
    return addAdjective(phrase, length);
  }
}

// Nicole WUZ HERE
export function shortenWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);

  adjustment = -adjustment;

  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)) {
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);

    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    }

    else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables > adjustment) && (synonym[1] < currentWordSyllables)).sort(function(a, b) {return a[1]-b[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }

}

function possibleSynonymArray(word) {
  if (thesaurus[word]) {
    return thesaurus[word];
  }
}

function possibleSynonymArrayAsync(word) {
  var promise = $.Deferred();

  var possibleNewWords = [];
  wordnet.lookup(word, function(err, definitions) {
    if (definitions) {
      definitions.forEach(function(definition) {
        var words = definition.meta.words;
        words.forEach(function(word) {
          if (!_.includes(possibleNewWords, word.word)) {
            possibleNewWords.push(word.word);
          }
        });
      });
    }
    promise.resolve(possibleNewWords);
  });
  return promise;
}

export function expandWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);
  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)){
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);
    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    } else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables < adjustment) && (synonym[1] > currentWordSyllables)).sort(function(a, b) {return b[1]-a[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }
}

let countSyllables = function(phrase) {
  let tokens = phrase.split(/\W/);
  return _.sum(tokens.map(syllable));
};

function adjustWord(word, adjustment) {
  if (adjustment > 0) {
    return expandWord(word, adjustment);
  } else if (adjustment < 0) {
    return shortenWord(word, adjustment);
  } else {
    return word;
  }
}

export function adjustPhrase(phrase, adjustment) {
  if (adjustment > 0) {
    return addWords(phrase, adjustment);
  } else if (adjustment < 0) {
    return removeWords(phrase, adjustment);
  } else {
    return phrase;
  }
}

function adjustSyllables(lines, adjustment) {
  let line = 0;
  let idx = 0;
  let token = lines[line][idx];

  // First loop to make small adjustments to existing words' lengths.
  while (adjustment !== 0 && line < 3) {
    let newWord = adjustWord(token, adjustment);

    if (newWord) {
      lines[line][idx] = newWord;
      adjustment -= (syllable(newWord) - syllable(token));
    }

    idx++;
    token = lines[line][idx];
    if (!token) {
      line++;
      idx = 0;
      if (line > 2) {
        break;
      }
      token = lines[line][idx];

    }
  }

  var joined = lines.map(line => line.join(' '));
  line = 0;

  // Second while loop to add / remove extraneous words
  while (adjustment !== 0 && line < 3) {
    let oldPhrase = joined[line];
    let lineCount = countSyllables(oldPhrase);

    if ((line === 1 && lineCount === 7) || lineCount === 5) {
      line++;
    } else {
      var newPhrase;
      var maxLineAdjustment = (line === 1) ? 7 : 5;
      var lineAdjustment;

      if (adjustment < 0) {
        maxLineAdjustment *= -1;
        lineAdjustment = adjustment < maxLineAdjustment ?  maxLineAdjustment : adjustment;
        // lineAdjustment += lineCount;
      } else if (adjustment > 0) {

        let maxPossibleAdjustment = (maxLineAdjustment - lineCount);
        lineAdjustment = adjustment > maxPossibleAdjustment ? maxPossibleAdjustment : adjustment;

      }

      newPhrase = adjustPhrase(oldPhrase, lineAdjustment);

      joined[line] = newPhrase;
      adjustment -= (countSyllables(newPhrase) - countSyllables(oldPhrase));
      line++;
    }

  }

  return joined.join(' ' + separator + ' ');
}

export function isHaiku(msg) {
  return countSyllables(msg, separator) === HAIKU_LENGTH;
}

export function breakIntoHaiku(msg) {
  var tokens = msg.trim().split(/\W/);
  var rows = [[], [], []];
  var rowSyllables = 0;
  var line = 0;
  while (tokens.length) {
    let token = tokens.shift();
    let tokenLength = syllable(token);

    if (line === 0) {
      var diff = (rowSyllables + tokenLength) - 5;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    } else if (line === 1) {

      var diff = (rowSyllables + tokenLength) - 7;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    }

    rowSyllables += tokenLength;
    rows[line].push(token);

  }

  return rows;
}

/**
 * steps to check if it is a haiku
 * 1. check syllable length of commit
 * 2. if longer - > check for haikus in commit..
 *  a) if haiku -> print done !
 *  b) if not -> get most of haiku and continue? choose key words and continue?
 * 3. if shorter -> check syllable counts?
 * for what is missing -> fill in rhyme etc. to make up length ?? nonsensical ??
 */
 export function makeHaiku(msg) {
  let syllables = countSyllables(msg);
  let difference = HAIKU_LENGTH - syllables;

  msg = breakIntoHaiku(msg);
  return adjustSyllables(msg, difference);
}<|endoftext|>


<commit_before>'use strict';

angular.module('emuwebApp')
	.directive('osci', function (viewState, Soundhandlerservice, ConfigProviderService, Drawhelperservice) {
		return {
			templateUrl: 'views/osci.html',
			replace: true,
			restrict: 'E',
			scope: {},
			link: function postLink(scope, element, attrs) {

				// select the needed DOM elements from the template
				var canvasLength = element.find('canvas').length;
				var canvas = element.find('canvas')[0];
				var markupCanvas = element.find('canvas')[canvasLength - 1];
				// assign attributes to scope
				scope.order = attrs.order;
				scope.trackName = attrs.trackName;
				scope.cps = ConfigProviderService;
				// console.log(scope.trackName);

				scope.enlargeCanvas = {
					'height': 100 / ConfigProviderService.vals.perspectives[viewState.curPerspectiveIdx].signalCanvases.order.length + '%'
				};

				scope.viewState = viewState;

				///////////////
				// watches

				//
				scope.$watch('viewState.curPerspectiveIdx', function () {
					scope.updateCSS();
				}, true);

				//
				scope.$watch('viewState.playHeadAnimationInfos', function () {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							drawPlayHead(scope, ConfigProviderService);
						}
					}
				}, true);

				//
				scope.$watch('viewState.movingBoundarySample', function (newValue) {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							drawVpOsciMarkup(scope, ConfigProviderService, true);
						}
					}
				}, true);

				//
				scope.$watch('viewState.movingBoundary', function () {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							drawVpOsciMarkup(scope, ConfigProviderService, true);
						}
					}
				}, true);

				//
				scope.$watch('viewState.curViewPort', function (newValue, oldValue) {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							// check for changed zoom
							if (oldValue.sS !== newValue.sS || oldValue.sE !== newValue.sE || newValue.selectS === -1) { // SIC -1 check not that clean...
								var allPeakVals = Drawhelperservice.calculatePeaks(viewState, canvas, Soundhandlerservice.wavJSO.Data);
								Drawhelperservice.osciPeaks = allPeakVals;
								Drawhelperservice.freshRedrawDrawOsciOnCanvas(viewState, canvas, Drawhelperservice.osciPeaks, Soundhandlerservice.wavJSO.Data, ConfigProviderService);
							}
							drawVpOsciMarkup(scope, ConfigProviderService, true);
							scope.updateCSS();
						}
					}
				}, true);

				//
				/////////////////////////

				/**
				 *
				 */
				scope.updateCSS = function () {
					var parts = ConfigProviderService.vals.perspectives[viewState.curPerspectiveIdx].signalCanvases.order.length;
					if (viewState.getenlarge() == -1) {
						scope.enlargeCanvas = {
							'height': 100 / parts + '%'
						};
					} else {
						if (viewState.getenlarge() == scope.order) {
							scope.enlargeCanvas = {
								'height': 3 * 100 / (parts + 2) + '%'
							};
						} else {
							scope.enlargeCanvas = {
								'height': 100 / (parts + 2) + '%'
							};
						}
					}
				};

				/**
				 *
				 */
				function drawPlayHead(scope, config) {
					var ctx = markupCanvas.getContext('2d');
					ctx.clearRect(0, 0, canvas.width, canvas.height);

					var posS = viewState.getPos(markupCanvas.width, viewState.playHeadAnimationInfos.sS);
					var posCur = viewState.getPos(markupCanvas.width, viewState.playHeadAnimationInfos.curS);
					// console.log(viewState.playHeadAnimationInfos.curS)

					ctx.fillStyle = ConfigProviderService.vals.colors.selectedAreaColor;
					ctx.fillRect(posS, 0, posCur - posS, canvas.height);

					//console.log(posS,posCur);

					drawVpOsciMarkup(scope, config, false);

				}

				/**
				 * draws markup of osci according to
				 * the information that is specified in
				 * the viewport
				 */
				function drawVpOsciMarkup(scope, config, reset) {

					var ctx = markupCanvas.getContext('2d');
					if (reset) {
						ctx.clearRect(0, 0, markupCanvas.width, markupCanvas.height);
					}

					// draw moving boundary line if moving
					Drawhelperservice.drawMovingBoundaryLine(ctx);

					Drawhelperservice.drawViewPortTimes(ctx, true);
					// draw current viewport selected
					Drawhelperservice.drawCurViewPortSelected(ctx, true);
				}
			}
		};
	});<commit_msg>fixed check<commit_after>'use strict';

angular.module('emuwebApp')
	.directive('osci', function (viewState, Soundhandlerservice, ConfigProviderService, Drawhelperservice) {
		return {
			templateUrl: 'views/osci.html',
			replace: true,
			restrict: 'E',
			scope: {},
			link: function postLink(scope, element, attrs) {

				// select the needed DOM elements from the template
				var canvasLength = element.find('canvas').length;
				var canvas = element.find('canvas')[0];
				var markupCanvas = element.find('canvas')[canvasLength - 1];
				// assign attributes to scope
				scope.order = attrs.order;
				scope.trackName = attrs.trackName;
				scope.cps = ConfigProviderService;
				// console.log(scope.trackName);

				scope.enlargeCanvas = {
					'height': 100 / ConfigProviderService.vals.perspectives[viewState.curPerspectiveIdx].signalCanvases.order.length + '%'
				};

				scope.viewState = viewState;

				///////////////
				// watches

				//
				scope.$watch('viewState.curPerspectiveIdx', function () {
					scope.updateCSS();
				}, true);

				//
				scope.$watch('viewState.playHeadAnimationInfos', function () {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							drawPlayHead(scope, ConfigProviderService);
						}
					}
				}, true);

				//
				scope.$watch('viewState.movingBoundarySample', function (newValue) {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							drawVpOsciMarkup(scope, ConfigProviderService, true);
						}
					}
				}, true);

				//
				scope.$watch('viewState.movingBoundary', function () {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							drawVpOsciMarkup(scope, ConfigProviderService, true);
						}
					}
				}, true);

				//
				scope.$watch('viewState.curViewPort', function (newValue, oldValue) {
					if (!$.isEmptyObject(Soundhandlerservice)) {
						if (!$.isEmptyObject(Soundhandlerservice.wavJSO)) {
							// check for changed zoom
							if (oldValue.sS !== newValue.sS || oldValue.eS !== newValue.eS) {
								var allPeakVals = Drawhelperservice.calculatePeaks(viewState, canvas, Soundhandlerservice.wavJSO.Data);
								Drawhelperservice.osciPeaks = allPeakVals;
								Drawhelperservice.freshRedrawDrawOsciOnCanvas(viewState, canvas, Drawhelperservice.osciPeaks, Soundhandlerservice.wavJSO.Data, ConfigProviderService);
							}
							drawVpOsciMarkup(scope, ConfigProviderService, true);
							scope.updateCSS();
						}
					}
				}, true);

				//
				/////////////////////////

				/**
				 *
				 */
				scope.updateCSS = function () {
					var parts = ConfigProviderService.vals.perspectives[viewState.curPerspectiveIdx].signalCanvases.order.length;
					if (viewState.getenlarge() == -1) {
						scope.enlargeCanvas = {
							'height': 100 / parts + '%'
						};
					} else {
						if (viewState.getenlarge() == scope.order) {
							scope.enlargeCanvas = {
								'height': 3 * 100 / (parts + 2) + '%'
							};
						} else {
							scope.enlargeCanvas = {
								'height': 100 / (parts + 2) + '%'
							};
						}
					}
				};

				/**
				 *
				 */
				function drawPlayHead(scope, config) {
					var ctx = markupCanvas.getContext('2d');
					ctx.clearRect(0, 0, canvas.width, canvas.height);

					var posS = viewState.getPos(markupCanvas.width, viewState.playHeadAnimationInfos.sS);
					var posCur = viewState.getPos(markupCanvas.width, viewState.playHeadAnimationInfos.curS);
					// console.log(viewState.playHeadAnimationInfos.curS)

					ctx.fillStyle = ConfigProviderService.vals.colors.selectedAreaColor;
					ctx.fillRect(posS, 0, posCur - posS, canvas.height);

					//console.log(posS,posCur);

					drawVpOsciMarkup(scope, config, false);

				}

				/**
				 * draws markup of osci according to
				 * the information that is specified in
				 * the viewport
				 */
				function drawVpOsciMarkup(scope, config, reset) {

					var ctx = markupCanvas.getContext('2d');
					if (reset) {
						ctx.clearRect(0, 0, markupCanvas.width, markupCanvas.height);
					}

					// draw moving boundary line if moving
					Drawhelperservice.drawMovingBoundaryLine(ctx);

					Drawhelperservice.drawViewPortTimes(ctx, true);
					// draw current viewport selected
					Drawhelperservice.drawCurViewPortSelected(ctx, true);
				}
			}
		};
	});<|endoftext|>


<commit_before>'use strict'
import {app, ipcMain, BrowserWindow} from 'electron'
import {join} from 'path'
import settings from 'electron-settings'
import {isEnvDeveloper} from './helper.js'

settings.configure({
  prettify: true
})

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow = null

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  // if (process.platform != 'darwin') {
  //   app.quit()
  // }
})

app.on('ready', () => {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: settings.getSync('window.width') || 800,
    height: settings.getSync('window.height') || 600,
    x: settings.getSync('window.position.x') || undefined,
    y: settings.getSync('window.position.y') || undefined,
    icon: join(__dirname, '..', 'assets/icon.png')
  })
  // otherwise app will initiate with default menu, and then changes to the custom one
  mainWindow.setMenu(null)
  if(settings.getSync('window.maximized')) {
    mainWindow.maximize()
  }
  // pass args to renderer, needed for when we want to open a file/folder via context menu
  let argIndex = process.argv.findIndex((arg) => {
    return (arg.indexOf('-meview-open') > -1)
  })
  // -meview-open was passed and the idnex after that exists
  if(argIndex > -1 && !!process.argv[argIndex+1]) {
    mainWindow.webContents.once('did-finish-load', () => {
      mainWindow.webContents.send('open', {
        path: process.argv[argIndex + 1]
      } )
    })
  } else if(settings.getSync('reopenLastFile')) {
    let reopen = {
      reopen: true,
      path: settings.getSync('lastFile.dirname'),
      file: settings.getSync('lastFile.filename')
    }
    mainWindow.webContents.once('did-finish-load', () => {
      mainWindow.webContents.send('open', reopen )
    })
  }

  console.log(process.argv)
  let index = join('file://', __dirname, '..', 'index.html')
  mainWindow.loadURL(index)

  // Open the DevTools when in dev env
  if(isEnvDeveloper()) {
    mainWindow.webContents.openDevTools()
  }

  mainWindow.on('close', () => {
    let [width, height] = mainWindow.getSize()
    let [x, y] = mainWindow.getPosition()
    let maximized = mainWindow.isMaximized()
    settings.setSync('window', {
      width,
      height,
      'position': {x, y},
      maximized
    })
  })

  // Emitted when the window is closed.
  mainWindow.on('closed', () => {
    mainWindow = null
  })
})

ipcMain.on('folderBrowser', (event, arg) => {
  if(arg) {
    console.log(arg)
    mainWindow.webContents.send('open', arg)
  }
})<commit_msg>Fixed: main.js readded app.quit()...whoops<commit_after>'use strict'
import {app, ipcMain, BrowserWindow} from 'electron'
import {join} from 'path'
import settings from 'electron-settings'
import {isEnvDeveloper} from './helper.js'

settings.configure({
  prettify: true
})

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow = null

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  // if (process.platform != 'darwin') {
  app.quit()
  // }
})

app.on('ready', () => {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: settings.getSync('window.width') || 800,
    height: settings.getSync('window.height') || 600,
    x: settings.getSync('window.position.x') || undefined,
    y: settings.getSync('window.position.y') || undefined,
    icon: join(__dirname, '..', 'assets/icon.png')
  })
  // otherwise app will initiate with default menu, and then changes to the custom one
  mainWindow.setMenu(null)
  if(settings.getSync('window.maximized')) {
    mainWindow.maximize()
  }
  // pass args to renderer, needed for when we want to open a file/folder via context menu
  let argIndex = process.argv.findIndex((arg) => {
    return (arg.indexOf('-meview-open') > -1)
  })
  // -meview-open was passed and the idnex after that exists
  if(argIndex > -1 && !!process.argv[argIndex+1]) {
    mainWindow.webContents.once('did-finish-load', () => {
      mainWindow.webContents.send('open', {
        path: process.argv[argIndex + 1]
      } )
    })
  } else if(settings.getSync('reopenLastFile')) {
    let reopen = {
      reopen: true,
      path: settings.getSync('lastFile.dirname'),
      file: settings.getSync('lastFile.filename')
    }
    mainWindow.webContents.once('did-finish-load', () => {
      mainWindow.webContents.send('open', reopen )
    })
  }

  console.log(process.argv)
  let index = join('file://', __dirname, '..', 'index.html')
  mainWindow.loadURL(index)

  // Open the DevTools when in dev env
  if(isEnvDeveloper()) {
    mainWindow.webContents.openDevTools()
  }

  mainWindow.on('close', () => {
    let [width, height] = mainWindow.getSize()
    let [x, y] = mainWindow.getPosition()
    let maximized = mainWindow.isMaximized()
    settings.setSync('window', {
      width,
      height,
      'position': {x, y},
      maximized
    })
  })

  // Emitted when the window is closed.
  mainWindow.on('closed', () => {
    mainWindow = null
  })
})

ipcMain.on('folderBrowser', (event, arg) => {
  if(arg) {
    console.log(arg)
    mainWindow.webContents.send('open', arg)
  }
})<|endoftext|>


<commit_before>/**
 * Controller for Delving search module.
 */
define( ['backbone', 'backbone.marionette', 'communicator', 'plugins/module-search', 'backgrid', 'backgrid.paginator',
    'plugins/zev/zev-collection', 'models/state',
    'views/search/search-wait', 'views/results-view', 'views/search/search-field', 'plugins/zev/zev-facets-view', 'plugins/zev/zev-date-filter-view'],
  function(Backbone, Marionette, Communicator, SearchModule, Backgrid, PaginatorView,
           DelvingCollection, State,
           WaitView, ResultsView, DelvingSearchView, ZevFacetsView, ZevDateFilterView) {

    return SearchModule.extend({

      module: {
        'type': 'search',
        'title': 'Zoek ONH'
      },

      markers: null,
      facets: null,
      items: null,
      query: null,

      initialize: function(o) {

        var self = this;

        this.markers = o.markers_collection;
        this.facets = new Backbone.Collection();
        this.results = new DelvingCollection();
        var SearchModel = Backbone.Model.extend( {
          defaults: {
            terms: '',
            date: {
              from: '',
              to: ''
            },
            facets: [],
            viewportFilter: false,
            numfound: 0
          }
        });
        this.model = new SearchModel();

        // Event triggered by "VOEG TOE" action on search result card.
        Communicator.mediator.on( "marker:addModelId", function(cid) {
          var result = self.results.findWhere( {cid: cid} );
          if (!result) return;

          // The record model contains a lot of extract information that the marker doesn't need,
          // and the essential info (a unique ID) is not available. Here we extra the useful info
          // so the result model can be destroyed with pagination, etc.
          console.log(result);
          var attrs = ['__id__', 'title', 'image', 'description', 'youtube', 'externalUrl', 'spatial'];
          var vars = {};
          _.each(attrs, function(key) {
            vars[key] = result.get(key);
          });
          if ( !State.getPlugin('geojson_features').collection.findWhere({
              '__id__': vars['__id__']
            })) {
            State.getPlugin('geojson_features').collection.add( vars );
          }
        });

        this.listenTo(this.model, "change:terms", function() {
          self.results.state.terms = self.model.get('terms');
          self.getResults();
        });

        this.listenTo(this.model, "change:facets", function() {
          self.results.state.facets = self.model.get('facets');
          self.getResults();
        });

        this.listenTo(this.model, "change:date", function() {
          self.results.state.date = self.model.get('date');
          self.getResults();
        });

        this.listenTo(this.model, "change:viewportFilter", function() {
          self.getResults();
        });
      },

      // Overrides parent to implement facets (a bit overkill)
      getResults: function() {

        var self = this;
        if (this.resultsView) this.resultsView.destroy();
        if (this.facetsView) this.facetsView.remove();
        if (this.paginationView) this.paginationView.remove();
        this.layout.getRegion( 'progress' ).show( new WaitView() );

        if (self.model.get('viewportFilter')) {
          // Update model with current map location before executing the search.
          var map = Communicator.reqres.request( 'getMap'),
              bounds = map.getBounds(),
              sw = bounds.getSouthWest(),
              ne = bounds.getNorthEast();

          self.results.state.geoFence = {
            type: 'AND',
            values: [
              'minGeoLat=' + sw.lat,
              'minGeoLong=' + sw.lng,
              'maxGeoLat=' + ne.lat,
              'maxGeoLong=' + ne.lng
            ]
          };
        }
        else {
          self.results.state.geoFence = null;
        }

        self.results.fetch({
          success: function(collection) {

            self.facetsView = new ZevFacetsView({ collection: collection.getFacetConfig(), searchModel: self.model });
            self.resultsView = new ResultsView( {collection: collection} );
            self.paginationView = new Backgrid.Extension.Paginator( {
              collection: collection,
              windowSize: 5
            } );

            self.layout.getRegion( 'facets' ).show( self.facetsView );
            self.layout.getRegion( 'results' ).show( self.resultsView );
            self.layout.getRegion( 'pagination' ).show( self.paginationView );
            self.layout.getRegion( 'progress' ).reset();
          }
        });

      },

      render: function() {
        this.layout.getRegion('search').show(new DelvingSearchView({
          model: this.model
        }) );

        this.layout.getRegion( 'filters' ).show( new ZevDateFilterView({ model: this.model }) );
      },

      onRender: function() {
        this.layout.render();
      }

    });

  }
);<commit_msg>fix inaccurate variable name<commit_after>/**
 * Controller for Delving search module.
 */
define( ['backbone', 'backbone.marionette', 'communicator', 'plugins/module-search', 'backgrid', 'backgrid.paginator',
    'plugins/zev/zev-collection', 'models/state',
    'views/search/search-wait', 'views/results-view', 'views/search/search-field', 'plugins/zev/zev-facets-view', 'plugins/zev/zev-date-filter-view'],
  function(Backbone, Marionette, Communicator, SearchModule, Backgrid, PaginatorView,
           ZoekEnVindCollection, State,
           WaitView, ResultsView, DelvingSearchView, ZevFacetsView, ZevDateFilterView) {

    return SearchModule.extend({

      module: {
        'type': 'search',
        'title': 'Zoek ONH'
      },

      markers: null,
      facets: null,
      items: null,
      query: null,

      initialize: function(o) {

        var self = this;

        this.markers = o.markers_collection;
        this.facets = new Backbone.Collection();
        this.results = new ZoekEnVindCollection();
        var SearchModel = Backbone.Model.extend( {
          defaults: {
            terms: '',
            date: {
              from: '',
              to: ''
            },
            facets: [],
            viewportFilter: false,
            numfound: 0
          }
        });
        this.model = new SearchModel();

        // Event triggered by "VOEG TOE" action on search result card.
        Communicator.mediator.on( "marker:addModelId", function(cid) {
          var result = self.results.findWhere( {cid: cid} );
          if (!result) return;

          // The record model contains a lot of extract information that the marker doesn't need,
          // and the essential info (a unique ID) is not available. Here we extra the useful info
          // so the result model can be destroyed with pagination, etc.
          var attrs = ['__id__', 'title', 'image', 'description', 'youtube', 'externalUrl', 'spatial'];
          var vars = {};
          _.each(attrs, function(key) {
            vars[key] = result.get(key);
          });
          if ( !State.getPlugin('geojson_features').collection.findWhere({
              '__id__': vars['__id__']
            })) {
            State.getPlugin('geojson_features').collection.add( vars );
          }
        });

        this.listenTo(this.model, "change:terms", function() {
          self.results.state.terms = self.model.get('terms');
          self.getResults();
        });

        this.listenTo(this.model, "change:facets", function() {
          self.results.state.facets = self.model.get('facets');
          self.getResults();
        });

        this.listenTo(this.model, "change:date", function() {
          self.results.state.date = self.model.get('date');
          self.getResults();
        });

        this.listenTo(this.model, "change:viewportFilter", function() {
          self.getResults();
        });
      },

      // Overrides parent to implement facets (a bit overkill)
      getResults: function() {

        var self = this;
        if (this.resultsView) this.resultsView.destroy();
        if (this.facetsView) this.facetsView.remove();
        if (this.paginationView) this.paginationView.remove();
        this.layout.getRegion( 'progress' ).show( new WaitView() );

        if (self.model.get('viewportFilter')) {
          // Update model with current map location before executing the search.
          var map = Communicator.reqres.request( 'getMap'),
              bounds = map.getBounds(),
              sw = bounds.getSouthWest(),
              ne = bounds.getNorthEast();

          self.results.state.geoFence = {
            type: 'AND',
            values: [
              'minGeoLat=' + sw.lat,
              'minGeoLong=' + sw.lng,
              'maxGeoLat=' + ne.lat,
              'maxGeoLong=' + ne.lng
            ]
          };
        }
        else {
          self.results.state.geoFence = null;
        }

        self.results.fetch({
          success: function(collection) {

            self.facetsView = new ZevFacetsView({ collection: collection.getFacetConfig(), searchModel: self.model });
            self.resultsView = new ResultsView( {collection: collection} );
            self.paginationView = new Backgrid.Extension.Paginator( {
              collection: collection,
              windowSize: 5
            } );

            self.layout.getRegion( 'facets' ).show( self.facetsView );
            self.layout.getRegion( 'results' ).show( self.resultsView );
            self.layout.getRegion( 'pagination' ).show( self.paginationView );
            self.layout.getRegion( 'progress' ).reset();
          }
        });

      },

      render: function() {
        this.layout.getRegion('search').show(new DelvingSearchView({
          model: this.model
        }) );

        this.layout.getRegion( 'filters' ).show( new ZevDateFilterView({ model: this.model }) );
      },

      onRender: function() {
        this.layout.render();
      }

    });

  }
);<|endoftext|>


<commit_before>'use babel'

import Path from 'path'
import FS from 'fs'
import * as Chokidar from 'chokidar'
import {Disposable} from 'sb-event-kit'
import {findRoot} from './helpers/find-root'
import {findFiles} from './helpers/find-files'
import {getConfig} from './helpers/get-config'
import {getRules} from './helpers/get-rules'
import {getPlugins} from './helpers/get-plugins'
import {saveFile} from './helpers/save-file'
import {execute} from './helpers/execute'

export function compile(path = null, options = {}) {
  options = Object.assign({
    ignored: [],
    root: null,
    cwd: null,
    config: {}
  }, options)

  const root = findRoot(path, options)
  const config = Object.assign({}, options.config, getConfig(root))
  const files = findFiles(path, options.ignored, {root, config, cwd: options.cwd})

  return Promise.all(files.map(function({relativePath, absolutePath, fileName}) {
    // TODO: Reverse source maps when they change
    const localConfig = getRules(relativePath, config)
    const plugins = getPlugins(root, localConfig)
    const contents = FS.readFileSync(absolutePath, {encoding: 'utf8'})
    const state = {sourceMap: null, imports: [], ext: Path.extname(fileName).slice(1)}
    const paths = {root, relativePath, absolutePath, fileName}

    return execute(plugins, contents, paths, {state, config: localConfig}).then(function(newContents) {
      return saveFile(newContents, localConfig, paths, state)
    })
  }))
}

export function watch(path, options = {}) {
  options = Object.assign({
    cwd: process.cwd()
  }, options)

  const watcher = Chokidar.watch(path)

  function onChange(path) {
    compile(path, options).catch(function(e) {
      console.error(e)
    })
  }

  watcher.on('change', onChange)
  watcher.on('add', onChange)

  return new Disposable(function() {
    watcher.close()
  })
}
<commit_msg>:new: Return a proper compilation result<commit_after>'use babel'

import Path from 'path'
import FS from 'fs'
import * as Chokidar from 'chokidar'
import {Disposable} from 'sb-event-kit'
import {findRoot} from './helpers/find-root'
import {findFiles} from './helpers/find-files'
import {getConfig} from './helpers/get-config'
import {getRules} from './helpers/get-rules'
import {getPlugins} from './helpers/get-plugins'
import {saveFile} from './helpers/save-file'
import {execute} from './helpers/execute'

export function compile(path = null, options = {}, errorCallback = null) {
  options = Object.assign({
    ignored: [],
    root: null,
    cwd: null,
    config: {}
  }, options)

  const root = findRoot(path, options)
  const config = Object.assign({}, options.config, getConfig(root))
  const files = findFiles(path, options.ignored, {root, config, cwd: options.cwd})
  let result = {status: true, contents: {}}

  return Promise.all(files.map(function({relativePath, absolutePath, fileName}) {
    // TODO: Reverse source maps when they change
    const localConfig = getRules(relativePath, config)
    const plugins = getPlugins(root, localConfig)
    const contents = FS.readFileSync(absolutePath, {encoding: 'utf8'})
    const state = {sourceMap: null, imports: [], ext: Path.extname(fileName).slice(1)}
    const paths = {root, relativePath, absolutePath, fileName}

    return execute(plugins, contents, paths, {state, config: localConfig}).then(function(newContents) {
      return saveFile(newContents, localConfig, paths, state)
    }).then(function(result) {
      result.contents[absolutePath] = result
    }, function(error) {
      result.status = false
      if (typeof errorCallback === 'function') {
        errorCallback(error)
      }
      result.contents[absolutePath] = null
    })
  })).then(function() {
    return result
  })
}

export function watch(path, options = {}, errorCallback = null) {
  options = Object.assign({
    cwd: process.cwd()
  }, options)

  const watcher = Chokidar.watch(path)

  function onChange(path) {
    const promise = compile(path, options)
    if (typeof errorCallback === 'function') {
      promise.catch(errorCallback)
    }
  }

  watcher.on('change', onChange)
  watcher.on('add', onChange)

  return new Disposable(function() {
    watcher.close()
  })
}
<|endoftext|>


<commit_before>/**
 * @file mdjs
 * @author xiaowu
 * @email fe.xiaowu@gmail.com
 */

'use strict';

import extend from 'extend';
import template from 'art-template/node/template-native';

import express from 'express';
import serve_static from 'serve-static';

import fs from 'fs';
import url from 'url';
import path from 'path';

import Key_cache from 'key-cache';

import marked from 'marked';
import highlight from 'highlight.js';

export default class {
    options = {
        /**
         * 文档名
         *
         * @type {String}
         */
        name: 'mdjs',

        /**
         * 监听的端口
         *
         * @type {Number}
         */
        port: 8091,

        /**
         * 文档根目录
         *
         * @type {String}
         */
        root: './',

        /**
         * 缓存文件目录
         *
         * @type {String}
         */
        cache_path: './.cache/',

        /**
         * 目录别名
         *
         * @type {Object}
         */
        dir_alias: {},

        /**
         * mdjs静态资源前缀
         *
         * @description 监听内置的静态资源，配置是为了解决与别的名冲突
         * @type {String}
         */
        static_prefix: 'static',

        /**
         * 忽略的目录
         *
         * @type {Array}
         */
        ignore_dir: [
            '.svn',
            '.git',
            'node_modules'
        ],

        /**
         * 导航里额外追加的链接
         *
         * @example
         *     [
         *         {
         *             "text": "链接名称-默认往导航之前插件",
         *             "url": "链接"
         *         },
         *         {
         *             "text": "链接名称-往导航之后追加",
         *             "url": "链接",
         *             "type": "after"
         *         }
         *     ]
         * @type {Array}
         */
        links: [
        ],

        /**
         * 调试模式
         *
         * @description 开启后不使用缓存
         * @type {Boolean}
         */
        debug: false
    }

    /**
     * 构造器
     *
     * @param  {Object} options 配置参数
     */
    constructor(options = {}) {
        let package_options;
        try {
            package_options = require(path.resolve('./package.json')).mdjs || {};
        }
        catch (e) {
            package_options = {};
        }

        // 合并默认配置
        // 合并的顺序是： 参数 > package.mdjs > 默认 （由左向右合并）
        options = this.options = extend({}, this.options, package_options, options);

        options.root = path.resolve('./', options.root);
        options.cache_path = path.resolve('./', options.cache_path);

        // 缓存当前运行的目录
        this.__dirname = path.dirname(__dirname);

        this.run();
    }

    /**
     * 获取渲染后的导航html代码
     *
     * @param  {string|undefined} uri 当前高亮的路径，如果为空则全不高亮， 高亮即展开
     *
     * @return {string}     html代码
     */
    get_render_nav(uri) {
        let data = this.get_list();
        let str = '';

        if (!data || !data.length) {
            return str;
        }

        uri = decodeURIComponent(uri);

        let filter = (filepath, type) => {
            if (!uri) {
                return false;
            }

            if (type === 'dir') {
                if (uri.indexOf(filepath + '/') === 0) {
                    return true;
                }
            }
            else if (type === 'file') {
                if (uri === filepath) {
                    return true;
                }
            }

            return false;
        };

        let fn = (res) => {
            let html = '';

            res.forEach((val) => {
                if (!val.children || !val.children.length) {
                    if (filter(val.uri, 'file')) {
                        html += `<li class="nav-tree-file nav-tree-current">`;
                    }
                    else {
                        html += `<li class="nav-tree-file">`;
                    }
                    html += `

                                    ${val.text}

                    `;
                }
                else {
                    if (filter(val.uri, 'dir')) {
                        html += `<li class="nav-tree-dir nav-tree-dir-open">`;
                    }
                    else {
                        html += `<li class="nav-tree-dir">`;
                    }
                    html += `

                                    ${val.text}

                            ${fn(val.children)}

                    `;
                }
            });

            return '
' + html + '
';
        };

        return fn(data);
    }

    /**
     * 清空缓存
     *
     * @return {Object} this
     */
    clear_cache() {
        let cache = new Key_cache({
            dir: this.options.cache_path
        });

        cache.remove();

        return this;
    }

    /**
     * 获取navtree使用数据，会追加options.links
     *
     * @description 会先读取缓存
     * @return {Array} 数组
     */
    get_list() {
        let cache;

        // 必须关闭调试模式才读取缓存
        if (!this.options.debug) {
            // 优化读取缓存
            cache = new Key_cache({
                dir: this.options.cache_path
            });
            let nav_data = cache.get('nav_data');

            // 如果缓存存在
            if (nav_data) {
                return nav_data;
            }
        }

        let data = this._get_list();

        if (!data.children) {
            data.children = [];
        }

        // 如果有链接，则追加
        if (this.options.links && this.options.links.length) {
            this.options.links.forEach(val => {
                if (val.type === 'after') {
                    data.children.push(val);
                }
                else {
                    data.children.unshift(val);
                }
            });
        }

        let nav_data = data.children;

        // 如果没有调试则写入缓存
        if (!this.options.debug  && cache && cache.set) {
            cache.set('nav_data', nav_data);
        }

        return nav_data;
    }

    /**
     * 渲染md文件
     *
     * @param  {string} content md源码
     *
     * @return {Object}         {content:html代码, catalog: h2,3分类}
     */
    renderMarkdown(content = '') {
        let renderer = new marked.Renderer();
        let cachekey = {};

        let catalog = [];

        // 渲染标题
        renderer.heading = (text, level) => {
            let key;

            if (level !== 2 && level !== 3) {
                return `<h${level}>${text}</h${level}>`;
            }

            if (!cachekey[level]) {
                cachekey[level] = 0;
            }

            key = ++cachekey[level];

            catalog.push({
                text: text,
                level: level,
                id: `h${level}-${key}`
            });

            return `
                <h${level}>

                        ${text}

                </h${level}>
            `;
        };

        // 渲染代码
        renderer.code = (data, lang) => {
            data = highlight.highlightAuto(data).value;

            // 必须有语言且行数>=3
            if (lang && data.split(/\n/).length >= 3) {
                return `

                        ${lang}${data}

`;
            }

            return `<pre><code class="hljs">${data}</code></pre>`;
        };

        // md => html
        content = marked(content, {
            renderer: renderer
        });

        // 兼容todo
        content = content.replace(/
\s*\[ \]\s*/g, '
<input type="checkbox" class="ui-todo" disabled>');
        content = content.replace(/
\s*\[x\]\s*/g, '
<input type="checkbox" disabled checked class="ui-todo">');

        return {
            content: content,
            catalog: catalog
        };
    }

    /**
     * 运行
     */
    run() {
        let app = this.express = express();

        template.config('base', '');
        template.config('extname', '.html');

        app.engine('.html', template.__express);
        app.set('views', path.resolve(this.__dirname, './views/'));
        app.set('view engine', 'html');

        // 解析md，解决中文路径问题
        app.use((req, res, next) => {
            // 写入变量
            res.locals.options = this.options;

            return next();
        });

        // 绑定.md文档
        app.get(/([\s\S]+?)\.md$/, this._md.bind(this));

        // 监听以目录结束的，其实是为了解决默认主页为md文档问题
        app.get(/(^\/$|\/$)/, (req, res, next) => {
            // url中的文件路径
            let pathname = url.parse(req.url).pathname;

            // 相对文件的路径,用来判断文件是否存在
            let filepath = decodeURIComponent('.' + pathname);

            // 默认主页
            let default_index = [
                'readme.md',
                'README.md'
            ];
            let flag = false;
            for (let i = 0, len = default_index.length; i < len; i++) {
                if (fs.existsSync(path.resolve(this.options.root, filepath, default_index[i]))) {
                    flag = default_index[i];
                    break;
                }
            }

            if (flag) {
                req.url = pathname + flag;
                return this._md(req, res, next);
            }

            next();
        });

        // 委托静态资源
        app.use('/' + this.options.static_prefix, serve_static(path.resolve(this.__dirname, './static/')));

        // 委托源目录
        app.use('/', serve_static(this.options.root));

        app.listen(this.options.port);
    }

    /**
     * 内部获取列表数据
     *
     * @private
     * @param  {string|undefined} dir 目录
     *
     * @return {Object}     {path:'', children:[]}
     */
    _get_list(dir) {
        let options = this.options;
        let result;

        dir = dir || options.root;

        let basename = path.basename(dir);

        result = {
            uri: dir.replace(options.root, '') || '/',
            children: [],
            text: options.dir_alias[basename] || basename
        };

        let data = fs.readdirSync(dir);

        data.forEach(file => {
            let filepath = path.resolve(dir, file);
            let stat = fs.statSync(filepath);

            if (stat.isDirectory()) {
                if (options.ignore_dir && options.ignore_dir.indexOf(file) !== -1) {
                    return;
                }

                let res = this._get_list(filepath);

                if (res.children && res.children.length) {
                    result.children.push(res);
                }
            }
            else if (stat.isFile()) {
                if (path.extname(file) !== '.md') {
                    return;
                }

                result.children.push({
                    text: this._get_md_title(dir + '/' + file),
                    uri: (dir + '/' + file).replace(options.root, '')
                });
            }
        });

        return result;
    }

    /**
     * 渲染md文档
     *
     * @private
     * @param  {Object}   req  express.req
     * @param  {Object}   res  express.res
     * @param  {Function} next 下一个路由
     * @return {Object} res
     */
    _md(req, res, next) {
        let parseUrl = url.parse(req.url, true);

        // 如果要读取源码
        if (parseUrl.query.source) {
            return next();
        }

        // 加.是为了变成相对路径
        let filepath = path.resolve(this.options.root, '.' + parseUrl.pathname);

        // 为了中文
        filepath = decodeURIComponent(filepath);

        // 如果md文件不存在
        if (!fs.existsSync(filepath)) {
            return next();
        }

        let htmldata = this.renderMarkdown(fs.readFileSync(filepath).toString()).content;

        // 如果是pjax
        if (parseUrl.query.pjax) {
            return res.end(htmldata);
        }

        // 渲染md
        return res.render('markdown', {
            nav_data: this.get_render_nav(parseUrl.pathname),
            markdown_data: htmldata,
            title: `${this._get_md_title(filepath)} - ${this.options.name}`
        });
    }

    /**
     * 内部获取md文档的标题
     *
     * @private
     * @param  {string} filepath 文件路径
     *
     * @return {string}     标题
     */
    _get_md_title(filepath) {
        // 如果是md扩展
        if (path.extname(filepath) === '.md') {
            // 获取文件内容
            let filedata = fs.readFileSync(filepath).toString();

            // 正则取出#标题的文字
            if (filedata.match(/^\#+\s?(.+?)[\r\n]/)) {
                return String(RegExp.$1).trim();
            }
        }

        return path.basename(filepath);
    }
}
<commit_msg>优化code折行<commit_after>/**
 * @file mdjs
 * @author xiaowu
 * @email fe.xiaowu@gmail.com
 */

'use strict';

import extend from 'extend';
import template from 'art-template/node/template-native';

import express from 'express';
import serve_static from 'serve-static';

import fs from 'fs';
import url from 'url';
import path from 'path';

import Key_cache from 'key-cache';

import marked from 'marked';
import highlight from 'highlight.js';

export default class {
    options = {
        /**
         * 文档名
         *
         * @type {String}
         */
        name: 'mdjs',

        /**
         * 监听的端口
         *
         * @type {Number}
         */
        port: 8091,

        /**
         * 文档根目录
         *
         * @type {String}
         */
        root: './',

        /**
         * 缓存文件目录
         *
         * @type {String}
         */
        cache_path: './.cache/',

        /**
         * 目录别名
         *
         * @type {Object}
         */
        dir_alias: {},

        /**
         * mdjs静态资源前缀
         *
         * @description 监听内置的静态资源，配置是为了解决与别的名冲突
         * @type {String}
         */
        static_prefix: 'static',

        /**
         * 忽略的目录
         *
         * @type {Array}
         */
        ignore_dir: [
            '.svn',
            '.git',
            'node_modules'
        ],

        /**
         * 导航里额外追加的链接
         *
         * @example
         *     [
         *         {
         *             "text": "链接名称-默认往导航之前插件",
         *             "url": "链接"
         *         },
         *         {
         *             "text": "链接名称-往导航之后追加",
         *             "url": "链接",
         *             "type": "after"
         *         }
         *     ]
         * @type {Array}
         */
        links: [
        ],

        /**
         * 调试模式
         *
         * @description 开启后不使用缓存
         * @type {Boolean}
         */
        debug: false
    }

    /**
     * 构造器
     *
     * @param  {Object} options 配置参数
     */
    constructor(options = {}) {
        let package_options;
        try {
            package_options = require(path.resolve('./package.json')).mdjs || {};
        }
        catch (e) {
            package_options = {};
        }

        // 合并默认配置
        // 合并的顺序是： 参数 > package.mdjs > 默认 （由左向右合并）
        options = this.options = extend({}, this.options, package_options, options);

        options.root = path.resolve('./', options.root);
        options.cache_path = path.resolve('./', options.cache_path);

        // 缓存当前运行的目录
        this.__dirname = path.dirname(__dirname);

        this.run();
    }

    /**
     * 获取渲染后的导航html代码
     *
     * @param  {string|undefined} uri 当前高亮的路径，如果为空则全不高亮， 高亮即展开
     *
     * @return {string}     html代码
     */
    get_render_nav(uri) {
        let data = this.get_list();
        let str = '';

        if (!data || !data.length) {
            return str;
        }

        uri = decodeURIComponent(uri);

        let filter = (filepath, type) => {
            if (!uri) {
                return false;
            }

            if (type === 'dir') {
                if (uri.indexOf(filepath + '/') === 0) {
                    return true;
                }
            }
            else if (type === 'file') {
                if (uri === filepath) {
                    return true;
                }
            }

            return false;
        };

        let fn = (res) => {
            let html = '';

            res.forEach((val) => {
                if (!val.children || !val.children.length) {
                    if (filter(val.uri, 'file')) {
                        html += `<li class="nav-tree-file nav-tree-current">`;
                    }
                    else {
                        html += `<li class="nav-tree-file">`;
                    }
                    html += `

                                    ${val.text}

                    `;
                }
                else {
                    if (filter(val.uri, 'dir')) {
                        html += `<li class="nav-tree-dir nav-tree-dir-open">`;
                    }
                    else {
                        html += `<li class="nav-tree-dir">`;
                    }
                    html += `

                                    ${val.text}

                            ${fn(val.children)}

                    `;
                }
            });

            return '
' + html + '
';
        };

        return fn(data);
    }

    /**
     * 清空缓存
     *
     * @return {Object} this
     */
    clear_cache() {
        let cache = new Key_cache({
            dir: this.options.cache_path
        });

        cache.remove();

        return this;
    }

    /**
     * 获取navtree使用数据，会追加options.links
     *
     * @description 会先读取缓存
     * @return {Array} 数组
     */
    get_list() {
        let cache;

        // 必须关闭调试模式才读取缓存
        if (!this.options.debug) {
            // 优化读取缓存
            cache = new Key_cache({
                dir: this.options.cache_path
            });
            let nav_data = cache.get('nav_data');

            // 如果缓存存在
            if (nav_data) {
                return nav_data;
            }
        }

        let data = this._get_list();

        if (!data.children) {
            data.children = [];
        }

        // 如果有链接，则追加
        if (this.options.links && this.options.links.length) {
            this.options.links.forEach(val => {
                if (val.type === 'after') {
                    data.children.push(val);
                }
                else {
                    data.children.unshift(val);
                }
            });
        }

        let nav_data = data.children;

        // 如果没有调试则写入缓存
        if (!this.options.debug  && cache && cache.set) {
            cache.set('nav_data', nav_data);
        }

        return nav_data;
    }

    /**
     * 渲染md文件
     *
     * @param  {string} content md源码
     *
     * @return {Object}         {content:html代码, catalog: h2,3分类}
     */
    renderMarkdown(content = '') {
        let renderer = new marked.Renderer();
        let cachekey = {};

        let catalog = [];

        // 渲染标题
        renderer.heading = (text, level) => {
            let key;

            if (level !== 2 && level !== 3) {
                return `<h${level}>${text}</h${level}>`;
            }

            if (!cachekey[level]) {
                cachekey[level] = 0;
            }

            key = ++cachekey[level];

            catalog.push({
                text: text,
                level: level,
                id: `h${level}-${key}`
            });

            return `
                <h${level}>

                        ${text}

                </h${level}>
            `;
        };

        // 渲染代码
        renderer.code = (data, lang) => {
            data = highlight.highlightAuto(data).value;

            // 必须有语言且行数>=3
            if (lang && data.split(/\n/).length >= 3) {
                return `

                    ${lang}${data}
`;
            }

            return `<pre><code class="hljs">${data}</code></pre>`;
        };

        // md => html
        content = marked(content, {
            renderer: renderer
        });

        // 兼容todo
        content = content.replace(/
\s*\[ \]\s*/g, '
<input type="checkbox" class="ui-todo" disabled>');
        content = content.replace(/
\s*\[x\]\s*/g, '
<input type="checkbox" disabled checked class="ui-todo">');

        return {
            content: content,
            catalog: catalog
        };
    }

    /**
     * 运行
     */
    run() {
        let app = this.express = express();

        template.config('base', '');
        template.config('extname', '.html');

        app.engine('.html', template.__express);
        app.set('views', path.resolve(this.__dirname, './views/'));
        app.set('view engine', 'html');

        // 解析md，解决中文路径问题
        app.use((req, res, next) => {
            // 写入变量
            res.locals.options = this.options;

            return next();
        });

        // 绑定.md文档
        app.get(/([\s\S]+?)\.md$/, this._md.bind(this));

        // 监听以目录结束的，其实是为了解决默认主页为md文档问题
        app.get(/(^\/$|\/$)/, (req, res, next) => {
            // url中的文件路径
            let pathname = url.parse(req.url).pathname;

            // 相对文件的路径,用来判断文件是否存在
            let filepath = decodeURIComponent('.' + pathname);

            // 默认主页
            let default_index = [
                'readme.md',
                'README.md'
            ];
            let flag = false;
            for (let i = 0, len = default_index.length; i < len; i++) {
                if (fs.existsSync(path.resolve(this.options.root, filepath, default_index[i]))) {
                    flag = default_index[i];
                    break;
                }
            }

            if (flag) {
                req.url = pathname + flag;
                return this._md(req, res, next);
            }

            next();
        });

        // 委托静态资源
        app.use('/' + this.options.static_prefix, serve_static(path.resolve(this.__dirname, './static/')));

        // 委托源目录
        app.use('/', serve_static(this.options.root));

        app.listen(this.options.port);
    }

    /**
     * 内部获取列表数据
     *
     * @private
     * @param  {string|undefined} dir 目录
     *
     * @return {Object}     {path:'', children:[]}
     */
    _get_list(dir) {
        let options = this.options;
        let result;

        dir = dir || options.root;

        let basename = path.basename(dir);

        result = {
            uri: dir.replace(options.root, '') || '/',
            children: [],
            text: options.dir_alias[basename] || basename
        };

        let data = fs.readdirSync(dir);

        data.forEach(file => {
            let filepath = path.resolve(dir, file);
            let stat = fs.statSync(filepath);

            if (stat.isDirectory()) {
                if (options.ignore_dir && options.ignore_dir.indexOf(file) !== -1) {
                    return;
                }

                let res = this._get_list(filepath);

                if (res.children && res.children.length) {
                    result.children.push(res);
                }
            }
            else if (stat.isFile()) {
                if (path.extname(file) !== '.md') {
                    return;
                }

                result.children.push({
                    text: this._get_md_title(dir + '/' + file),
                    uri: (dir + '/' + file).replace(options.root, '')
                });
            }
        });

        return result;
    }

    /**
     * 渲染md文档
     *
     * @private
     * @param  {Object}   req  express.req
     * @param  {Object}   res  express.res
     * @param  {Function} next 下一个路由
     * @return {Object} res
     */
    _md(req, res, next) {
        let parseUrl = url.parse(req.url, true);

        // 如果要读取源码
        if (parseUrl.query.source) {
            return next();
        }

        // 加.是为了变成相对路径
        let filepath = path.resolve(this.options.root, '.' + parseUrl.pathname);

        // 为了中文
        filepath = decodeURIComponent(filepath);

        // 如果md文件不存在
        if (!fs.existsSync(filepath)) {
            return next();
        }

        let htmldata = this.renderMarkdown(fs.readFileSync(filepath).toString()).content;

        // 如果是pjax
        if (parseUrl.query.pjax) {
            return res.end(htmldata);
        }

        // 渲染md
        return res.render('markdown', {
            nav_data: this.get_render_nav(parseUrl.pathname),
            markdown_data: htmldata,
            title: `${this._get_md_title(filepath)} - ${this.options.name}`
        });
    }

    /**
     * 内部获取md文档的标题
     *
     * @private
     * @param  {string} filepath 文件路径
     *
     * @return {string}     标题
     */
    _get_md_title(filepath) {
        // 如果是md扩展
        if (path.extname(filepath) === '.md') {
            // 获取文件内容
            let filedata = fs.readFileSync(filepath).toString();

            // 正则取出#标题的文字
            if (filedata.match(/^\#+\s?(.+?)[\r\n]/)) {
                return String(RegExp.$1).trim();
            }
        }

        return path.basename(filepath);
    }
}
<|endoftext|>


<commit_before>$(document).ready(function(){
  init_madness();
});

function init_madness(){
  var canvas = document.getElementById("mad"),
  ctx = canvas.getContext("2d"),
  letters = [],
  phrases = ["Login", "March Madness", "Rock", "Paper", "Scissor"],
  lim = Math.floor(Math.random(0, 100));

  for(var i = 97; i < 122; i++){
    letters.push(String.fromCharCode(i));
  }

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  if(Math.floor(Math.random(0, 2)) == 1){
    use_phrases();
  }else{
    use_letters();
  }

  function use_phrases(){
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for(var i = 0; i < 100; i++){
      ctx.fillRect(Math.random(0, canvas.width), Math.random(0, canvas.height), Math.random(10, 100), Math.random(10, 100));
    }
  }

  function use_letters(){
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for(var i = 0; i < 100; i++){
      ctx.fillRect(Math.random(0, canvas.width), Math.random(0, canvas.height), Math.random(10, 100), Math.random(10, 100));
    }
  }
}
<commit_msg>Delete thisismadness.js<commit_after><|endoftext|>


<commit_before>//app-specific sentence

module.exports = {
  debug : true,
  slackChannel : "#football",
  serverPort : 8080,
  pingInteralInMilliseconds : 1000, // * 60, // server main loop interval.
  postBeforeTheMatch : true,
  postAfterTheMatch : true,
  preMatchWindowInMinutes: 5, // time before the match in minutes when we are ready to rant
  preMatchWindowCloseTimeInMinutesBeforeMatch: 1, //time before the match in minutes when ranting closes
  postMatchWindowInHours: 2,  // time after then match in hours when we are ready to rant
  postMatchWindowCloseTimeInHoursAfterMatch: 12, // time after the match in hours when rant window closes
  GA : 'UA-68256772-1'// Google analytics tracking ID
};
<commit_msg>settings to production mode<commit_after>//app-specific sentence

module.exports = {
  debug : false,
  slackChannel : "#football",
  serverPort : 8080,
  pingInteralInMilliseconds : 1000 * 60, // server main loop interval.
  postBeforeTheMatch : true,
  postAfterTheMatch : true,
  preMatchWindowInMinutes: 5, // time before the match in minutes when we are ready to rant
  preMatchWindowCloseTimeInMinutesBeforeMatch: 1, //time before the match in minutes when ranting closes
  postMatchWindowInHours: 2,  // time after then match in hours when we are ready to rant
  postMatchWindowCloseTimeInHoursAfterMatch: 12, // time after the match in hours when rant window closes
  GA : 'UA-68256772-1'// Google analytics tracking ID
};
<|endoftext|>