<commit_before>const DEFAULT_LOCALE = 'zh-cn'; // TODO: change to en when w3help ready.
const W3HELP_LOCALES = {
  'en': true,
  'zh-cn': true
};

const STATUS_BASE = 'base';
const STATUS_ADVANCED = 'advanced';

var w3helpLocale = chrome.i18n.getMessage('@@ui_locale');

// TODO: '@@ui_locale' can be en_GB
if (w3helpLocale)
  w3helpLocale = w3helpLocale.toLowerCase().replace('_', '-');
if (!W3HELP_LOCALES.hasOwnProperty(w3helpLocale))
  w3helpLocale = DEFAULT_LOCALE;
w3helpLocale = 'http://www.w3help.org/' + w3helpLocale;

// ----
// Helper functions

function stringTemplate(param) {
  return param.str.replace(param.regexp || /\${([^{}]*)}/g,
      function(a,b) {
        var r = param.obj[b];
        return (typeof r == 'string') ? r : a ;
      })
}

function $(id) {
  return document.getElementById(id);
}

function bulidHTMLView(templateObject, element) {
  var HTMTemplate = element.innerHTML;
  element.innerHTML = stringTemplate({
    str: HTMTemplate,
    obj: templateObject
  });
}

function log(message) {
  var backgroundPage = chrome.extension.getBackgroundPage();
  backgroundPage.log('(popup.js) ' + message);
}

// ----
// Event handlers

// TODO: break the huge anonymous into pieces
document.addEventListener('DOMContentLoaded', function() {
  log('DOMContentLoaded begin');
  // HTMLView i18n
  bulidHTMLView({
    popup_cannotDetect: chrome.i18n.getMessage('popup_cannotDetect'),
    popup_loading: chrome.i18n.getMessage('popup_loading'),
    popup_baseDetection: chrome.i18n.getMessage('popup_baseDetection'),
    popup_advancedDetection: chrome.i18n.getMessage(
        'popup_advancedDetection'),
    popup_detecting: chrome.i18n.getMessage('popup_detecting'),
    popup_noProblem: chrome.i18n.getMessage('popup_noProblem'),
    popup_issueDescription: chrome.i18n.getMessage('popup_issueDescription'),
    popup_issueCount: chrome.i18n.getMessage('popup_issueCount'),
    popup_detectionStatus: chrome.i18n.getMessage('popup_detectionStatus'),
    popup_checkboxEffectTip: chrome.i18n.getMessage('popup_checkboxEffectTip')
  }, $('warp'));

  var $body = document.body;
  var $tab = $('tab');
  var $content = $('content');
  var $baseDetection = $('base_detection');
  var $advancedDetection = $('advanced_detection');

  var backgroundPage = chrome.extension.getBackgroundPage();

  function showBaseDetectionResult(data) {
    log('showBaseDetectionResult begin');
    $content.className = 'processing';
    var result = [];

    var KB001 = chrome.i18n.getMessage('bd_aboutRCAorKB') +
        '' +
        chrome.i18n.getMessage('KB001') + '';

    if (data.documentMode.pageDTD) {
      result.push('
' + chrome.i18n.getMessage('bd_hasDTD'));
      if (data.documentMode.strangeName ||
          data.documentMode.strangePublicId ||
          data.documentMode.strangeSystemId)
        result.push(chrome.i18n.getMessage('bd_strangeDTD'));
      if (data.documentMode.hasCommentBeforeDTD)
        result.push(chrome.i18n.getMessage('bd_makeIEBeInQuirksMode') +
            chrome.i18n.getMessage('bd_aboutRCAorKB') +
            '' +
            chrome.i18n.getMessage('HG8001') + '');
      if (data.documentMode.compatMode.IE ==
          data.documentMode.compatMode.WebKit) {
        var mode = (data.documentMode.compatMode.WebKit == 'S')
            ? '' + chrome.i18n.getMessage('bd_S') + ''
            : '' + chrome.i18n.getMessage('bd_Q') + '';
        result.push(chrome.i18n.getMessage('bd_sameDTD',
            ['' + chrome.i18n.getMessage('bd_same') + '', mode]));
        if (data.documentMode.compatMode.WebKit == 'Q') {
          result.push(chrome.i18n.getMessage('bd_inQuirksMode') +
              chrome.i18n.getMessage('bd_reducePossibility') + KB001);
        }
        result.push('
');
      } else {
        result.push('
' + chrome.i18n.getMessage('bd_differentDTD',
            ['' + chrome.i18n.getMessage('bd_different') +
            '']) + chrome.i18n.getMessage('bd_reducePossibility') +
            KB001 + '
');
      }
    } else {
      result.push('
' + chrome.i18n.getMessage('bd_noDTD',
          ['' + chrome.i18n.getMessage('bd_Q') + '']) +
          chrome.i18n.getMessage('bd_reducePossibility') + '
');
    }
    // Process data.DOM to HTML
    result.push('
' + chrome.i18n.getMessage('bd_nodeCount',
        ['' + data.DOM.count + '']) + '
');

    if (data.DOM.IECondComm.length)
      result.push('
' + chrome.i18n.getMessage('bd_IECondCommCount',
          ['' + data.DOM.IECondComm.length + '']) + '
');
    // Process data.STYLE to HTML
    result.push('
');
    if (data.STYLE.totalCount != 0) {
      result.push(chrome.i18n.getMessage('bd_styleTotalCount',
          ['' + data.STYLE.totalCount + '']));
      if (data.STYLE.noInHeadCount != 0) {
        result.push(chrome.i18n.getMessage('bd_styleNoInHeadCount',
            ['' + data.STYLE.noInHeadCount + '']));
      } else {
        result.push(chrome.i18n.getMessage('bd_noStyleNoInHeadCount'));
      }
    } else {
      result.push(chrome.i18n.getMessage('bd_noStyleTotalCount'));
    }
    result.push('
');
    // Process data.SCRIPT to HTML
    result.push('
');
    if (data.SCRIPT.totalCount != 0) {
      result.push(chrome.i18n.getMessage('bd_scriptTotalCount',
          ['' + data.SCRIPT.totalCount + '']));
      if (data.SCRIPT.noInHeadCount != 0) {
        result.push(chrome.i18n.getMessage('bd_scriptNoInHeadCount',
            ['' + data.SCRIPT.noInHeadCount + '']));
      } else {
        result.push(chrome.i18n.getMessage('bd_noScriptNoInHeadCount'));
      }
    } else {
      result.push(chrome.i18n.getMessage('bd_noScriptTotalCount'));
    }
    result.push('
');
    // Process data.HTMLBase.HTMLDeprecatedTag to HTML
    var deprecatedTag = [];
    for (var tag in data.HTMLBase.HTMLDeprecatedTag) {
      deprecatedTag.push(tag);
    }
    var deprecatedTagLength = deprecatedTag.length;
    if (deprecatedTagLength) {
      for (var i = 0; i < deprecatedTagLength; ++i) {
        result.push('
' + chrome.i18n.getMessage('bd_hasDeprecatedTag',
            ['' + deprecatedTag[i] + '']) + '
');
      }
    } else {
      result.push('
' +
          chrome.i18n.getMessage('bd_noDeprecatedTag') + '
');
    }
    // Process data.HTMLBase.HTMLDeprecatedAttribute to HTML
    var tagsHaveDeprecatedAttributes =
        Object.keys(data.HTMLBase.HTMLDeprecatedAttribute);
    var tagsLength = tagsHaveDeprecatedAttributes.length;
    if (tagsLength) {
      for (var i = 0; i < tagsLength; ++i) {
        var tagListString = [];
        var attrs =
            data.HTMLBase.HTMLDeprecatedAttribute[
              tagsHaveDeprecatedAttributes[i]
            ];
        for (var attr in attrs) {
          tagListString.push(attr);
        }
        result.push('
' +
            chrome.i18n.getMessage('bd_hasDeprecatedAttribute',
            ['' + tagsHaveDeprecatedAttributes[i] + '',
            '' + tagListString.join(' ') + '']) + '
');
      }
    } else {
      result.push('
' +
          chrome.i18n.getMessage('bd_noDeprecatedAttribute') + '
');
    }

    // Show result.
    $baseDetection.innerHTML = result.join('');
    $content.className = '';
  }

  /**
   * Change pop-up page's status.
   */
  function setStatus(status) {
    log('setStatus: ' + status);
    switch (status) {
      case 'disabled':
        $body.className = 'disabled';
        break;
      case 'loading':
        $body.className = 'loading';
        break;
      case STATUS_BASE:
        $body.className = 'base';
        break;
      case STATUS_ADVANCED:
        $body.className = 'advanced';
        break;
    }
  }

  var runBaseDetection = function() {};

  window.setDetectionFinishedMessage = function() {};
  window.updateSummary = function() {};
  window.updateDetectionResult = function() {};
  window.showNoProblemResult = function() {};
  window.restoreAnnotationCheck = function() {};

  // TODO: break the huge anonymous function into pieces
  chrome.tabs.getSelected(null, function(tab) {
    // Get current tab's id, many functions need it.
    var tabId = tab.id;

    // Advanced detection.
    window.advancedDetection = function() {
      var detectionResult = getDetectionResult(tabId);
      // If detection finished, then show result from cache.
      if (detectionResult.detected) {
        var problems = detectionResult.problems;
        if (Object.keys(problems).length == 0) {
          showNoProblemResult();
        } else {
          for (var typeId in problems) {
            var problem = problems[typeId];
            updateDetectionResult(tabId, typeId, problem);
            updateSummary(problem.severity);
          }
          setDetectionFinishedMessage();
          restoreAnnotationCheck();
        }
      } else {
        detectProblems();
      }
    }

    window.setDetectionFinishedMessage = function() {
      var detectionStatus = $('detectionStatus');
      detectionStatus.innerHTML = chrome.i18n.getMessage('detectionFinished');
    }

    /**
     * function updateSummary
     * @param {error | warning} type
     */
    window.updateSummary = function(type) {
      var detectionResult = getDetectionResult(tabId);
      var number = (type == 'warning')? 'totalWarnings' : 'totalErrors';
      var summary = chrome.i18n.getMessage(type + 'ProblemsSummary',
          [detectionResult[number]]);
      var allProblemsSummary = chrome.i18n.getMessage('allProblemsSummary',
          [detectionResult.totalProblems]);
      $(type + 'ProblemsSummary').innerHTML = summary;
      $('allProblemsSummary').innerHTML = allProblemsSummary;
    }

    window.updateDetectionResult = function(senderTabId, typeId, problem) {
      if (tabId != senderTabId)
        return;

      var detectionResult = getDetectionResult(tabId);
      var occurrencesNumber = problem.occurrencesNumber;

      var severity = problem.severity;
      $content.className = '';
      $('detectionResult').style.display = 'block';
      $(severity + 'Area').style.display = 'block';
      var table = $(severity + 'Problems').firstElementChild;
      var problemRow = $(typeId);
      if (problemRow) {
        problemRow.cells[2].innerText = occurrencesNumber;
      } else {
        var row = document.createElement('tr');
        row.setAttribute('id', typeId);
        table.appendChild(row);
        insertCell(row, problem.occurrencesNumber);
        insertCell(row, problem.description);
        var checkbox = insertCell(row, '<input type="checkbox" name="' +
            severity + '" class="issue">').firstElementChild;
        checkbox.addEventListener('click', toggleCheckProblem, false);
      }

      function insertCell(row, html) {
        var cell = row.insertCell(0);
        cell.innerHTML = html;
        return cell;
      }
    }

    window.showNoProblemResult = function() {
      $content.className = '';
      $('noProblemFoundInfo').style.display = 'block';
    }

    window.restoreAnnotationCheck = function() {
      var detectionResult = getDetectionResult(tabId);
      var annotatedReasons = detectionResult.annotatedReasons;
      Object.keys(annotatedReasons).forEach(function(reason) {
        $(reason).firstElementChild.firstElementChild.checked = true;
      });
      restoreCheckAll(document.getElementsByName('warning'), 'warning');
      restoreCheckAll(document.getElementsByName('error'), 'error');

      function restoreCheckAll(checkboxes, type) {
        for (var i = 0, length = checkboxes.length; i < length; ++i) {
          if (!checkboxes[i].checked)
            return;
        }
        $(type + 'CheckAll').checked = true;
      }
    }

    // use local variable: tabId
    runBaseDetection = function () {
      log('runBaseDetection begin');
      // TODO: check DetectionResult.baseResultHTML first
      chrome.tabs.sendRequest(tabId, {type: 'runBaseDetection'},
          showBaseDetectionResult);
    };

    var detectionResult = getDetectionResult(tabId);
    if (detectionResult.showAdvanced) {
      setStatus(STATUS_ADVANCED);
      advancedDetection();
    } else {
      setStatus(STATUS_BASE);
      runBaseDetection();
    }

    // Change the tab panel.
    log('$tab.addEventListener click');
    $tab.addEventListener('click', function(event) {
      var currentDetecionType = $body.className;
      var status = event.target.className;
      log('$tab click fired, status=' + status);
      if (status && currentDetecionType != status) {
        // TODO: modify this
        var detectionResult = getDetectionResult(tabId);
        detectionResult.showAdvanced = (status == 'advanced');
        if (detectionResult.showAdvanced) {
          setStatus(STATUS_ADVANCED);
          advancedDetection();
        } else {
          setStatus(STATUS_BASE);
          runBaseDetection();
        }
      }
    });

    function getDetectionResult(tabId) {
      return backgroundPage.getDetectionResult(tabId);
    }
    function detectProblems() {
      chrome.tabs.sendRequest(tabId, {type: 'DetectProblems'});
    }

    /**
     * Update annotation status
     * @param {Array} checkboxes
     */
    function updateAnnotatedStatus(checkboxes) {
      var detectionResult = getDetectionResult(tabId);
      var annotatedReasons = detectionResult.annotatedReasons;
      checkboxes.forEach(function(checkbox) {
        var reason = checkbox.parentNode.parentNode.id;
        if (annotatedReasons[reason] && !checkbox.checked)
          delete annotatedReasons[reason];
        else if (!annotatedReasons[reason] && checkbox.checked)
          annotatedReasons[reason] = true;
      });
      return Object.keys(annotatedReasons);
    }

    /**
     * Handle one checkbox click event.
     */
    function toggleCheckProblem() {
      var annotatedReasons = updateAnnotatedStatus([this]);
      backgroundPage.annotate(annotatedReasons);
      updateCheckAllStatus(this);
    }

    /**
     * Handle check all or check no checkbox click event.
     * @param {Element} checkAll
     * @param {String} type
     */
    function toggleCheckAllProblems(checkAll, type) {
      var checkboxes =
          Array.prototype.slice.call(document.getElementsByName(type));
      var checked = checkAll.checked;
      checkboxes.forEach(function(checkbox) {
        checkbox.checked = checked;
      });
      var problems = updateAnnotatedStatus(checkboxes);
      backgroundPage.annotate(problems);
    }

    function updateCheckAllStatus(checkbox) {
      var checkAll = $(checkbox.name + 'CheckAll');
      if (checkbox.checked) {
        var checkboxes = document.getElementsByName(checkbox.name);
        for (var i = 0, length = checkboxes.length; i < length; ++i) {
          if (!checkboxes[i].checked) {
            return;
          }
        }
        checkAll.checked = true;
      } else {
        checkAll.checked = false;
      }
    }

    $('errorCheckAll').addEventListener('click', function() {
      toggleCheckAllProblems(this, 'error');
    }, false);

    $('warningCheckAll').addEventListener('click', function() {
      toggleCheckAllProblems(this, 'warning');
    }, false);

  });
}, false);
<commit_msg>Refactor popup.js Split the mono function into pieces.<commit_after>
// TODO: put these status variables in background.html
var DEFAULT_LOCALE = 'zh-cn'; // TODO: change to en when w3help ready.
var W3HELP_LOCALES = {
  en: true,
  'zh-cn': true
};

var STATUS_BASE = 'base';
var STATUS_ADVANCED = 'advanced';

var w3helpLocale = chrome.i18n.getMessage('@@ui_locale');

// TODO: '@@ui_locale' can be en_GB
if (w3helpLocale)
  w3helpLocale = w3helpLocale.toLowerCase().replace('_', '-');
if (!W3HELP_LOCALES.hasOwnProperty(w3helpLocale))
  w3helpLocale = DEFAULT_LOCALE;
w3helpLocale = 'http://www.w3help.org/' + w3helpLocale;

// ----
// Helper functions

function stringTemplate(param) {
  return param.str.replace(param.regexp || /\${([^{}]*)}/g,
      function(a,b) {
        var r = param.obj[b];
        return (typeof r == 'string') ? r : a ;
      })
}

function $(id) {
  return document.getElementById(id);
}

function bulidHTMLView(templateObject, element) {
  var HTMTemplate = element.innerHTML;
  element.innerHTML = stringTemplate({
    str: HTMTemplate,
    obj: templateObject
  });
}

function log(message) {
  var backgroundPage = chrome.extension.getBackgroundPage();
  backgroundPage.log('(popup.js) ' + message);
}

// ----
// Event handlers

var selectedTabId;
var hasSelectedTabId = false;

var backgroundPage = chrome.extension.getBackgroundPage();

function windowLoad() {
  log('windowLoad begin');
  // HTMLView i18n
  bulidHTMLView({
    popup_cannotDetect: chrome.i18n.getMessage('popup_cannotDetect'),
    popup_loading: chrome.i18n.getMessage('popup_loading'),
    popup_baseDetection: chrome.i18n.getMessage('popup_baseDetection'),
    popup_advancedDetection: chrome.i18n.getMessage(
        'popup_advancedDetection'),
    popup_detecting: chrome.i18n.getMessage('popup_detecting'),
    popup_noProblem: chrome.i18n.getMessage('popup_noProblem'),
    popup_issueDescription: chrome.i18n.getMessage('popup_issueDescription'),
    popup_issueCount: chrome.i18n.getMessage('popup_issueCount'),
    popup_detectionStatus: chrome.i18n.getMessage('popup_detectionStatus'),
    popup_checkboxEffectTip: chrome.i18n.getMessage('popup_checkboxEffectTip')
  }, $('warp'));

  chrome.tabs.getSelected(null, onGetSelectedTab);
}

function showBaseDetectionResult(data) {
  log('showBaseDetectionResult begin');
  $('content').className = 'processing';

  var result = [];

  var KB001 = chrome.i18n.getMessage('bd_aboutRCAorKB') +
      '' +
      chrome.i18n.getMessage('KB001') + '';

  // Process data.documentMode
  if (data.documentMode.pageDTD) {
    result.push('
' + chrome.i18n.getMessage('bd_hasDTD'));
    if (data.documentMode.strangeName ||
        data.documentMode.strangePublicId ||
        data.documentMode.strangeSystemId)
      result.push(chrome.i18n.getMessage('bd_strangeDTD'));
    if (data.documentMode.hasCommentBeforeDTD)
      result.push(chrome.i18n.getMessage('bd_makeIEBeInQuirksMode') +
          chrome.i18n.getMessage('bd_aboutRCAorKB') +
          '' +
          chrome.i18n.getMessage('HG8001') + '');
    if (data.documentMode.compatMode.IE ==
        data.documentMode.compatMode.WebKit) {
      var mode = (data.documentMode.compatMode.WebKit == 'S')
          ? '' + chrome.i18n.getMessage('bd_S') + ''
          : '' + chrome.i18n.getMessage('bd_Q') + '';
      result.push(chrome.i18n.getMessage('bd_sameDTD',
          ['' + chrome.i18n.getMessage('bd_same') + '', mode]));
      if (data.documentMode.compatMode.WebKit == 'Q') {
        result.push(chrome.i18n.getMessage('bd_inQuirksMode') +
            chrome.i18n.getMessage('bd_reducePossibility') + KB001);
      }
      result.push('
');
    } else {
      result.push('
' + chrome.i18n.getMessage('bd_differentDTD',
          ['' + chrome.i18n.getMessage('bd_different') +
          '']) + chrome.i18n.getMessage('bd_reducePossibility') +
          KB001 + '
');
    }

  } else {
    result.push('
' + chrome.i18n.getMessage('bd_noDTD',
        ['' + chrome.i18n.getMessage('bd_Q') + '']) +
        chrome.i18n.getMessage('bd_reducePossibility') + '
');
  }

  // Process data.DOM to HTML
  result.push('
' + chrome.i18n.getMessage('bd_nodeCount',
      ['' + data.DOM.count + '']) + '
');
  if (data.DOM.IECondComm.length)
    result.push('
' + chrome.i18n.getMessage('bd_IECondCommCount',
        ['' + data.DOM.IECondComm.length + '']) + '
');

  // Process data.STYLE to HTML
  result.push('
');
  if (data.STYLE.totalCount != 0) {
    result.push(chrome.i18n.getMessage('bd_styleTotalCount',
        ['' + data.STYLE.totalCount + '']));
    if (data.STYLE.noInHeadCount != 0) {
      result.push(chrome.i18n.getMessage('bd_styleNoInHeadCount',
          ['' + data.STYLE.noInHeadCount + '']));
    } else {
      result.push(chrome.i18n.getMessage('bd_noStyleNoInHeadCount'));
    }
  } else {
    result.push(chrome.i18n.getMessage('bd_noStyleTotalCount'));
  }
  result.push('
');

  // Process data.SCRIPT to HTML
  result.push('
');
  if (data.SCRIPT.totalCount != 0) {
    result.push(chrome.i18n.getMessage('bd_scriptTotalCount',
        ['' + data.SCRIPT.totalCount + '']));
    if (data.SCRIPT.noInHeadCount != 0) {
      result.push(chrome.i18n.getMessage('bd_scriptNoInHeadCount',
          ['' + data.SCRIPT.noInHeadCount + '']));
    } else {
      result.push(chrome.i18n.getMessage('bd_noScriptNoInHeadCount'));
    }
  } else {
    result.push(chrome.i18n.getMessage('bd_noScriptTotalCount'));
  }
  result.push('
');

  // Process data.HTMLBase.HTMLDeprecatedTag to HTML
  var deprecatedTag = [];
  for (var tag in data.HTMLBase.HTMLDeprecatedTag) {
    deprecatedTag.push(tag);
  }
  var deprecatedTagLength = deprecatedTag.length;
  if (deprecatedTagLength) {
    for (var i = 0; i < deprecatedTagLength; ++i) {
      result.push('
' + chrome.i18n.getMessage('bd_hasDeprecatedTag',
          ['' + deprecatedTag[i] + '']) + '
');
    }
  } else {
    result.push('
' +
        chrome.i18n.getMessage('bd_noDeprecatedTag') + '
');
  }

  // Process data.HTMLBase.HTMLDeprecatedAttribute to HTML
  var tagsHaveDeprecatedAttributes =
      Object.keys(data.HTMLBase.HTMLDeprecatedAttribute);
  var tagsLength = tagsHaveDeprecatedAttributes.length;
  if (tagsLength) {
    for (var i = 0; i < tagsLength; ++i) {
      var tagListString = [];
      var attrs =
          data.HTMLBase.HTMLDeprecatedAttribute[
            tagsHaveDeprecatedAttributes[i]
          ];
      for (var attr in attrs) {
        tagListString.push(attr);
      }
      result.push('
' +
          chrome.i18n.getMessage('bd_hasDeprecatedAttribute',
          ['' + tagsHaveDeprecatedAttributes[i] + '',
          '' + tagListString.join(' ') + '']) + '
');
    }
  } else {
    result.push('
' +
        chrome.i18n.getMessage('bd_noDeprecatedAttribute') + '
');
  }

  // Show result.
  $('base_detection').innerHTML = result.join('');
  $('content').className = '';
}

/**
 * Change pop-up page's status.
 */
function setStatus(status) {
  log('setStatus: ' + status);
  var body = document.body;
  switch (status) {
    case 'disabled':
      body.className = 'disabled';
      break;
    case 'loading':
      body.className = 'loading';
      break;
    case STATUS_BASE:
      body.className = 'base';
      break;
    case STATUS_ADVANCED:
      body.className = 'advanced';
      break;
  }
}

function getDetectionResult(tabId) {
  return backgroundPage.getDetectionResult(tabId);
}

function detectProblems(tabId) {
  chrome.tabs.sendRequest(tabId, {type: 'DetectProblems'});
}

function runBaseDetection() {
  if (!hasSelectedTabId)
    return;

  log('runBaseDetection begin');
  chrome.tabs.sendRequest(selectedTabId, {type: 'runBaseDetection'},
      showBaseDetectionResult);
};

function advancedDetection() {
  if (!hasSelectedTabId)
    return;

  var detectionResult = getDetectionResult(selectedTabId);
  // If detection finished, then show result from cache.
  if (detectionResult.detected) {
    var problems = detectionResult.problems;
    if (Object.keys(problems).length == 0) {
      showNoProblemResult();
    } else {
      for (var typeId in problems) {
        var problem = problems[typeId];
        updateDetectionResult(selectedTabId, typeId, problem);
        updateSummary(problem.severity);
      }
      setDetectionFinishedMessage();
      restoreAnnotationCheck();
    }
  } else {
    detectProblems(selectedTabId);
  }
}

function setDetectionFinishedMessage() {
  $('detectionStatus').innerHTML = chrome.i18n.getMessage('detectionFinished');
}

/**
 * @param {error | warning} type
 */
function updateSummary(type) {
  if (!hasSelectedTabId) {
    // TODO: cache the request and use it when hasSelectedTabId
    return;
  }

  var detectionResult = getDetectionResult(selectedTabId);
  var number = (type == 'warning')? 'totalWarnings' : 'totalErrors';
  var summary = chrome.i18n.getMessage(type + 'ProblemsSummary',
      [detectionResult[number]]);
  var allProblemsSummary = chrome.i18n.getMessage('allProblemsSummary',
      [detectionResult.totalProblems]);
  $(type + 'ProblemsSummary').innerHTML = summary;
  $('allProblemsSummary').innerHTML = allProblemsSummary;
}

function updateDetectionResult(senderTabId, typeId, problem) {
  if (!hasSelectedTabId) {
    // TODO: cache the request and use it when hasSelectedTabId
    return;
  }

  if (selectedTabId != senderTabId)
    return;

  var detectionResult = getDetectionResult(selectedTabId);
  var occurrencesNumber = problem.occurrencesNumber;

  var severity = problem.severity;
  $('content').className = '';
  $('detectionResult').style.display = 'block';
  $(severity + 'Area').style.display = 'block';
  var table = $(severity + 'Problems').firstElementChild;
  var problemRow = $(typeId);
  if (problemRow) {
    problemRow.cells[2].innerText = occurrencesNumber;
  } else {
    var row = document.createElement('tr');
    row.setAttribute('id', typeId);
    table.appendChild(row);
    insertCell(row, problem.occurrencesNumber);
    insertCell(row, problem.description);
    var checkbox = insertCell(row, '<input type="checkbox" name="' +
        severity + '" class="issue">').firstElementChild;
    checkbox.addEventListener('click', toggleCheckProblem, false);
  }

  function insertCell(row, html) {
    var cell = row.insertCell(0);
    cell.innerHTML = html;
    return cell;
  }
}

function showNoProblemResult() {
  $('content').className = '';
  $('noProblemFoundInfo').style.display = 'block';
}

function restoreAnnotationCheck() {
  if (!hasSelectedTabId)
    return;

  var detectionResult = getDetectionResult(selectedTabId);
  var annotatedReasons = detectionResult.annotatedReasons;
  Object.keys(annotatedReasons).forEach(function(reason) {
    $(reason).firstElementChild.firstElementChild.checked = true;
  });
  restoreCheckAll(document.getElementsByName('warning'), 'warning');
  restoreCheckAll(document.getElementsByName('error'), 'error');

  function restoreCheckAll(checkboxes, type) {
    for (var i = 0, length = checkboxes.length; i < length; ++i) {
      if (!checkboxes[i].checked)
        return;
    }
    $(type + 'CheckAll').checked = true;
  }
}

function onGetSelectedTab(tab) {
  selectedTabId = tab.id;
  hasSelectedTabId = true;

  var detectionResult = getDetectionResult(selectedTabId);
  if (detectionResult.showAdvanced) {
    setStatus(STATUS_ADVANCED);
    advancedDetection();
  } else {
    setStatus(STATUS_BASE);
    runBaseDetection();
  }

  // Change the tab panel.
  log('$tab.addEventListener click');
  $('tab').addEventListener('click', function(event) {
    var currentDetecionType = document.body.className;
    var status = event.target.className;
    log('$tab click fired, status=' + status);
    if (status && currentDetecionType != status) {
      // TODO: modify this
      var detectionResult = getDetectionResult(selectedTabId);
      detectionResult.showAdvanced = (status == 'advanced');
      if (detectionResult.showAdvanced) {
        setStatus(STATUS_ADVANCED);
        advancedDetection();
      } else {
        setStatus(STATUS_BASE);
        runBaseDetection();
      }
    }
  });

  $('errorCheckAll').addEventListener('click', function() {
    toggleCheckAllProblems(this, 'error');
  }, false);

  $('warningCheckAll').addEventListener('click', function() {
    toggleCheckAllProblems(this, 'warning');
  }, false);
}

/**
 * Update annotation status
 * @param {Array} checkboxes
 */
function updateAnnotatedStatus(checkboxes) {
  if (!hasSelectedTabId)
    return;
  var detectionResult = getDetectionResult(selectedTabId);
  var annotatedReasons = detectionResult.annotatedReasons;
  checkboxes.forEach(function(checkbox) {
    var reason = checkbox.parentNode.parentNode.id;
    if (annotatedReasons[reason] && !checkbox.checked)
      delete annotatedReasons[reason];
    else if (!annotatedReasons[reason] && checkbox.checked)
      annotatedReasons[reason] = true;
  });
  return Object.keys(annotatedReasons);
}

/**
 * Handle one checkbox click event.
 */
function toggleCheckProblem() {
  var checkbox = this;
  var annotatedReasons = updateAnnotatedStatus([checkbox]);
  backgroundPage.annotate(annotatedReasons);
  updateCheckAllStatus(checkbox);
}

/**
 * Handle check all or check no checkbox click event.
 * @param {Element} checkAll
 * @param {String} type
 */
function toggleCheckAllProblems(checkAll, type) {
  var checkboxes =
      Array.prototype.slice.call(document.getElementsByName(type));
  var checked = checkAll.checked;
  checkboxes.forEach(function(checkbox) {
    checkbox.checked = checked;
  });
  var problems = updateAnnotatedStatus(checkboxes);
  backgroundPage.annotate(problems);
}

function updateCheckAllStatus(checkbox) {
  var checkAll = $(checkbox.name + 'CheckAll');
  if (checkbox.checked) {
    var checkboxes = document.getElementsByName(checkbox.name);
    for (var i = 0, length = checkboxes.length; i < length; ++i) {
      if (!checkboxes[i].checked) {
        return;
      }
    }
    checkAll.checked = true;
  } else {
    checkAll.checked = false;
  }
}

window.addEventListener('load', windowLoad, false);
<|endoftext|>


<commit_before>const net = require('net')
const Koa = require('koa')
const koaRouter = require('koa-router')
const convert = require('koa-convert')
const body = require('koa-better-body')
const { Logger, transports } = require('winston')
const fs = require('fs')
const path = require('path')
const moment = require('moment')

/**
 * logger
 */
const LOGS_DIR = path.resolve(__dirname, '..', 'logs')
if (!fs.existsSync(LOGS_DIR)) {
  fs.mkdirSync(LOGS_DIR)
}

function dateFormatter () {
  return moment().format('MM/DD h:mm:ss')
}

const logger = new Logger({
  transports: [
    new transports.File({
      timestamp: dateFormatter,
      name: 'file.info',
      filename: path.resolve(LOGS_DIR, 'info'),
      level: 'info'
    }),
    new transports.File({
      timestamp: dateFormatter,
      name: 'file.error',
      filename: path.resolve(LOGS_DIR, 'error'),
      level: 'error',
      handleExceptions: true
    })
  ],
  exitOnError: false
})

/**
 * tcp 长连接，用于转发 pr 请求
 */
const server= net.createServer()
let sockets = []

server.on('connection', socket => {
  sockets.push(socket)
  socket.on('close', hadError => {
    sockets = sockets.filter(s => s !== socket)
    if (hadError) logger.error('socket close error!')
  })
})

server.on('error', error => {
  logger.error(error.message)
})

server.listen(4000, () => {
  console.log('tcp server is listening on port 4000')
})

// pr 代理服务器
const app = new Koa()
const router = koaRouter()
const END_SYMBOL = '$$$$'

router.post('/hooks', async (ctx, next) => {
  const event = ctx.request.headers['x-github-event']
  const payload = Object.assign({ 'x-github-event': event }, ctx.request.fields)
  const { sender, repository } = payload
  const message = `${sender.login} has ${event} on ${repository.name}`
  logger.info(message)
  let socket = sockets[0]
  let i = 0
  while (socket) {
    // 如果连接已关闭，删除 sockets 数组中对应的项
    if (socket.destroyed) {
      sockets.splice(i, 1)
    } else {
      socket.write(JSON.stringify(payload))
      socket.write(END_SYMBOL)
      i++
    }
    socket = sockets[i]
  }
  ctx.body = message
})

app.use(convert(body()))
app.use(router.routes())

app.listen(3000, () => {
  console.log('pr server is listening on port 3000')
})
<commit_msg>fix: miss .log suffix<commit_after>const net = require('net')
const Koa = require('koa')
const koaRouter = require('koa-router')
const convert = require('koa-convert')
const body = require('koa-better-body')
const { Logger, transports } = require('winston')
const fs = require('fs')
const path = require('path')
const moment = require('moment')

/**
 * logger
 */
const LOGS_DIR = path.resolve(__dirname, '..', 'logs')
if (!fs.existsSync(LOGS_DIR)) {
  fs.mkdirSync(LOGS_DIR)
}

function dateFormatter () {
  return moment().format('MM/DD h:mm:ss')
}

const logger = new Logger({
  transports: [
    new transports.File({
      timestamp: dateFormatter,
      name: 'file.info',
      filename: path.resolve(LOGS_DIR, 'info.log'),
      level: 'info'
    }),
    new transports.File({
      timestamp: dateFormatter,
      name: 'file.error',
      filename: path.resolve(LOGS_DIR, 'error.log'),
      level: 'error',
      handleExceptions: true
    })
  ],
  exitOnError: false
})

/**
 * tcp 长连接，用于转发 pr 请求
 */
const server= net.createServer()
let sockets = []

server.on('connection', socket => {
  sockets.push(socket)
  socket.on('close', hadError => {
    sockets = sockets.filter(s => s !== socket)
    if (hadError) logger.error('socket close error!')
  })
})

server.on('error', error => {
  logger.error(error.message)
})

server.listen(4000, () => {
  console.log('tcp server is listening on port 4000')
})

// pr 代理服务器
const app = new Koa()
const router = koaRouter()
const END_SYMBOL = '$$$$'

router.post('/hooks', async (ctx, next) => {
  const event = ctx.request.headers['x-github-event']
  const payload = Object.assign({ 'x-github-event': event }, ctx.request.fields)
  const { sender, repository } = payload
  const message = `${sender.login} has ${event} on ${repository.name}`
  logger.info(message)
  let socket = sockets[0]
  let i = 0
  while (socket) {
    // 如果连接已关闭，删除 sockets 数组中对应的项
    if (socket.destroyed) {
      sockets.splice(i, 1)
    } else {
      socket.write(JSON.stringify(payload))
      socket.write(END_SYMBOL)
      i++
    }
    socket = sockets[i]
  }
  ctx.body = message
})

app.use(convert(body()))
app.use(router.routes())

app.listen(3000, () => {
  console.log('pr server is listening on port 3000')
})
<|endoftext|>


<commit_before>/*
 * Qajax.js - Simple Promise ajax library based on Q
 */
/*jslint newcap: true */
(function (definition) {
  var Q;
  if (typeof exports === "object") {
    Q = require("q");
    module.exports = definition(Q);
  }
  else if (typeof define === 'function' && define.amd){
    define(['q'], definition);
  }
  else {
    Q = window.Q;
    window.Qajax = definition(Q);
  }
})(function (Q) {
  "use strict";

  // Qajax
  // ===
  // *Perform an asynchronous HTTP request (ajax).*
  //
  // Signatures
  // ---
  //
  // * `Qajax(url: String) => Promise[XHR]`
  // * `Qajax(options: Object) => Promise[XHR]`
  // * `Qajax(url: String, options: Object) => Promise[XHR]`
  //
  // Parameters
  // ---
  // `settings` **(object)** or **(string)** URL:
  //
  // - `url` **(string)**: the URL of the resource
  // - `method` **(string)** *optional*: the http method to use *(default: GET)*.
  // - `timeout` **(number)** *optional*: the time in ms to reject the XHR if not terminated.
  // - `data` **(any)** *optional*: the data to send.
  // - headers **(object)** *optional*: a map of headers to use for the XHR.
  // - `responseType` **(string)** *optional*: a responseType to set the XHR with.
  // - `cancellation` **(Promise)** *optional*: provide a "cancellation" promise which if fulfilled will cancel the current XHR.
  // - **Or any other parameter from the Qajax.defaults**.
  //
  // Result
  // ---
  // returns a **Promise of XHR**, whatever the status code is.
  //
  var Qajax = function () {
    var args = arguments, settings;
    /* Validating arguments */
    if (!args.length) {
      throw new Error("Qajax: settings are required");
    }
    if (typeof args[0] === "string") {
      settings = (typeof args[1] === 'object' && args[1]) || {};
      settings.url = args[0];
    }
    else if (typeof args[0] === "object"){
      settings = args[0];
    }
    else {
      throw new Error("Qajax: settings must be an object");
    }
    if (!settings.url) {
      throw new Error("Qajax: settings.url is required");
    }
    if ("cancellation" in settings && !Q.isPromiseAlike(settings.cancellation)) {
      throw new Error("cancellation must be a Promise.");
    }

    var xhr = new XMLHttpRequest(),
      cancellation = settings.cancellation || Q.defer().promise, // default is a never ending promise
      method = getOrElse("method", settings),
      base = getOrElse("base", settings),
      url = settings.url,
      data = settings.data,
      responseType = settings.responseType,
      params = settings.params || {},
      xhrResult = Q.defer(),
      timeout = getOrElse("timeout", settings),
      headers = extend1({}, getOrElse("headers", settings)),
      cacheParam = getOrElse("cache", settings);

    if (cacheParam) {
      params[cacheParam === true ? "_" : cacheParam] = (new Date()).getTime();
    }

    // Let's build the url based on the configuration
    // * Prepend the base if one
    if (base) {
      url = base + url;
    }

    // * Serialize and append the params if any
    var queryParams = serializeQuery(params);
    if (queryParams) {
      url = url + (hasQuery(url) ? "?" : "&") + queryParams;
    }

    // if data is a Javascript object, JSON is used
    if (data !== null && typeof data === "object") {
      if (!(CONTENT_TYPE in headers)) {
        headers[CONTENT_TYPE] = "application/json";
      }
      data = JSON.stringify(data);
    }

    return Q.fcall(function () { // Protect from any exception

      // Bind the XHR finished callback
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          try {
            log(method + " " + url + " => " + xhr.status);
            if (xhr.status) {
              xhrResult.resolve(xhr);
            } else {
              xhrResult.reject(xhr); // this case occured mainly when xhr.abort() has been called.
            }
          } catch (e) {
            xhrResult.reject(xhr); // IE could throw an error
          }
        }
      };

      xhr.onprogress = function (progress) {
          xhrResult.notify(progress);
      };

      // Open the XHR
      xhr.open(method, url, true);

      if (responseType) {
        xhr.responseType = responseType;
      }

      // Add headers
      for (var h in headers) {
        if (headers.hasOwnProperty(h)) {
          xhr.setRequestHeader(h, headers[h]);
        }
      }

      // Send the XHR
      if (data !== undefined && data !== null) {
        xhr.send(data);
      } else {
        xhr.send();
      }

      cancellation.fin(function () {
          if (!xhrResult.promise.isFulfilled()) {
              log("Qajax cancellation reached.");
              xhr.abort();
          }
      });

      // If no timeout, just return the promise
      if (!timeout) {
        return xhrResult.promise;
      }
      // Else, either the xhr promise or the timeout is reached
      else {
        return xhrResult.promise.timeout(timeout).fail(function (errorOrXHR) {
          // If timeout has reached (Error is triggered)
          if (errorOrXHR instanceof Error) {
            log("Qajax request delay reach in " + method + " " + url);
            xhr.abort(); // Abort this XHR so it can reject xhrResult
          }
          // Make the promise fail again.
          throw xhr;
        });
      }
    });
  };

  /*
   * DEPRECATED. Use Qajax.defaults.timeout instead.
   * Default XMLHttpRequest timeout.
   */
  Qajax.TIMEOUT = undefined;

  // Qajax Defaults
  // ===

  // Defaults settings of Qajax.
  // Feel free to override any of them.

  Qajax.defaults = {
    // `logs` **(boolean)**: Flag to enable logs
    logs: false,
    // `timeout` **(number)**: The timeout, in ms, to apply to the request.
    // If no response after that delay, the promise will be failed
    timeout: 60000,
    // `cache` **(boolean | string)**: cache flag to enable a hack appending the current timestamp
    // to your requests to prevent IE from caching them and always returning the same result.
    // If "true", will set the param with the name "_"
    // If a string, will use it as the param name
    cache: window.ActiveXObject || "ActiveXObject" in window,
    // `method` **(string)**: The default HTTP method to apply when calling Qajax(url)
    method: "GET",
    // `header` **(object)**: The default HTTP headers to apply to your requests
    headers: {},
    // `base` **(string)**: The base of all urls of your requests. Will be prepend to all urls.
    base: ""
  };

  // Qajax.filterStatus
  // ===
  // *Filter an XHR to a given status, to consider only valid status to be success.*
  //
  // Parameters
  // ---
  // `validStatus` **(number or function)**: either a http code (like 200) or a predicate function (statusCode).
  //
  // Result
  // ---
  // Returns a **(function)** returning a Promise of XHR considered successful (according to validStatus)
  //
  // Usage example
  // ---
  // ```javascript
  // Qajax(settings).then(Qajax.filterStatus(200))
  //
  // Qajax(settings).then(
  //    Qajax.filterStatus(function(s){ return s == 200 })
  // )
  // ```
  //
  Qajax.filterStatus = function (validStatus) {
    var check, typ;
    typ = typeof validStatus;
    if (typ === "function") {
      check = validStatus;
    } else if (typ === "number") {
      check = function (s) {
        return s === validStatus;
      };
    } else {
      throw "validStatus type " + typ + " unsupported";
    }
    return function (xhr) {
      var status = 0;
      try {
        status = xhr.status; // IE can fail to access status
      } catch (e) {
        log("Qajax: failed to read xhr.status");
      }
      if (status === 1223) {
        status = 204; // 204 No Content IE bug
      }
      return check(status) ? Q.resolve(xhr) : Q.reject(xhr);
    };
  };

  // Qajax.filterSuccess
  // ===
  // *Filter all Success status code case.*
  // A good example of `Qajax.filterStatus` implementation.
  //
  Qajax.filterSuccess = Qajax.filterStatus(function (s) {
    return (s >= 200 && s < 300) || s === 304;
  });

  // Qajax.toJSON
  // ===
  // *Extract a JSON from a XHR.*
  //
  // Parameters
  // ---
  // `xhr` **(XMLHttpRequest)**: the XHR.
  //
  // Result
  // ---
  // A **(promise)** of the parsed JSON.
  //
  // Usage example
  // ---
  // ```
  // Qajax(settings).then(Qajax.toJSON)
  // ```
  //
  Qajax.toJSON = function (xhr) {
    return Q.fcall(function () {
      return JSON.parse(xhr.responseText);
    });
  };

  // Qajax.getJSON
  // ===
  // *Get a JSON from an URL - shortcut to Qajax.*
  //
  // Parameters
  // ---
  // `url` **(string)**: the ressource to fetch.
  //
  // Result
  // ---
  // Returns a **(promise)** of a JS Object.
  //
  Qajax.getJSON = function (url) {
    return Qajax({ url: url, method: "GET" })
      .then(Qajax.filterSuccess)
      .then(Qajax.toJSON);
  };

  // Qajax.serialize
  // ===
  // *Make a query string from a JS Object.*
  //
  // Parameters
  // ---
  // `paramsObj` **(object)** the params to serialize.
  //
  // Result
  // ---
  // Returns the serialized query **(string)**.
  //
  Qajax.serialize = serializeQuery;

  // Private util functions
  // ===

  // Get a param from the current settings of the request,
  // if missing, try to return the "else" argument,
  // if also missing, return it from the "defaults"
  function getOrElse(paramName, settings) {
    return paramName in settings ? settings[paramName] : Qajax.defaults[paramName];
  }

  function extend1 (extendee, object) {
    for (var key in object) {
      if (object.hasOwnProperty(key)) {
        extendee[key] = object[key];
      }
    }
    return extendee;
  }

  // Serialize a map of properties (as a JavaScript object) to a query string
  function serializeQuery(paramsObj) {
    var k, params = [];
    for (k in paramsObj) {
      if (paramsObj.hasOwnProperty(k)) {
        params.push(encodeURIComponent(k) + "=" + encodeURIComponent(paramsObj[k]));
      }
    }
    return params.join("&");
  }

  // Test if a given url has already a query string
  function hasQuery(url) {
    return (url.indexOf("?") === -1);
  }

  // safe log function
  function log (msg) {
    if (Qajax.defaults.logs && window.console) {
      console.log(msg);
    }
  }

  var CONTENT_TYPE = "Content-Type";

  return Qajax;

});
<commit_msg>Cast cache as a boolean<commit_after>/*
 * Qajax.js - Simple Promise ajax library based on Q
 */
/*jslint newcap: true */
(function (definition) {
  var Q;
  if (typeof exports === "object") {
    Q = require("q");
    module.exports = definition(Q);
  }
  else if (typeof define === 'function' && define.amd){
    define(['q'], definition);
  }
  else {
    Q = window.Q;
    window.Qajax = definition(Q);
  }
})(function (Q) {
  "use strict";

  // Qajax
  // ===
  // *Perform an asynchronous HTTP request (ajax).*
  //
  // Signatures
  // ---
  //
  // * `Qajax(url: String) => Promise[XHR]`
  // * `Qajax(options: Object) => Promise[XHR]`
  // * `Qajax(url: String, options: Object) => Promise[XHR]`
  //
  // Parameters
  // ---
  // `settings` **(object)** or **(string)** URL:
  //
  // - `url` **(string)**: the URL of the resource
  // - `method` **(string)** *optional*: the http method to use *(default: GET)*.
  // - `timeout` **(number)** *optional*: the time in ms to reject the XHR if not terminated.
  // - `data` **(any)** *optional*: the data to send.
  // - headers **(object)** *optional*: a map of headers to use for the XHR.
  // - `responseType` **(string)** *optional*: a responseType to set the XHR with.
  // - `cancellation` **(Promise)** *optional*: provide a "cancellation" promise which if fulfilled will cancel the current XHR.
  // - **Or any other parameter from the Qajax.defaults**.
  //
  // Result
  // ---
  // returns a **Promise of XHR**, whatever the status code is.
  //
  var Qajax = function () {
    var args = arguments, settings;
    /* Validating arguments */
    if (!args.length) {
      throw new Error("Qajax: settings are required");
    }
    if (typeof args[0] === "string") {
      settings = (typeof args[1] === 'object' && args[1]) || {};
      settings.url = args[0];
    }
    else if (typeof args[0] === "object"){
      settings = args[0];
    }
    else {
      throw new Error("Qajax: settings must be an object");
    }
    if (!settings.url) {
      throw new Error("Qajax: settings.url is required");
    }
    if ("cancellation" in settings && !Q.isPromiseAlike(settings.cancellation)) {
      throw new Error("cancellation must be a Promise.");
    }

    var xhr = new XMLHttpRequest(),
      cancellation = settings.cancellation || Q.defer().promise, // default is a never ending promise
      method = getOrElse("method", settings),
      base = getOrElse("base", settings),
      url = settings.url,
      data = settings.data,
      responseType = settings.responseType,
      params = settings.params || {},
      xhrResult = Q.defer(),
      timeout = getOrElse("timeout", settings),
      headers = extend1({}, getOrElse("headers", settings)),
      cacheParam = getOrElse("cache", settings);

    if (cacheParam) {
      params[cacheParam === true ? "_" : cacheParam] = (new Date()).getTime();
    }

    // Let's build the url based on the configuration
    // * Prepend the base if one
    if (base) {
      url = base + url;
    }

    // * Serialize and append the params if any
    var queryParams = serializeQuery(params);
    if (queryParams) {
      url = url + (hasQuery(url) ? "?" : "&") + queryParams;
    }

    // if data is a Javascript object, JSON is used
    if (data !== null && typeof data === "object") {
      if (!(CONTENT_TYPE in headers)) {
        headers[CONTENT_TYPE] = "application/json";
      }
      data = JSON.stringify(data);
    }

    return Q.fcall(function () { // Protect from any exception

      // Bind the XHR finished callback
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          try {
            log(method + " " + url + " => " + xhr.status);
            if (xhr.status) {
              xhrResult.resolve(xhr);
            } else {
              xhrResult.reject(xhr); // this case occured mainly when xhr.abort() has been called.
            }
          } catch (e) {
            xhrResult.reject(xhr); // IE could throw an error
          }
        }
      };

      xhr.onprogress = function (progress) {
          xhrResult.notify(progress);
      };

      // Open the XHR
      xhr.open(method, url, true);

      if (responseType) {
        xhr.responseType = responseType;
      }

      // Add headers
      for (var h in headers) {
        if (headers.hasOwnProperty(h)) {
          xhr.setRequestHeader(h, headers[h]);
        }
      }

      // Send the XHR
      if (data !== undefined && data !== null) {
        xhr.send(data);
      } else {
        xhr.send();
      }

      cancellation.fin(function () {
          if (!xhrResult.promise.isFulfilled()) {
              log("Qajax cancellation reached.");
              xhr.abort();
          }
      });

      // If no timeout, just return the promise
      if (!timeout) {
        return xhrResult.promise;
      }
      // Else, either the xhr promise or the timeout is reached
      else {
        return xhrResult.promise.timeout(timeout).fail(function (errorOrXHR) {
          // If timeout has reached (Error is triggered)
          if (errorOrXHR instanceof Error) {
            log("Qajax request delay reach in " + method + " " + url);
            xhr.abort(); // Abort this XHR so it can reject xhrResult
          }
          // Make the promise fail again.
          throw xhr;
        });
      }
    });
  };

  /*
   * DEPRECATED. Use Qajax.defaults.timeout instead.
   * Default XMLHttpRequest timeout.
   */
  Qajax.TIMEOUT = undefined;

  // Qajax Defaults
  // ===

  // Defaults settings of Qajax.
  // Feel free to override any of them.

  Qajax.defaults = {
    // `logs` **(boolean)**: Flag to enable logs
    logs: false,
    // `timeout` **(number)**: The timeout, in ms, to apply to the request.
    // If no response after that delay, the promise will be failed
    timeout: 60000,
    // `cache` **(boolean | string)**: cache flag to enable a hack appending the current timestamp
    // to your requests to prevent IE from caching them and always returning the same result.
    // If "true", will set the param with the name "_"
    // If a string, will use it as the param name
    cache: !!(window.ActiveXObject || "ActiveXObject" in window),
    // `method` **(string)**: The default HTTP method to apply when calling Qajax(url)
    method: "GET",
    // `header` **(object)**: The default HTTP headers to apply to your requests
    headers: {},
    // `base` **(string)**: The base of all urls of your requests. Will be prepend to all urls.
    base: ""
  };

  // Qajax.filterStatus
  // ===
  // *Filter an XHR to a given status, to consider only valid status to be success.*
  //
  // Parameters
  // ---
  // `validStatus` **(number or function)**: either a http code (like 200) or a predicate function (statusCode).
  //
  // Result
  // ---
  // Returns a **(function)** returning a Promise of XHR considered successful (according to validStatus)
  //
  // Usage example
  // ---
  // ```javascript
  // Qajax(settings).then(Qajax.filterStatus(200))
  //
  // Qajax(settings).then(
  //    Qajax.filterStatus(function(s){ return s == 200 })
  // )
  // ```
  //
  Qajax.filterStatus = function (validStatus) {
    var check, typ;
    typ = typeof validStatus;
    if (typ === "function") {
      check = validStatus;
    } else if (typ === "number") {
      check = function (s) {
        return s === validStatus;
      };
    } else {
      throw "validStatus type " + typ + " unsupported";
    }
    return function (xhr) {
      var status = 0;
      try {
        status = xhr.status; // IE can fail to access status
      } catch (e) {
        log("Qajax: failed to read xhr.status");
      }
      if (status === 1223) {
        status = 204; // 204 No Content IE bug
      }
      return check(status) ? Q.resolve(xhr) : Q.reject(xhr);
    };
  };

  // Qajax.filterSuccess
  // ===
  // *Filter all Success status code case.*
  // A good example of `Qajax.filterStatus` implementation.
  //
  Qajax.filterSuccess = Qajax.filterStatus(function (s) {
    return (s >= 200 && s < 300) || s === 304;
  });

  // Qajax.toJSON
  // ===
  // *Extract a JSON from a XHR.*
  //
  // Parameters
  // ---
  // `xhr` **(XMLHttpRequest)**: the XHR.
  //
  // Result
  // ---
  // A **(promise)** of the parsed JSON.
  //
  // Usage example
  // ---
  // ```
  // Qajax(settings).then(Qajax.toJSON)
  // ```
  //
  Qajax.toJSON = function (xhr) {
    return Q.fcall(function () {
      return JSON.parse(xhr.responseText);
    });
  };

  // Qajax.getJSON
  // ===
  // *Get a JSON from an URL - shortcut to Qajax.*
  //
  // Parameters
  // ---
  // `url` **(string)**: the ressource to fetch.
  //
  // Result
  // ---
  // Returns a **(promise)** of a JS Object.
  //
  Qajax.getJSON = function (url) {
    return Qajax({ url: url, method: "GET" })
      .then(Qajax.filterSuccess)
      .then(Qajax.toJSON);
  };

  // Qajax.serialize
  // ===
  // *Make a query string from a JS Object.*
  //
  // Parameters
  // ---
  // `paramsObj` **(object)** the params to serialize.
  //
  // Result
  // ---
  // Returns the serialized query **(string)**.
  //
  Qajax.serialize = serializeQuery;

  // Private util functions
  // ===

  // Get a param from the current settings of the request,
  // if missing, try to return the "else" argument,
  // if also missing, return it from the "defaults"
  function getOrElse(paramName, settings) {
    return paramName in settings ? settings[paramName] : Qajax.defaults[paramName];
  }

  function extend1 (extendee, object) {
    for (var key in object) {
      if (object.hasOwnProperty(key)) {
        extendee[key] = object[key];
      }
    }
    return extendee;
  }

  // Serialize a map of properties (as a JavaScript object) to a query string
  function serializeQuery(paramsObj) {
    var k, params = [];
    for (k in paramsObj) {
      if (paramsObj.hasOwnProperty(k)) {
        params.push(encodeURIComponent(k) + "=" + encodeURIComponent(paramsObj[k]));
      }
    }
    return params.join("&");
  }

  // Test if a given url has already a query string
  function hasQuery(url) {
    return (url.indexOf("?") === -1);
  }

  // safe log function
  function log (msg) {
    if (Qajax.defaults.logs && window.console) {
      console.log(msg);
    }
  }

  var CONTENT_TYPE = "Content-Type";

  return Qajax;

});
<|endoftext|>


<commit_before>import React from 'react'
import styles from './our-styles.less'

class TextSizeButton extends React.Component {
	onClick() {
		function changeText(type) {
			let stylesheet = document.getElementById('styles')
			let currentSize = document.getElementByTagName('RoundButton').fontSize
			switch (type) {
			case 'add':
				let newSize = currentSize + 20
				stylesheet.deleteRule(0)
				stylesheet.insertRule('* {font-size:' + newSize + '%;}', 0)
				break
			case 'subtract':
				let newSize1 = currentSize - 20
				stylesheet.deleteRule(0)
				stylesheet.insertRule('* {font-size:' + newSize1 + '%;}', 0)
				break
			default:
				stylesheet.deleteRule(0)
				stylesheet.insertRule('* {font-size: 100%;}', 0)
			}
		}
	}
	render() {
		return (
			<button onClick={this.onClick(this.props.type)}>{this.props.children}</button>
		)
	}
}

export default TextSizeButton<commit_msg>Deleted Text Size Button component since we no longer use it.<commit_after><|endoftext|>


<commit_before>import isRegExp from "lodash/lang/isRegExp";
import isString from "lodash/lang/isString";
import isObject from "lodash/lang/isObject";
import isEqual from "lodash/internal/baseIsEqual";

import * as utils from "./utils";

function isEqlRegex (objA, objB) {
  return isRegExp(objA) &&
    isRegExp(objB) &&
    objA.source === objB.source &&
    objA.global === objB.global &&
    objA.ignoreCase === objB.ignoreCase &&
    objA.multiline === objB.multiline;
}

const operators = {
  $eq (deepValue, referenceValue) {
    return isEqlRegex(deepValue, referenceValue) || isEqual(deepValue, referenceValue);
  },
  $gt (deepValue, referenceValue) {
    return deepValue > referenceValue;
  },
  $lt (deepValue, referenceValue) {
    return deepValue < referenceValue;
  },
  $gte (deepValue, referenceValue) {
    return deepValue >= referenceValue;
  },
  $lte (deepValue, referenceValue) {
    return deepValue <= referenceValue;
  },
  $neq (deepValue, referenceValue) {
    return deepValue !== referenceValue;
  },
  $contains (deepValue, referenceValue) {
    return isString(deepValue) &&
      isString(referenceValue) &&
      deepValue.indexOf(referenceValue) > 0;
  },
  $regex (deepValue, regex) {
    return regex.test(deepValue);
  },
  $fn (deepValue, testFn) {
    let isMatch = false;
    try {
      isMatch = testFn(deepValue);
    } catch (e) {
      isMatch = false;
    }
    return isMatch;
  },
  $fnUnsafe (deepValue, testFn) {
    return testFn(deepValue);
  }
};

function isComparisonObj (comparisonObj) {
  return Object.keys(comparisonObj)
    .map(operator => operator in operators)
    .reduce((result, opOkay) => result && opOkay, true);
}

function constructCondition (queryAspect) {
  if (isObject(queryAspect) && isComparisonObj(queryAspect)) {
    const subconditions = Object.keys(queryAspect).map(operator => operators[operator]);
    return val => utils.all(subconditions, subcondition => subcondition(val));
  } else if (isRegExp(queryAspect)) {
    return operators.$regex;
  }
  return operators.$eq;
}

export default function query (queryLiteral) {
  const conditions = Object.keys(queryLiteral).map(keypath => {
    const keypathArray = utils.getKeypathArray(keypath);
    const condition = constructCondition(queryLiteral[keypath]);

    return obj => {
      const deepValue = utils.getDeepValue(obj, keypathArray);
      return condition(deepValue);
    };
  });

  return obj => utils.all(conditions, condition => condition(obj));
}
<commit_msg>Simplify condition construction.<commit_after>import isRegExp from "lodash/lang/isRegExp";
import isString from "lodash/lang/isString";
import isObject from "lodash/lang/isObject";
import isEqual from "lodash/internal/baseIsEqual";

import * as utils from "./utils";

function isEqlRegex (objA, objB) {
  return isRegExp(objA) &&
    isRegExp(objB) &&
    objA.source === objB.source &&
    objA.global === objB.global &&
    objA.ignoreCase === objB.ignoreCase &&
    objA.multiline === objB.multiline;
}

const operators = {
  $eq (deepValue, referenceValue) {
    return isEqlRegex(deepValue, referenceValue) || isEqual(deepValue, referenceValue);
  },
  $gt (deepValue, referenceValue) {
    return deepValue > referenceValue;
  },
  $lt (deepValue, referenceValue) {
    return deepValue < referenceValue;
  },
  $gte (deepValue, referenceValue) {
    return deepValue >= referenceValue;
  },
  $lte (deepValue, referenceValue) {
    return deepValue <= referenceValue;
  },
  $neq (deepValue, referenceValue) {
    return deepValue !== referenceValue;
  },
  $contains (deepValue, referenceValue) {
    return isString(deepValue) &&
      isString(referenceValue) &&
      deepValue.indexOf(referenceValue) > 0;
  },
  $regex (deepValue, regex) {
    return regex.test(deepValue);
  },
  $fn (deepValue, testFn) {
    let isMatch = false;
    try {
      isMatch = testFn(deepValue);
    } catch (e) {
      isMatch = false;
    }
    return isMatch;
  },
  $fnUnsafe (deepValue, testFn) {
    return testFn(deepValue);
  }
};

function isComparisonObj (comparisonObj) {
  return Object.keys(comparisonObj)
    .map(operator => operator in operators)
    .reduce((result, opOkay) => result && opOkay, true);
}

function constructCondition (queryAspect) {
  if (isObject(queryAspect) && isComparisonObj(queryAspect)) {
    const subconditions = Object.keys(queryAspect).map(operator => operators[operator]);
    return val => utils.all(subconditions, subcondition => subcondition(val));
  } else if (isRegExp(queryAspect)) {
    return operators.$regex;
  }
  return operators.$eq;
}

export default function query (queryLiteral) {
  const conditions = Object.keys(queryLiteral).map(keypath => {
    const keypathArray = utils.getKeypathArray(keypath);
    const condition = constructCondition(queryLiteral[keypath]);
    return obj => condition(utils.getDeepValue(obj, keypathArray));
  });

  return obj => utils.all(conditions, condition => condition(obj));
}
<|endoftext|>


<commit_before>/**
 * Rajah.js : runner of jasmine.
 *
 *
 */

var Rajah = (function () {
  /**
   * User should call this function in user's doGet() function.
   * and should return results of this function.
   *
   * @param {object} Currently not in use. for futur extention.
   */
  var doGet = function (e) {
    var app = UiApp.createApplication();

    var splitPanel = app.createSplitLayoutPanel().setSize("100%","100%");

    var vPanel = app.createVerticalPanel().setSize("100%","");
    var title = app.createHTML("
[ jasmine console ]
").setSize("100%","");
    vPanel.add(title);
    var text = app.createHTML("------").setSize("100%","").setId("text");
    vPanel.add(text);

    var scrollPanel = app.createScrollPanel().setSize("100%", "100%");
    scrollPanel.add(vPanel);

    var handler = app.createServerHandler("executeJasmine").addCallbackElement(text);
    var b = app.createButton("Execute jasmine", handler).setSize("100%", "30");

    splitPanel.addNorth(b, 38).setWidgetMinSize(b, 38);
    splitPanel.add(scrollPanel);
    app.add(splitPanel);

    return app;
  };

  function executeJasmine(eventInfo) {
    var app = UiApp.createApplication(),
        logText = "",
        consoleHTML = app.getElementById("text"),
        colorChanged = "";

    function console(message) {
      var str, clearCode = "";
      message = message.replace(/\n/g, "
");

      var str = message.match(/\033\[32m|\033\[31m|\033\[33m|\033\[0m/);
      while (str !== null) {
        switch (str[0]) {
          case ('\033[32m'): // green
            message = message.replace(/\033\[32m/, clearCode + '');
            clearCode = '';
            break;
          case ('\033[31m'): // red
            message = message.replace(/\033\[32m/, clearCode + '');
            clearCode = '';
            break;
          case ('\033[33m'): // yellow
            message = message.replace(/\033\[32m/, clearCode + '');
            clearCode = '';
            break;
          case ('\033[0m'):  // none
            message = message.replace(/\033\[0m/, clearCode);
            clearCode = "";
            break;
          default:
            break;
        }
        str = message.match(/\033\[32m|\033\[31m|\033\[33m|\033\[0m/);
      }

      logText += message;
      consoleHTML.setHTML(logText);
    }

    main(console);

    return app;
  }

  function main(console) {

    var jasmineEnv = jasmine.getEnv();
    var ConsoleReporter = new jasmine.ConsoleReporter(console, (function (r) {
      var rStr = "result = ";
      console(rStr);
      // rStr =  Utilities.jsonStringify(r);
      // console(rStr);
    }), true);
    jasmineEnv.addReporter(ConsoleReporter);

    jasmineEnv.execute();

    return true;
  }

})();

function setTimeout(f, t) {
  Utilities.sleep(t);
  f();
}

function clearTimeout() {}

function setInterval() {}

function clearInterval() {}

<commit_msg>update rajah.js<commit_after>/**
 * Rajah.js : junsmine runner on google apps script.
 * @fileoverview jasmine runner on google apps script.
 *
 */

var Rajah = (function () {
  /**
   * Main application should call this function in main doGet() function.
   * and should return results of this function.
   *
   * @param {object} Currently not in use. for futhur extention.
   */
  var doGet = function (e) {
    var app = UiApp.createApplication();

    var splitPanel = app.createSplitLayoutPanel().setSize("100%","100%");

    var vPanel = app.createVerticalPanel().setSize("100%","");
    var title = app.createHTML("
[ jasmine console ]
").setSize("100%","");
    vPanel.add(title);
    var text = app.createHTML("------").setSize("100%","").setId("text");
    vPanel.add(text);

    var scrollPanel = app.createScrollPanel().setSize("100%", "100%");
    scrollPanel.add(vPanel);

    var handler = app.createServerHandler("executeTrigger").addCallbackElement(text);
    var b = app.createButton("Execute jasmine", handler).setSize("100%", "30");

    splitPanel.addNorth(b, 38).setWidgetMinSize(b, 38);
    splitPanel.add(scrollPanel);
    app.add(splitPanel);

    return app;
  };

  /**
   * UI-handler, set-up environment and execute jasmine.
   *
   */
  var executeTrigger = function (eventInfo) {
    var app = UiApp.createApplication(),
        logText = "",
        consoleHTML = app.getElementById("text"),
        colorChanged = "";

    var console = function (message) {
      var str, clearCode = "";
      message = message.replace(/\n/g, "
");

      var str = message.match(/\033\[32m|\033\[31m|\033\[33m|\033\[0m/);
      while (str !== null) {
        switch (str[0]) {
          case ('\033[32m'): // green
            message = message.replace(/\033\[32m/, clearCode + '');
            clearCode = '';
            break;
          case ('\033[31m'): // red
            message = message.replace(/\033\[32m/, clearCode + '');
            clearCode = '';
            break;
          case ('\033[33m'): // yellow
            message = message.replace(/\033\[32m/, clearCode + '');
            clearCode = '';
            break;
          case ('\033[0m'):  // none
            message = message.replace(/\033\[0m/, clearCode);
            clearCode = "";
            break;
          default:
            break;
        }
        str = message.match(/\033\[32m|\033\[31m|\033\[33m|\033\[0m/);
      }

      logText += message;
      consoleHTML.setHTML(logText);
    };

    executeJasmine(console);

    return app;
  };

  var executeJasmine = function (console) {

    var jasmineEnv = jasmine.getEnv();
    var ConsoleReporter = new jasmine.ConsoleReporter(console, (function (r) { }), true);
    jasmineEnv.addReporter(ConsoleReporter);

    jasmineEnv.execute();

    return true;
  };

  var exports = {
    doGet: doGet
  }

  return exports;
})();

function setTimeout(f, t) {
  Utilities.sleep(t);
  f();
}

function clearTimeout() {}

function setInterval() {}

function clearInterval() {}

<|endoftext|>


<commit_before>/* jshint node:true */
var compiler = require('./compiler.js');

var Razor = (function() {
    'use strict';

    function _indent(count) {
        count *= 4;
        return new Array(++count).join(' ');
    }

    function _escape(string) {
        return string.replace(/%([\w\-]+)/g, 'this.escape(@$1)');
    }

    function _templateNameFromView(view) {
        return view.split('.')[0];
    }

    function _replaceArgs(string) {
        return string.replace(/\$([\w\-]+)/g, function(match, arg) {
            if (arg.indexOf('-') === -1) {
                return 'args.' + arg;
            }

            return 'args[\'' + arg + '\']';
        });
    }

    function _templateToJavascript(string) {

        string = string.replace(/\s{2,}/g, ' ').replace(/> </g, '><');

        // replace inline variables
        string = string.replace(new RegExp('{{\\s*(.*?);?\\s*}}', 'g'), function(group, code) {
            code = _replaceArgs(_escape(code));
            code = "' + " + code + " + '";
            return code.replace(/\'/g, '_QUOTE_');
        });

        var regex = new RegExp('{%\\s*(.*?):?\\s*%}', 'g'),
            bits = string.split(regex),
            length = bits.length,
            matches,
            bit,
            line,
            start,
            definedVars = {},
            activeVar = 't',
            line_ending,
            code = [],
            first_word,
            expression,
            extend,
            indent = 0,
            i;

        for (i = 0; i < length; i++) {
            line = bits[i].replace(/^\s+/, '').replace(/\s+$/, '');

            if (!line) {
                continue;
            }

            if (i % 2) {
                first_word = line.split(' ')[0];
                bit = line.replace(first_word, '');
                line_ending = ';';

                if (first_word === 'elseif') {
                    first_word = 'else if';
                }

                switch (first_word) {
                    case 'case':
                        line_ending = ':';
                        break;
                    case 'if':
                    case 'for':
                    case 'switch':
                        line_ending = ' {';
                        break;
                    case 'else if':
                    case 'else':
                        indent -= 1;
                        first_word = '} ' + first_word;
                        line_ending = ' {';
                        break;
                }

                // if the first line is an if statement or loop we need to make
                // sure that t is defined for later
                if (!start) {
                    start = 'var ' + activeVar + ' = \'\';\n\n';
                    definedVars[activeVar] = 1;
                    code.push(start);
                }

                if (first_word.indexOf('end') === 0) {
                    if (extend && --extend.level === 0) {
                        code.push(_indent(indent) + 't += this.render(\'' + extend.templateName + '\', {' + extend.variableName + ': ' + extend.variableName + '});\n');
                        extend = false;
                        continue;
                    }

                    indent -= 1;
                    code.push(_indent(Math.max(indent, 0)) + '}\n\n');
                    continue;
                }

                expression = line_ending === ';';

                if (expression && bit.charAt(bit.length - 1) === ';') {
                    line_ending = '';
                }

                // special case for extending views
                if (first_word === 'extend' || first_word.indexOf('extend(') === 0) {
                    matches = /extend\s*\(\s*(['"])(.*?)\1\s*,\s*\$(.*?)\)/.exec(line);
                    extend = {};
                    extend.level = 1;
                    extend.templateName = _templateNameFromView(matches[2]);
                    extend.variableName = matches[3];
                    activeVar = extend.variableName;
                    continue;
                }

                // special case for rendering sub views
                if (first_word === 'render' || first_word.indexOf('render(') === 0) {
                    matches = /render\s*\(\s*(['"])(.*?)\1(,(.*?)$)?/.exec(line);
                    var templateName = _templateNameFromView(matches[2]);
                    code.push(_indent(indent) + activeVar + ' += this.' + _replaceArgs(line.replace(matches[2], templateName)) + line_ending + '\n');
                    continue;
                }

                if (extend) {
                    extend.level++;
                }

                code.push(_indent(indent) + first_word + _replaceArgs(_escape(bit)) + line_ending + '\n');

                if (!expression) {
                    indent += 1;
                }

                if (first_word === 'break') {
                    indent -= 1;
                }

                continue;
            }

            start = activeVar + ' += ';
            if (!definedVars[activeVar]) {
                start = 'var ' + activeVar + ' = ';
                definedVars[activeVar] = 1;
            }

            code.push(_indent(indent) + start + '\'' + line.replace(/\'/g, "\\'").replace(/\n/g, '').replace(/_QUOTE_/g, "'") + '\'' + ';\n');
        }

        code.push('return t;');
        return code.join('');
    }

    return {
        generate: function(string) {
            return _templateToJavascript(string);
        },

        compile: function(string) {
            return new Function(string);
        },

        process: compiler.process
    };
}) ();

module.exports = Razor;
<commit_msg>Switch back to t variable<commit_after>/* jshint node:true */
var compiler = require('./compiler.js');

var Razor = (function() {
    'use strict';

    function _indent(count) {
        count *= 4;
        return new Array(++count).join(' ');
    }

    function _escape(string) {
        return string.replace(/%([\w\-]+)/g, 'this.escape(@$1)');
    }

    function _templateNameFromView(view) {
        return view.split('.')[0];
    }

    function _replaceArgs(string) {
        return string.replace(/\$([\w\-]+)/g, function(match, arg) {
            if (arg.indexOf('-') === -1) {
                return 'args.' + arg;
            }

            return 'args[\'' + arg + '\']';
        });
    }

    function _templateToJavascript(string) {

        string = string.replace(/\s{2,}/g, ' ').replace(/> </g, '><');

        // replace inline variables
        string = string.replace(new RegExp('{{\\s*(.*?);?\\s*}}', 'g'), function(group, code) {
            code = _replaceArgs(_escape(code));
            code = "' + " + code + " + '";
            return code.replace(/\'/g, '_QUOTE_');
        });

        var regex = new RegExp('{%\\s*(.*?):?\\s*%}', 'g'),
            bits = string.split(regex),
            length = bits.length,
            matches,
            bit,
            line,
            start,
            definedVars = {},
            activeVar = 't',
            line_ending,
            code = [],
            first_word,
            expression,
            extend,
            indent = 0,
            i;

        for (i = 0; i < length; i++) {
            line = bits[i].replace(/^\s+/, '').replace(/\s+$/, '');

            if (!line) {
                continue;
            }

            if (i % 2) {
                first_word = line.split(' ')[0];
                bit = line.replace(first_word, '');
                line_ending = ';';

                if (first_word === 'elseif') {
                    first_word = 'else if';
                }

                switch (first_word) {
                    case 'case':
                        line_ending = ':';
                        break;
                    case 'if':
                    case 'for':
                    case 'switch':
                        line_ending = ' {';
                        break;
                    case 'else if':
                    case 'else':
                        indent -= 1;
                        first_word = '} ' + first_word;
                        line_ending = ' {';
                        break;
                }

                // if the first line is an if statement or loop we need to make
                // sure that t is defined for later
                if (!start) {
                    start = 'var ' + activeVar + ' = \'\';\n\n';
                    definedVars[activeVar] = 1;
                    code.push(start);
                }

                if (first_word.indexOf('end') === 0) {
                    if (extend && --extend.level === 0) {
                        code.push(_indent(indent) + 't += this.render(\'' + extend.templateName + '\', {' + extend.variableName + ': ' + extend.variableName + '});\n');
                        extend = false;
                        activeVar = 't';
                        continue;
                    }

                    indent -= 1;
                    code.push(_indent(Math.max(indent, 0)) + '}\n\n');
                    continue;
                }

                expression = line_ending === ';';

                if (expression && bit.charAt(bit.length - 1) === ';') {
                    line_ending = '';
                }

                // special case for extending views
                if (first_word === 'extend' || first_word.indexOf('extend(') === 0) {
                    matches = /extend\s*\(\s*(['"])(.*?)\1\s*,\s*\$(.*?)\)/.exec(line);
                    extend = {};
                    extend.level = 1;
                    extend.templateName = _templateNameFromView(matches[2]);
                    extend.variableName = matches[3];
                    activeVar = extend.variableName;
                    continue;
                }

                // special case for rendering sub views
                if (first_word === 'render' || first_word.indexOf('render(') === 0) {
                    matches = /render\s*\(\s*(['"])(.*?)\1(,(.*?)$)?/.exec(line);
                    var templateName = _templateNameFromView(matches[2]);
                    code.push(_indent(indent) + activeVar + ' += this.' + _replaceArgs(line.replace(matches[2], templateName)) + line_ending + '\n');
                    continue;
                }

                if (extend) {
                    extend.level++;
                }

                code.push(_indent(indent) + first_word + _replaceArgs(_escape(bit)) + line_ending + '\n');

                if (!expression) {
                    indent += 1;
                }

                if (first_word === 'break') {
                    indent -= 1;
                }

                continue;
            }

            start = activeVar + ' += ';
            if (!definedVars[activeVar]) {
                start = 'var ' + activeVar + ' = ';
                definedVars[activeVar] = 1;
            }

            code.push(_indent(indent) + start + '\'' + line.replace(/\'/g, "\\'").replace(/\n/g, '').replace(/_QUOTE_/g, "'") + '\'' + ';\n');
        }

        code.push('return t;');
        return code.join('');
    }

    return {
        generate: function(string) {
            return _templateToJavascript(string);
        },

        compile: function(string) {
            return new Function(string);
        },

        process: compiler.process
    };
}) ();

module.exports = Razor;
<|endoftext|>


<commit_before>/**
 * @module Keo
 * @submodule Redux
 * @author Adam Timberlake
 * @link https://github.com/Wildhoney/Keo
 */
import {createWithCompose, wrap} from './keo';
import {connect} from 'react-redux';
export {memoize, trace, partial, compose, composeDeferred} from 'funkel';
export {default as objectAssign} from 'object-assign';
export {compose, composeDeferred, resolutionMap} from './keo';

/**
 * @method stitch
 * @param {Object|Function} component
 * @param {Function} [mapStateToProps]
 * @return {React.createClass}
 */
export const stitch = (component, mapStateToProps) => {
    return connect(mapStateToProps)(createWithCompose(wrap(component)));
};
<commit_msg>Exporting pipe and pipeDeferred<commit_after>/**
 * @module Keo
 * @submodule Redux
 * @author Adam Timberlake
 * @link https://github.com/Wildhoney/Keo
 */
import {createWithCompose, wrap} from './keo';
import {connect} from 'react-redux';
export {memoize, trace, partial, compose, composeDeferred} from 'funkel';
export {default as objectAssign} from 'object-assign';
export {pipe, pipeDeferred, resolutionMap} from './keo';

/**
 * @method stitch
 * @param {Object|Function} component
 * @param {Function} [mapStateToProps]
 * @return {React.createClass}
 */
export const stitch = (component, mapStateToProps) => {
    return connect(mapStateToProps)(createWithCompose(wrap(component)));
};
<|endoftext|>


<commit_before>/*	MediaType
	Determines the type of media the url string is.
	returns an object with .type and .id
	the id is a key piece of information needed to make
	the request of the api.
================================================== */
if(typeof VMM != 'undefined' && typeof VMM.MediaType == 'undefined') {

	VMM.MediaType = function(_d) {
		var d		= _d.replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
			success	= false,
			media	= {
				type:		"unknown",
				id:			"",
				start:		0,
				hd:			false,
				link:		"",
				lang:		VMM.Language.lang,
				uniqueid:	VMM.Util.unique_ID(6)
			};

		if (d.match("div class='twitter'")) {
			media.type = "twitter-ready";
		    media.id = d;
		    success = true;
		} else if (d.match('<blockquote')) {
			media.type = "quote";
			media.id = d;
			success = true;
		} else if (d.match('<iframe')) {
			media.type = "iframe";
			trace("IFRAME")
			regex = /src=['"](\S+?)['"]/;
			group = d.match(regex);
			if (group) {
				media.id = group[1];
			}
			trace( "iframe url: " + media.id );
			success = Boolean(media.id);
		} else if (d.match('(www.)?youtube|youtu\.be')) {
			if (d.match('v=')) {
				media.id	= VMM.Util.getUrlVars(d)["v"];
			} else if (d.match('\/embed\/')) {
				// TODO Issue #618 better splitting
				media.id	= d.split("embed\/")[1].split(/[?&]/)[0];
			} else if (d.match(/v\/|v=|youtu\.be\//)){
				media.id	= d.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0];
			} else {
				trace("YOUTUBE IN URL BUT NOT A VALID VIDEO");
			}
			media.start	= VMM.Util.getUrlVars(d)["t"];
			media.hd	= VMM.Util.getUrlVars(d)["hd"];
		    media.type = "youtube";
		    success = true;
		} else if (d.match('(player.)?vimeo\.com')) {
		    media.type = "vimeo";
		    media.id = d.split(/video\/|\/\/vimeo\.com\//)[1].split(/[?&]/)[0];;
		    success = true;
	    } else if (d.match('(www.)?dailymotion\.com')) {
			media.id = d.split(/video\/|\/\/dailymotion\.com\//)[1];
			media.type = "dailymotion";
			success = true;
	    } else if (d.match('(www.)?vine\.co')) {
			trace("VINE");
			//https://vine.co/v/b55LOA1dgJU
			if (d.match("vine.co/v/")) {
				media.id = d.split("vine.co/v/")[1];
				trace(media.id);
			}
			trace(d);
			media.type = "vine";
			success = true;
		} else if (d.match('(player.)?soundcloud\.com')) {
			media.type = "soundcloud";
			media.id = d;
			success = true;
		} else if (d.match('(www.)?twitter\.com') && d.match('status') ) {
			if (d.match("status\/")) {
				media.id = d.split("status\/")[1];
			} else if (d.match("statuses\/")) {
				media.id = d.split("statuses\/")[1];
			} else {
				media.id = "";
			}
			media.type = "twitter";
			success = true;
		} else if (d.match("maps.google") && !d.match("staticmap") && !d.match('streetview')) {
			media.type = "google-map";
		    media.id = d.split(/src=['|"][^'|"]*?['|"]/gi);
			success = true;
		} else if (d.match(/www.google.\w+\/maps/)) {
			media.type = "google-map";
		    media.id = d;
			success = true;
		} else if (d.match("plus.google")) {
			media.type = "googleplus";
		    media.id = d.split("/posts/")[1];
			//https://plus.google.com/u/0/112374836634096795698/posts/bRJSvCb5mUU
			//https://plus.google.com/107096716333816995401/posts/J5iMpEDHWNL
			if (d.split("/posts/")[0].match("u/0/")) {
				media.user = d.split("u/0/")[1].split("/posts")[0];
			} else {
				media.user = d.split("google.com/")[1].split("/posts/")[0];
			}
			success = true;
		} else if (d.match("flickr.com/photos/")) {
			media.type = "flickr";
			media.id = VMM.ExternalAPI.flickr.getFlickrIdFromUrl(d)
			media.link = d;
			success = Boolean(media.id);
		} else if (VMM.ExternalAPI.instagram.isInstagramUrl(d)) {
			media.type = "instagram";
			media.link = d;
			media.id = VMM.ExternalAPI.instagram.getInstagramIdFromUrl(d)
			success = Boolean(media.id);
		} else if (d.match(/jpg|jpeg|png|gif|svg|bmp/i) ||
				   d.match("staticmap") ||
				   d.match("yfrog.com") ||
				   d.match("twitpic.com") ||
				   d.match('maps.googleapis.com/maps/api/streetview')) {
			media.type = "image";
			media.id = d;
			success = true;
		} else if (VMM.FileExtention.googleDocType(d)) {
			media.type = "googledoc";
			media.id = d;
			success = true;
		} else if (d.match('(www.)?wikipedia\.org')) {
			media.type = "wikipedia";
			//media.id = d.split("wiki\/")[1];
			// TODO Issue #618 better splitting
			var wiki_id = d.split("wiki\/")[1].split("#")[0].replace("_", " ");
			media.id = wiki_id.replace(" ", "%20");
			media.lang = d.split("//")[1].split(".wikipedia")[0];
			success = true;
		} else if (d.indexOf('http://') == 0) {
			media.type = "website";
			media.id = d;
			success = true;
		} else if (d.match('storify')) {
			media.type = "storify";
			media.id = d;
			success = true;
		} else {
			trace("unknown media");
			media.type = "unknown";
			media.id = d;
			success = true;
		}

		if (success) {
			return media;
		} else {
			trace("No valid media id detected");
			trace(d);
		}
		return false;
	}
}<commit_msg>don't use return from split, which is an array, which should really have meant someone found this broken before now... (cf. ZenDesk no. 402)<commit_after>/*	MediaType
	Determines the type of media the url string is.
	returns an object with .type and .id
	the id is a key piece of information needed to make
	the request of the api.
================================================== */
if(typeof VMM != 'undefined' && typeof VMM.MediaType == 'undefined') {

	VMM.MediaType = function(_d) {
		var d		= _d.replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
			success	= false,
			media	= {
				type:		"unknown",
				id:			"",
				start:		0,
				hd:			false,
				link:		"",
				lang:		VMM.Language.lang,
				uniqueid:	VMM.Util.unique_ID(6)
			};

		if (d.match("div class='twitter'")) {
			media.type = "twitter-ready";
		    media.id = d;
		    success = true;
		} else if (d.match('<blockquote')) {
			media.type = "quote";
			media.id = d;
			success = true;
		} else if (d.match('<iframe')) {
			media.type = "iframe";
			trace("IFRAME")
			regex = /src=['"](\S+?)['"]/;
			group = d.match(regex);
			if (group) {
				media.id = group[1];
			}
			trace( "iframe url: " + media.id );
			success = Boolean(media.id);
		} else if (d.match('(www.)?youtube|youtu\.be')) {
			if (d.match('v=')) {
				media.id	= VMM.Util.getUrlVars(d)["v"];
			} else if (d.match('\/embed\/')) {
				// TODO Issue #618 better splitting
				media.id	= d.split("embed\/")[1].split(/[?&]/)[0];
			} else if (d.match(/v\/|v=|youtu\.be\//)){
				media.id	= d.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0];
			} else {
				trace("YOUTUBE IN URL BUT NOT A VALID VIDEO");
			}
			media.start	= VMM.Util.getUrlVars(d)["t"];
			media.hd	= VMM.Util.getUrlVars(d)["hd"];
		    media.type = "youtube";
		    success = true;
		} else if (d.match('(player.)?vimeo\.com')) {
		    media.type = "vimeo";
		    media.id = d.split(/video\/|\/\/vimeo\.com\//)[1].split(/[?&]/)[0];;
		    success = true;
	    } else if (d.match('(www.)?dailymotion\.com')) {
			media.id = d.split(/video\/|\/\/dailymotion\.com\//)[1];
			media.type = "dailymotion";
			success = true;
	    } else if (d.match('(www.)?vine\.co')) {
			trace("VINE");
			//https://vine.co/v/b55LOA1dgJU
			if (d.match("vine.co/v/")) {
				media.id = d.split("vine.co/v/")[1];
				trace(media.id);
			}
			trace(d);
			media.type = "vine";
			success = true;
		} else if (d.match('(player.)?soundcloud\.com')) {
			media.type = "soundcloud";
			media.id = d;
			success = true;
		} else if (d.match('(www.)?twitter\.com') && d.match('status') ) {
			if (d.match("status\/")) {
				media.id = d.split("status\/")[1];
			} else if (d.match("statuses\/")) {
				media.id = d.split("statuses\/")[1];
			} else {
				media.id = "";
			}
			media.type = "twitter";
			success = true;
		} else if (d.match("maps.google") && !d.match("staticmap") && !d.match('streetview')) {
			media.type = "google-map";
		    media.id = d;
			success = true;
		} else if (d.match(/www.google.\w+\/maps/)) {
			media.type = "google-map";
		    media.id = d;
			success = true;
		} else if (d.match("plus.google")) {
			media.type = "googleplus";
		    media.id = d.split("/posts/")[1];
			//https://plus.google.com/u/0/112374836634096795698/posts/bRJSvCb5mUU
			//https://plus.google.com/107096716333816995401/posts/J5iMpEDHWNL
			if (d.split("/posts/")[0].match("u/0/")) {
				media.user = d.split("u/0/")[1].split("/posts")[0];
			} else {
				media.user = d.split("google.com/")[1].split("/posts/")[0];
			}
			success = true;
		} else if (d.match("flickr.com/photos/")) {
			media.type = "flickr";
			media.id = VMM.ExternalAPI.flickr.getFlickrIdFromUrl(d)
			media.link = d;
			success = Boolean(media.id);
		} else if (VMM.ExternalAPI.instagram.isInstagramUrl(d)) {
			media.type = "instagram";
			media.link = d;
			media.id = VMM.ExternalAPI.instagram.getInstagramIdFromUrl(d)
			success = Boolean(media.id);
		} else if (d.match(/jpg|jpeg|png|gif|svg|bmp/i) ||
				   d.match("staticmap") ||
				   d.match("yfrog.com") ||
				   d.match("twitpic.com") ||
				   d.match('maps.googleapis.com/maps/api/streetview')) {
			media.type = "image";
			media.id = d;
			success = true;
		} else if (VMM.FileExtention.googleDocType(d)) {
			media.type = "googledoc";
			media.id = d;
			success = true;
		} else if (d.match('(www.)?wikipedia\.org')) {
			media.type = "wikipedia";
			//media.id = d.split("wiki\/")[1];
			// TODO Issue #618 better splitting
			var wiki_id = d.split("wiki\/")[1].split("#")[0].replace("_", " ");
			media.id = wiki_id.replace(" ", "%20");
			media.lang = d.split("//")[1].split(".wikipedia")[0];
			success = true;
		} else if (d.indexOf('http://') == 0) {
			media.type = "website";
			media.id = d;
			success = true;
		} else if (d.match('storify')) {
			media.type = "storify";
			media.id = d;
			success = true;
		} else {
			trace("unknown media");
			media.type = "unknown";
			media.id = d;
			success = true;
		}

		if (success) {
			return media;
		} else {
			trace("No valid media id detected");
			trace(d);
		}
		return false;
	}
}<|endoftext|>